Skip to content

Commit b7ce450

Browse files
authored
Allow to configure the views tab bar per user (#10379)
* allow to configure the views tab bar per user * apply prettier * fix spotbugs * add license header
1 parent ae9d1f9 commit b7ce450

File tree

20 files changed

+172
-139
lines changed

20 files changed

+172
-139
lines changed

core/src/main/java/hudson/model/MyViewsProperty.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import hudson.security.ACL;
3535
import hudson.util.FormValidation;
3636
import hudson.util.ListBoxModel;
37+
import hudson.views.DefaultViewsTabBar;
3738
import hudson.views.MyViewsTabBar;
3839
import hudson.views.ViewsTabBar;
3940
import jakarta.servlet.ServletException;
@@ -81,6 +82,8 @@ public class MyViewsProperty extends UserProperty implements ModifiableViewGroup
8182
@CheckForNull
8283
private String primaryViewName;
8384

85+
private ViewsTabBar viewsTabBar = new DefaultViewsTabBar();
86+
8487
/**
8588
* Always hold at least one view.
8689
*/
@@ -124,6 +127,9 @@ public Object readResolve() {
124127
protected void primaryView(String name) { primaryViewName = name; }
125128
};
126129

130+
if (viewsTabBar == null) {
131+
viewsTabBar = new DefaultViewsTabBar();
132+
}
127133
return this;
128134
}
129135

@@ -284,6 +290,7 @@ public ListBoxModel doFillPrimaryViewNameItems(@AncestorInPath User user) throws
284290
MyViewsProperty property = user.getProperty(MyViewsProperty.class);
285291
if (property == null) {
286292
property = new MyViewsProperty();
293+
property.readResolve();
287294
user.addProperty(property);
288295
}
289296
for (View view : property.views) {
@@ -303,7 +310,11 @@ public UserProperty reconfigure(StaplerRequest2 req, JSONObject form) throws For
303310

304311
@Override
305312
public ViewsTabBar getViewsTabBar() {
306-
return Jenkins.get().getViewsTabBar();
313+
return viewsTabBar;
314+
}
315+
316+
public void setViewsTabBar(ViewsTabBar viewsTabBar) {
317+
this.viewsTabBar = viewsTabBar;
307318
}
308319

309320
@Override

core/src/main/java/hudson/model/ViewGroup.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.LinkedHashSet;
3434
import java.util.List;
3535
import jenkins.model.Jenkins;
36+
import jenkins.views.ViewsTabBarUserProperty;
3637

3738
/**
3839
* Container of {@link View}s.
@@ -159,4 +160,23 @@ default List<Action> getViewActions() {
159160
return Jenkins.get().getActions();
160161
}
161162

163+
/**
164+
* Returns the ViewsTabBar that the user has configured.
165+
*
166+
* @return users TabBar
167+
* @since TODO
168+
*/
169+
default ViewsTabBar getUserViewsTabBar() {
170+
User user = User.current();
171+
if (user != null) {
172+
ViewsTabBarUserProperty viewsTabBarUserProperty = user.getProperty(ViewsTabBarUserProperty.class);
173+
if (viewsTabBarUserProperty != null) {
174+
ViewsTabBar userViewTabsBars = viewsTabBarUserProperty.getViewsTabBar();
175+
if (userViewTabsBars != null) {
176+
return userViewTabsBars;
177+
}
178+
}
179+
}
180+
return getViewsTabBar();
181+
}
162182
}

