source: trunk/www/views/jobs/view_job.jsp @ 4890

Last change on this file since 4890 was 4890, checked in by Nicklas Nordborg, 14 years ago

Fixes #1292: Use colours when reporting job status in a pop-up

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 17.3 KB
Line 
1<%-- $Id: view_job.jsp 4890 2009-04-07 07:03:55Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2005 Nicklas Nordborg
4  Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg, Gregory Vincic
5  Copyright (C) 2007 Nicklas Nordborg
6
7  This file is part of BASE - BioArray Software Environment.
8  Available at http://base.thep.lu.se/
9
10  BASE is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License
12  as published by the Free Software Foundation; either version 3
13  of the License, or (at your option) any later version.
14
15  BASE is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with BASE. If not, see <http://www.gnu.org/licenses/>.
22  ------------------------------------------------------------------
23
24  @author Nicklas
25  @version 2.0
26--%>
27<%@ page session="false"
28  import="net.sf.basedb.core.SessionControl"
29  import="net.sf.basedb.core.DbControl"
30  import="net.sf.basedb.core.SystemItems"
31  import="net.sf.basedb.core.Item"
32  import="net.sf.basedb.core.ItemContext"
33  import="net.sf.basedb.core.Permission"
34  import="net.sf.basedb.core.Job"
35  import="net.sf.basedb.core.JobAgent"
36  import="net.sf.basedb.core.BasicItem"
37  import="net.sf.basedb.core.Nameable"
38  import="net.sf.basedb.core.File"
39  import="net.sf.basedb.core.Path"
40  import="net.sf.basedb.core.User"
41  import="net.sf.basedb.core.ItemQuery"
42  import="net.sf.basedb.core.ItemResultList"
43  import="net.sf.basedb.core.PermissionDeniedException"
44  import="net.sf.basedb.core.PluginDefinition"
45  import="net.sf.basedb.core.PluginConfiguration"
46  import="net.sf.basedb.core.ParameterInfo"
47  import="net.sf.basedb.core.plugin.GuiContext"
48  import="net.sf.basedb.core.plugin.Plugin"
49  import="net.sf.basedb.core.signal.SignalTransporter"
50  import="net.sf.basedb.core.signal.Signal"
51  import="net.sf.basedb.plugins.util.Parameters"
52  import="net.sf.basedb.clients.web.Base"
53  import="net.sf.basedb.clients.web.util.HTML"
54  import="net.sf.basedb.util.Values"
55  import="net.sf.basedb.util.formatter.Formatter"
56  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
57  import="java.util.Date"
58  import="java.util.Map"
59  import="java.util.Set"
60  import="java.util.List"
61  import="java.util.Collections"
62  import="java.util.Collection"
63%>
64<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
65<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
66<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
67<%!
68  private static final Item itemType = Item.JOB;
69  private static final GuiContext guiContext = new GuiContext(itemType, GuiContext.Type.ITEM);
70%>
71<%
72final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
73final String ID = sc.getId();
74final ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, null);
75final int itemId = cc.getId();
76final String tab = Values.getString(request.getParameter("tab"), "properties");
77final float scale = Base.getScale(sc);
78final DbControl dc = sc.newDbControl();
79try
80{
81  Job job = Job.getById(dc, itemId);
82  String title = "View job -- " + HTML.encodeTags(job.getName());
83 
84  final boolean writePermission = job.hasPermission(Permission.WRITE);
85  final boolean deletePermission = job.hasPermission(Permission.DELETE);
86  final boolean isRemoved = job.isRemoved();
87  final boolean isUsed = isRemoved && job.isUsed();
88  final boolean deletePermanentlyPermission = deletePermission && !isUsed;
89 
90  boolean readCurrentConfig = true;
91  PluginConfiguration currentConfig = null;
92  try
93  {
94    currentConfig = job.getPluginConfiguration();
95  }
96  catch (PermissionDeniedException ex)
97  {
98    readCurrentConfig = false;
99  }
100  boolean readAgent = true;
101  JobAgent agent = null;
102  try
103  {
104    agent = job.getJobAgent();
105  }
106  catch (PermissionDeniedException ex)
107  {
108    readAgent = false;
109  }
110
111  int parameterVersion = job.getParameterVersion();
112  int latestParameterVersion = currentConfig == null ? parameterVersion : currentConfig.getParameterVersion();
113
114  final Job.Status status = job.getStatus();
115  final boolean autoUpdate = status == Job.Status.WAITING || 
116    status == Job.Status.PREPARED || status == Job.Status.EXECUTING || status == Job.Status.ABORTING;
117  Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
118  Formatter<Date> dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
119  Set<String> jobParameters = job.getParameterNames();
120  File logFile = null;
121  if (!autoUpdate && jobParameters != null && jobParameters.contains(Parameters.LOGFILE_PARAMETER))
122  {
123    try
124    {
125      Object temp = job.getParameterValue(Parameters.LOGFILE_PARAMETER);
126      if (temp instanceof File)
127      {
128        logFile = (File)temp;
129      }
130      else if (temp instanceof String)
131      {
132        logFile = File.getByPath(dc, new Path((String)temp, Path.Type.FILE), false);
133      }
134    }
135    catch (Throwable t)
136    {}
137  }
138 
139  // Check if the plug-in supports the "Abort" signal
140  boolean supportsAbort = status == Job.Status.WAITING && writePermission;
141  if (status == Job.Status.EXECUTING && writePermission)
142  {
143    try
144    {
145      SignalTransporter signalTransporter = job.getSignalTransporter();
146      Collection<Signal> supportedSignals = signalTransporter != null ? 
147        signalTransporter.getSupportedSignals() : null;
148      supportsAbort = signalTransporter != null && 
149        (supportedSignals == null || supportedSignals.contains(Signal.ABORT));
150    }
151    catch (Exception ex)
152    {}
153  }
154  %>
155
156  <base:page type="popup" title="<%=title%>"> 
157  <base:head scripts="tabcontrol.js" styles="tabcontrol.css,progressbar.css">
158  <script language="JavaScript">
159  function autoUpdate()
160  {
161    var autoUpdate = <%=autoUpdate ? "true" : "false"%>;
162    if (autoUpdate)
163    {
164      setTimeout('location.reload()', 10000);
165    }
166  }
167  function abortJob()
168  {
169    if (confirm('Are you sure? This action may not be undone'))
170    {
171      location.href = 'index.jsp?ID=<%=ID%>&cmd=AbortJob&item_id=<%=itemId%>';
172    }
173  }
174  function restartJob(clearDryRun)
175  {
176    var parameterVersion = <%=parameterVersion%>;
177    var latestVersion = <%=latestParameterVersion%>;
178    var useLatestConfiguration = 0;
179    if (parameterVersion != latestVersion)
180    {
181      var msg = 'The configuration parameters for the plugin has changed since\n';
182      msg += 'the job was added to the job queue. Do you want to use the new\n';
183      msg += 'configuration parameters?\n\n';
184      msg += 'Ok / Yes = Use the new parameters (version = '+latestVersion + ')\n';
185      msg += 'Cancel / No = Use the current parameters (version = ' + parameterVersion + ')';
186      if (confirm(msg)) useLatestConfiguration = 1;
187    }
188    var url = 'index.jsp?ID=<%=ID%>&cmd=RestartJob&item_id=<%=itemId%>';
189    url += '&useLatestConfiguration='+useLatestConfiguration;
190    if (clearDryRun) url += '&clearDryRun=' + clearDryRun;
191    location.href = url;
192  }
193  function reconfigureJob()
194  {
195    location.href = '../../common/plugin/index.jsp?ID=<%=ID%>&cmd=ConfigureJob&job_id=<%=itemId%>';
196  }
197 
198    function deleteItemPermanently()
199    {
200      Main.deleteItemPermanently('<%=ID%>', true, '<%=itemType.name()%>', <%=itemId%>, '&callback=itemDeleted');
201    }
202    function itemDeleted()
203    {
204      location.href = getRoot() + 'common/close_popup.jsp?ID=<%=ID%>&refresh_opener=1&wait=0';
205    }
206    function showUsingItems()
207    {
208      Main.showUsingItems('<%=ID%>', '<%=itemType.name()%>', <%=itemId%>);
209    }
210  </script>
211  </base:head>
212  <base:body onload="autoUpdate()">
213    <h3 class="docked"><%=title%> <base:help tabcontrol="main" /></h3>
214    <t:tabcontrol id="main" active="<%=tab%>" position="bottom" contentstyle="<%="height: "+(int)(scale*350)+"px;"%>">
215    <t:tab id="properties" title="Properties" helpid="job.view.properties">
216
217      <%
218      if (job.isRemoved())
219      {
220        %>
221        <div class="itemstatus">
222          <base:icon 
223            image="<%=deletePermanentlyPermission ? "deleted.gif" : "deleted_disabled.gif"%>"
224            onclick="<%=deletePermanentlyPermission ? "deleteItemPermanently()" : null%>"
225            tooltip="<%=deletePermanentlyPermission ? "Permanently delete this item" : null%>"
226            visible="<%=isRemoved%>"> This item has been flagged for deletion<br></base:icon>
227          <base:icon image="used.gif" 
228            onclick="showUsingItems()"
229            tooltip="Show the items that are using this one"
230            visible="<%=isUsed%>"> This item is used by other items and can't be permanently deleted<br></base:icon>
231        </div>
232        <%
233      }
234      %>
235      <table class="form" cellspacing=0>
236      <tr>
237        <td class="prompt">Name</td>
238        <td><%=HTML.encodeTags(job.getName())%></td>
239      </tr>
240      <tr>
241        <td class="prompt">Description</td>
242        <td><%=HTML.niceFormat(job.getDescription())%></td>
243      </tr>
244      <tr valign="top">
245        <td class="prompt">Priority</td>
246        <td>
247          <%=job.getPriority()%> (1 = highest, 10 = lowest)
248        </td>
249      </tr>
250      <tr valign="top">
251        <td class="prompt">Status</td>
252        <td <%=job.getStatus() == Job.Status.ERROR ? "class=\"error\" style=\"text-align: left;\"" : "" %>>
253          <%=job.getStatus()%><%=job.isDryRun() ? " (dry-run)" : "" %>: <%=HTML.niceFormat(job.getStatusMessage())%>
254        </td>
255      </tr>
256      <tr valign="middle">
257        <td class="prompt">Percent complete</td>
258        <td>
259          <table border=0 cellspacing=0 cellpadding=0>
260          <tr>
261          <td width="100" valign="middle">
262            <table width="100" class="progressbar" border=0 cellspacing=0 cellpadding=0>
263            <tr>
264              <%
265              int percent = job.getPercentComplete();
266              if (percent > 0) 
267              {
268                %>
269                <td width="<%=percent%>%" class="done">&nbsp;</td>
270                <% 
271              }
272              if (percent < 100) 
273              { 
274                %>
275                <td width="<%=100-percent%>%" class="remain">&nbsp;</td>
276                <%
277              }
278              %>
279            </tr>
280            </table>
281          </td>
282          <td valign="middle">&nbsp;<%=percent%>%</td>
283          <%
284          if (logFile != null)
285          {
286            %>
287            <td valign="middle" style="padding-left: 10px;"><base:button image="view.gif" 
288                title="View log&hellip;"
289                onclick="<%="Main.viewFile('" + ID + "', " + logFile.getId() + ")"%>"
290                tooltip="View the log file with detailed information about this job"
291                /></td>
292              <%
293            }
294            %>
295          </tr>
296          </table>
297        </td>
298      </tr>
299      <tr valign="top">
300        <td class="prompt">Created</td>
301        <td>
302          <%=dateTimeFormatter.format(job.getCreated())%>
303        </td>
304      </tr>
305      <tr valign="top">
306        <td class="prompt">Started</td>
307        <td>
308          <%=dateTimeFormatter.format(job.getStarted())%>
309        </td>
310      </tr>
311      <tr valign="top">
312        <td class="prompt">Ended</td>
313        <td>
314          <%=dateTimeFormatter.format(job.getEnded())%>
315        </td>
316      </tr>
317      <tr valign="top">
318        <td class="prompt">Running time</td>
319        <td>
320          <%
321          Date started = job.getStarted();
322          if (started != null)
323          {
324            Date ended = job.getEnded();
325            if (ended == null) ended = new Date();
326            long runningTime = ended.getTime() - started.getTime();
327            %>
328            <%=Values.formatTime(runningTime / 1000)%>
329            <%
330          }
331          %>
332        </td>
333      </tr>
334      <tr valign="top">
335        <td class="prompt">Server</td>
336        <td>
337          <%=HTML.encodeTags(job.getServer())%>
338        </td>
339      </tr>
340      <tr valign="top">
341        <td class="prompt">Job agent</td>
342        <td><%=Base.getEncodedName(agent, !readAgent)%></td>
343      </tr>
344      <tr valign="top">
345        <td class="prompt">User</td>
346        <td>
347          <base:propertyvalue item="<%=job%>" property="owner.name" />
348        </td>
349      </tr>
350      <tr valign="top">
351        <td class="prompt">Experiment</td>
352        <td>
353          <base:propertyvalue item="<%=job%>" property="experiment.name" />
354        </td>
355      </tr>
356      <tr valign="top">
357        <td class="prompt">Plugin</td>
358        <td>
359          <base:propertyvalue item="<%=job%>" property="pluginDefinition.name" /> 
360          <%=job.getPluginVersion() == null ?
361            "" : "(version " + HTML.encodeTags(job.getPluginVersion()) + ")"%>
362        </td>
363      </tr>
364      <tr valign="top">
365        <td class="prompt">Configuration</td>
366        <td>
367          <base:propertyvalue item="<%=job%>" property="pluginConfiguration.name" />
368        </td>
369      </tr>
370      </table>
371      </t:tab>
372      <%
373      if (job.getStackTrace() != null)
374      {
375        %>
376        <t:tab id="stacktrace" title="Stack trace" helpid="job.view.stacktrace">
377          <div style="font-family: monospace">
378          <%=HTML.niceFormat(job.getStackTrace())%>
379          </div>
380        </t:tab>
381        <%
382      }
383      %>
384 
385      <t:tab id="parameters" title="Parameters" helpid="job.view.parameters">
386        <h4>Job parameters</h4>
387        <table class="form" cellspacing=0>
388        <%
389        List<String> names = new java.util.ArrayList<String>(jobParameters);
390        Collections.sort(names);
391        for (String name : names)
392        {
393          StringBuilder sb = new StringBuilder();
394          String displayValue = "";
395          String description = "";
396          try
397          {
398            ParameterInfo pi = job.getParameterInfo(name);
399            if (pi.getLabel() != null) name = HTML.encodeTags(pi.getLabel());
400            description = HTML.encodeTags(pi.getDescription());
401            List<?> values = pi.getValues();
402            int i = 0;
403            for (Object value : values)
404            {
405              if (value != null)
406              {
407                if (i > 0) sb.append(", ");
408                i++;
409                if (value instanceof BasicItem)
410                {
411                  BasicItem item = (BasicItem)value;
412                  String itemName = "";
413                  if (item instanceof File)
414                  {
415                    itemName = ((File)item).getPath().toString();
416                  }
417                  else if (item instanceof Nameable)
418                  {
419                    itemName = ((Nameable)item).getName();
420                  }
421                  else
422                  {
423                    itemName = item.toString();
424                  }
425                  sb.append(HTML.encodeTags(itemName));
426                }
427                else if (value instanceof Date)
428                {
429                  sb.append(dateFormatter.format((Date)value));
430                }
431                else
432                {
433                  sb.append(HTML.encodeTags(value.toString()));
434                }
435              }
436            }
437            displayValue = sb.toString();
438          }
439          catch (Throwable ex)
440          {
441            displayValue = "<i>ERROR: "+ex.getMessage()+"</i>";
442          }
443          %>
444          <tr>
445            <td class="prompt"><span title="<%=description%>"><%=name%></span></td>
446            <td>
447              <%=displayValue%>
448            </td>
449          </tr>
450          <%
451        }
452        %>
453        </table>
454
455        <%
456        if (!readCurrentConfig)
457        {
458          %>
459          <h4>Plugin configuration parameters</h4>
460          <i>- denied -</i>
461          <%
462        }
463        else if (currentConfig != null)
464        {
465          %>
466          <h4>Plugin configuration parameters</h4>
467          <table class="form" cellspacing=0>
468          <tr>
469            <td class="prompt"><span 
470              title="The version of the parmeters used for this job, current version in paranthesis">Parameter version</span></td>
471            <td><%=parameterVersion%> (<%=latestParameterVersion %>)</td>
472          </tr>
473          <%
474          names = new java.util.ArrayList<String>(currentConfig.getParameterNames(parameterVersion));
475          Collections.sort(names);
476          for (String name : names)
477          {
478            StringBuilder sb = new StringBuilder();
479            String displayValue = "";
480            String description = "";
481            try
482            {
483              ParameterInfo pi = currentConfig.getParameterInfo(name, parameterVersion);
484              if (pi.getLabel() != null) name = HTML.encodeTags(pi.getLabel());
485              description = HTML.encodeTags(pi.getDescription());
486              List<?> values = pi.getValues();
487              int i = 0;
488              for (Object value : values)
489              {
490                if (value != null)
491                {
492                  if (i > 0) sb.append(", ");
493                  i++;
494                  if (value instanceof BasicItem)
495                  {
496                    BasicItem item = (BasicItem)value;
497                    String itemName = "";
498                    if (item instanceof File)
499                    {
500                      itemName = ((File)item).getPath().toString();
501                    }
502                    else if (item instanceof Nameable)
503                    {
504                      itemName = ((Nameable)item).getName();
505                    }
506                    else
507                    {
508                      itemName = item.toString();
509                    }
510                    sb.append(HTML.encodeTags(itemName));
511                  }
512                  else if (value instanceof Date)
513                  {
514                    sb.append(dateFormatter.format((Date)value));
515                  }
516                  else
517                  {
518                    sb.append(HTML.encodeTags(value.toString()));
519                  }
520                }
521              }
522              displayValue = sb.toString();
523            }
524            catch (Throwable ex)
525            {
526              displayValue = "<i>ERROR: "+ex.getMessage()+"</i>";
527            }
528            %>
529            <tr>
530              <td class="prompt"><span title="<%=description%>"><%=name%></span></td>
531              <td>
532                <%=displayValue%>
533              </td>
534            </tr>
535            <%
536          }
537          %>
538          </table>
539          <%
540        }
541        %>
542       
543      </t:tab>
544      </t:tabcontrol>
545 
546    <base:buttongroup align="center">
547      <%
548      if (autoUpdate)
549      {
550        %>
551        <base:button onclick="location.reload()" title="Refresh" image="refresh.gif" />
552        <%
553      }
554      %>
555      <%
556      if (supportsAbort)
557      {
558        %>
559        <base:button onclick="abortJob()" title="Abort&hellip;" image="abort.png" />
560        <%
561      }
562      %>
563      <%
564      if (job.getStatus() == Job.Status.ERROR && job.getJobType() == Job.Type.RUN_PLUGIN)
565      {
566        %>
567        <base:button onclick="restartJob(0)" title="Restart job" 
568          image="refresh.gif" 
569          tooltip="Try to run this job again with the same parameters"
570        />
571        <base:button onclick="reconfigureJob()" title="Re-configure job"
572          image="runplugin.gif"
573          tooltip="Change the parameters for this job and try again"
574          visible="<%=job.hasContext()%>"
575        />
576        <%
577      }
578      if (job.getStatus() == Job.Status.DONE && job.isDryRun())
579      {
580        %>
581        <base:button onclick="restartJob(1)" title="Really run" 
582          image="refresh.gif" 
583          tooltip="Run this dry-run job for real"
584        />
585        <%
586      }
587      %>
588      <base:button onclick="window.close()" title="Close" />
589     
590    </base:buttongroup>
591    <center>
592    <%
593    if (autoUpdate)
594    {
595      %>
596      <i>(This page will automatically refresh itself every 10 seconds)</i>
597      <%
598    }
599    %></center>
600  </base:body>
601  </base:page>
602  <%
603}
604finally
605{
606  if (dc != null) dc.close();
607}
608
609%>
Note: See TracBrowser for help on using the repository browser.