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> |     <dependency> | ||||||
|       <groupId>org.kohsuke.stapler</groupId> |       <groupId>org.kohsuke.stapler</groupId> | ||||||
|       <artifactId>stapler-adjunct-timeline</artifactId> |       <artifactId>stapler-adjunct-timeline</artifactId> | ||||||
|       <version>1.0</version> |       <version>1.1</version> | ||||||
|     </dependency> |     </dependency> | ||||||
|     <dependency><!-- this helps us see the source code of the control while we edit Hudson. --> |     <dependency><!-- this helps us see the source code of the control while we edit Hudson. --> | ||||||
|       <groupId>org.kohsuke.stapler</groupId> |       <groupId>org.kohsuke.stapler</groupId> | ||||||
|  |  | ||||||
|  | @ -55,7 +55,6 @@ import hudson.util.ShiftedCategoryAxis; | ||||||
| import hudson.util.StackedAreaRenderer2; | import hudson.util.StackedAreaRenderer2; | ||||||
| import hudson.util.TextFile; | import hudson.util.TextFile; | ||||||
| import hudson.util.Graph; | import hudson.util.Graph; | ||||||
| import hudson.util.TimeUnit2; |  | ||||||
| import hudson.widgets.HistoryWidget; | import hudson.widgets.HistoryWidget; | ||||||
| import hudson.widgets.Widget; | import hudson.widgets.Widget; | ||||||
| import hudson.widgets.HistoryWidget.Adapter; | import hudson.widgets.HistoryWidget.Adapter; | ||||||
|  | @ -68,15 +67,16 @@ import java.io.StringWriter; | ||||||
| import java.io.PrintWriter; | import java.io.PrintWriter; | ||||||
| import java.net.URLEncoder; | import java.net.URLEncoder; | ||||||
| import java.text.ParseException; | import java.text.ParseException; | ||||||
|  | import java.util.AbstractList; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
|  | import java.util.Comparator; | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.SortedMap; | import java.util.SortedMap; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.concurrent.TimeUnit; |  | ||||||
| 
 | 
 | ||||||
| import javax.servlet.ServletException; | import javax.servlet.ServletException; | ||||||
| import javax.xml.transform.Transformer; | 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.StreamResult; | ||||||
| import javax.xml.transform.stream.StreamSource; | import javax.xml.transform.stream.StreamSource; | ||||||
| 
 | 
 | ||||||
| import net.sf.json.JSONArray; |  | ||||||
| import net.sf.json.JSONObject; | import net.sf.json.JSONObject; | ||||||
| import net.sf.json.JSONException; | import net.sf.json.JSONException; | ||||||
| 
 | 
 | ||||||
