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

Last change on this file since 5909 was 5909, checked in by Nicklas Nordborg, 10 years ago

References #1655: GUI improvements

  • Project dialog
  • Permission template dialog
  • Jobs dialog
  • Messages dialog
  • Session dialog
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 20.8 KB
Line 
1<%-- $Id: view_job.jsp 5909 2011-12-14 08:33:07Z 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 pageEncoding="UTF-8" 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.ChangeHistory"
42  import="net.sf.basedb.core.ItemResultIterator"
43  import="net.sf.basedb.core.ItemQuery"
44  import="net.sf.basedb.core.ItemResultList" 
45  import="net.sf.basedb.core.PermissionDeniedException"
46  import="net.sf.basedb.core.PluginDefinition"
47  import="net.sf.basedb.core.PluginConfiguration"
48  import="net.sf.basedb.core.PluginType"
49  import="net.sf.basedb.core.ParameterInfo"
50  import="net.sf.basedb.core.query.Orders"
51  import="net.sf.basedb.core.query.Hql"
52  import="net.sf.basedb.core.plugin.GuiContext"
53  import="net.sf.basedb.core.plugin.NonRestartable"
54  import="net.sf.basedb.core.plugin.Plugin"
55  import="net.sf.basedb.core.signal.SignalTransporter"
56  import="net.sf.basedb.core.signal.Signal"
57  import="net.sf.basedb.plugins.util.Parameters"
58  import="net.sf.basedb.clients.web.Base"
59  import="net.sf.basedb.clients.web.ChangeHistoryUtil"
60  import="net.sf.basedb.clients.web.util.HTML"
61  import="net.sf.basedb.util.Values"
62  import="net.sf.basedb.util.formatter.Formatter"
63  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
64  import="java.util.Date"
65  import="java.util.Map"
66  import="java.util.Set"
67  import="java.util.List"
68  import="java.util.Collections"
69  import="java.util.Collection"
70%>
71<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
72<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
73<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
74<%!
75  private static final Item itemType = Item.JOB;
76  private static final GuiContext guiContext = new GuiContext(itemType, GuiContext.Type.ITEM);
77
78  private String getItemName(BasicItem item)
79  {
80    String itemName = "";
81    if (item instanceof File)
82    {
83      itemName = ((File)item).getPath().toString();
84    }
85    else if (item instanceof Nameable)
86    {
87      itemName = ((Nameable)item).getName();
88    }
89    else
90    {
91      itemName = item.toString();
92    }
93    return itemName;
94  }
95%>
96<%
97final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
98final String ID = sc.getId();
99final ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, null);
100final int itemId = cc.getId();
101final String tab = Values.getString(request.getParameter("tab"), "properties");
102final float scale = Base.getScale(sc);
103final DbControl dc = sc.newDbControl();
104try
105{
106  Job job = Job.getById(dc, itemId);
107  String title = "View job -- " + HTML.encodeTags(job.getName());
108 
109  final boolean writePermission = job.hasPermission(Permission.WRITE);
110  final boolean deletePermission = job.hasPermission(Permission.DELETE);
111  final boolean isRemoved = job.isRemoved();
112  final boolean isUsed = isRemoved && job.isUsed();
113  final boolean deletePermanentlyPermission = deletePermission && !isUsed;
114 
115  boolean readCurrentConfig = true;
116  PluginConfiguration currentConfig = null;
117  try
118  {
119    currentConfig = job.getPluginConfiguration();
120  }
121  catch (PermissionDeniedException ex)
122  {
123    readCurrentConfig = false;
124  }
125  boolean readAgent = true;
126  JobAgent agent = null;
127  try
128  {
129    agent = job.getJobAgent();
130  }
131  catch (PermissionDeniedException ex)
132  {
133    readAgent = false;
134  }
135
136  int parameterVersion = job.getParameterVersion();
137  int latestParameterVersion = currentConfig == null ? parameterVersion : currentConfig.getParameterVersion();
138
139  final Job.Status status = job.getStatus();
140  final boolean autoUpdate = status == Job.Status.WAITING || 
141    status == Job.Status.PREPARED || status == Job.Status.EXECUTING || status == Job.Status.ABORTING;
142  Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
143  Formatter<Date> dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
144  Set<String> jobParameters = job.getParameterNames();
145  File logFile = null;
146  if (!autoUpdate && jobParameters != null && jobParameters.contains(Parameters.LOGFILE_PARAMETER))
147  {
148    try
149    {
150      Object temp = job.getParameterValue(Parameters.LOGFILE_PARAMETER);
151      if (temp instanceof File)
152      {
153        logFile = (File)temp;
154      }
155      else if (temp instanceof String)
156      {
157        logFile = File.getByPath(dc, new Path((String)temp, Path.Type.FILE), false);
158      }
159    }
160    catch (Throwable t)
161    {}
162  }
163 
164  // Check if the plug-in supports the "Abort" signal
165  boolean supportsAbort = status == Job.Status.WAITING && writePermission;
166  if (status == Job.Status.EXECUTING && writePermission)
167  {
168    try
169    {
170      SignalTransporter signalTransporter = job.getSignalTransporter();
171      Collection<Signal> supportedSignals = signalTransporter != null ? 
172        signalTransporter.getSupportedSignals() : null;
173      supportsAbort = signalTransporter != null && 
174        (supportedSignals == null || supportedSignals.contains(Signal.ABORT));
175    }
176    catch (Exception ex)
177    {}
178  }
179  %>
180  <base:page type="popup" title="<%=title%>"> 
181  <base:head scripts="tabcontrol.js,table.js,ajax.js,json2.js" styles="tabcontrol.css,progressbar.css,table.css">
182  <script language="JavaScript">
183  function autoUpdate()
184  {
185    var autoUpdate = <%=autoUpdate ? "true" : "false"%>;
186    if (autoUpdate) sendProgressUpdateRequest();
187  }
188  function abortJob()
189  {
190    if (confirm('Are you sure? This action may not be undone'))
191    {
192      location.href = 'index.jsp?ID=<%=ID%>&cmd=AbortJob&item_id=<%=itemId%>';
193    }
194  }
195  function restartJob(clearDryRun)
196  {
197    var parameterVersion = <%=parameterVersion%>;
198    var latestVersion = <%=latestParameterVersion%>;
199    var useLatestConfiguration = 0;
200    if (parameterVersion != latestVersion)
201    {
202      var msg = 'The configuration parameters for the plugin has changed since\n';
203      msg += 'the job was added to the job queue. Do you want to use the new\n';
204      msg += 'configuration parameters?\n\n';
205      msg += 'Ok / Yes = Use the new parameters (version = '+latestVersion + ')\n';
206      msg += 'Cancel / No = Use the current parameters (version = ' + parameterVersion + ')';
207      if (confirm(msg)) useLatestConfiguration = 1;
208    }
209    var url = 'index.jsp?ID=<%=ID%>&cmd=RestartJob&item_id=<%=itemId%>';
210    url += '&useLatestConfiguration='+useLatestConfiguration;
211    if (clearDryRun) url += '&clearDryRun=' + clearDryRun;
212    location.href = url;
213  }
214  function reconfigureJob()
215  {
216    location.href = '../../common/plugin/index.jsp?ID=<%=ID%>&cmd=ConfigureJob&job_id=<%=itemId%>';
217  }
218 
219    function deleteItemPermanently()
220    {
221      Main.deleteItemPermanently('<%=ID%>', true, '<%=itemType.name()%>', <%=itemId%>, '&callback=itemDeleted');
222    }
223    function itemDeleted()
224    {
225      location.href = getRoot() + 'common/close_popup.jsp?ID=<%=ID%>&refresh_opener=1&wait=0';
226    }
227    function showUsingItems()
228    {
229      Main.showUsingItems('<%=ID%>', '<%=itemType.name()%>', <%=itemId%>);
230    }
231   
232    var lastStatus = '<%=status.name()%>';
233    function sendProgressUpdateRequest()
234    {
235      var request = Ajax.getXmlHttpRequest();
236      var url = 'ajax.jsp?ID=<%=ID%>&cmd=GetProgress&item_id=<%=itemId%>&'+Math.random();
237      request.open("GET", url, true);
238      Ajax.setReadyStateHandler(request, progressUpdateCallback);
239      request.send(null);
240    }
241    function progressUpdateCallback(request)
242    {
243      var progress = Ajax.parseJsonResponse(request.responseText);
244      if (progress && progress.status == 'ok')
245      {
246        var status = progress.jobStatus;
247        var message = progress.message;
248        var percentComplete = progress.percentComplete;
249        var runningTime = progress.runningTime;
250       
251        if (lastStatus != status) location.reload();
252        if (status == 'EXECUTING')
253        {
254          displayProgress(percentComplete, message, runningTime);
255        }
256      }
257      setTimeout('sendProgressUpdateRequest()', 1500);
258    }
259
260    function displayProgress(percentDone, message, runningTime)
261    {
262      // Percent complete
263      var doneElement = document.getElementById('percentDone');
264      var remainElement = document.getElementById('percentRemain');
265      var unknownElement = document.getElementById('percentUnknown');
266      if (percentDone == -1)
267      {
268        Main.hide('percentDone');
269        Main.hide('percentRemain');
270        Main.show('percentUnknown');
271        Main.hide('percentText');
272      }
273      else
274      {
275        Main.hide('percentUnknown');
276        Main.show('percentText');
277        document.getElementById('percentText').innerHTML = percentDone+'%';
278        doneElement.style.width = percentDone+'%';
279        remainElement.style.width = (100-percentDone)+'%';
280        Main.showHide('percentDone', percentDone > 0);
281        Main.showHide('percentRemain', percentDone < 100);
282      }
283
284      // Message
285      document.getElementById('message').innerHTML = message;
286
287      // Running time
288      document.getElementById('runningTime').innerHTML = runningTime;
289    }
290  </script>
291  </base:head>
292  <base:body onload="autoUpdate()">
293    <h1><%=title%> <base:help tabcontrol="main" /></h1>
294    <t:tabcontrol id="main" 
295      subclass="content dialogtabcontrol"
296      active="<%=tab%>" position="bottom">
297    <t:tab id="properties" title="Properties" helpid="job.view.properties">
298      <table class="fullform outlined">
299      <%
300      if (isRemoved)
301      {
302        %>
303        <tr>
304          <td colspan="2" style="background: #E8E8E8; border-bottom: 1px solid #A0A0A0;">
305          <div class="itemstatus">
306            <base:icon 
307              image="<%=deletePermanentlyPermission ? "deleted.gif" : "deleted_disabled.gif"%>"
308              onclick="<%=deletePermanentlyPermission ? "deleteItemPermanently()" : null%>"
309              tooltip="<%=deletePermanentlyPermission ? "Permanently delete this item" : null%>"
310              visible="<%=isRemoved%>"> This item has been flagged for deletion<br></base:icon>
311            <base:icon image="used.gif" 
312              onclick="showUsingItems()"
313              tooltip="Show the items that are using this one"
314              visible="<%=isUsed%>"> This item is used by other items and can't be permanently deleted<br></base:icon>
315          </div>
316          </td>
317        </tr>
318        <%
319      }
320      %>
321      <tr>
322        <th style="border-top: 0px;">Name</th>
323        <td><%=HTML.encodeTags(job.getName())%></td>
324      </tr>
325      <tr>
326        <th>Plugin</th>
327        <td>
328          <base:propertyvalue item="<%=job%>" property="pluginDefinition.name" /> 
329          <%=job.getPluginVersion() == null ?
330            "" : "(version " + HTML.encodeTags(job.getPluginVersion()) + ")"%>
331        </td>
332      </tr>
333      <%
334      if (currentConfig != null)
335      {
336        %>
337        <tr>
338          <th class="subprompt">- configuration</th>
339          <td>
340            <base:propertyvalue item="<%=job%>" property="pluginConfiguration.name" />
341          </td>
342        </tr>
343        <%
344      }
345      %>
346      <tr>
347        <th>User</th>
348        <td>
349          <base:propertyvalue item="<%=job%>" property="owner.name" />
350        </td>
351      </tr>
352      <tr>
353        <th>Experiment</th>
354        <td>
355          <base:propertyvalue item="<%=job%>" property="experiment.name" />
356        </td>
357      </tr>
358      <tr>
359        <th>Status</th>
360        <td class="<%=job.getStatus() == Job.Status.ERROR ? "error" : ""%>">
361          <%=job.getStatus()%><%=job.isDryRun() ? " (dry-run)" : "" %>:
362          <span id="message"><%=HTML.niceFormat(job.getStatusMessage())%></span>
363        </td>
364      </tr>
365      <tr>
366        <th class="subprompt">- percent complete</th>
367        <td>
368          <table class="progressbar">
369          <tr>
370          <td>
371            <table id="bar" style="width: 200px;">
372            <tr>
373              <%
374              int percent = job.getPercentComplete();
375              %>
376              <td id="percentDone" style="width: <%=percent%>%; <%=percent <= 0 ? "display: none;" : ""%>">&nbsp;</td>
377              <td id="percentRemain" style="width: <%=100-percent%>%; <%=percent == 100 || percent == -1 ? "display: none;" : ""%>">&nbsp;</td>
378              <td id="percentUnknown" width="100%" 
379                style="<%=percent != -1 ? "display: none" : "" %>">unknown</td>
380            </tr>
381            </table>
382          </td>
383          <td id="percentText" 
384            style="<%=percent < 0 ? "display: none;" : "" %>"><%=percent%>%</td>
385            <%
386            if (logFile != null)
387            {
388              %>
389              <td  style="padding-left: 10px;"><base:button image="view.gif" 
390                title="View log&hellip;"
391                onclick="<%="Main.viewFile('" + ID + "', " + logFile.getId() + ")"%>"
392                tooltip="View the log file with detailed information about this job"
393                /></td>
394              <%
395            }
396            %>
397          </tr>
398          </table>
399        </td>
400      </tr>
401      <tr>
402        <th>Description</th>
403        <td><%=HTML.niceFormat(job.getDescription())%></td>
404      </tr>
405      <tr>
406        <th>Created</th>
407        <td>
408          <%=dateTimeFormatter.format(job.getCreated())%>
409        </td>
410      </tr>
411      <tr>
412        <th class="subprompt">- scheduled</th>
413        <td>
414          <%=dateTimeFormatter.format(job.getScheduled())%>
415        </td>
416      </tr>
417      <tr>
418        <th class="subprompt">- priority</th>
419        <td>
420          <%=job.getPriority()%> (1 = highest, 10 = lowest)
421        </td>
422      </tr>
423      <tr>
424        <th>Running time</th>
425        <td id="runningTime">
426          <%
427          Date started = job.getStarted();
428          if (started != null)
429          {
430            Date ended = job.getEnded();
431            if (ended == null) ended = new Date();
432            long runningTime = ended.getTime() - started.getTime();
433            %>
434            <%=Values.formatTime(runningTime / 1000)%>
435            <%
436          }
437          %>
438        </td>
439      </tr>
440      <tr>
441        <th class="subprompt">- started</th>
442        <td>
443          <%=dateTimeFormatter.format(job.getStarted())%>
444        </td>
445      </tr>
446      <tr>
447        <th class="subprompt">- ended</th>
448        <td>
449          <%=dateTimeFormatter.format(job.getEnded())%>
450        </td>
451      </tr>
452      <tr>
453        <th>Server</th>
454        <td>
455          <%=HTML.encodeTags(job.getServer())%>
456        </td>
457      </tr>
458      <tr>
459        <th>Job agent</th>
460        <td><%=Base.getEncodedName(agent, !readAgent)%></td>
461      </tr>
462      <tr class="dynamic">
463        <th></th>
464        <td></td>
465      </tr>
466      </table>
467      </t:tab>
468      <%
469      if (job.getStackTrace() != null)
470      {
471        %>
472        <t:tab id="stacktrace" title="Stack trace" helpid="job.view.stacktrace">
473          <div style="font-family: monospace; padding: 5px;">
474          <%=HTML.niceFormat(job.getStackTrace())%>
475          </div>
476        </t:tab>
477        <%
478      }
479      %>
480      <t:tab id="parameters" title="Parameters" helpid="job.view.parameters">
481        <table class="fullform outlined">
482        <tbody>
483        <tr class="section">
484          <th colspan="2">Job parameters</th>
485        </tr>
486        <%
487        List<String> names = new java.util.ArrayList<String>(jobParameters);
488        Collections.sort(names);
489        for (String name : names)
490        {
491          StringBuilder sb = new StringBuilder();
492          String displayValue = "";
493          String description = "";
494          try
495          {
496            ParameterInfo pi = job.getParameterInfo(name);
497            if (pi.getLabel() != null) name = HTML.encodeTags(pi.getLabel());
498            description = HTML.encodeTags(pi.getDescription());
499            List<?> values = pi.getValues();
500            int i = 0;
501            for (Object value : values)
502            {
503              if (value != null)
504              {
505                if (i > 0) sb.append(", ");
506                i++;
507                if (value instanceof BasicItem)
508                {
509                  sb.append(HTML.encodeTags(getItemName((BasicItem)value)));
510                }
511                else if (value instanceof Date)
512                {
513                  sb.append(dateFormatter.format((Date)value));
514                }
515                else
516                {
517                  sb.append(HTML.encodeTags(value.toString()));
518                }
519              }
520            }
521            displayValue = sb.toString();
522          }
523          catch (Throwable ex)
524          {
525            displayValue = "<i>ERROR: "+ex.getMessage()+"</i>";
526          }
527          %>
528          <tr>
529            <th><span title="<%=description%>"><%=name%></span></th>
530            <td>
531              <%=displayValue%>
532            </td>
533          </tr>
534          <%
535        }
536        %>
537        <%
538        if (!readCurrentConfig)
539        {
540          %>
541          </tbody>
542          <tbody>
543          <tr class="section">
544            <th colspan="2">Plugin configuration parameters</th>
545          </tr>
546          <tr>
547            <th></th>
548            <td><i>- denied -</i></td>
549          </tr>
550          <%
551        }
552        else if (currentConfig != null)
553        {
554          %>
555          </tbody>
556          <tbody>
557          <tr class="section">
558            <th colspan="2">Plugin configuration parameters</th>
559          </tr>
560          <tr>
561            <th><span 
562              title="The version of the parmeters used for this job, current version in paranthesis">Parameter version</span></td>
563            <td><%=parameterVersion%> (<%=latestParameterVersion %>)</th>
564          </tr>
565          <%
566          names = new java.util.ArrayList<String>(currentConfig.getParameterNames(parameterVersion));
567          Collections.sort(names);
568          for (String name : names)
569          {
570            StringBuilder sb = new StringBuilder();
571            String displayValue = "";
572            String description = "";
573            try
574            {
575              ParameterInfo pi = currentConfig.getParameterInfo(name, parameterVersion);
576              if (pi.getLabel() != null) name = HTML.encodeTags(pi.getLabel());
577              description = HTML.encodeTags(pi.getDescription());
578              List<?> values = pi.getValues();
579              int i = 0;
580              for (Object value : values)
581              {
582                if (value != null)
583                {
584                  if (i > 0) sb.append(", ");
585                  i++;
586                  if (value instanceof BasicItem)
587                  {
588                    sb.append(HTML.encodeTags(getItemName((BasicItem)value)));
589                  }
590                  else if (value instanceof Date)
591                  {
592                    sb.append(dateFormatter.format((Date)value));
593                  }
594                  else
595                  {
596                    sb.append(HTML.encodeTags(value.toString()));
597                  }
598                }
599              }
600              displayValue = sb.toString();
601            }
602            catch (Throwable ex)
603            {
604              displayValue = "<i>ERROR: "+ex.getMessage()+"</i>";
605            }
606            %>
607            <tr>
608              <th><span title="<%=description%>"><%=name%></span></th>
609              <td>
610                <%=displayValue%>
611              </td>
612            </tr>
613            <%
614          }
615          %>
616          <%
617        }
618        %>
619        <tr class="dynamic">
620          <th></th>
621          <td></td>
622        </tr>
623        </tbody>
624        </table>
625      </t:tab>
626     
627      <t:tab id="changes" title="Changed items"
628        tooltip="Display a log of all modifications made by this job"
629        visible="<%=!autoUpdate && ChangeHistoryUtil.showChangeHistoryTab(sc) %>">
630        <%
631        ItemQuery<ChangeHistory> query = ChangeHistory.getChangesBy(job);
632        query.order(Orders.asc(Hql.property("id")));
633        ItemResultIterator<ChangeHistory> changes = query.iterate(dc);
634        int numChanges = 0;
635        %>
636        <tbl:table id="history" clazz="itemlist" columns="all">
637          <tbl:columndef id="changeType" title="Change type" />
638          <tbl:columndef id="item" title="Item" />
639          <tbl:columndef id="info" title="Info" />
640         
641          <tbl:data>
642            <tbl:columns>
643            </tbl:columns>
644            <tbl:rows>
645            <%
646            while (changes.hasNext())
647            {
648              numChanges++;
649              ChangeHistory change = changes.next();
650              %>
651              <tbl:row>
652                <tbl:cell column="changeType"><%=change.getChangeType()%> <%=change.getItemType()%></tbl:cell>
653                <tbl:cell column="item"><%=ChangeHistoryUtil.getItem(dc, change, false, false)%></tbl:cell>
654                <tbl:cell column="info"><%=HTML.encodeTags(change.getChangeInfo())%></tbl:cell>
655              </tbl:row>
656              <%
657            }
658            %>
659            </tbl:rows>
660          </tbl:data>
661          <%
662          if (numChanges == 0)
663          {
664            %>
665            <tbl:panel>
666            No log entries found for this job. NOTE! This job may have made
667            other changes that are not recorded by the logging mechanism.
668            </tbl:panel>
669            <%
670          }
671          %>
672        </tbl:table>
673      </t:tab>
674      </t:tabcontrol>
675 
676    <base:buttongroup subclass="dialogbuttons">
677      <%
678      if (supportsAbort)
679      {
680        %>
681        <base:button onclick="abortJob()" title="Abort&hellip;" image="abort.png" />
682        <%
683      }
684      %>
685      <%
686      if (job.getStatus() == Job.Status.ERROR && job.getJobType() == Job.Type.RUN_PLUGIN)
687      {
688        boolean restartable = !job.getPluginDefinition().supports("net.sf.basedb.core.plugin.NonRestartable");       
689        if (restartable)
690        {
691          %>
692          <base:button onclick="restartJob(0)" title="Restart job" 
693            image="refresh.gif" 
694            tooltip="Try to run this job again with the same parameters"
695          />
696          <base:button onclick="reconfigureJob()" title="Re-configure job"
697            image="runplugin.gif"
698            tooltip="Change the parameters for this job and try again"
699            visible="<%=job.hasContext()%>"
700          />
701          <%
702        }
703      }
704      if (job.getStatus() == Job.Status.DONE && job.isDryRun())
705      {
706        %>
707        <base:button onclick="restartJob(1)" title="Really run" 
708          image="refresh.gif" 
709          tooltip="Run this dry-run job for real"
710        />
711        <%
712      }
713      %>
714      <base:button onclick="window.close()" title="Close" />
715    </base:buttongroup>
716  </base:body>
717  </base:page>
718  <%
719}
720finally
721{
722  if (dc != null) dc.close();
723}
724
725%>
Note: See TracBrowser for help on using the repository browser.