Giter Club home page Giter Club logo

falling-fruit-web's Issues

Fix fonts absent from certain areas in Safari

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Sync map view state to query params

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

Description

Add location search, with suggestions populated by Google Places Autocomplete.

Suggested branch name: location-search

image
image

Refs #22

Learning objectives

  • Using 3rd-party React hooks. What exactly is a hook? What's the common thread between useState, useEffect, and third-party hooks like this one?
  • Passing state through a component hierarchy via react-router
  • Wrapping 3rd-party UI components
  • Advanced: component polymorphism in Reach libraries

Todo

Please, thoroughly read through the front pages of both pieces of documentation.

  • In components/search/Search.js, start building the location searchbox.
  • Follow the guide in the autocomplete API to use Reach combobox with it.
  • Investigate the 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)
  • Reference Figma designs for styling. (Note: we are not doing any of the "Entry" rows in the search, nor will there be gray category bars)
  • You will need to add the Search component into the desktop as well, which is why it's essential to try to create a reusable component. Almost all your code should be the same, except for some styling differences with how the dropdown for search suggestions appears on desktop. Please check with @SirajChokshi on this.
  • Figure out how to pass the selected place name, latitude, and longitude into the MapPage component, using react-router-dom's query params (history.push, useParams, and useEffect (to update the map when the params change))
  • As a finishing touch, use react-cool-onclickoutside to close the search bar when the users clicks outside of it.

Useful links

Form headings

Description

image

Branch name: form-headings

Todo

  • Create styled versions of <label> for the form, with a standardized margin-top
    image

  • Create section headings
    image

  • Create the tags
    image
    image

    • These should be inline, not block
  • Remove label from Input

Useful links

  • Review what inline vs. block is

Individual review

Description

Review component

image

Todo

  • Break component down into separate components
  • Make sure the great/good/poor section supports any number of attributes
  • Final exported component should be easy to use

Useful links

  • Flexbox...

Form textarea

Description

Wrap <textarea> in ui/Textarea.js to look like this:

image

See ui/Input.js for details.

Branch name: form-textarea

Todo

  • Follow Input as guideline

Useful links

  • ui/Input.js

Unrecognized/Invalid Bounds during Map Roll Around

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:

  1. Go to http://localhost:3000/login
  2. Click on the map and rotate to the right by 360 degrees until you are back at the location you started on
  3. Clusters will not appear on this view of the map.
  4. Go back 360 degrees to the left to reverse your actions and clusters will once again appear.
  5. Using chrome developer tools, the increment of longitude through these roll arounds can be seen as well.

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
Screen Shot 2021-03-01 at 7 59 51 PM
Screen Shot 2021-03-01 at 8 00 42 PM
Screen Shot 2021-03-01 at 8 01 37 PM

Form slider

Description

Style and wrap @reach/slider to make a slider component:

image

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

Todo

  • Gain a thorough understanding of Reach's Slider component (read through the entire page)
  • Create a new Slider component in ui/Slider.js.
  • Get Reach's slider appearing on the page
  • Style the slider track itself
  • Make each step appear as a discrete circle
    • SliderMarker
  • Style the currently selected step
    • Use data attributes to do this
  • Add support for labels underneath each step
    • This will have to be a custom prop passed into your Slider (that doesn't get passed into Reach's Slider), an array of labels
    • Each label gets rendered underneath each step
    • Perhaps you can achieve this by rendering the labels equally spaced under the slider
    • But it's probably better to wrap SlideerMarker and render some text under it

Useful links

Form progress bar

Description

Create progress bar showing the steps in the form:

image

ui/ProgressBar.js

Branch name: form-progress

Todo

  • Create the component in ui
  • Break down the whole progress bar component into multiple components for easier styling and separation of concerns
  • Decide on what makes sense to take as props for this component
    • currentStep
    • onChange
    • labels: an array of N labels. This also determines the number of steps (N)
  • Styling
    • Track, circles, labels under the track
  • Integrate props
  • Test

Useful links

Reviews

Description

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).

Objectives

  • P1: Users should be able to look over past reviews for a particular location that is displayed on the location details page.
  • P1: Users should be able to fill out the review form with relevant information about the types observed so they can document a trip to a pre-existing location.

Todo / Backlog

