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

LPS-122662 Make vocabularies not searchable #473

Conversation

victorg1991
Copy link

@victorg1991 victorg1991 commented Nov 3, 2020

This pr includes:

  • prop name filterQuery renamed to filter in TreeView component
  • prop can now admit two types: string and function
    • string: same behaviour, when not falsy it will filter the nodes comparing the string with the name of the node
    • function: a function that receives the node and should return true or false deciding if the tree should include the node in the search
  • Filter out vocabularies in SelectCategory component using the new API
  • Adapt filterQuery usages to fit the new name

For testing:

  • Go to Categorization
  • Create a new vocabulary 'vocab1'
  • Create a new category under vocabulary 'vocab1' called 'vocab1category'
  • Go to Apps menu -> content dashboard
  • Click Filter and Order -> Filter by.. Categories
  • Type "vocab1" in the search field

Before:

  • Both vocab1 and vocab1category are displayed

After:

  • only vocab1category is displayed

Thanks!

@liferay-continuous-integration
Copy link
Collaborator

To conserve resources, the PR Tester does not automatically run for every pull.

If your code changes were already tested in another pull, reference that pull in this pull so the test results can be analyzed.

If your pull was never tested, comment "ci:test" to run the PR Tester for this pull.

@victorg1991
Copy link
Author

ci:test:relevant

@victorg1991
Copy link
Author

ci:test:sf

@jbalsas
Copy link

jbalsas commented Nov 3, 2020

Sending this pr here because I believe you are the owners of the TreeView component, correct me if I'm wrong :)

We can give it to you if you want it!! 😘

@victorg1991
Copy link
Author

I think we may be open to exchange, are you interested in iframe or weather portlet? 😏

@liferay-continuous-integration
Copy link
Collaborator

✔️ ci:test:sf - 1 out of 1 jobs passed in 4 minutes

Click here for more details.

Base Branch:

Branch Name: master
Branch GIT ID: afb229df01a027b6f438bf1628290d9470d1e4d8

Sender Branch:

Branch Name: LPS-122662_disabling_nodes_search
Branch GIT ID: ec01e9d2955045e5813d40cdf82502e954d1ae82

1 out of 1jobs PASSED
1 Successful Jobs:
For more details click here.

@@ -84,7 +84,12 @@ function filterNodes(nodes, filterQuery) {
const filteredNodes = [];

nodes.forEach((node) => {
if (node.name.toLowerCase().indexOf(filterQuery) !== -1) {
const isSearchable = node.searchable ?? true;
Copy link

@jbalsas jbalsas Nov 3, 2020

Choose a reason for hiding this comment

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

I don't have a better idea right away and probably lack a lot of context but this feels a bit of an ad-hoc API that will fail to deliver soon enough...

Is it guaranteed that you'll always be able to add the searchable attribute to every node in your model? This might be coming from a remote request which we might have no control over.

Not sure if possible, but could we make the filterFn the prop instead? I see you already have something like vocabulary: true, which maybe we could use together with a custom filter function to avoid adding those to the search?

Something like:

<TreeView
    filter={(node, query) => !node.vocabulary && node.name.toLowerCase().indexOf(filterQuery) !== -1}
    nodes={vocabularies}
/>

Copy link
Author

Choose a reason for hiding this comment

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

I guess in those cases you could decorate the response 🤔 but nonetheless, I think that your suggestions would make it more flexible, so I'll go for it :) Thanks!

@jbalsas
Copy link

jbalsas commented Nov 3, 2020

I think we may be open to exchange, are you interested in iframe or weather portlet? 😏

😂

We basically took iframe already with Remote Apps, so you might need to take this 😂

@liferay-continuous-integration
Copy link
Collaborator

@victorg1991 victorg1991 force-pushed the LPS-122662_disabling_nodes_search branch from ec01e9d to 13d3bc2 Compare November 3, 2020 16:14
@victorg1991
Copy link
Author

Hey @jbalsas I've updated the PR :)

Comment on lines 195 to 203
filter={(node, filterQuery) =>
!node.vocabulary &&
node.name
.toLowerCase()
.indexOf(filterQuery.toLowerCase()) !==
-1
}
Copy link

Choose a reason for hiding this comment

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

Just thinking out loud here, but the API has a bit of a "redundant" feel to it, and not just because the word filter appears in two props (which might be confusing for people and definitely requires documentation, unless you think it will be obvious to people what filter and filterQuery are, and how to use them, and when).

The thing is, the callsite here has access to filterQuery already, and it's then passing in a function that will get that same filterQuery passed back into it, when it could have just accessed it via the closure. Among other things this function we pass in is going to call toLowerCase() again and again on the passed in filterQuery in a loop (due to the forEach() calls), always producing exactly the same result.

All of which is to say I wonder if we couldn't do this with a single prop (PropTypes.oneOfType[PropTypes.func. PropTypes.string]): if passed a string, behave exactly as before, if passed a func, use it to filter; eg.

const query = filterQuery.toLowerCase();

<Treeview
    filter={(node) =>
        !node.vocabulary &&
        node.name.toLowerCase().includes(query)
    }
/>

Copy link
Author

Choose a reason for hiding this comment

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

I agree this approach is better, the only thing that worries me is that is a breaking change, but I'm not sure if someone outside Liferay is using it 🤔 Should we just go for it removing the old prop? or maybe leave the prop for compatibility?

What do you think?

@jbalsas what do we usually do with breaking changes in javascript API?

Copy link

Choose a reason for hiding this comment

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

I assumed filterQuery was local to the treeview... based on this I guess the search input is controlled from the outside, which makes sense.

I think we could deprecate the filterQuery prop but keep it in this version. If filter is passed, we ignore filterQuery, otherwise it works as before.

I think it's almost certain no one is using this outside of Liferay, but we could be using it inside in different ways. The cost of keeping this for backwards compatibility seems relatively small, so I guess we can keep it around.

Copy link

Choose a reason for hiding this comment

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

the only thing that worries me is that is a breaking change

Ah, I didn't mean to propose a breaking change — instead of replacing filterQuery with filter, I meant to augment the behavior of the existing prop in a non-breaking way; the rename is just me being careless and imprecise. (Of course, filter is a better name, but 🤷‍♂️ ).

I think it's almost certain no one is using this outside of Liferay

If that's true, then maybe we shouldn't worry about this?...

but we could be using it inside in different ways. The cost of keeping this for backwards compatibility seems relatively small, so I guess we can keep it around.

Well, that is the cost I was trying to avoid (of having two confusingly similar props) — the thing is, complexity accrues one prop at a time, and before you know it you've got a ghastly, Frankenstein API that is hard to use and hard to evolve.

Copy link

Choose a reason for hiding this comment

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

If that's true, then maybe we shouldn't worry about this?...

I wouldn't necessarily worry about this right now... just check for internal usages...

Copy link
Author

Choose a reason for hiding this comment

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

Is there any protocol for deprecating props like that? If none exist I think it may be better to leave the name of the property unchanged to avoid confusion 🤔 what do you think?

Copy link

Choose a reason for hiding this comment

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

Just remove it 😂

Copy link
Author

Choose a reason for hiding this comment

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

@liferay-continuous-integration
Copy link
Collaborator

✔️ ci:test:stable - 9 out of 9 jobs passed

✔️ ci:test:relevant - 25 out of 25 jobs passed in 3 hours 4 minutes

Click here for more details.

Base Branch:

Branch Name: master
Branch GIT ID: afb229df01a027b6f438bf1628290d9470d1e4d8

Copied in Private Modules Branch:

Branch Name: master-private
Branch GIT ID: 8d22a791300569a6c92e7b9152e6ae1c6bdc863a

ci:test:stable - 9 out of 9 jobs PASSED
9 Successful Jobs:
ci:test:relevant - 25 out of 25 jobs PASSED
25 Successful Jobs:
For more details click here.

@liferay-continuous-integration
Copy link
Collaborator

@victorg1991 victorg1991 force-pushed the LPS-122662_disabling_nodes_search branch 2 times, most recently from 0791d0b to 8259799 Compare November 4, 2020 11:00
@victorg1991
Copy link
Author

Well, here we go again @jbalsas @wincent

I'm not really sure about this commit 7543666

I have to do that because treeview has a "search" mode enabled when searching that flatten the nodes, I have to do that comparison because there isn't other way to know right now if we are in search mode or not. Before this change filteredQuery containing a falsy value was the flag for enabling/disabling this kind of view.

Let me know what do you think :)

PD: I'm starting to prefer the first version (simply including a new searchable prop to the nodes) 😂

@victorg1991
Copy link
Author

I'm realizing that I've missed updating the usages, but I think I'll wait until we have the definitive version of this

Copy link

@wincent wincent left a comment

Choose a reason for hiding this comment

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

I'm not really sure about this commit 7543666

I have to do that because treeview has a "search" mode enabled when searching that flatten the nodes, I have to do that comparison because there isn't other way to know right now if we are in search mode or not. Before this change filteredQuery containing a falsy value was the flag for enabling/disabling this kind of view.

Couldn't you just not pass a filter function if the query is empty? Then you wouldn't need to make such invasive changes inside the Treeview; eg.

  • Pass a string: behavior is as before.
  • Pass a function: let caller take care of filtering.
  • Pass nothing: don't filter.

@@ -39,21 +39,23 @@ function SelectCategory({
nodes,
}) {
const flattenedNodes = useMemo(() => {
if (nodes.length === 1 && nodes[0].vocabulary) {
if (nodes.length === 1 && nodes[0].vocabulary && nodes[0].id !== '0') {
Copy link

Choose a reason for hiding this comment

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

I don't really get this change, what's the reason for it?

Copy link
Author

Choose a reason for hiding this comment

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

The view look like this:

Screenshot 2020-11-04 at 14 45 56

I've changed the model to add the property vocabulary: true to the root node, but doing so this code is removing that root, so I've just had to add this check here to preserve the root after setting the property

Another option would be to check for id !== '0' in the filter function, but I think it isn't much of an improvement

Also I am not sure where this code is used, I've seen that this code can be improved a lot, but I've wanted to make minimal changes here in order to fix the bug, and revisit this later, (when removing aui stuff for example)

@victorg1991
Copy link
Author

Couldn't you just not pass a filter function if the query is empty? Then you wouldn't need to make such invasive changes inside the Treeview; eg.

Pass a string: behavior is as before.
Pass a function: let caller take care of filtering.
Pass nothing: don't filter.

I did something of the sorts in my first approach but it didn't look right, I think it is not that intuitive to rely on passing null to the query in case you want to filter, isn't it?

@wincent
Copy link

wincent commented Nov 4, 2020

I did something of the sorts in my first approach but it didn't look right, I think it is not that intuitive to rely on passing null to the query in case you want to filter, isn't it?

As I understand it, the old system did this:

  • Empty search query: show everything, and stay out of "search mode".
  • Any other query: perform search over flattened list.

With the proposed change, instead of a query we can now pass a function or a string, and every single call site in liferay-portal except one will behave exactly as it used to, because they will all still be passing a string. Seeing as strings can be "empty" or "non-empty", and that signals whether a search is happening, and functions cannot (ie. they're always functions), that suggests that the only way for our special function-based case to signal "I'm not really searching" is to not pass the function (ie. what I suggested in my last comment), or to do this with two props instead of one. I have a mild preference for the first option (because reasoning about combinations of props is hard, and if you're not careful you can create situations where multiple props are in mutually incompatible/conflicting states, compared to a single prop that can only be in one state at t time), but I also don't really care.

The other question lurking behind all this is that the responsibility of Treeview itself is a bit blurred, as it can do rather too many things (selection, searching etc). This is a double-edged sword: by handling it all internally, it frees callers from all having to implement their own selection, their own searching etc (which is what they would have to do if it were a fully controlled component), but the cost is complexity, or rather, we're concentrating the complexity in one specific place as opposed to having it dispersed around in multiple places. This may or may not be a good thing, depending on your point of view.

@victorg1991 victorg1991 force-pushed the LPS-122662_disabling_nodes_search branch from 7fe68af to bc067f1 Compare November 5, 2020 10:20
Copy link

@jbalsas jbalsas left a comment

Choose a reason for hiding this comment

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

Looks good to me from 30.000 ft, so let's wait for @wincent!

Copy link

@wincent wincent left a comment

Choose a reason for hiding this comment

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

After seeing this code get better, worse, better, worse, I now think we have attained a global maximum!

snape-approves

@wincent
Copy link

wincent commented Nov 5, 2020

ci:forward

@liferay-continuous-integration
Copy link
Collaborator

CI is automatically triggering the following test suites:

  •     ci:test:relevant
  •     ci:test:sf

The pull request will automatically be forwarded to the user brianchandotcom if the following test suites pass:

  •     ci:test:relevant
  •     ci:test:sf
  •     ci:test:stable

@liferay-continuous-integration
Copy link
Collaborator

✔️ ci:test:sf - 1 out of 1 jobs passed in 3 minutes

Click here for more details.

Base Branch:

Branch Name: master
Branch GIT ID: 6e486ffaee3faa9e0c7495781ebeab5518d6a94b

Sender Branch:

Branch Name: LPS-122662_disabling_nodes_search
Branch GIT ID: bc067f1937bb2c3737cc237914d3954c94e79d11

1 out of 1jobs PASSED
1 Successful Jobs:
For more details click here.

@liferay-continuous-integration
Copy link
Collaborator

@liferay-continuous-integration
Copy link
Collaborator

✔️ ci:test:stable - 9 out of 9 jobs passed

✔️ ci:test:relevant - 26 out of 27 jobs passed in 2 hours 23 minutes

Click here for more details.

Base Branch:

Branch Name: master
Branch GIT ID: 6e486ffaee3faa9e0c7495781ebeab5518d6a94b

Copied in Private Modules Branch:

Branch Name: master-private
Branch GIT ID: 8d22a791300569a6c92e7b9152e6ae1c6bdc863a

ci:test:stable - 9 out of 9 jobs PASSED
9 Successful Jobs:
ci:test:relevant - 25 out of 27 jobs PASSED
25 Successful Jobs:
For more details click here.

This pull contains no unique failures.


Failures in common with acceptance upstream results at 6e486ff:

@liferay-continuous-integration
Copy link
Collaborator

All required test suite(s) passed.
Forwarding pullrequest to brianchandotcom.

@liferay-continuous-integration
Copy link
Collaborator

Pull request has been successfully forwarded to brianchandotcom#95674

@liferay-continuous-integration
Copy link
Collaborator

@victorg1991 victorg1991 deleted the LPS-122662_disabling_nodes_search branch November 13, 2020 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants