OpenBazaar / openbazaar-desktop

OpenBazaar 2.0 Desktop Client (talks to openbazaar-go server daemon)
MIT License
647 stars 186 forks source link

Add feature stores #1870

Closed fengzie closed 4 years ago

fengzie commented 4 years ago

Enable category views for third-party search engine, and add feature stores section if third-party API has links.featureStores link in response. If there is no featureStores link, keep the current one.

Below is the effect: Default OB1 image

Third-party without the link image

Third-party with the link image

jjeffryes commented 4 years ago

@fengzie thank you for your work here, but I have to reject this, I'm sorry. My original code to add categories was pretty hacky, and this just adds more hacks on top of it. I spent a few hours reviewing the code and making suggestions, and was halfway done with re-writing the entire search.js view by the time I realized how much this would have to change.

To do this properly, search.js would need to be refactored so that it handles the home tab in a more universal way. I don't like the idea of making it so any provider with featured stores also shows categories, since we can't be sure that's what a provider actually intends.

A better system would be if showing both featured stores and categories were controlled by the provider having featured stores and/or categories in their data.

That way a provider with only categories would show them, a provider with only featured stores would show them above the normal listings view, and a provider with both would show both.

I think the code outside the search view was mostly fine. If you want to try and tackle a more complete refactor of the search view I'd be happy to look at it, otherwise I think this has to wait for us to be able to prioritize time for our team to do it.

fengzie commented 4 years ago

@jjeffryes , Hi Josh, the expected behavior is still confused. Does it mean that for a provider, the page depends on the result of the provider is called?

No matter with and without query and filter, there is no special home page or listing page. Does the page always depend on the provider API result, but is not mandatorily differentiated by the client? The below is current response data structure. If so, what's your expected data structure, by considering categories and feature stores? image

Btw, for current home page, there are totally more than 10 URL calls with one call for one category, which is costly. Different provider might have different default categories.

jjeffryes commented 4 years ago

Off the top of my head, I think something like the following would be better:

name: blahblahblah,
logo: urltologo,
links: {link object, do not put featuredStores in here},
options: {...},
sortBy: {...},
results: {...},
featuredStores: {this should be very similar to results, with node data for each node},
categories: [
{
  title: 'Electronics',
  term: 'electronics' (used to search on when the "show more" button is clicked),
  listings: [array of listings objects, like the ones found in results},
},
{
  title: 'Clothing',
  term: 'clothing',
  listings: [array of listings objects, like the ones found in results},
},
]

I'd have to spend some time thinking about it to finalize a spec, I'm open to suggestions. The goal would be to minimize the number of calls needed, and to give consistency and flexibility to search providers.

jjeffryes commented 4 years ago

For the page behavior, my expectation would be:

  1. if the data returned from the provider has a featuredStores object, show it at the top of the page. This would happen on any search request, so providers can control when the featured stores are shown. They might want to only show them on blank requests, or change the featured stores based on the search query used (ie: if the user searches for "shoes" return featured shoe stores).
  2. if the data returned from provider has a categories array, and the user has not made a search (they have just arrived on the page, or just activated the provider) show the categories.
  3. if the data does not have categories, or the user has performed a search query, show the listings in the results object.

The old spec I mentioned to you previously was more advanced, in it providers could return lists of nodes or listings in sections, with headlines and buttons, which allowed them to construct whatever kinds of groups of results they wanted. That would be the most flexible, but probably more difficult, and not as backwards compatible.

fengzie commented 4 years ago

@jjeffryes , the thought is good, but it might not be easy. The stores might need to be tagged. If a tag is matched when a search query is performed, then show the matched stores. Many tags might need to be maintained. It is possible that no featured store is found for many searches.

  1. If the data returned from the provider has a featuredStores object, show it at the top of the page. This would happen on any search request, so providers can control when the featured stores are shown. They might want to only show them on blank requests, or change the featured stores based on the search query used (ie: if the user searches for "shoes" return featured shoe stores).

For 2, when activating the provider, besides categories, there might be global featured stores. What kind of cases would affect backwards compatible?

That would be the most flexible, but probably more difficult, and not as backwards compatible.

jjeffryes commented 4 years ago

Structuring all results into groups would break old providers.

The more advanced version is instead of the results object just being a list of results it would be like this:

results: [
{
  title: "Featured Stores",
  total: 10,
  actionQuery: '',
  actionText: '',
  results: [
    {
      type: 'vendor',
      relationships: {...},
      data: {...},
      },
      { one of these for each featured store },
    ],
  },
  {
    title: "Electronics",
    total: 24,
    actionQuery: 'q=electronics',
    actionText: 'See All Electronics',
    results: [
      {
        type: 'listing',
        relationships: {...},
        data: {...},
      },
      { one for each electronic listing in the category display },
    ],
  },
  {
    title: "Special Discounted Items",
    total: 6,
    actionQuery: 'q=discount',
    actionText: 'Click for More Special Deals',
    results: [
      {
        type: 'listing',
        relationships: {...},
        data: {...},
      },
      { one for each electronic listing in the category display },
    ],
  },
  {
    title: "", (no title means these are just normal results)
    total: 2015,
    actionQuery: '',
    actionText: '',
    results: [
      {
        type: 'listing',
        relationships: {...},
        data: {...},
      },
      { ...etc. },
    ],
  },
]
jjeffryes commented 4 years ago

We could handle things with two objects, one is the old results with the current format, and then updated providers could have a groupedResults object like above. Then backwards compatibility would be maintained.

fengzie commented 4 years ago

From the advanced version, how to differentiate the featured stores section and category section, is it from the results.item.type field? They may have different effect in the page, for example featured stores use swiper with 3 stores in a view, and category section has 2 lines with 4 listings in one line. What's the format of the queried listings in the advanced version?

jjeffryes commented 4 years ago

The advanced version would treat all groups as the same, so no swiper on anything. I don't think the swiper is a critical feature.

There would be no difference between queried and non-queried responses. The provider would decide what to send back. If they want to show a page of just results, they'd send back one very large group, which would get paginated.

There would probably need to be a rule that any group over X results gets pagination. Or pagination becomes entirely up to the provider, and there is a format for returning multiple action buttons to handle next and previous page queries, but that gets complicated.

fengzie commented 4 years ago

The listings results are different, by comparing to categories and featured stores it has multiple filters and sort options for selection. So how do we organize it in the above format?

For the advance format, should we have a field to indicate it is a new version format? For example: { "name": "blabla..", "logo": "blabla", "version": "2", ... }

jjeffryes commented 4 years ago

If a user sets a filter, I think it should be assumed they are doing a search.

It is up to the provider to decide how to respond to that search.

The provider could respond with one group of normal listings that fit the search.

Or they could still return a group for featured stores, which might or might not match the search, then after that a group of listings that match the search.

I think the best route is to try and be flexible, and leave decisions to the provider.

For the advanced format, I think it's ok to just add an advancedResults object. That way the client logic can just be to show the advanced (grouped) results if they are present, and the normal results if they are not.

fengzie commented 4 years ago

OK. For the format, I mean how to render it in the search result page, is the page cascaded from the advancedResults, and then starting the search listings results? image

jjeffryes commented 4 years ago

The page would just render the groups in order.

So if the featured stores are first, they're first.

If they're last, it would be weird, but they would be on the bottom under the other results.

Each group would need it's own pagination, if I remember right there's a field in the data for whether there are more pages or not.

fengzie commented 4 years ago

yes, that's true, OK. Looks like it becomes clear. We need an advancedResults object with the above designed format to resolve the case. Yes, current listing result has its pagination. image