List view

Description

Adds list view.

Mobile:

image

Desktop:

image

Epic: #54

Learning objectives

  • Virtualization
  • Delaying API calls for more info until the user scrolls down

Todo

  • Start reading about react-virtualized or react-window and determine which is best for this purpose.
  • Start with mobile first:
  • Use ListEntry for each individual entry
  • The list view's "bounds" should be synced to the map view. Using the view bounds in MapContext, make a new request to /locations.json (with all the relevant SearchContext filters) specifying lng and lat.
  • Using limit and offset, make new API requests as the user scrolls down the list
  • Make sure the list is virtualized

Once finished with mobile, start thinking about component design for desktop

  • We do need to talk with Siraj more about desktop view and what the behavior should be
  • What happens after clicking on "View All Entries"
  • If on desktop: add "go to location" and "go to entry details" buttons to the ListEntry

Useful links

  • react-window

Location Information View

Description

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.

Objectives

  • P0: Users should be able to click on a pin on the map then navigate to this mini view so they can get more information about the location they're interested in.
  • P0: Users should be able to navigate to the location's address on the map view so they can view the location in relation to other map objects.
  • P0: Users should be able to read more about the particular location and associated edible, as well as other metadata so they can learn details about a location.
  • P0: Users should be able to edit a location that they wrote so they can make appropriate updates or corrections on a location.
  • P1: Users should be able to click on a list location and then navigate to this mini view so they can access information on a location they're interested in.
  • P1: Users should be able to read through reviews of a location so they can get other people's opinions on the location and edible.

Todo / Backlog

Add request functions to API wrapper

Description

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.

Learning objectives

  • How to use axios
  • Importance of an abstraction layer. Why do we need an API wrapper? Why not make axios calls in the components directly?
  • Designing a module so that it's easy to use by other components
  • What's the best way to store an API key & authentication token so that it doesn't have to be passed in repeatedly to the API wrapper?

Todo

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?"

  • Create a series of exported functions in src/utils/api.js that will cover all the functionality in v0.2 of the Falling Fruit API
  • Design these functions in a way that they're easy to use.
    • For example, is it best to pass in latitude and longitude bounds as four separate arguments?
  • (Last priority) Think about and document how the API could potentially be improved. Ethan is working on v0.3 of the FF API and has explicitly mentioned he would really appreciate hearing our opinions

If you're unsure, it's best to keep the API wrappers "thin," i.e. not too different from the REST endpoints.

Useful links

Add adaptive layout

Description

  • Add breakpoints to website so that depending on window width, a mobile or desktop layout is rendered

Map labels

Description

Add labels to the locations on the map.

image

Relevant component: components/map/Location.js
Branch name: map-labels

Learning objectives

  • Context
  • Centering

Todo

  • Style and rework Location.js to optionally take a label via a label prop
  • This label should be centered below the blue circle
  • Take a look at Slider.js ([data-reach-slider-marker] div) for how to center text under a small div
  • Map.js should take a boolean prop, showLabels
  • Add a SettingsContext in ui/. This should be modeled off of SearchContext
  • Add a showLabels field in the object
  • MapPage should pass the showLabels boolean in SettingsContext to Map
  • Map should grab the appropriate field from the locations prop (for the common name) to pass as the label prop in Location

Useful links

  • Swagger for finding which field is the common name

Reports

Description

Reports 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).

Objectives

  • P1: Users should be able to flag locations that are not valid by submitting a form (check valid problem types in the feature spec doc).
  • P2: Admins should be able to review and edit/delete the given location.

Todo / Backlog

  • Outcome of flagged activity being documented?

Fix current location with no permissions appears in the ocean in Safari

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Form caption input

Description

Wrap ListEntry, use CircleIcon, Input, IconButton

image

Component: ui/CaptionInput.js
Branch name: form-caption-input

Todo

  • In your final exposed component, have props: value (for the Input), onChange (for the Input), onDelete (for the IconButton), image (for the CircleIcon)

Useful links

  • Useful link

Location Form