|  | @ -109,6 +108,8 @@ import org.kohsuke.stapler.WebMethod; | ||||||
| import org.kohsuke.stapler.export.Exported; | import org.kohsuke.stapler.export.Exported; | ||||||
| import org.kohsuke.args4j.Argument; | import org.kohsuke.args4j.Argument; | ||||||
| import org.kohsuke.args4j.CmdLineException; | 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. |  * 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); |         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 |     @CLIResolver | ||||||
|     public RunT getBuildForCLI(@Argument(required=true,metaVar="BUILD#",usage="Build number") String id) throws CmdLineException { |     public RunT getBuildForCLI(@Argument(required=true,metaVar="BUILD#",usage="Build number") String id) throws CmdLineException { | ||||||
|         try { |         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); |         return Hudson.getInstance().getAuthorizationStrategy().getACL(this); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void doTimelineData(@QueryParameter long min, @QueryParameter long max, StaplerResponse rsp) throws IOException { |     public TimelineEventList doTimelineData(StaplerRequest req, @QueryParameter long min, @QueryParameter long max) throws IOException { | ||||||
|         Date l = new Date(min); |         TimelineEventList result = new TimelineEventList(); | ||||||
|         Date h = new Date(max); |         for (RunT r : getBuildsByTimestamp(min,max)) { | ||||||
|         List<Event> result = new ArrayList<Event>(); |  | ||||||
|         for (int i=0; i<10; i++) { |  | ||||||
|             Event e = new Event(); |             Event e = new Event(); | ||||||
|             e.start = new Date(min+ TimeUnit2.HOURS.toMillis(i)); |             e.start = r.getTime(); | ||||||
|             e.title = "Event "+i; |             e.end   = new Date(r.timestamp+r.getDuration()); | ||||||
|             e.description = "Longish description of event "+i; |             e.title = r.getFullDisplayName(); | ||||||
|             JSONObject.fromObject(e); |             // 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); |             result.add(e); | ||||||
|         } |         } | ||||||
|         JSONObject o = new JSONObject(); |         return result; | ||||||
|         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; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -32,28 +32,6 @@ THE SOFTWARE. | ||||||
|       <div id="tl" style="height:500px; border:1px solid black;" /> |       <div id="tl" style="height:500px; border:1px solid black;" /> | ||||||
|       <div id="status" /> |       <div id="status" /> | ||||||
|       <script><![CDATA[ |       <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() { |         window.addEventListener('load', function() { | ||||||
|             var tl_el = document.getElementById("tl"); |             var tl_el = document.getElementById("tl"); | ||||||
|             var eventSource1 = new Timeline.DefaultEventSource(); |             var eventSource1 = new Timeline.DefaultEventSource(); | ||||||
|  | @ -61,6 +39,7 @@ THE SOFTWARE. | ||||||
|             var interval = 24*60*60*1000; |             var interval = 24*60*60*1000; | ||||||
|             eventSource1.ensureVisible = function(band) { |             eventSource1.ensureVisible = function(band) { | ||||||
|               // make sure all data are loaded for the portion visible in the 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 min = Math.floor(band.getMinDate().getTime()/interval); | ||||||
|               var max = Math.ceil(band.getMaxDate().getTime()/interval); |               var max = Math.ceil(band.getMaxDate().getTime()/interval); | ||||||
|               for (var i=min; i<=max; i++) { |               for (var i=min; i<=max; i++) { | ||||||
|  | @ -70,7 +49,11 @@ THE SOFTWARE. | ||||||
|                       method:"POST", |                       method:"POST", | ||||||
|                       parameters: {min: i*interval, max:(i+1)*interval}, |                       parameters: {min: i*interval, max:(i+1)*interval}, | ||||||
|                       onSuccess: function(t) { |                       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. | //            theme1.autoWidth = true; // Set the Timeline's "width" automatically. | ||||||
|                                      // Set autoWidth on the Timeline's first band's theme, |                                      // Set autoWidth on the Timeline's first band's theme, | ||||||
|                                      // will affect all bands. |                                      // will affect all bands. | ||||||
|             theme1.timeline_start = new Date(Date.UTC(1890, 0, 1)); |             theme1.timeline_start = new Date(${it.firstBuild.timeInMillis-24*60*60*1000}); | ||||||
|             theme1.timeline_stop  = new Date(Date.UTC(2160, 0, 1)); |             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 = [ |             var bandInfos = [ | ||||||
|                 // the bar that shows outline |                 // the bar that shows outline | ||||||
|                 Timeline.createBandInfo({ |                 Timeline.createBandInfo({ | ||||||
|  | @ -110,18 +93,15 @@ THE SOFTWARE. | ||||||
|             bandInfos[0].syncWith = 1; |             bandInfos[0].syncWith = 1; | ||||||
| 
 | 
 | ||||||
|             // create the Timeline |             // 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); |                 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 |             tl.layout(); // display the Timeline | ||||||
|         },false); |  | ||||||
| 
 | 
 | ||||||
|  |             // if resized, redo layout | ||||||
|             var resizeTimerID = null; |             var resizeTimerID = null; | ||||||
|             window.addEventListener('resize',function() { |             window.addEventListener('resize',function() { | ||||||
|                 if (resizeTimerID == null) { |                 if (resizeTimerID == null) { | ||||||
|  | @ -131,6 +111,7 @@ THE SOFTWARE. | ||||||
|                     }, 500); |                     }, 500); | ||||||
|                 } |                 } | ||||||
|             },false); |             },false); | ||||||
|  |         },false); | ||||||
|       ]]></script> |       ]]></script> | ||||||
|     </l:main-panel> |     </l:main-panel> | ||||||
| 	</l:layout> | 	</l:layout> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue