提交 6804299a 编写于 作者: V Vincent Latombe

Fix following jglick review on PR

https://github.com/jenkinsci/jenkins/pull/757.
上级 a210e489
......@@ -25,13 +25,33 @@
*/
package hudson;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import hudson.cli.CLICommand;
import hudson.console.ConsoleAnnotationDescriptor;
import hudson.console.ConsoleAnnotatorFactory;
import hudson.model.*;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.model.DescriptorVisibilityFilter;
import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.Items;
import hudson.model.JDK;
import hudson.model.Job;
import hudson.model.JobPropertyDescriptor;
import hudson.model.ModelObject;
import hudson.model.Node;
import hudson.model.PageDecorator;
import hudson.model.ParameterDefinition;
import hudson.model.ParameterDefinition.ParameterDescriptor;
import hudson.model.Project;
import hudson.model.Run;
import hudson.model.TopLevelItem;
import hudson.model.User;
import hudson.model.View;
import hudson.scm.SCM;
import hudson.scm.SCMDescriptor;
import hudson.search.SearchableModelObject;
import hudson.security.AccessControlled;
import hudson.security.AuthorizationStrategy;
......@@ -53,36 +73,11 @@ import hudson.tasks.Publisher;
import hudson.tasks.UserAvatarResolver;
import hudson.util.Area;
import hudson.util.Iterators;
import hudson.scm.SCM;
import hudson.scm.SCMDescriptor;
import hudson.util.Secret;
import hudson.views.MyViewsTabBar;
import hudson.views.ViewsTabBar;
import hudson.widgets.RenderOnDemandClosure;
import jenkins.model.GlobalConfiguration;
import jenkins.model.GlobalConfigurationCategory;
import jenkins.model.GlobalConfigurationCategory.Unclassified;
import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithContextMenu;
import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyTagException;
import org.apache.commons.jelly.Script;
import org.apache.commons.jelly.XMLOutput;
import org.apache.commons.jexl.parser.ASTSizeFunction;
import org.apache.commons.jexl.util.Introspector;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.jvnet.tiger_types.Types;
import org.kohsuke.stapler.Ancestor;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.jelly.InternationalizedStringExpression.RawHtmlArgument;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
......@@ -93,8 +88,8 @@ import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Type;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
......@@ -108,6 +103,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
......@@ -115,14 +111,42 @@ import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jenkins.model.GlobalConfiguration;
import jenkins.model.GlobalConfigurationCategory;
import jenkins.model.GlobalConfigurationCategory.Unclassified;
import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithContextMenu;
import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyTagException;
import org.apache.commons.jelly.Script;
import org.apache.commons.jelly.XMLOutput;
import org.apache.commons.jexl.parser.ASTSizeFunction;
import org.apache.commons.jexl.util.Introspector;
import org.apache.commons.lang.StringUtils;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.jvnet.tiger_types.Types;
import org.kohsuke.stapler.Ancestor;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.jelly.InternationalizedStringExpression.RawHtmlArgument;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
/**
* Utility functions used in views.
......@@ -921,6 +945,17 @@ public class Functions {
i = (Item) ig;
}
}
public static List<TopLevelItem> getAllTopLevelItems(ItemGroup root) {
return Items.getAllItems(root, TopLevelItem.class);
}
public static String getRelativeDisplayNameFrom(Item p, ItemGroup g) {
if (p == null) return null;
String relativeName = p.getRelativeNameFrom(g);
if (relativeName == null) return null;
return relativeName.replace("/", " \u00BB ");
}
public static Map<Thread,StackTraceElement[]> dumpAllThreads() {
Map<Thread,StackTraceElement[]> sorted = new TreeMap<Thread,StackTraceElement[]>(new ThreadSorter());
......
......@@ -43,8 +43,6 @@ import hudson.util.AtomicFileWriter;
import hudson.util.IOException2;
import hudson.util.IOUtils;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.kohsuke.stapler.WebMethod;
......@@ -56,7 +54,6 @@ import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......@@ -330,21 +327,22 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
else return n+" \u00BB "+getDisplayName();
}
public String getRelativeDisplayNameFrom(ItemGroup p) {
String relativeName = getRelativeNameFrom(p);
if (relativeName == null) return null;
return relativeName.replace("/", " \u00BB ");
}
/**
* This method only exists to disambiguate getRelativeNameFrom(Itemgroup) and getRelativeNameFrom(Item)
* @param p
* @return
* This method only exists to disambiguate {@link #getRelativeNameFrom(ItemGroup)} and {@link #getRelativeNameFrom(Item)}
* @since XXX
* @see #getRelativeNameFrom(ItemGroup)
*/
public String getRelativeNameFromGroup(ItemGroup p) {
return getRelativeNameFrom(p);
}
/**
* @param p
* The ItemGroup instance used as context to evaluate the relative name of this AbstractItem
* @return
* The name of the current item, relative to p.
* Nested ItemGroups are separated by / character.
*/
public String getRelativeNameFrom(ItemGroup p) {
// first list up all the parents
Map<ItemGroup,Integer> parents = new HashMap<ItemGroup,Integer>();
......@@ -385,7 +383,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
/**
* Called right after when a {@link Item} is loaded from disk.
* This is an opportunity to do a post load processing.
* This is an opporunity to do a post load processing.
*/
public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
this.parent = parent;
......@@ -425,7 +423,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
public String getShortUrl() {
return getParent().getUrlChildPrefix()+'/'+Util.rawEncode(getName())+'/';
}
public String getSearchUrl() {
return getShortUrl();
}
......
......@@ -124,14 +124,6 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
* of the ancestors.
*/
String getFullDisplayName();
/**
* Gets the relative display name to this item from the specified group
*
* @since 1.512
* @return
*/
String getRelativeDisplayNameFrom(ItemGroup g);
/**
* Gets the relative name to this item from the specified group.
......@@ -167,7 +159,7 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
* URL that ends with '/'.
*/
String getShortUrl();
/**
* Returns the absolute URL of this item. This relies on the current
* {@link StaplerRequest} to figure out what the host name is,
......
......@@ -239,8 +239,10 @@ public class Items {
/**
* Gets all the {@link Item}s recursively in the {@link ItemGroup} tree
* and filter them by the given type.
*
* @since XXX
*/
public static <T extends Item> List<T> getAllItems(ItemGroup root, Class<T> type) {
public static <T extends Item> List<T> getAllItems(final ItemGroup root, Class<T> type) {
List<T> r = new ArrayList<T>();
Stack<ItemGroup> q = new Stack<ItemGroup>();
......@@ -257,7 +259,23 @@ public class Items {
q.push((ItemGroup)i);
}
}
// sort by relative name, ignoring case
Collections.sort(r, new Comparator<T>() {
@Override
public int compare(T o1, T o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
}
return 1;
}
if (o2 == null) {
return -1;
}
return o1.getRelativeNameFrom(root).compareToIgnoreCase(o2.getRelativeNameFrom(root));
}
});
return r;
}
......
......@@ -39,7 +39,6 @@ import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
......@@ -85,7 +84,7 @@ public class ListView extends View implements Saveable {
/**
* Whether to recurse in ItemGroups
*/
private boolean recurse = true;
private boolean recurse;
/**
* Compiled include pattern from the includeRegex string.
......@@ -186,27 +185,6 @@ public class ListView extends View implements Saveable {
return items;
}
private TopLevelItem getItem(ItemGroup<? extends TopLevelItem> parent, String name) {
if (!name.contains("/")) { // same namespace
return parent.getItem(name);
}
StringTokenizer stringTokenizer = new StringTokenizer(name, "/");
TopLevelItem leaf = null;
ItemGroup<? extends TopLevelItem> node = parent;
// Navigate down to the item using / as separator
while(stringTokenizer.hasMoreTokens()) {
leaf = node.getItem(stringTokenizer.nextToken());
if (stringTokenizer.hasMoreTokens()) {
if (leaf instanceof ItemGroup) {
node = (ItemGroup<? extends TopLevelItem>)leaf;
} else {
return null;
}
}
}
return leaf;
}
private void includeItems(ItemGroup<? extends TopLevelItem> parent, SortedSet<String> names) {
includeItems(parent, parent, names);
}
......@@ -224,6 +202,11 @@ public class ListView extends View implements Saveable {
}
}
}
public synchronized boolean jobNamesContains(TopLevelItem item) {
if (item == null) return false;
return jobNames.contains(item.getRelativeNameFrom(getOwnerItemGroup()));
}
public synchronized boolean contains(TopLevelItem item) {
if(allJobNames == null) {
......@@ -317,10 +300,19 @@ public class ListView extends View implements Saveable {
protected void submit(StaplerRequest req) throws ServletException, FormException, IOException {
JSONObject json = req.getSubmittedForm();
synchronized (this) {
recurse = json.optBoolean("recurse", true);
jobNames.clear();
for (TopLevelItem item : getOwnerItemGroup().getItems()) {
if(req.getParameter(item.getName())!=null)
jobNames.add(item.getName());
Iterable<? extends TopLevelItem> items;
if (recurse) {
items = Items.getAllItems(getOwnerItemGroup(), TopLevelItem.class);
} else {
items = getOwnerItemGroup().getItems();
}
for (TopLevelItem item : items) {
String relativeNameFrom = item.getRelativeNameFrom(getOwnerItemGroup());
if(req.getParameter(relativeNameFrom)!=null) {
jobNames.add(relativeNameFrom);
}
}
}
......@@ -334,7 +326,6 @@ public class ListView extends View implements Saveable {
includeRegex = null;
includePattern = null;
}
recurse = json.optBoolean("recurse", true);
if (columns == null) {
columns = new DescribableList<ListViewColumn,Descriptor<ListViewColumn>>(this);
......
......@@ -36,24 +36,27 @@ THE SOFTWARE.
<f:option value="2" selected="${it.statusFilter==false}">${%Disabled jobs only}</f:option>
</select>
</f:entry>
<f:entry title="${%Recurse in subfolders}" field="recurse">
<f:checkbox id="recurse"/>
</f:entry>
<f:entry title="${%Jobs}">
<div class="listview-jobs">
<j:forEach var="job" items="${it.ownerItemGroup.items}">
<f:checkbox name="${job.getRelativeNameFromGroup(it.ownerItemGroup)}" checked="${it.contains(job)}" title="${job.getRelativeDisplayNameFrom(it.ownerItemGroup)}" />
<br/>
<j:forEach var="job" items="${h.getAllTopLevelItems(it.ownerItemGroup)}">
<span class="${job.parent==it.ownerItemGroup?'':'nested'}" style="${it.recurse?'':'display:none'}">
<f:checkbox name="${job.getRelativeNameFrom(it.ownerItemGroup)}" checked="${it.jobNamesContains(job)}" title="${h.getRelativeDisplayNameFrom(job,it.ownerItemGroup)}" />
<br/>
</span>
</j:forEach>
</div>
</f:entry>
<f:optionalBlock name="useincluderegex" title="${%Use a regular expression to include jobs into the view}"
checked="${it.includeRegex != null}" help="/help/view-config/includeregex.html" inline="true">
checked="${it.includeRegex != null}" help="/help/view-config/includeregex.html">
<f:entry title="${%Regular expression}">
<f:textbox name="includeRegex" field="includeRegex" />
</f:entry>
<f:entry title="${%Recurse in subfolders}" field="recurse">
<f:checkbox/>
</f:entry>
</f:optionalBlock>
<j:if test="${it.hasJobFilterExtensions()}">
......@@ -69,5 +72,18 @@ THE SOFTWARE.
<f:repeatableHeteroProperty field="columns" hasHeader="true" addCaption="${%Add column}"/>
</f:block>
</f:section>
<script>
(function() {
Behaviour.specify("#recurse", 'ListView', 0, function(e) {
var nestedElements = $$('SPAN.nested')
e.onclick = function() {
nestedElements.each(function(el) {
e.checked ? el.show() : el.hide();
});
}
});
}());
</script>
</j:jelly>
......@@ -11,7 +11,7 @@ if (items.isEmpty()) {
}
include(my,"noJob.jelly");
} else {
t.projectView(jobs: items, jobBaseUrl: "", showViewTabs: true, columnExtensions: my.columns, indenter: my.indenter, useFullName: true) {
t.projectView(jobs: items, jobBaseUrl: "", showViewTabs: true, columnExtensions: my.columns, indenter: my.indenter) {
set("views",my.owner.views);
set("currentView",my);
if (my.owner.class == hudson.model.MyViewsProperty.class) {
......
......@@ -26,7 +26,7 @@ THE SOFTWARE.
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<td>
<j:if test="${job.buildable and job.hasPermission(job.BUILD)}">
<a href="${jobBaseUrl}${job.shortUrl}build?delay=0sec">
<a href="${h.getRelativeLinkTo(job)}build?delay=0sec">
<img src="${imagesURL}/${subIconSize}/clock.png"
title="${%Schedule a build}" alt="${%Schedule a build}"
onclick="${job.parameterized ? null : 'return build(this)'}"
......
......@@ -25,6 +25,6 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<td style="${indenter.getCss(job)}">
<a href="${h.getRelativeLinkTo(job)}" class='model-link'> ${useFullName ? job.getRelativeDisplayNameFrom(currentView.owner.itemGroup) : job.displayName}</a>
<a href="${h.getRelativeLinkTo(job)}" class='model-link'> ${useFullName ? job.fullDisplayName : h.getRelativeDisplayNameFrom(job,currentView.owner.itemGroup)}</a>
</td>
</j:jelly>
\ No newline at end of file
......@@ -79,7 +79,7 @@ THE SOFTWARE.
</j:forEach>
<j:forEach var="job" items="${jobs}">
<t:projectViewRow jobBaseUrl="${jobBaseUrl}"/>
<t:projectViewRow jobBaseUrl="${useFullName ? (jobBaseUrl ? jobBaseUrl + job.parent.url : job.parent.url) : jobBaseUrl}"/>
</j:forEach>
</table>
<t:iconSize><t:rssBar/></t:iconSize>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册