core/src/main/java/hudson/views/DefaultMyViewsTabBar.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
* @author Winston Prakash
3636
* @since 1.378
3737
* @see MyViewsTabBar
38+
* @deprecated No longer used
3839
*/
40+
@Deprecated
3941
public class DefaultMyViewsTabBar extends MyViewsTabBar {
4042
@DataBoundConstructor
4143
public DefaultMyViewsTabBar() {

core/src/main/java/hudson/views/MyViewsTabBar.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@
5858
* @author Winston Prakash
5959
* @since 1.378
6060
* @see MyViewsTabBarDescriptor
61+
* @deprecated Implement {@link ViewsTabBar}
6162
*/
63+
@Deprecated
6264
public abstract class MyViewsTabBar implements Describable<MyViewsTabBar>, ExtensionPoint {
6365
/**
6466
* Returns all the registered {@link ListViewColumn} descriptors.

core/src/main/java/jenkins/model/Jenkins.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,10 +1941,12 @@ public Jenkins getItemGroup() {
19411941
return this;
19421942
}
19431943

1944+
@Deprecated
19441945
public MyViewsTabBar getMyViewsTabBar() {
19451946
return myViewsTabBar;
19461947
}
19471948

1949+
@Deprecated
19481950
public void setMyViewsTabBar(MyViewsTabBar myViewsTabBar) {
19491951
this.myViewsTabBar = myViewsTabBar;
19501952
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025 Markus Winter
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.views;
26+
27+
import edu.umd.cs.findbugs.annotations.CheckForNull;
28+
import edu.umd.cs.findbugs.annotations.NonNull;
29+
import hudson.Extension;
30+
import hudson.model.User;
31+
import hudson.model.UserProperty;
32+
import hudson.model.UserPropertyDescriptor;
33+
import hudson.model.userproperty.UserPropertyCategory;
34+
import hudson.views.ViewsTabBar;
35+
import org.jenkinsci.Symbol;
36+
import org.kohsuke.accmod.Restricted;
37+
import org.kohsuke.accmod.restrictions.NoExternalUse;
38+
import org.kohsuke.stapler.DataBoundConstructor;
39+
import org.kohsuke.stapler.DataBoundSetter;
40+
41+
@Restricted(NoExternalUse.class)
42+
public class ViewsTabBarUserProperty extends UserProperty {
43+
44+
private ViewsTabBar viewsTabBar;
45+
46+
@DataBoundConstructor
47+
public ViewsTabBarUserProperty() {
48+
}
49+
50+
@DataBoundSetter
51+
public void setViewsTabBar(ViewsTabBar viewsTabBar) {
52+
this.viewsTabBar = viewsTabBar;
53+
}
54+
55+
@CheckForNull
56+
public ViewsTabBar getViewsTabBar() {
57+
return viewsTabBar;
58+
}
59+
60+
@Extension
61+
@Symbol("viewsTabBar")
62+
public static class DescriptorImpl extends UserPropertyDescriptor {
63+
64+
@NonNull
65+
@Override
66+
public String getDisplayName() {
67+
return Messages.ViewsTabBarUserProperty_DisplayName();
68+
}
69+
70+
@Override
71+
public UserProperty newInstance(User user) {
72+
return new ViewsTabBarUserProperty();
73+
}
74+
75+
@Override
76+
public @NonNull UserPropertyCategory getUserPropertyCategory() {
77+
return UserPropertyCategory.get(UserPropertyCategory.Preferences.class);
78+
}
79+
}
80+
}

core/src/main/resources/hudson/model/MyViewsProperty/config.jelly

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,8 @@ THE SOFTWARE.
2828
description="${%description}">
2929
<f:select field="primaryViewName"/>
3030
</f:entry>
31+
<j:invokeStatic var="allViewsTabBar" className="hudson.views.ViewsTabBar" method="all"/>
32+
<j:if test="${allViewsTabBar.size() > 1}">
33+
<f:dropdownDescriptorSelector field="viewsTabBar" title="${%Views Tab Bar}"/>
34+
</j:if>
3135
</j:jelly>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div>
2+
The Views Tab Bar to use on
3+
<em>My Views</em>
4+
.
5+
</div>
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package hudson.model.View
22

3+
import hudson.model.MyViewsProperty
4+
35
t=namespace(lib.JenkinsTagLib)
46
st=namespace("jelly:stapler")
57

@@ -9,17 +11,21 @@ if (items == null) {
911
if (app.items.size() != 0) {
1012
set("views",my.owner.views)
1113
set("currentView",my)
12-
include(my.owner.viewsTabBar, "viewTabs")
14+
if (my.owner.class == MyViewsProperty.class) {
15+
include(my.owner?.viewsTabBar, "viewTabs")
16+
} else {
17+
include(my.owner.userViewsTabBar, "viewTabs")
18+
}
1319
}
1420
include(my,"noJob.jelly")
1521
} else {
1622
t.projectView(jobs: items, showViewTabs: true, columnExtensions: my.columns, indenter: my.indenter, itemGroup: my.owner.itemGroup) {
1723
set("views",my.owner.views)
1824
set("currentView",my)
19-
if (my.owner.class == hudson.model.MyViewsProperty.class) {
20-
include(my.owner?.myViewsTabBar, "myViewTabs")
25+
if (my.owner.class == MyViewsProperty.class) {
26+
include(my.owner?.viewsTabBar, "viewTabs")
2127
} else {
22-
include(my.owner.viewsTabBar,"viewTabs")
28+
include(my.owner.userViewsTabBar,"viewTabs")
2329
}
2430
}
2531
}

core/src/main/resources/hudson/views/MyViewsTabBar/GlobalConfigurationImpl/config.groovy

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)