Description

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:

  1. The user can click on the floating "+" button that appears on map view. This will lead them to the first part of the form (desktop: left sidebar, mobile: new separate page).
  2. The first part is marker placement. By default, the marker is at the "current location" of the user (whether that's their actual current location or the last address they've searched). On mobile, the marker is static in the middle of the screen and the user can move the map around it. On desktop, you can click and place the pin. Confirming on mobile and placing the pin on desktop will both update the "current address" field in the form.
  3. The default info screen. This should include types, position, description, and photo.
  4. The optional info screen. This should include season, access status, and verification. This only exists on a separate screen in mobile.
  5. The optional visit screen. Documenting a location doesn’t necessarily mean that you had visited at the time. For this reason, you have to submit a separate review form that documents your visit -- this is done on desktop, currently, through embedding the second form within the first if you click a checkbox. The optional visit screen will essentially be the review form, but it will not be the same review form that is used on the location information page. This only exists on a separate screen in mobile.
  6. The last part is the confirmation screen. They should be able to view all of the information they've inputted, then click submit if they're satisfied.
  7. After submitting the form, the user should automatically navigate to the new location and open up the entry details page they just made!

Objectives

  • P1: Users should be able to fill out the location form with relevant information about the types observed, and then submit it so it shows up in both Map and List View.
  • P1: Users should be able to have the default address of the location as the center of the map they are on for ease of access.
  • P1: Users should be able to move the address marker and confirm it on the form submission (in mobile) so they can easily pin their location. This location should also yield the semantic description of the coordinates.
  • P1: Users should be able to review and confirm all the details of their submission before submitting and be permitted to go back and edit any section they want to correct.
  • P1: User should be able to navigate to their newly create entry details page after submitting their location.

Todo / Backlog

Fix type filtering infinite scroll

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:

  1. Press the filter icon in the top right to bring up the tree selector
  2. Console log the data that is passed into the tree to verify that 100+ type filters are fetched from the server
  3. Scroll down to the bottom of the tree selector
  4. See error (additional types not loaded into the tree as you scroll to the bottom)

Expected behavior
Additional type options should be loaded into the tree selector as you scroll towards the bottom.

Hook up Google Maps wrapper component to API

Description

Hook up the Google Maps wrapper component (Map) to Ethan's API (via utils/api). This is done in pages/MapPage.

Refs #21

Learning objectives

  • Making asynchronous API requests. Please use async/await!
  • Working with a TypeScript API wrapper. Let's say you import getClusters from utils/api. Try mousing over getClusters in VS Code to see what params it takes.

Todo

  • Make sure clusters and locations are being shown on the map, depending on the zoom level. To increase the amount of data for now, you can pass muni: 1 to getClusters and getLocations.
  • Make sure the appropriate bounds are being sent to the API.
  • Ensure that clicking on clusters zooms in on the map.
  • Try to figure out a way to show "Loading" somewhere on the map when data is loading from the API. Exactly where you show it is not important, rather that your component can hold the "state" that API data has been requested, but not received yet.

Useful links

User analytics

Describe the the feature request
A clear and concise description of the feature.

Main Map Display

Description

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.

Objectives

  • Users should be able to view location pins on the map, clustered by density, on a Google Map so they can see a general overview of nearby pins.
  • Users should also be able to scroll and zoom to move on the map so they can browse local locations.

Todo / Backlog

Map Location Filter

Description

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.

Objectives

  • Users should be able to select which edible types they want to include on the map display so they can narrow down what sorts of locations they'd like to explore.
  • Users should be able to select and unselect special filters (tree inventories, invasive species).

Todo / Backlog

Entry location and seasonality

Description

Add location and seasonality to entry details:

image

Full entry details page for context:

image

Closes #47

Todo

  • Reverse geocode latitude and longitude of location to produce a street
    • Don't do this logic in the actual component, import a helper function to do this
    • You prob want to move search/locationInfo.js to general utils, and add your helper function there
  • Convert season_start and season_end, if no_season is true, to month names
    • Same here: the EntryDetails component is already on the large side
    • Maybe move ACCESS_TYPE, formatISOString, formatSeasonality to entry/textFormatters.js
  • Consider creating a separate component (kind of like ResourceList) for the location and seasonality
  • Clicking on the location (the address or the icon) should center the map view on the lat and lng of the location itself
    image
    • After clicking on the address, a pin should appear over the location:
      image
    • Push /map on desktop too
    • You can do this by adding a field in SearchContext called selectedLocation), passing that to Map
    • So EntryDetails needs to set selectedLocation with the entire location object
    • MapPage has a new useEffect on selectedLocation that's pretty similar to the one on searchViewport, except it does setView(fitContainerBounds(getGeolocationBounds({ bounds of the location })
    • Map adds a boolean prop called selected to <Location> if location.id === selectedLocation
    • Style Location.js to support having a pin over it, if selected is true

