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

Allow multiple searches in the state #93

Merged
merged 12 commits into from
Jan 29, 2021
Merged

Allow multiple searches in the state #93

merged 12 commits into from
Jan 29, 2021

Conversation

fgravin
Copy link
Member

@fgravin fgravin commented Jan 26, 2021

This PR aims to change the search state structure to handle multiple searches in the same page.
Before, the state structure allowed to store a unique search, matching the SearchSate interface. This structure has been enhanced so the state stores a dictionnary of searches, the SearchSate has become a dictionnary of SearchSateSearch.
The dictionnary key is the search id, used to bind any component and action to a specific search, the default key is default.

I tried to keep the code simple so the change is quite transparent:

  • I kept the original reducer that is now called to reduce one element of the state pool
  • If the state pool does not contain the search id provided by the action, it initiates a new search structure for this new id
  • If an action does not provide any id, then it passes the default value
  • All effects propagate the search id along the actions flow

By default, the initialState contains a search state for the default id, and all actions work on this id in a transparent way.
At the moment, the application looks to run exactly the same.

  • Refactor the search state
  • Add 2 searches in the same page
  • Update the effects and the facade to dispatch the correct search id
  • Demonstrate the work in a web component

State Facade

  • The facade has been reworked so it is transparent for any component to be binded with the correct search.
  • Facade is no more a singleton, there should be one facade per search
  • Facade is not injected at root level
  • Facade is instanciated when you declare the searchSearchStateContainer="mainSearch" directive
  • If you don't provide the directive (I made it almost mandatory to force the developper to know what is is doing), you are responsible to inject and initiate the Facade service (as done in the web component)
  • Any component that is below the directive in the DOM, and that inject the facade, will retrieve the directive instance of the facade, binded to a specific searchId
  • When you don't provide a searchId, the default value is default.

I had to refactor many components and tests that were using the store directly.

I don't guarantee everything is working perfectly but it looks ok with the tests I've made.
Demo: https://geonetwork.github.io/geonetwork-ui/multiple_search/demo/webcomponents/gn-results-list-multiple.sample.html

The commit 1057df2 should be adressed (usage of flatMap operator).

this action is responsible to create (if not exists) a new entry in the state dictionnary
for the dedicated search, action.id is the new search key
It's responsible to interact with just a slice of the state: the search matching its searchId
The facade must be init with a searchId, all observables are created during the init, and not during the instanciation
because we need to know the searchId.
This way, using the facade will be transparent for other services and component.

This service is not instanciated at Root level and is not meant to be a
singleton, we MUST implicitly inject and instanciate this service for
each searches
…chFacade

the facade will be used by all components under the DOM node where the directive is applied
and never use the store directly.
Observable based on the state selector must be init during onInit() phase
This implies to create a new component that embed all the search elements. The directive must be applied
outside of the directive otherwise the SearchFacade service is no correctly injected
the facade ist inject in root module
abstract component class handle the init of the facade, I didn't want to use the directive cause it implies
to create a sub component
… can trigger

a search at the same time.

We should implement our own observable to manage this.
@fgravin fgravin marked this pull request as ready for review January 28, 2021 12:34
response,
this.searchService.configuration.basePath
switchMap((action: SearchActions) =>
this.authService.authReady().pipe(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional to pipe all the work inside the authReady stream ? Why not go back to the actions$ stream like before ?

@LHBruneton-C2C
Copy link
Collaborator

I'm a little confused with the name 'getSearchStateSearch'. Will there be anything else than searches in the state ? And if it's to recognize that we only get one search in the dictionary, why not getSearchById or getSearchByKey ?

@fgravin
Copy link
Member Author

fgravin commented Jan 29, 2021

I'm a little confused with the name 'getSearchStateSearch'. Will there be anything else than searches in the state ? And if it's to recognize that we only get one search in the dictionary, why not getSearchById or getSearchByKey ?

Yes good idea, I used the common pattern but it's not appropriate here, thanks.

Beside that, what do you think of the global approach ?

@LHBruneton-C2C
Copy link
Collaborator

It's really nice that you tried to stay as close as possible to the previous state. Now that I think about it, managing the state as ngrx entities would have been a step too far.
Great idea keeping a default search, it makes the PR much more readable.
I never worked with the web components, so I can't say much there.
And a last question, won't there ever be interactions between searches ? Otherwise, one facade per search is great.

@fgravin fgravin merged commit 648df86 into master Jan 29, 2021
@fgravin fgravin deleted the multiple_search branch January 29, 2021 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants