Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-43507] Give traits dynamic section headers
  • Loading branch information
stephenc committed May 5, 2017
1 parent 5a06456 commit 9fb3797
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 4 deletions.
70 changes: 68 additions & 2 deletions src/main/java/jenkins/scm/impl/form/NamedArrayList.java
Expand Up @@ -26,15 +26,15 @@

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import jenkins.scm.api.FormTagLib;

/**
* An {@link ArrayList} that also has an associated name for use with the {@link FormTagLib#traits()} tag.
* An {@link ArrayList} that also has an associated name for use with the {@code FormTagLib.traits()} tag.
*
* @param <E> the type of element.
*/
Expand Down Expand Up @@ -139,6 +139,71 @@ public static <E> void select(@NonNull List<? extends E> source, @NonNull String
}
}

/**
* Combines {@link Predicate} instances using a boolean short-circuit logical AND.
*
* @param predicates the predicates to combine.
* @param <E> type.
* @return a composite predicate.
*/
public static <E> Predicate<E> allOf(final Predicate<? super E>... predicates) {
if (predicates.length < 2) {
throw new IllegalArgumentException("Must supply at least two predicates");
}
return new Predicate<E>() {
@Override
public boolean test(E e) {
for (Predicate<? super E> p : predicates) {
if (!p.test(e)) {
return false;
}
}
return true;
}
};
}

/**
* Combines {@link Predicate} instances using a boolean short-circuit logical OR.
*
* @param predicates the predicates to combine.
* @param <E> type.
* @return a composite predicate.
*/
public static <E> Predicate<E> anyOf(final Predicate<E>... predicates) {
if (predicates.length < 2) {
throw new IllegalArgumentException("Must supply at least two predicates");
}
return new Predicate<E>() {
@Override
public boolean test(E e) {
for (Predicate<? super E> p : predicates) {
if (p.test(e)) {
return true;
}
}
return false;
}
};
}

/**
* Returns a {@link Predicate} that checks if the object class has been annotated with the supplied
* annotation.
*
* @param annotation the annotation to check.
* @param <A> the type of annotation.
* @return the predicate.
*/
public static <A extends Annotation> Predicate<Object> withAnnotation(final Class<A> annotation) {
return new Predicate<Object>() {
@Override
public boolean test(Object o) {
return o.getClass().getAnnotation(annotation) != null;
}
};
}

/**
* Represents a predicate (boolean-valued function) of one argument.
*
Expand All @@ -152,4 +217,5 @@ public static <E> void select(@NonNull List<? extends E> source, @NonNull String
public interface Predicate<T> { // extends java.util.function.Predicate<T>
boolean test(T t);
}

}
51 changes: 51 additions & 0 deletions src/main/java/jenkins/scm/impl/trait/Discovery.java
@@ -0,0 +1,51 @@
/*
* The MIT License
*
* Copyright (c) 2017, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.scm.impl.trait;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.mixin.TagSCMHead;
import jenkins.scm.api.trait.SCMNavigatorTrait;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMTraitDescriptor;

/**
* Annotation to apply to {@link SCMTraitDescriptor} types that are control the initial scope of discovery. For example
* a {@link SCMSourceTrait} that will enable the discovery of {@link TagSCMHead} instances on its {@link SCMSource}
* or a {@link SCMNavigatorTrait} that will enable the discovery of projects from a "forks".
*
* @since 2.2.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Discovery {
}
Expand Up @@ -113,6 +113,7 @@ public boolean isExcluded(@NonNull SCMSource source, @NonNull SCMHead head) {
* Our descriptor.
*/
@Extension
@Selection
public static class DescriptorImpl extends SCMSourceTraitDescriptor {

/**
Expand Down
Expand Up @@ -112,6 +112,7 @@ public boolean isExcluded(@NonNull SCMNavigator source, @NonNull String projectN
* Our descriptor.
*/
@Extension
@Selection
public static class DescriptorImpl extends SCMNavigatorTraitDescriptor {

/**
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/jenkins/scm/impl/trait/Selection.java
@@ -0,0 +1,46 @@
/*
* The MIT License
*
* Copyright (c) 2017, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.scm.impl.trait;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import jenkins.scm.api.trait.SCMTraitDescriptor;

/**
* Annotation to apply to {@link SCMTraitDescriptor} types that are pure filters. These traits will restrict the
* effective discovery
*
* @since 2.2.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Selection {
}
Expand Up @@ -131,6 +131,7 @@ private String getPattern(String branches) {
* Our descriptor.
*/
@Extension
@Selection
public static class DescriptorImpl extends SCMSourceTraitDescriptor {

/**
Expand Down
Expand Up @@ -129,6 +129,7 @@ private String getPattern(String branches) {
* Our descriptor.
*/
@Extension
@Selection
public static class DescriptorImpl extends SCMNavigatorTraitDescriptor {

/**
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/jenkins/scm/api/form/traits.jelly
Expand Up @@ -96,7 +96,7 @@ THE SOFTWARE.
</j:invoke>
</j:if>
<j:set var="renderSections" value="${descriptorLists.size() &gt; 1}"/>
<div class="hetero-list-container with-drag-drop one-each honor-order">
<div class="hetero-list-container with-drag-drop one-each honor-order trait-container">
<!-- display existing items -->
<j:set var="instances"
value="${instance != null ? instance[attrs.field] : (attrs.default ?: descriptor[attrs.field+'Defaults'])}"/>
Expand Down Expand Up @@ -146,7 +146,7 @@ THE SOFTWARE.
</j:if>
<j:forEach var="descriptor" items="${filteredDescriptors}" varStatus="loop">
<div name="${attrs.field}" title="${descriptor.displayName}"
tooltip="${descriptor.tooltip?:'Why does nobody use me'}"
tooltip="${descriptor.tooltip}"
descriptorId="${descriptor.id}">
<j:set var="capture" value="${attrs.capture?:''}"/>
<local:body deleteCaption="${attrs.deleteCaption}">
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/jenkins/scm/api/form/traits/traits.css
Expand Up @@ -5,6 +5,10 @@ DIV.repeated-chunk.trait-section {
padding: 0.1em;
}

DIV.repeated-chunk.trait-section.trait-section-empty {
display: none;
}

SPAN.trait-section-header {
position: relative;
overflow: hidden;
Expand Down
50 changes: 50 additions & 0 deletions src/main/resources/jenkins/scm/api/form/traits/traits.js
@@ -0,0 +1,50 @@
(function () {
var traitSectionRule = function (e) {
e = $(e);
var p = $(e.previousSibling);
var n = $(e.nextSibling);
var empty = (!n || n.hasClassName("trait-section") || n.hasClassName("repeatable-insertion-point"));
// find any previous entries
while (p && p.hasClassName("trait-section")) {
p = $(p.previousSibling);
}
if (!empty) {
// skip our entries
while (n && !n.hasClassName("trait-section") && !n.hasClassName("repeatable-insertion-point")) {
n = $(n.nextSibling);
}
}
// find next section entries
while (n && n.hasClassName("trait-section") && !n.hasClassName("repeatable-insertion-point")) {
n = $(n.nextSibling);
}
if ((!p && n.hasClassName("repeatable-insertion-point")) || empty) {
e.addClassName("trait-section-empty");
} else {
e.removeClassName("trait-section-empty");
}
};
Behaviour.specify("DIV.trait-container", 'traits', -50, function (e) {
e = $(e);
if (isInsideRemovable(e)) {
return;
}
layoutUpdateCallback.add(function () {
findElementsBySelector(e, ".trait-section").each(traitSectionRule);
})
});
Behaviour.specify(".repeatable-delete", 'traits', 500, function (e) {
var c = findAncestorClass(e, "trait-container");
if (c) {
var btn = YAHOO.widget.Button.getButton(e.id);
if (btn) {
btn.on("click", function () {
window.setTimeout(function () {
findElementsBySelector(c, ".trait-section").each(traitSectionRule);
}, 250);
});
}
}
});
})();

0 comments on commit 9fb3797

Please sign in to comment.