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

Add filter action to achievements manager. #2328

Merged
merged 8 commits into from
Mar 2, 2024

Conversation

somiaj
Copy link
Contributor

@somiaj somiaj commented Feb 17, 2024

This adds a action to filter achievements as suggested by @Alex-Jordan.

Copy link
Member

@drgrice1 drgrice1 left a comment

Choose a reason for hiding this comment

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

There are a few details that need attention.

If a filter happens to filter out all achievements, then the message shown is "No achievements shown. Create an achievement!" For example, in my test course all achievements are enabled. So when I selected the "disabled achievements" filter, that gave me none. That message is not appropriate anymore if there are achievements, but none are shown because of the filter.

lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm Outdated Show resolved Hide resolved
htdocs/js/AchievementList/achievementlist.js Outdated Show resolved Hide resolved
htdocs/js/AchievementList/achievementlist.js Outdated Show resolved Hide resolved
Copy link
Member

@drgrice1 drgrice1 left a comment

Choose a reason for hiding this comment

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

This looks good now. Everything seems to be working in my tests.

@pstaabp
Copy link
Member

pstaabp commented Feb 20, 2024

Overall, looks good. Seems like the filter by category should be a dropdown/select list of categories, instead of requiring it to be typed in exactly. The default list only has 6 categories, and this should be easy to pull out of the list.

@somiaj
Copy link
Contributor Author

somiaj commented Feb 20, 2024

@pstaabp I thought about that, but the only way I could think to get the list of all categories is to first pull all achievements from the database and cycle through them getting all categories. But once a filter is applied not all achievements are pulled from the database, only the filtered ones.

@drgrice1
Copy link
Member

There are some real problems with the javascript that you are using. This goes back to what you did in #2294.

You are repeatedly adding event handlers to various elements each time the form is submitted. Those event handlers pile up. Note that the once: true option makes the event handler go away if it is called, but each time the form is submitted while that has not been called another event handler is added. Eventually all of those fire at the same time if the event does occur.

Also you getElementById in many cases where you have already obtained a reference to that element. That is an expensive query. Each time it is called, the entire DOM has to be searched until that element is found. For example on line 24 of achievementlist.js you find the filter_select element (and even save a reference in a variable), and then on line 36 you search the DOM again, instead of just using the already found reference. Several places you just blindly search the DOM each time without saving a reference. For example, on line 43 you find the filter_text_err_msg, and then on line 49 you search for it again.

I mentioned the redundancy in the code before, but this is just a total kludge really. The achievementlist.js file is 233 lines long, merely to validate a few form fields. That is really excessive.

@somiaj
Copy link
Contributor Author

somiaj commented Feb 23, 2024

I have been thinking about ways to clean up the code and remove the redundancy, though unsure on the best approach here. My thought was to have helper functions do the work.

As for the change event methods, the reason I was calling getElementById again is I didn't realize that inside the event function I had access to the previously defined variables. Now that I know that I do have access, I'll update things to avoid calling getElementById multiple times when not needed.

I'm not quite sure the what to do about multiple events, it sounds like I should also be removing these events to avoid them piling up when one of the companion events fires?

@somiaj
Copy link
Contributor Author

somiaj commented Feb 23, 2024

I will have time to look at this and see what I can come up with this weekend.

@drgrice1
Copy link
Member

I did a little with the multiple event thing for userlist.js in #2335. Look at what I did there for a start.

@somiaj
Copy link
Contributor Author

somiaj commented Feb 24, 2024

@drgrice1 There is my approach at reducing the code duplication and adding/removing event listeners, so they don't pile up. If you prefer this, and any code cleanup you may see, I can apply this to the other two pages as well (though maybe I should leave userlist.js alone since you have gotten it in your PR).

@somiaj somiaj force-pushed the achievement-filter branch 3 times, most recently from 5042028 to c40f2f7 Compare February 24, 2024 23:38
@drgrice1
Copy link
Member

Yeah, that looks considerably better. Go ahead and do that for the other two pages as well. I will work my changes to userlist.js into your scheme.

@somiaj somiaj force-pushed the achievement-filter branch 3 times, most recently from 08cce02 to c8ca3df Compare February 25, 2024 01:31
@somiaj
Copy link
Contributor Author

somiaj commented Feb 25, 2024

I have updated the other two action form validation location to match what was done here.

@somiaj
Copy link
Contributor Author

somiaj commented Feb 25, 2024

There was some achievement transition code that was suggested to remove around 2017....I can open another PR for that if preferred.

@drgrice1
Copy link
Member

Deleting that code is fine.

The updated javascript is considerably better. Perhaps in the future it would be nice to do this more uniformly for all pages that use action tabs (and the actiontabs.js file). But this is good for now.

@somiaj somiaj force-pushed the achievement-filter branch from dfe0c2e to 92f9cfc Compare February 25, 2024 03:37
Copy link
Member

@drgrice1 drgrice1 left a comment

Choose a reason for hiding this comment

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

I missed a few things before.

I see that you removed the { once: true } option to the error hiding event listeners. That is needed. Otherwise the handler will continue to be called even after the form validation messages have been cleared any time a checkbox is checked or unchecked.

htdocs/js/AchievementList/achievementlist.js Outdated Show resolved Hide resolved
@somiaj somiaj force-pushed the achievement-filter branch 2 times, most recently from d9c291e to 69dabc5 Compare February 25, 2024 07:34
Copy link
Member

@drgrice1 drgrice1 left a comment

Choose a reason for hiding this comment

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

This is better, and works to prevent handlers for events from piling up.

That stack exchange post you linked to is certainly not accurate. You have to read the comments responding to it to really see what is needed.

In the code I was using in userlist.js I was only dealing with one handler being added, and so didn't need something more complicated. Although, as mentioned in that #2335, there was more work needed. I saw that there were other event listeners that would need similar handling.

@somiaj somiaj force-pushed the achievement-filter branch from 69dabc5 to b3ecaa9 Compare February 29, 2024 20:35
@Alex-Jordan
Copy link
Contributor

Thanks for this. I was testing it, and I thought I would make the category selection be a dropdown. I opened a PR to your branch (@somiaj ):

somiaj#13

@somiaj
Copy link
Contributor Author

somiaj commented Mar 1, 2024

@Alex-Jordan updated this so the category filter is now a drop down menu instead of a text field.

@pstaabp
Copy link
Member

pstaabp commented Mar 2, 2024

Already 2 approvals, but this looks better to me now.

somiaj and others added 8 commits March 2, 2024 09:50
  Achievements can now be filtered based off of selected achievements,
  match multiple IDs, match a single category, enabled, and disabled.
  This also adds the javascript form validation.
  Fix text showing disabled achievements.

  Fix text when no achievements are found in the filter, but
  the course has achievements.

  Fix a bug where export/edit all achievements didn't show all
  achievements if they were previously filtered. This is done
  by adding a variable to show all achievements so any previous
  filter remains unchanged.
  Add helper functions to show and hide errors validation to
  reduce duplication of code. The helper functions also add
  and remove event listeners to remove the error messages.
@somiaj somiaj force-pushed the achievement-filter branch from 674c724 to 49f9ea8 Compare March 2, 2024 16:50
@drgrice1
Copy link
Member

drgrice1 commented Mar 2, 2024

I will merge this with 2+1 approvals.

@drgrice1 drgrice1 merged commit 3f6ac13 into openwebwork:develop Mar 2, 2024
2 checks passed
Comment on lines +1293 to +1297
sub getAchievementCategories {
my ($self) = shift->checkArgs(\@_);
return map {@$_} $self->{achievement}->get_fields_where("DISTINCT category", undef, "category");
}

Copy link
Member

Choose a reason for hiding this comment

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

@Alex-Jordan: I realized I didn't look closely at your commit at the end of this. I just saw this. This is a nice. A good new database method.

@somiaj somiaj deleted the achievement-filter branch March 2, 2024 18:18
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.

4 participants