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 recommendation module for LibGuides Profiles #2977

Merged
merged 30 commits into from Jul 7, 2023

Conversation

maccabeelevine
Copy link
Member

@maccabeelevine maccabeelevine commented Jul 5, 2023

A LibGuides Profile page contains information about a LibGuides user. In practice it's for a librarian who created one or more subject guides. From https://ask.springshare.com/libapps/faq/638

Your profile page displays all of the information from your profile box, in addition to:

  • An optional personal statement
  • A list of all of the guides you own in LibGuides
  • Any LibGuides subject categories to which you're assigned as an expert

This recommendation module displays the photo and basic information about a librarian who would be relevant based on the search query. To be specific:

  • Relevancy is based on comparing the query with the names of the subject guides owned by each librarian. That's not a great metric, but it works with no additional configuration so that's nice. I did some testing with a local subject librarian and this worked acceptably well. However a future enhancement could use local configuration to associate a profile to specific search terms, or to specific factors from the result set (i.e. call numbers).
  • The default (boostrap3) template displays their name, title (i.e. Humanities Librarian), email address and profile photo, with the name and photo linking to the actual LibGuides Profile page. However the template has access to the entire JSON data for the LibGuides account, so other info could also be displayed by a custom template.

I borrowed the connection logic (including OAuth token negotiation) from OverdriveConnector. I did refactor it into a new reusable trait, but I didn't touch the original.

TODO

  • Refactor OverdriveConnector to use the new OauthServiceTrait.
  • Add configuration options to select an account based on call number facets in the results.

@demiankatz
Copy link
Member

Looks like a good start, @maccabeelevine; let me know when you're ready for a full review. And don't forget to put in a comment in searches.ini to describe the new module. :-)

@maccabeelevine
Copy link
Member Author

Looks like a good start, @maccabeelevine; let me know when you're ready for a full review. And don't forget to put in a comment in searches.ini to describe the new module. :-)

Thanks for the reminder @demiankatz, fixed that. This is ready for an initial review. See all my comments of course, there are things left to do. But I'd appreciate your input at this point on the general approach, and the light refactoring of OverdriveConnector, before I go further.

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Thanks again, @maccabeelevine -- I can't test this, but I've given it a pretty thorough readthrough and left some comments/suggestions.

config/vufind/contentsecuritypolicy.ini Show resolved Hide resolved
config/vufind/searches.ini Outdated Show resolved Hide resolved
config/vufind/LibGuidesAPI.ini Show resolved Hide resolved
module/VuFind/src/VuFind/Recommend/LibGuidesProfile.php Outdated Show resolved Hide resolved
module/VuFind/src/VuFind/Recommend/LibGuidesProfile.php Outdated Show resolved Hide resolved
module/VuFind/src/VuFind/Recommend/LibGuidesProfile.php Outdated Show resolved Hide resolved
Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

One more very small thing...

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Thanks for the progress! A couple more related suggestions.

@maccabeelevine maccabeelevine marked this pull request as ready for review July 6, 2023 22:26
@maccabeelevine
Copy link
Member Author

@demiankatz This is maybe actually ready now.

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Definitely getting close to done, though a few (mostly nitpicky) comments.

Beyond that, the only other thing to consider is whether test coverage would be feasible. On the one hand, I suspect it would be a bit of a headache to collect all the necessary fixtures and put things together, so I'm sympathetic if you don't think it's worth the effort. On the other hand, this is something I can't personally test, so having some automated test coverage would give me greater confidence that it won't get broken by future refactoring.


; Calls to GET (...)/accounts endpoint
[GetAccounts]
; Duration (seconds) to cache repsonse data. Default is 600.
Copy link
Member

Choose a reason for hiding this comment

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

Typo: repsonse.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup fixed.

*
* @return array An array containing the idToAccount and subjectToId maps
*/
protected function loadDataIfNeeded()
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick, but I don't really like the method name loadDataIfNeeded -- that describes an internal implementation detail that the caller doesn't necessarily need to worry about. Maybe I'd call this one getLibGuidesData, since that's the one the user definitely wants to call, and then rename loadData to populateLibGuidesCache or something like that, to make it clear this is the primary entry point, and that is support for this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you, I hated those two names and tried various options but couldn't come up with something reasonable. I actually had "maybeLoadData()" at one point. Your suggestions are much better.

@@ -32,7 +32,7 @@
/**
* Interface for classes using OauthServiceTrait.
*
* Classes which use this trait should also use LoggerAwareTrait.
* Classes which use this trait should also implement LoggerAwareInterface.
Copy link
Member

Choose a reason for hiding this comment

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

"this trait" --> "this interface"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops fixed

@maccabeelevine
Copy link
Member Author

Beyond that, the only other thing to consider is whether test coverage would be feasible. On the one hand, I suspect it would be a bit of a headache to collect all the necessary fixtures and put things together, so I'm sympathetic if you don't think it's worth the effort. On the other hand, this is something I can't personally test, so having some automated test coverage would give me greater confidence that it won't get broken by future refactoring.

Yes I agree it's a good idea. Have to see which parts are effectively unit testable.

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Thanks, @maccabeelevine, I think this is in good shape. I won't merge it yet in case you'd like to add tests here first, but if you prefer to merge this and do tests in a separate PR, that's fine too.

You might find it helpful to look at the json_log_file setting in the AbstractAPI ILS driver code (

if ($jsonLog = ($this->config['API']['json_log_file'] ?? false)) {
) for a possible way to capture fixtures... and the FolioTest offers an example of how these can be used.

@maccabeelevine
Copy link
Member Author

Thanks. I'm writing tests now and I can see they will be some work so I will do them separately.

@maccabeelevine maccabeelevine merged commit 1f6bf42 into vufind-org:dev Jul 7, 2023
7 checks passed
@maccabeelevine maccabeelevine deleted the libguides-profile branch July 7, 2023 13:39
bpalme pushed a commit to bpalme/vufind that referenced this pull request Aug 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants