-
Notifications
You must be signed in to change notification settings - Fork 12
Add Favorites Plugin Integration to Auto-show/hide App Nav Button #211
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
base: main
Are you sure you want to change the base?
Changes from 3 commits
5e58f17
0e71b6d
89d0312
925ae3b
b4304e1
af90d8a
e620577
cf03a8e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "java.configuration.updateBuildConfiguration": "interactive" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Netscape HTTP Cookie File | ||
| # https://curl.se/docs/http-cookies.html | ||
| # This file was generated by libcurl! Edit at your own risk. | ||
|
|
||
| #HttpOnly_localhost FALSE /jenkins FALSE 0 JSESSIONID.05c074da node01ocqegq00mpin7k03soapl07p5.node0 |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This class is not needed. When the appnav button is visible it will fetch dynamically all links including the currently defined favorites for a user. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| package io.jenkins.plugins.customizable_header; | ||
|
|
||
| import hudson.Extension; | ||
| import hudson.model.Item; | ||
| import hudson.model.User; | ||
| import hudson.plugins.favorite.Favorites; | ||
| import hudson.plugins.favorite.listener.FavoriteListener; | ||
| import jenkins.model.Jenkins; | ||
| import org.kohsuke.stapler.Stapler; | ||
| import org.kohsuke.stapler.StaplerRequest2; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.logging.Level; | ||
| import java.util.logging.Logger; | ||
|
|
||
| @Extension(optional = true) | ||
| public class FavoriteIntegrationListener extends FavoriteListener { | ||
|
|
||
| private static final Logger LOGGER = Logger.getLogger(FavoriteIntegrationListener.class.getName()); | ||
| private static final String FAVORITES_ID = "favorites-nav"; | ||
|
|
||
| @Override | ||
| public void onAddFavourite(Item item, User user) { | ||
| LOGGER.info("DEBUG: onAddFavourite triggered for item " + item.getFullName() + " and user " + user.getId()); | ||
| updateFavoritesNavLink(user, true); | ||
| // Trigger the favorite status refresh event for UI | ||
| triggerAppNavRefresh(); | ||
| } | ||
|
|
||
| @Override | ||
| public void onRemoveFavourite(Item item, User user) { | ||
| LOGGER.info("DEBUG: onRemoveFavourite triggered for item " + item.getFullName() + " and user " + user.getId()); | ||
| // Check if the user has any favorites left | ||
| boolean hasFavorites = !isEmpty(Favorites.getFavorites(user)); | ||
| LOGGER.info("DEBUG: User " + user.getId() + " has favorites: " + hasFavorites); | ||
| updateFavoritesNavLink(user, hasFavorites); | ||
| // Trigger the favorite status refresh event for UI | ||
| triggerAppNavRefresh(); | ||
| } | ||
|
|
||
| private void updateFavoritesNavLink(User user, boolean hasFavorites) { | ||
| try { | ||
| // Get user header | ||
| UserHeader headerProp = user.getProperty(UserHeader.class); | ||
| if (headerProp == null) { | ||
| return; | ||
| } | ||
|
|
||
| List<AbstractLink> links = headerProp.getLinks(); | ||
|
|
||
| // Find existing favorites link | ||
| AppNavLink favoritesLink = null; | ||
| for (AbstractLink link : links) { | ||
| if (link instanceof AppNavLink && FAVORITES_ID.equals(((AppNavLink)link).getId())) { | ||
| favoritesLink = (AppNavLink) link; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (hasFavorites) { | ||
| // Add favorites link if it doesn't exist and there are no other links | ||
| if (favoritesLink == null && links.isEmpty()) { | ||
| AppNavLink newLink = createFavoritesLink(user); | ||
| List<AbstractLink> newLinks = new ArrayList<>(); | ||
| newLinks.add(newLink); | ||
| headerProp.setLinks(newLinks); | ||
| user.save(); | ||
| LOGGER.fine("Added favorites link for user: " + user.getId()); | ||
| } | ||
| } else { | ||
| // Remove favorites link if it exists and it's the only link | ||
| if (favoritesLink != null && links.size() == 1) { | ||
| headerProp.setLinks(new ArrayList<>()); | ||
| user.save(); | ||
| LOGGER.fine("Removed favorites link for user: " + user.getId()); | ||
| } | ||
| } | ||
| } catch (Exception e) { | ||
| LOGGER.log(Level.WARNING, "Failed to update favorites link for user: " + user.getId(), e); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Triggers a refresh of the app-nav button visibility in the UI | ||
| * Called after favorite status changes to update the UI in real-time | ||
| */ | ||
| private void triggerAppNavRefresh() { | ||
| try { | ||
| // Use Jenkins.getInstance() to get the Jenkins instance | ||
| Jenkins jenkins = Jenkins.get(); | ||
| if (jenkins != null) { | ||
| LOGGER.info("DEBUG: Triggering app-nav refresh after favorite change"); | ||
| // Notify the frontend about the favorite status change | ||
| jenkins.getExtensionList(HeaderRootAction.class) | ||
| .get(0) | ||
| .notifyFavoriteStatusChanged(); | ||
| } | ||
| } catch (Exception e) { | ||
| LOGGER.log(Level.WARNING, "Failed to trigger app-nav refresh after favorite change", e); | ||
| } | ||
| } | ||
|
|
||
| private AppNavLink createFavoritesLink(User user) { | ||
| // Create a new App Nav Link for favorites | ||
| AppNavLink link = new AppNavLink( | ||
| "user/" + user.getId() + "/favorites", | ||
| "Favorites", | ||
| new io.jenkins.plugins.customizable_header.logo.Symbol("symbol-star") | ||
| ); | ||
| link.setId(FAVORITES_ID); | ||
| return link; | ||
| } | ||
|
|
||
| private boolean isEmpty(Iterable<?> iterable) { | ||
| return !iterable.iterator().hasNext(); | ||
| } | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changes are not needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed