mirror of https://github.com/jenkinsci/jenkins.git
Integrated a newer timeline component.
git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@25557 71c3de6d-444a-0410-be80-ed276b4c234a
This commit is contained in:
parent
df0170ec87
commit
43791a1a35
|
|
@ -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,26 +93,24 @@ 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);
|
||||
|
||||
var resizeTimerID = null;
|
||||
window.addEventListener('resize',function() {
|
||||
if (resizeTimerID == null) {
|
||||
resizeTimerID = window.setTimeout(function() {
|
||||
resizeTimerID = null;
|
||||
tl.layout();
|
||||
}, 500);
|
||||
}
|
||||
// if resized, redo layout
|
||||
var resizeTimerID = null;
|
||||
window.addEventListener('resize',function() {
|
||||
if (resizeTimerID == null) {
|
||||
resizeTimerID = window.setTimeout(function() {
|
||||
resizeTimerID = null;
|
||||
tl.layout();
|
||||
}, 500);
|
||||
}
|
||||
},false);
|
||||
},false);
|
||||
]]></script>
|
||||
</l:main-panel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue