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

Redesign the Jenkins header #10245

Draft
wants to merge 131 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 129 commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
5a0eee2
WB
janfaracik Jan 16, 2025
c9c8669
Push
janfaracik Jan 16, 2025
82b85a2
More responsive
janfaracik Jan 16, 2025
3d08ab8
Update headerContent.jelly
janfaracik Jan 16, 2025
f04343b
Push
janfaracik Jan 16, 2025
6fbb8e8
Update logo.jelly
janfaracik Jan 16, 2025
6fbabad
Update _page-header.scss
janfaracik Jan 16, 2025
363b63a
Update _page-header.scss
janfaracik Jan 16, 2025
278f8c5
Update header
janfaracik Jan 16, 2025
0b1eb50
Merge branch 'master' into new-header
janfaracik Jan 16, 2025
46b4296
Merge branch 'master' into new-header
janfaracik Jan 18, 2025
53d1f72
Tidy up breadcrumbs
janfaracik Jan 18, 2025
ae239df
Tidy up focus
janfaracik Jan 18, 2025
d85458f
Update _breadcrumbs.scss
janfaracik Jan 18, 2025
cd3c384
Update configure.jelly
janfaracik Jan 18, 2025
a5e3d54
push
janfaracik Jan 18, 2025
5b340a8
Add badges
janfaracik Jan 18, 2025
73b81a3
Tidy
janfaracik Jan 18, 2025
a04b8f2
Push
janfaracik Jan 18, 2025
82a3d80
Update headerContent.jelly
janfaracik Jan 18, 2025
1123309
Update ManageJenkinsAction.java
janfaracik Jan 18, 2025
d5c986f
Update headerContent.jelly
janfaracik Jan 18, 2025
25f04d9
Working!
janfaracik Jan 18, 2025
244f48d
WB
janfaracik Jan 18, 2025
abe4770
Tidy up
janfaracik Jan 18, 2025
3970e8d
Fixes
janfaracik Jan 18, 2025
be07296
Update sidepanel.jelly
janfaracik Jan 18, 2025
7134580
Lint
janfaracik Jan 19, 2025
cf56f45
Tidy up
janfaracik Jan 19, 2025
21c74a7
Update ManageJenkinsAction.java
janfaracik Jan 19, 2025
aab79d0
Simplify
janfaracik Jan 19, 2025
5ddd415
Update _side-panel-tasks.scss
janfaracik Jan 19, 2025
5c8f872
Merge branch 'simplify-search' into new-header
janfaracik Jan 19, 2025
181d9d2
Update _side-panel-tasks.scss
janfaracik Jan 19, 2025
46a9c35
Update UserAction.java
janfaracik Jan 19, 2025
bb7b73f
Update Jenkins.java
janfaracik Jan 19, 2025
7131e9a
Add border to account image
janfaracik Jan 19, 2025
15fc210
Tidy up avatars
janfaracik Jan 19, 2025
9b5dd43
Merge branch 'master' into new-header
janfaracik Jan 20, 2025
a309687
Update _side-panel-tasks.scss
janfaracik Jan 20, 2025
564f050
Init
janfaracik Jan 20, 2025
b447e27
Tidy up
janfaracik Jan 20, 2025
0ebc7f1
Merge branch 'circle-avatar' into new-header
janfaracik Jan 20, 2025
77b0baa
Merge branch 'improve-dialog' into new-header
janfaracik Jan 20, 2025
c2fb2ad
Merge branch 'rename-jenkins-in-tab-title' into new-header
janfaracik Jan 20, 2025
a800200
Merge branch 'master' into new-header
janfaracik Jan 22, 2025
60e0a00
Hide behind flag
janfaracik Jan 23, 2025
9cc86bd
Update sidepanel.jelly
janfaracik Jan 23, 2025
b403502
Push
janfaracik Jan 23, 2025
d89c24c
Tidy up
janfaracik Jan 23, 2025
6bacea0
Update logo.jelly
janfaracik Jan 23, 2025
ac72328
Merge branch 'master' into new-header
janfaracik Jan 25, 2025
1becb26
Accessibility
janfaracik Jan 26, 2025
7a42953
Update _breadcrumbs-new.scss
janfaracik Jan 26, 2025
f76088b
Fix dropdown theme
janfaracik Jan 27, 2025
7c16c18
Update _breadcrumbs.scss
janfaracik Jan 29, 2025
dc7a46d
Update _header.scss
janfaracik Jan 29, 2025
e5c3670
Update ManageJenkinsAction.java
janfaracik Jan 30, 2025
3397f39
Remove flag
janfaracik Jan 30, 2025
79c1280
Tidy up
janfaracik Jan 30, 2025
2ea0b1f
Update with HeaderAction
janfaracik Jan 31, 2025
bee9422
Merge branch 'master' into new-header
janfaracik Feb 1, 2025
19b4f27
Revert "Update with HeaderAction"
janfaracik Feb 1, 2025
0875038
Tidy
janfaracik Feb 1, 2025
a9c648d
Update RootAction.java
janfaracik Feb 1, 2025
9feda44
Update _breadcrumbs.scss
janfaracik Feb 1, 2025
56a808f
Push
janfaracik Feb 1, 2025
025a596
Update _header.scss
janfaracik Feb 1, 2025
1e67e70
Update _header.scss
janfaracik Feb 1, 2025
4a60bb7
Fix invisible actions not actually being invisible, make avatar huge …
janfaracik Feb 1, 2025
4a3f71a
Tidy
janfaracik Feb 1, 2025
abdb235
Push
janfaracik Feb 1, 2025
950cdee
Fix breadcrumbs + notification
janfaracik Feb 2, 2025
5bd87dc
Update jumplist.jelly
janfaracik Feb 2, 2025
ef847c9
Getting there 🚀
janfaracik Feb 2, 2025
49cb8cc
WB
janfaracik Feb 2, 2025
18677f1
Update index.jelly
janfaracik Feb 3, 2025
eed89b7
Update headerContent.jelly
janfaracik Feb 3, 2025
c6324ca
Responsive
janfaracik Feb 3, 2025
76b9bcf
Push
janfaracik Feb 3, 2025
857885c
Push
janfaracik Feb 3, 2025
6752284
Push
janfaracik Feb 3, 2025
062636c
Update index.js
janfaracik Feb 3, 2025
d586b51
Push
janfaracik Feb 3, 2025
e2d75a5
Tidy up
janfaracik Feb 3, 2025
4a2cd7e
Tidy up
janfaracik Feb 3, 2025
668871b
Tidy
janfaracik Feb 3, 2025
575632f
Update logo.jelly
janfaracik Feb 3, 2025
a222707
Delete NewHeaderUserExperimentalFlag.java
janfaracik Feb 3, 2025
a8a8af7
Merge branch 'master' into new-header
janfaracik Feb 6, 2025
def576a
Lint
janfaracik Feb 6, 2025
6066472
Update index.js
janfaracik Feb 6, 2025
32ac982
Update index.js
janfaracik Feb 6, 2025
e8903b8
Fix some tests
janfaracik Feb 6, 2025
531e1b8
Update headerContent.jelly
janfaracik Feb 6, 2025
540ae4b
Update headerContent.jelly
janfaracik Feb 6, 2025
770f5d9
Remove bravo test - need to confirm this
janfaracik Feb 6, 2025
615e5a0
Update Security3349Test.java
janfaracik Feb 6, 2025
ff33e12
Update pom.xml
janfaracik Feb 7, 2025
e89f74a
Merge branch 'master' into new-header
janfaracik Feb 7, 2025
90dd49f
Fix SpotBugs + i18n
janfaracik Feb 8, 2025
c493a41
Add doc for header scroll, support prefers contrast
janfaracik Feb 8, 2025
cadf01e
Add overflow menu for actions, improve accessibility
janfaracik Feb 8, 2025
f740741
Update actions-overflow.js
janfaracik Feb 8, 2025
dbb67ca
Fix tests + accessibility
janfaracik Feb 8, 2025
2fdb00b
Merge branch 'master' into new-header
janfaracik Feb 8, 2025
8eda9d1
Fix JS
janfaracik Feb 10, 2025
57e67af
Update breadcrumbs-overflow.js
janfaracik Feb 11, 2025
ddc968a
Merge branch 'master' into new-header
janfaracik Feb 11, 2025
1f8cc8b
Update breadcrumbs-overflow.js
janfaracik Feb 12, 2025
ee5c7fe
Merge branch 'master' into new-header
janfaracik Feb 12, 2025
c4de77b
Merge branch 'master' into new-header
janfaracik Feb 17, 2025
6df76ce
Merge branch 'master' into new-header
janfaracik Feb 17, 2025
5fae312
Merge branch 'master' into new-header
janfaracik Feb 22, 2025
d967de5
Add breadcrumb menu on hover, fix issues on mobile
janfaracik Feb 22, 2025
27662c8
Update _breadcrumbs.scss
janfaracik Feb 24, 2025
9ea5305
i18n
janfaracik Feb 25, 2025
70e1608
Update pom.xml
janfaracik Feb 25, 2025
4306342
Merge branch 'master' into new-header
janfaracik Feb 26, 2025
7ca2e8f
Add tab support for user dropdown
janfaracik Feb 28, 2025
ca0176a
Squashed commit of the following:
janfaracik Feb 28, 2025
25647d6
Move logo
janfaracik Mar 2, 2025
1299718
Revert "Move logo"
janfaracik Mar 2, 2025
f4eb1e1
Move actions to taglib
janfaracik Mar 2, 2025
470c42c
Split logo from breadcrumbs
janfaracik Mar 2, 2025
4290f25
Fix sticky app bar
janfaracik Mar 2, 2025
a7876f7
Update _page-header.scss
janfaracik Mar 2, 2025
fb0d6fd
Update HudsonTest.java
janfaracik Mar 2, 2025
c80ddd4
Update _page-header.scss
janfaracik Mar 3, 2025
16d2064
Merge branch 'master' into new-header
janfaracik Mar 5, 2025
5bb55a9
Merge branch 'master' into new-header
janfaracik Mar 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/model/Computer.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
import jenkins.model.IComputer;
import jenkins.model.IDisplayExecutor;
import jenkins.model.Jenkins;
import jenkins.search.SearchGroup;
import jenkins.security.ImpersonatingExecutorService;
import jenkins.security.MasterToSlaveCallable;
import jenkins.security.stapler.StaplerDispatchable;
Expand Down Expand Up @@ -1109,6 +1110,11 @@ public String getSearchUrl() {
return getUrl();
}

@Override
public SearchGroup getSearchGroup() {
return SearchGroup.get(SearchGroup.ComputerSearchGroup.class);
}

/**
* {@link RetentionStrategy} associated with this computer.
*
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/model/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.io.IOException;
import java.util.Collection;
import jenkins.model.Jenkins;
import jenkins.search.SearchGroup;
import jenkins.util.SystemProperties;
import jenkins.util.io.OnMaster;
import org.kohsuke.stapler.StaplerRequest2;
Expand Down Expand Up @@ -249,6 +250,11 @@ default void onCreatedFromScratch() {
*/
void delete() throws IOException, InterruptedException;

@Override
default SearchGroup getSearchGroup() {
return SearchGroup.get(SearchGroup.ItemSearchGroup.class);
}

PermissionGroup PERMISSIONS = new PermissionGroup(Item.class, Messages._Item_Permissions_Title());
Permission CREATE =
new Permission(
Expand Down
33 changes: 31 additions & 2 deletions core/src/main/java/hudson/model/ManageJenkinsAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
import hudson.Extension;
import hudson.Util;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import jenkins.management.AdministrativeMonitorsDecorator;
import jenkins.management.Badge;
import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithContextMenu;
Expand All @@ -40,11 +44,11 @@
import org.kohsuke.stapler.StaplerResponse2;

/**
* Adds the "Manage Jenkins" link to the top page.
* Adds the "Manage Jenkins" link to the navigation bar.
*
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal = 100) @Symbol("manageJenkins")
@Extension(ordinal = 998) @Symbol("manageJenkins")
public class ManageJenkinsAction implements RootAction, StaplerFallback, ModelObjectWithContextMenu {
@Override
public String getIconFileName() {
Expand Down Expand Up @@ -88,4 +92,29 @@ public void addContextMenuItem(ContextMenu menu, String url, String icon, String
// If neither is the case, rewrite the relative URL to point to inside the /manage/ URL space
menu.add("manage/" + url, icon, iconXml, text, post, requiresConfirmation, badge, message);
}

@Override
public Badge getBadge() {
Jenkins jenkins = Jenkins.get();
AdministrativeMonitorsDecorator decorator = jenkins.getExtensionList(PageDecorator.class)
.get(AdministrativeMonitorsDecorator.class);

if (decorator == null) {
return null;
}

Collection<AdministrativeMonitor> activeAdministrativeMonitors = Optional.ofNullable(decorator.getMonitorsToDisplay()).orElse(Collections.emptyList());
boolean anySecurity = activeAdministrativeMonitors.stream().anyMatch(AdministrativeMonitor::isSecurity);

if (activeAdministrativeMonitors.isEmpty()) {
return null;
}

int size = activeAdministrativeMonitors.size();
String tooltip = size > 1 ? Messages.ManageJenkinsAction_notifications(size) : Messages.ManageJenkinsAction_notification(size);

return new Badge(String.valueOf(size),
tooltip,
anySecurity ? Badge.Severity.DANGER : Badge.Severity.WARNING);
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/MyViewsProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public MyViewsTabBar getMyViewsTabBar() {
return Jenkins.get().getMyViewsTabBar();
}

@Extension @Symbol("myView")
@Symbol("myView")
public static class GlobalAction implements RootAction {

@Override
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/java/hudson/model/RootAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@

package hudson.model;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import hudson.Extension;
import hudson.ExtensionPoint;
import jenkins.management.Badge;

/**
* Marker interface for actions that are added to {@link jenkins.model.Jenkins}.
Expand All @@ -38,4 +40,14 @@
* @since 1.311
*/
public interface RootAction extends Action, ExtensionPoint {

/**
* A {@link Badge} shown on the button for the action.
*
* @return badge or {@code null} if no badge should be shown.
* @since TODO
*/
default @CheckForNull Badge getBadge() {
return null;
}
}
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import jenkins.model.Loadable;
import jenkins.model.ModelObjectWithContextMenu;
import jenkins.scm.RunWithSCM;
import jenkins.search.SearchGroup;
import jenkins.security.ImpersonatingUserDetailsService2;
import jenkins.security.LastGrantedAuthoritiesProperty;
import jenkins.security.UserDetailsCache;
Expand Down Expand Up @@ -284,6 +285,11 @@ public String getSearchIcon() {
return UserAvatarResolver.resolve(this, "48x48");
}

@Override
public SearchGroup getSearchGroup() {
return SearchGroup.get(SearchGroup.UserSearchGroup.class);
}

/**
* The URL of the user page.
*/
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/model/View.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import jenkins.model.item_category.Categories;
import jenkins.model.item_category.Category;
import jenkins.model.item_category.ItemCategory;
import jenkins.search.SearchGroup;
import jenkins.security.stapler.StaplerNotDispatchable;
import jenkins.util.xml.XMLUtils;
import jenkins.widgets.HasWidgets;
Expand Down Expand Up @@ -565,6 +566,11 @@ public String getSearchIcon() {
return "symbol-jobs";
}

@Override
public SearchGroup getSearchGroup() {
return SearchGroup.get(SearchGroup.ViewSearchGroup.class);
}

/**
* Returns the transient {@link Action}s associated with the top page.
*
Expand Down
43 changes: 33 additions & 10 deletions core/src/main/java/hudson/search/Search.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.ExtensionComponent;
import hudson.ExtensionList;
import hudson.Util;
import hudson.util.EditDistance;
import io.jenkins.servlet.ServletExceptionWrapper;
Expand All @@ -37,12 +39,16 @@
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import jenkins.model.Jenkins;
import jenkins.search.SearchGroup;
import jenkins.security.stapler.StaplerNotDispatchable;
import jenkins.util.MemoryReductionUtil;
import jenkins.util.SystemProperties;
Expand Down Expand Up @@ -171,11 +177,26 @@ public void doSuggest(StaplerRequest2 req, StaplerResponse2 rsp, @QueryParameter

if (iconName.startsWith("symbol")) {
r.suggestions.add(new Item(curItem.getPath(), curItem.getUrl(),
Symbol.get(new SymbolRequest.Builder().withRaw(iconName).build())));
Symbol.get(new SymbolRequest.Builder().withRaw(iconName).build()), "symbol", curItem.item.getSearchGroup().getDisplayName()));
} else {
r.suggestions.add(new Item(curItem.getPath(), curItem.getUrl(), iconName, "image"));
r.suggestions.add(new Item(curItem.getPath(), curItem.getUrl(), iconName, "image", curItem.item.getSearchGroup().getDisplayName()));
}
}

// Sort results by group
ExtensionList<SearchGroup> groupsExtensionList = ExtensionList.lookup(SearchGroup.class);
List<ExtensionComponent<SearchGroup>> components = groupsExtensionList.getComponents();
Map<String, Double> searchGroupOrdinal = components.stream()
.collect(Collectors.toMap(
(k) -> k.getInstance().getDisplayName(),
ExtensionComponent::ordinal
));
r.suggestions.sort(
Comparator.comparingDouble((Item item) -> searchGroupOrdinal.getOrDefault(item.getGroup(), Double.MAX_VALUE))
.reversed()
.thenComparing(item -> item.name)
);

rsp.serveExposedBean(req, r, new ExportConfig());
}

Expand Down Expand Up @@ -279,22 +300,19 @@ public static class Item {

private final String icon;

private final String group;

public Item(String name) {
this(name, null, null);
this(name, null, null, "symbol", null);
}

public Item(String name, String url, String icon) {
public Item(String name, String url, String icon, String type, String group) {
this.name = name;
this.url = url;
this.icon = icon;
this.type = "symbol";
}

public Item(String name, String url, String icon, String type) {
this.name = name;
this.url = url;
this.icon = icon;
this.type = type;
this.group = group;
}

@Exported
Expand All @@ -311,6 +329,11 @@ public String getIcon() {
public String getType() {
return type;
}

@Exported
public String getGroup() {
return group;
}
}

private enum Mode {
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/hudson/search/SearchItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package hudson.search;

import hudson.model.Build;
import jenkins.search.SearchGroup;
import org.jenkins.ui.icon.IconSpec;

/**
Expand Down Expand Up @@ -63,6 +64,10 @@ default String getSearchIcon() {
return "symbol-search";
}

default SearchGroup getSearchGroup() {
return SearchGroup.get(SearchGroup.UnclassifiedSearchGroup.class);
}

/**
* Returns the {@link SearchIndex} to further search sub items inside this item.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import hudson.Extension;
import hudson.diagnosis.ReverseProxySetupMonitor;
import hudson.model.AdministrativeMonitor;
import hudson.model.ManageJenkinsAction;
import hudson.model.PageDecorator;
import hudson.util.HudsonIsLoading;
import hudson.util.HudsonIsRestarting;
Expand Down Expand Up @@ -56,9 +55,6 @@ public class AdministrativeMonitorsDecorator extends PageDecorator {
public AdministrativeMonitorsDecorator() {
// otherwise this would be added to every internal context menu building request
ignoredJenkinsRestOfUrls.add("contextMenu");

// don't show here to allow admins to disable malfunctioning monitors via AdministrativeMonitorsDecorator
ignoredJenkinsRestOfUrls.add("configure");
}

@NonNull
Expand Down Expand Up @@ -163,11 +159,6 @@ public Collection<AdministrativeMonitor> getMonitorsToDisplay() {
return null;
}

// Don't show on Manage Jenkins
if (o instanceof ManageJenkinsAction) {
return null;
}

// don't show for some URLs served directly by Jenkins
if (o instanceof Jenkins) {
String url = a.getRestOfUrl();
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/jenkins/model/Jenkins.java
Original file line number Diff line number Diff line change
Expand Up @@ -2350,7 +2350,7 @@ public String getSearchUrl() {
public SearchIndexBuilder makeSearchIndex() {
SearchIndexBuilder builder = super.makeSearchIndex();

this.actions.stream().filter(e -> e.getIconFileName() != null).forEach(action -> builder.add(new SearchItem() {
this.actions.stream().filter(e -> !(e.getIconFileName() == null || e.getUrlName() == null)).forEach(action -> builder.add(new SearchItem() {
@Override
public String getSearchName() {
return action.getDisplayName();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* The MIT License
*
* Copyright (c) 2011, CloudBees, Inc.
* Copyright (c) 2025, Jan Faracik
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand All @@ -22,31 +22,29 @@
* THE SOFTWARE.
*/

package lib.hudson;
package jenkins.model.navigation;

import static org.junit.Assert.assertNotNull;

import hudson.model.InvisibleAction;
import hudson.Extension;
import hudson.model.RootAction;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;

/**
* @author Kohsuke Kawaguchi
* TODO
*/
public class ActionsTest {
@Extension(ordinal = 999)
public class SearchAction implements RootAction {

@Rule
public JenkinsRule j = new JenkinsRule();
@Override
public String getIconFileName() {
return "symbol-search";
}

@Test
public void override() throws Exception {
assertNotNull(j.createWebClient().goTo("").getElementById("bravo"));
@Override
public String getDisplayName() {
return "Search";
}

@TestExtension
public static class RootActionImpl extends InvisibleAction implements RootAction {
@Override
public String getUrlName() {
return null;
}
}
Loading