提交 43791a1a 编写于 作者: K kohsuke

Integrated a newer timeline component.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@25557 71c3de6d-444a-0410-be80-ed276b4c234a
上级 df0170ec
......@@ -352,7 +352,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>stapler-adjunct-timeline</artifactId>
<version>1.0</version>
<version>1.1</version>
</dependency>
<dependency><!-- this helps us see the source code of the control while we edit Hudson. -->
<groupId>org.kohsuke.stapler</groupId>
......
......@@ -55,7 +55,6 @@ import hudson.util.ShiftedCategoryAxis;
import hudson.util.StackedAreaRenderer2;
import hudson.util.TextFile;
import hudson.util.Graph;
import hudson.util.TimeUnit2;
import hudson.widgets.HistoryWidget;
import hudson.widgets.Widget;
import hudson.widgets.HistoryWidget.Adapter;
......@@ -68,15 +67,16 @@ import java.io.StringWriter;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.xml.transform.Transformer;
......@@ -85,7 +85,6 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONException;
......@@ -109,6 +108,8 @@ import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.koshuke.stapler.simile.timeline.Event;
import org.koshuke.stapler.simile.timeline.TimelineEventList;
/**
* A job is an runnable entity under the monitoring of Hudson.
......@@ -621,6 +622,38 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
return _getRuns().get(n);
}
/**
* Obtains a list of builds, in the descending order, that are within the specified time range [start,end).
*
* @return can be empty but never null.
*/
public List<RunT> getBuildsByTimestamp(long start, long end) {
final List<RunT> builds = getBuilds();
AbstractList<Long> TIMESTAMP_ADAPTER = new AbstractList<Long>() {
public Long get(int index) {
return builds.get(index).timestamp;
}
public int size() {
return builds.size();
}
};
Comparator<Long> DESCENDING_ORDER = new Comparator<Long>() {
public int compare(Long o1, Long o2) {
if (o1 > o2) return -1;
if (o1 < o2) return +1;
return 0;
}
};
int s = Collections.binarySearch(TIMESTAMP_ADAPTER, start, DESCENDING_ORDER);
if (s<0) s=-(s+1); // min is inclusive
int e = Collections.binarySearch(TIMESTAMP_ADAPTER, end, DESCENDING_ORDER);
if (e<0) e=-(e+1); else e++; // max is exclusive, so the exact match should be excluded
return builds.subList(e,s);
}
@CLIResolver
public RunT getBuildForCLI(@Argument(required=true,metaVar="BUILD#",usage="Build number") String id) throws CmdLineException {
try {
......@@ -1285,27 +1318,22 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
return Hudson.getInstance().getAuthorizationStrategy().getACL(this);
}
public void doTimelineData(@QueryParameter long min, @QueryParameter long max, StaplerResponse rsp) throws IOException {
Date l = new Date(min);
Date h = new Date(max);
List<Event> result = new ArrayList<Event>();
for (int i=0; i<10; i++) {
public TimelineEventList doTimelineData(StaplerRequest req, @QueryParameter long min, @QueryParameter long max) throws IOException {
TimelineEventList result = new TimelineEventList();
for (RunT r : getBuildsByTimestamp(min,max)) {
Event e = new Event();
e.start = new Date(min+ TimeUnit2.HOURS.toMillis(i));
e.title = "Event "+i;
e.description = "Longish description of event "+i;
JSONObject.fromObject(e);
e.start = r.getTime();
e.end = new Date(r.timestamp+r.getDuration());
e.title = r.getFullDisplayName();
// what to put in the description?
// e.description = "Longish description of event "+r.getFullDisplayName();
// e.durationEvent = true;
e.link = req.getContextPath()+'/'+r.getUrl();
BallColor c = r.getIconColor();
e.color = String.format("#%06X",c.getBaseColor().darker().getRGB()&0xFFFFFF);
e.classname = "event-"+c.noAnime().toString()+" " + (c.isAnimated()?"animated":"");
result.add(e);
}
JSONObject o = new JSONObject();
o.put("events", JSONArray.fromObject(result));
rsp.setContentType("application/javascript;charset=UTF-8");
o.write(rsp.getWriter());
}
public static final class Event {
public Date start;
public Date end;
public String title, description;
return result;
}
}
......@@ -32,28 +32,6 @@ THE SOFTWARE.
<div id="tl" style="height:500px; border:1px solid black;" />
<div id="status" />
<script><![CDATA[
var timeline_data = { // save as a global variable
'dateTimeFormat': 'iso8601',
'events' : [
{'start': '1924',
'title': 'Barfusserkirche',
'description': 'by Lyonel Feininger, American/German Painter, 1871-1956',
'image': 'http://images.allposters.com/images/AWI/NR096_b.jpg',
'link': 'http://www.allposters.com/-sp/Barfusserkirche-1924-Posters_i1116895_.htm'
},
{'start': '1900',
'end': '1913',
'title': 'Three Figures',
'description': 'by Kasimir Malevich, Ukrainian Painter, 1878-1935',
'image': 'http://images.allposters.com/images/BRGPOD/75857_b.jpg',
'link': 'http://www.allposters.com/-sp/Three-Figures-1913-28-Posters_i1349989_.htm'
}
]};
var tl;
window.addEventListener('load', function() {
var tl_el = document.getElementById("tl");
var eventSource1 = new Timeline.DefaultEventSource();
......@@ -61,6 +39,7 @@ THE SOFTWARE.
var interval = 24*60*60*1000;
eventSource1.ensureVisible = function(band) {
// make sure all data are loaded for the portion visible in the band
// $('status').innerHTML = "min="+band.getMinDate()+" max="+band.getMaxDate();
var min = Math.floor(band.getMinDate().getTime()/interval);
var max = Math.ceil(band.getMaxDate().getTime()/interval);
for (var i=min; i<=max; i++) {
......@@ -70,7 +49,11 @@ THE SOFTWARE.
method:"POST",
parameters: {min: i*interval, max:(i+1)*interval},
onSuccess: function(t) {
eventSource1.loadJSON(eval(t.responseText));
try {
eventSource1.loadJSON(eval('('+t.responseText+')'),'.');
} catch (e) {
alert(e);
}
}
});
}
......@@ -82,10 +65,10 @@ THE SOFTWARE.
// theme1.autoWidth = true; // Set the Timeline's "width" automatically.
// Set autoWidth on the Timeline's first band's theme,
// will affect all bands.
theme1.timeline_start = new Date(Date.UTC(1890, 0, 1));
theme1.timeline_stop = new Date(Date.UTC(2160, 0, 1));
theme1.timeline_start = new Date(${it.firstBuild.timeInMillis-24*60*60*1000});
theme1.timeline_stop = new Date(${it.lastBuild.timeInMillis+24*60*60*1000});
var d = Timeline.DateTime.parseGregorianDateTime("1900")
var d = theme1.timeline_stop;
var bandInfos = [
// the bar that shows outline
Timeline.createBandInfo({
......@@ -110,18 +93,15 @@ THE SOFTWARE.
bandInfos[0].syncWith = 1;
// create the Timeline
tl = Timeline.create(tl_el, bandInfos, Timeline.HORIZONTAL);
var tl = Timeline.create(tl_el, bandInfos, Timeline.HORIZONTAL);
tl.getBand(1).addOnScrollListener(function(band) {
tl.getBand(0).addOnScrollListener(function(band) {
eventSource1.ensureVisible(band);
});
var url = '.'; // The base url for image, icon and background image
// references in the data
eventSource1.loadJSON(timeline_data, url);
tl.layout(); // display the Timeline
},false);
// if resized, redo layout
var resizeTimerID = null;
window.addEventListener('resize',function() {
if (resizeTimerID == null) {
......@@ -131,6 +111,7 @@ THE SOFTWARE.
}, 500);
}
},false);
},false);
]]></script>
</l:main-panel>
</l:layout>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册