Add Google Maps wrapper component

Description

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.

Learning objectives

  • Creating a "wrapper" component and why that might be better than using the third-party component directly
  • Uncontrolled vs controlled components
  • How to document component with JSDoc

Todo

These points are a rough guideline. Please feel free to discuss with me and other devs about the best way to design this component!

  • Make a draft PR for this, and push up changes often, so the rest of the team can see them
  • Create a components directory in src
  • Add a functional Map component
  • Props
    • onClusterSelect callback that is called when a "cluster" is selected. Called with cluster id as the argument
    • onLocationSelect callback that is called when a "location" is selected. Called with location id as the argument
    • onDeselect 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 map
    • locations Array of objects {id: xxx, lat: xxx, lng: xxx} displayed as pins on the map
    • props and callbacks for center, 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.
  • Document your component with JSDoc and PropTypes!

Useful links

Entry reviews

Description

Add list of reviews to the entry details page:

image

Full entry details page (for context):

image

Todo

  • Figure out where review information comes from (do you need a new API call?)
  • Create a new component called ReviewList (like ResourceList) that takes in the reviews information and renders the Review component that you made, for each review

Useful links

Form type selection

Description

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.

image

Branch name: form-type-selection

Todo

  • Refactor out existing component
  • Style tags
  • Take a prop that shows whether or not to display tags
  • When the component is used for selection in the form, the types tree will be a true dropdown/popover over existing content. This will require "unstyling" some of the things you did to make it lie directly on the page (height: 100%, etc.)
  • Take a prop for whether it's a popover or not ^^
  • Some additional logic changes: you might want to make parent components unselectable, because it shouldn't make sense for the user to easily select a ton of types. They should select one in particular. Clarify with Siraj

Useful links

  • Dow Jones documentation
  • Existing Falling Fruit implementation of selecting types in a new location

Bootstrap styling

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.

Map Search

Description

Pretty self-explanatory. Users should be able to search and travel to new addresses.

Objectives

  • Users should be able to type in a search query and then get back potential results.
  • Users should be able to click on a result and then navigate to that address.

Todo / Backlog

Add entry details page

Description

Add an entry details page that gets triggered when the user clicks a location on the screen.

Suggested branch name: entry-details

Refs #24

Learning objectives

  • Passing state through a component hierarchy via react-router
    • We're not using anything extra like React Context or Redux for this, since so much of our state will be present in the URL. This has the nice side-effect of enabling deep linking throughout our app (we can copy and share the link to most views in our app)
  • Setting up component routes
  • Styling reusable UI components with styled-components

Todo

  • In MapPage, call history.push (react-router) with /entry/{locationId} when a location is clicked.
  • Fill out the EntryDetails page with all the information from a getLocation request, with the given ID in the route.
    image
  • Create an IconButton UI component that wraps HTML button. Two versions:
    Unraised:
    image
    Raised:
    image
    Props should include: raised (bool), label (string), icon (Node), onClick (function). Please ask @SirajChokshi for specifics on how this component should take size as a parameter (via props or via styles), because there are multiple sizes in the design.
  • Fill out the EntryNav component, which is the top bar here:
    image
  • Figure out how to make the back button in EntryNav work as expected by calling history.goBack
  • Create a wrapper page around EntryDetails for the desktop. Put this in the desktop folder. Same thing with the back button as in the mobile EntryNav.
    image
  • You'll need to do some routing in SidePane to make the desktop EntryDetails appear. You can follow my example in MobileLayout.

Useful links

Add type filtering

Description

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:

image

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?)

image

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:

image

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.

Searching for types

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.

Styling

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.

Relevant Figma designs

Mobile:
image

Desktop:
image

Suggested branch name: type-filtering
Suggested PR title (as would probably be suggested by @code-arman): <some relevant emoji> Add type filtering

