Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/publisher'
Browse files Browse the repository at this point in the history
  • Loading branch information
kohsuke committed Apr 26, 2012
2 parents 35de7e7 + 58267c4 commit 749f4ff
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 16 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/Project.java
Expand Up @@ -195,7 +195,7 @@ protected void submit( StaplerRequest req, StaplerResponse rsp ) throws IOExcept

buildWrappers.rebuild(req,json, BuildWrappers.getFor(this));
builders.rebuildHetero(req,json, Builder.all(), "builder");
publishers.rebuild(req, json, BuildStepDescriptor.filter(Publisher.all(), this.getClass()));
publishers.rebuildHetero(req, json, Publisher.all(), "publisher");
}

@Override
Expand Down
16 changes: 13 additions & 3 deletions core/src/main/resources/lib/form/hetero-list.jelly
Expand Up @@ -52,6 +52,16 @@ THE SOFTWARE.
For each item, add a caption from descriptor.getDisplayName().
This also activates drag&drop (where the header is a grip), and help text support.
</st:attribute>
<st:attribute name="oneEach">
If true, only allow up to one instance per descriptor.
</st:attribute>
<st:attribute name="menuAlign">
Menu alignment against the button. Defaults to tl-bl
</st:attribute>
<st:attribute name="honorOrder">
If true, insert new addition by default to their 'desired' location, which
is the order induced by the descriptors.
</st:attribute>
</st:documentation>
<d:taglib uri="local">
<d:tag name="body">
Expand Down Expand Up @@ -90,12 +100,12 @@ THE SOFTWARE.
</d:taglib>

<j:set var="targetType" value="${attrs.targetType?:it.class}"/>
<div class="hetero-list-container${hasHeader?' with-drag-drop':''}">
<div class="hetero-list-container ${hasHeader?'with-drag-drop':''} ${attrs.oneEach?'one-each':''} ${attrs.honorOrder?'honor-order':''}">
<!-- display existing items -->
<j:forEach var="i" items="${attrs.items}">
<j:set var="descriptor" value="${i.descriptor}" />
<j:set var="instance" value="${i}" />
<div name="${attrs.name}" class="repeated-chunk">
<div name="${attrs.name}" class="repeated-chunk" descriptorId="${descriptor.id}">
<local:body deleteCaption="${attrs.deleteCaption}">
<st:include from="${descriptor}" page="${descriptor.configPage}" optional="true" />
</local:body>
Expand All @@ -121,7 +131,7 @@ THE SOFTWARE.
</div>

<div>
<input type="button" value="${attrs.addCaption?:'%Add'}" class="hetero-list-add" />
<input type="button" value="${attrs.addCaption?:'%Add'}" class="hetero-list-add" menualign="${attrs.menuAlign}"/>
</div>
</div>
</j:jelly>
14 changes: 11 additions & 3 deletions core/src/main/resources/lib/hudson/project/config-publishers.jelly
Expand Up @@ -27,7 +27,15 @@ 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:p="/lib/hudson/project">
<f:descriptorList title="${%Post-build Actions}"
descriptors="${h.getPublisherDescriptors(it)}"
instances="${it.publishers}" />
<f:section title="${%Post-build Actions}">
<f:block>
<f:hetero-list name="publisher" hasHeader="true"
descriptors="${h.getPublisherDescriptors(it)}"
items="${it.publishersList}"
oneEach="true"
menuAlign="bl-tl"
honorOrder="true"
addCaption="${%Add post-build action}"/>
</f:block>
</f:section>
</j:jelly>
142 changes: 133 additions & 9 deletions war/src/main/webapp/scripts/hudson-behavior.js
Expand Up @@ -510,6 +510,7 @@ var jenkinsRules = {
// other behavior rules change them (like YUI buttons.)

"DIV.hetero-list-container" : function(e) {
e=$(e);
if(isInsideRemovable(e)) return;

// components for the add button
Expand Down Expand Up @@ -537,24 +538,84 @@ var jenkinsRules = {

var withDragDrop = initContainerDD(e);

var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu });
var menuAlign = (btn.getAttribute("menualign")||"tl-bl");

var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu, menualignment: menuAlign.split("-") });
menuButton.getMenu().clickEvent.subscribe(function(type,args,value) {
var t = templates[parseInt(args[1].value)]; // where this args[1] comes is a real mystery
var item = args[1];
if (item.cfg.getProperty("disabled")) return;
var t = templates[parseInt(item.value)];

var nc = document.createElement("div");
nc.className = "repeated-chunk";
nc.setAttribute("name",t.name);
nc.setAttribute("descriptorId",t.descriptorId);
nc.innerHTML = t.html;
$(nc).setOpacity(0);

var scroll = document.body.scrollTop;

renderOnDemand(findElementsBySelector(nc,"TR.config-page")[0],function() {
insertionPoint.parentNode.insertBefore(nc, insertionPoint);
function findInsertionPoint() {
// given the element to be inserted 'prospect',
// and the array of existing items 'current',
// and preferred ordering function, return the position in the array
// the prospect should be inserted.
// (for example 0 if it should be the first item)
function findBestPosition(prospect,current,order) {
function desirability(pos) {
var count=0;
for (var i=0; i<current.length; i++) {
if ((i<pos) == (order(current[i])<=order(prospect)))
count++;
}
return count;
}

var bestScore = -1;
var bestPos = 0;
for (var i=0; i<=current.length; i++) {
var d = desirability(i);
if (bestScore<=d) {// prefer to insert them toward the end
bestScore = d;
bestPos = i;
}
}
return bestPos;
}

var current = e.childElements().findAll(function(e) {return e.match("DIV.repeated-chunk")});

function o(did) {
if (Object.isElement(did))
did = did.getAttribute("descriptorId");
for (var i=0; i<templates.length; i++)
if (templates[i].descriptorId==did)
return i;
return 0; // can't happen
}

var bestPos = findBestPosition(t.descriptorId, current, o);
if (bestPos<current.length)
return current[bestPos];
else
return insertionPoint;
}
(e.hasClassName("honor-order") ? findInsertionPoint() : insertionPoint).insert({before:nc});

if(withDragDrop) prepareDD(nc);

new YAHOO.util.Anim(nc, {
opacity: { to:1 }
}, 0.2, YAHOO.util.Easing.easeIn).animate();

Behaviour.applySubtree(nc,true);
ensureVisible(nc);
layoutUpdateCallback.call();
},true);
});

menuButton.getMenu().renderEvent.subscribe(function(type,args,value) {
menuButton.getMenu().renderEvent.subscribe(function() {
// hook up tooltip for menu items
var items = menuButton.getMenu().getItems();
for(i=0; i<items.length; i++) {
Expand All @@ -563,6 +624,20 @@ var jenkinsRules = {
applyTooltip(items[i].element,t);
}
});

if (e.hasClassName("one-each")) {
// does this container already has a ocnfigured instance of the specified descriptor ID?
function has(id) {
return Prototype.Selector.find(e.childElements(),"DIV.repeated-chunk[descriptorId=\""+id+"\"]")!=null;
}

menuButton.getMenu().showEvent.subscribe(function() {
var items = menuButton.getMenu().getItems();
for(i=0; i<items.length; i++) {
items[i].cfg.setProperty("disabled",has(templates[i].descriptorId));
}
});
}
},

"DIV.repeated-container" : function(e) {
Expand Down Expand Up @@ -1846,10 +1921,17 @@ var repeatableSupport = {
// called when 'delete' button is clicked
onDelete : function(n) {
n = findAncestorClass(n,"repeated-chunk");
var p = n.parentNode;
p.removeChild(n);
if (p.tag)
p.tag.update();
var a = new YAHOO.util.Anim(n, {
opacity: { to:0 },
height: {to:0 }
}, 0.2, YAHOO.util.Easing.easeIn);
a.onComplete.subscribe(function() {
var p = n.parentNode;
p.removeChild(n);
if (p.tag)
p.tag.update();
});
a.animate();
},

// called when 'add' button is clicked
Expand Down Expand Up @@ -1980,7 +2062,49 @@ function getStyle(e,a){
if(e.currentStyle)
return e.currentStyle[a];
return null;
};
}

/**
* Makes sure the given element is within the viewport.
*
* @param {HTMLElement} e
* The element to bring into the viewport.
*/
function ensureVisible(e) {
var viewport = YAHOO.util.Dom.getClientRegion();
var pos = YAHOO.util.Dom.getRegion(e);

var Y = viewport.top;
var H = viewport.height;

function handleStickers(name,f) {
var e = $(name);
if (e) f(e);
document.getElementsBySelector("."+name).each(f);
}

// if there are any stickers around, subtract them from the viewport
handleStickers("top-sticker",function (t) {
t = t.clientHeight;
Y+=t; H-=t;
});

handleStickers("bottom-sticker",function (b) {
b = b.clientHeight;
H-=b;
});

var y = pos.top;
var h = pos.height;

var d = (y+h)-(Y+H);
if (d>0) {
document.body.scrollTop += d;
} else {
var d = Y-y;
if (d>0) document.body.scrollTop -= d;
}
}

// set up logic behind the search box
function createSearchBox(searchURL) {
Expand Down

0 comments on commit 749f4ff

Please sign in to comment.