grandma-collaboration / skyportal_grandma_dev

Little Git Repo to keep track of the work done by the A4 ESILV TEAM
2 stars 0 forks source link

Carla Amat/Lydie Pont/Manon Flament - Use a search bar #24

Closed Carla802 closed 1 year ago

Carla802 commented 1 year ago

Hi @Theodlz 👋 I will be working on the third task Sarah gave us, which is adding a search bar to the sources page. First I am currently finishing the Adding features tutorial.

I will ask you for help if it is needed !

Thank you again 🚀

Carla802 commented 1 year ago

Hi @Theodlz ,

I am currently working on this task and for the moment I've implemented a search bar like this. I simply took the code of the QuickSearchBar component and adapted it to the source page. Do you think this is what Sarah asked for or do I need to code a search bar that filters the source list displayed ?

If you don't have more details than we do I will ask Sarah directly !

image

image

Carla802 commented 1 year ago

Hi again @Theodlz, Just in case you didn’t see it, I opened a PR for this task after Sarah told me it was what she expected. Guy did his review and approved it today, but I need your review as well ! Let me know when you have the time to look at it. Thank you 😄

Theodlz commented 1 year ago

Hi Carla! Let me have a look right now.

Carla802 commented 1 year ago

Hi @Theodlz ! I'm working on the changes you asked me to do, and so far I added the search bar to the MUI Datatable. However, I'm having trouble coding the function that is called on every search change. In static/js/components/SourceTable.jsx, in the table's options, I added this :

search: true,
onSearchChange: handleSearchChange,

And I want the handling function to look like this (just filtering the rows that include the search content, for now just in the id column but when it will work in the other columns as well). Then it should just set the new filtered rows. But since I'm having trouble understanding how the whole code works, I don't know which function (or property) of the table I'm supposed to call.

const handleSearchChange =  (searchText) => {
    const filteredRows = sources.filter(row => {
      return row.id.toLowerCase().includes(searchText.toLowerCase());
    });
    setOpenedRows(filteredRows);
  };

For example, when I write sources.filter I want to call the property that contains all the current rows, so I can filter it, but I know sources is probably not the right one ! Same for the function setOpenedRows, I want to call the function that allows to change the displayed rows, but I'm not sure of which one it is.

Sorry to bother you, I'm trying my best to understand the code but there's a lot... Thank you for helping me :)

Theodlz commented 1 year ago

Hi @Carla802, So the first code snippet is correct. However I'm not sure that's what you want to do for the second. You don't want to use the filter function of javascript to limit which rows are displayed. What you want, is to do the same as what is done when you use the filter option of the filter form (or any of the filtering options btw): you send an API call to fetch sources based on all the filters, including the one that filters on the name that you have set.

so in the handleSearchChange, you should:

Tell me if you understand what I mean by that.

Carla802 commented 1 year ago

Hi @Theodlz, Thank you for your explanations, I am now able to filter by name the table with this code :

const handleSearchChange =  (searchText) => {
    const data = {sourceID : searchText};
    paginateCallback(1, rowsPerPage, {}, data);
  };

It works well, and now I would want to do the same with the other filters, but I have some more questions !

So I believe you want the search bar to also filter the other columns, but I'm not sure how I can do that. First, I'm not sure how I can filter separately every columns, since in the filter form you can only accumulate filters, and not ask for sources that have a certain name OR a certain classification. Because for example, if I type "kilonova candidate" in the search bar, I think it's going to search for sources that both have a name containing it, AND this classification type (so naturally there will be no matching results). When it should show any source that has this classification, and not also filter the sources ID. I don't really know how to return independant filter results, because it would be like submitting two different forms and wanting both results in the same page.

On another hand, considering the different filtering options in the form, it looks like there are not that many that can be done with the search bar, from what I've understand. For example, the position data (RA and Dec) can't be filtered if one of them is left empty in the form, so I'm not sure if this can be handled from the search bar. I think it could be possible to search by date saved or by classification for example, but the rest seems more difficult. Could you tell me what you think and which filtering options you still want in the search bar ? Maybe I don't fully understand how it works and there are still solutions to handle all that ! And also it would help me a lot if you could give me some clues on how I can separate the filters on each column, so it doesn't combine all of them.

Thanks again for taking the time to help me !

Theodlz commented 1 year ago

Hi @lydie10. I had the chance to play with the Mui Data Table at some point. From what I remember, if you look at the logs while playing with existing filters/sorting, you'll see that you can indeed do multiple things at once (you can check the API calls that are made, and what's in the redux). All you need is to check what the paginateCallback does. Do you give it a new "data" var with filters, and then it merges it with an existing one (effectively applying a new filter on top of those being used),? If it does not, you might need to get the existing filters in a var called data, then add the sourceID to it with the value from the searchBar, and finally trigger the callback.

You want to keep all applied filters, and simply add the filtering on the sourceID to it and THEN trigger the paginateCallback.

Everything you need should be in the state variables of both SourceTable and SourceTableFilterForm, to find where the current filtering is kept. It might be kept in the ducks/redux and all managed there, so please consider looking at the sources.js ducks (or the source.js for that matter, they are some things a bit intertwined).

Also, why not looking at the handler to see what it returns. It could be that in the response of the API calls are listed the filters that gave this result! Some API's do that. I'll let you see for yourself. Even if it is not the case, It would be valuable to have a general understanding of the backend code that runs before modifying the frontend to be sure of what arguments you need to pass in the request, and what it returns.

I want to encourage you guys to find out how to do it without giving you an answer. If you are REALLY super stuck, add me as a collaborator to your fork with write access so I can modify the code. Let's say that if you can't find a solution on Tuesday night (France time) you can do that and I'll help write the code and/or give more precise indications about what to change :)

Have a nice weekend! 🚀

Theodlz commented 1 year ago

Hi @lydie10, any updates?

lydie10 commented 1 year ago

Hi @Theodlz, This is what we've done so far : const handleSearchChange = (searchText) => { const data = { sourceID: searchText }; setFilterFormData(data); paginateCallback(1, rowsPerPage, {}, data); setFilterFormSubmitted(true); };

This enables us to search by source ID. However, if we add more elements in data, it then filters all the columns with the text entered in the search bar which returns an error. We tried to look at the paginateCallback function but we didn't find where it is defined so we don't understand how we can use it to filter more columns.

Thanks for your help !

mcoughlin commented 1 year ago

When I run

grep paginateCallback *

I get

FavoritesPage.jsx: paginateCallback={handleSourcesTablePagination} GcnEventPage.jsx: paginateCallback={handleSourcesTablePagination} GroupSources.jsx: paginateCallback={handleSavedSourcesTablePagination} GroupSources.jsx: paginateCallback={handlePendingSourcesTablePagination} ShiftSummary.jsx: paginateCallback={handleSourcesTablePagination} SourceList.jsx: paginateCallback={handleSourceTablePagination} SourceTable.jsx: paginateCallback, SourceTable.jsx: paginateCallback( SourceTable.jsx: paginateCallback(1, tableState.rowsPerPage, {}, filterFormData); SourceTable.jsx: paginateCallback(1, rowsPerPage, {}, data); SourceTable.jsx: paginateCallback(1, rowsPerPage, {}, data); SourceTable.jsx: paginateCallback: PropTypes.func.isRequired,

The relevant entry there is SourceList.jsx