Refs #23

Learning objectives

  • Using React context to pass data around. We do this in order to avoid drilling props back and forth in a complicated component hierarchy. This one is pretty valuable, since some kind of structured state management is essential in larger apps. Don't worry, context is pretty easy to use, without a lot of boilerplate. (Remember how we said we wouldn't use Redux in our project? We're still not, but Redux is actually implemented with React contexts.)
  • Data structures and building a tree in JavaScript. Who would have thought?
  • Styling, styling, styling
  • Breaking a complex feature down into simple parts, and implementing each part cleanly

Todo

  • Since this is a big feature, let Jeffrey know about what he can help out on by sometime mid-week, if you think it's necessary
  • Adding a "pressed" prop to IconButton
  • Reorganizing the shared Search component that is currently in desktop and mobile to include the filter button and the tree select component. In that shared component, at most one of [search suggestions, type filtering] should be visible. Note that it's best to just wrap the existing Search component so it doesn't get too long
  • Building the tree with the type hierarchy into a format that the tree select will expect
    • In particular, ensuring that type counts are correct and adding the "Other" category to each parent type
  • Loading types data based on the current viewport of the map, from MapContext
  • Upon changes in the tree select, propagate the correct list of types to the map via SearchContext
    • Being careful with the "Other" category
  • Adding type search to the tree select
  • Style the tree select nodes
  • Style the tree select search input

Useful links

Additional notes

Type Hierarchy

  1. One simple solution is to multiple requests is to include 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.
  2. Another solution, which @ezwelty mentioned and requires a lot more work, is to change the API to only return type IDs throughout all requests, and expect the frontend to get all type information ahead of time. This may speed up the API a bit, but requires more investigation.

Virtualization

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.

[TBD] List View

Description

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).

Objectives

  • P1: Users should be able to switch tabs to the list view to view a list of nearby locations (to the center of the map).
  • P1: Users should be able to open up a location's details page to get more info on the location, then click back to go back to the list view.
  • P1: Users should be able to filter by both address and multiple types in mobile, similar to the desktop version.
  • P2: Users should be able to filter by other factors (including verification, etc) on the desktop version for more precise sorting.

Todo / Backlog

Add ListEntry, MapTooltip, and ListCategory UI components

Description

Create three new presentational components in components/ui:

ListEntry

image
image

ListCategory

image

MapTooltip

image

Learning objectives

  • Component reusability. Notice that MapTooltip is just a container that wraps ListEntry
  • The children prop in React
  • Wrapping external UI libraries. We're using Reach UI!
  • Styling React components with styled-components
  • Using flexbox to achieve modern CSS layouts
  • Styling components according to a Figma design, and treating the design as doctrine
  • Communicating with our designer, @SirajChokshi, to achieve expected results. Please feel free to reach out to him to ask CSS/styling/design questions! Direct contact there will often get things done faster in this area.

Todo

Please follow the existing UI components in components/ui as examples.

  • ListEntry
    • Use flexbox, probably
    • If primary text or secondary text is not present, vertically center the one that is within the entire entry
    • Width should be 100% width of parent, since the MapTooltip will wrap this component with a custom width
    • Props:
      • leftIcon: PropTypes.node
      • primaryText: PropTypes.string
      • secondaryText: PropTypes.string
      • rightIcon: PropTypes.node
  • ListCategory
    • Width should be 100% width of parent
    • Height should be fixed
    • Props:
      • text: PropTypes.string
  • MapTooltip
    • Wrap the Reach UI tooltip component (you need to install @reach/tooltip first)
      • Please use PageTabs as an example of how to wrap Reach UI!
    • Props:
      • children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node ])

Useful links

Search bar current location

Description

Allow selecting current location as an option in the search bar/suggestions

Todo

  • When input is empty and user clicks on it, show Current Location as an option
  • Don't show the option when the user starts typing
  • Only show current location option if the user has allowed access
  • Make a hook, useGeolocation, that returns the current location
  • You need to use watchPosition in the hook so that the location actually updates
  • Make a function in utils for reverse geocoding
  • On desktop, add 1 or more UI components to allow for a button to be next to the input (see design)
  • No current location in suggestions on desktop, only via button
  • Put "Fixes #55" in the PR description

Useful links

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.