]> git.sur5r.net Git - bacula/bacula/commitdiff
baculum: Show jobs stored on volume
authorMarcin Haba <marcin.haba@bacula.pl>
Sun, 28 Feb 2016 16:23:25 +0000 (17:23 +0100)
committerKern Sibbald <kern@sibbald.com>
Tue, 31 May 2016 06:20:22 +0000 (08:20 +0200)
14 files changed:
gui/baculum/protected/Class/JobManager.php
gui/baculum/protected/JavaScript/misc.js
gui/baculum/protected/JavaScript/slide-window.js
gui/baculum/protected/Lang/en/messages.mo
gui/baculum/protected/Lang/en/messages.po
gui/baculum/protected/Lang/pl/messages.mo
gui/baculum/protected/Lang/pl/messages.po
gui/baculum/protected/Lang/pt/messages.mo
gui/baculum/protected/Lang/pt/messages.po
gui/baculum/protected/Pages/API/JobsOnVolume.php [new file with mode: 0644]
gui/baculum/protected/Portlets/VolumeConfiguration.php
gui/baculum/protected/Portlets/VolumeConfiguration.tpl
gui/baculum/protected/Portlets/VolumeList.tpl
gui/baculum/protected/application.xml

index 729b80615747abcd93ddd2a283ecd38c67a3c123..f08a27001b6016596f09d6184aa0a9f0a177634b 100644 (file)
@@ -113,5 +113,23 @@ class JobManager extends TModule {
                $pdo = null;
                return $jobtotals;
        }
+
+       /**
+        * Get jobs stored on given volume.
+        *
+        * @param string $mediaid volume identifier
+        * @param array $allowed_jobs jobs allowed to show
+        * @return array jobs stored on volume
+        */
+       public function getJobsOnVolume($mediaid, $allowed_jobs = array()) {
+               $jobs_criteria = '';
+               if (count($allowed_jobs) > 0) {
+                       $jobs_sql = implode("', '", $allowed_jobs);
+                       $jobs_criteria = " AND Job.Name IN ('" . $jobs_sql . "')";
+               }
+               $sql = "SELECT DISTINCT Job.* FROM Job, JobMedia WHERE JobMedia.MediaId='$mediaid' AND JobMedia.JobId=Job.JobId $jobs_criteria";
+               return JobRecord::finder()->findAllBySql($sql);
+       }
+
 }
 ?>
index 4c1f6d044d4519f9c7e3a929037f99506d4d3bd0..bec1322cd0f2b67d1e63db7695f267595d9dbe60 100644 (file)
@@ -1,21 +1,30 @@
 var Units = {
        get_decimal_size: function(size) {
+               var dec_size;
+               var size_unit = 'B';
+               var units = ['K', 'M', 'G', 'T', 'P'];
+
                if (size === null) {
                        size = 0;
                }
 
-               size = parseInt(size, 10);
-               var size_unit = 'B';
-               var units = ['K', 'M', 'G', 'T', 'P'];
-               var unit;
-               var dec_size = size.toString() + ((size > 0 ) ? size_unit : '');
-               while(size >= 1000) {
-                       size /= 1000;
-                       unit = units.shift(units);
-               }
-               if (unit) {
-                       dec_size = (Math.floor(size * 10) / 10).toFixed(1);
-                       dec_size += unit + size_unit;
+               var size_pattern = new RegExp('^[\\d\\.]+(' + units.join('|') + ')?' + size_unit + '$');
+
+               if (size_pattern.test(size.toString())) {
+                       // size is already formatted
+                       dec_size = size;
+               } else {
+                       size = parseInt(size, 10);
+                       var unit;
+                       dec_size = size.toString() + ((size > 0 ) ? size_unit : '');
+                       while(size >= 1000) {
+                               size /= 1000;
+                               unit = units.shift(units);
+                       }
+                       if (unit) {
+                               dec_size = (Math.floor(size * 10) / 10).toFixed(1);
+                               dec_size += unit + size_unit;
+                       }
                }
                return dec_size;
        }
index 557b6e826de76b064d4b055f40ae4f643f157a96..423566ce13a703f46cc034fcc3d3b76498fb9282 100644 (file)
@@ -316,8 +316,8 @@ var SlideWindowClass = Class.create({
                return is_open;
        },
 
-       sortTable: function (col, reverse, set_cookie) {
-               var table = document.getElementById(this.gridEl);
+       sortTable: function (grid_id, col, reverse, set_cookie) {
+               var table = document.getElementById(grid_id);
                var tb = table.tBodies[0], tr = Array.prototype.slice.call(tb.rows, 0), i;
                reverse = -((+reverse) || -1);
                tr = tr.sort(function (a, b) {
@@ -353,9 +353,18 @@ var SlideWindowClass = Class.create({
                }
        },
 
-       makeSortable: function () {
+       makeSortable: function (grid) {
                var self = this;
-               var table = document.getElementById(this.gridEl);
+               var grid_id, set_cookie;
+               if (grid) {
+                       grid_id = grid;
+                       // for external grids (non-slide) do not remember sorting order
+                       set_cookie = false;
+               } else {
+                       grid_id = this.gridEl;
+                       set_cookie = true;
+               }
+               var table = document.getElementById(grid_id);
                table.tHead.style.cursor = 'pointer';
                var th = table.tHead, i;
                th && (th = th.rows[0]) && (th = th.cells);
@@ -372,7 +381,7 @@ var SlideWindowClass = Class.create({
                while (--i >= downCounter) (function (i) {
                        var dir = 1;
                        th[i].addEventListener('click', function () {
-                               self.sortTable(i, (dir = 1 - dir), true);
+                               self.sortTable(grid_id, i, (dir = 1 - dir), set_cookie);
                        });
                }(i));
        },
@@ -383,7 +392,7 @@ var SlideWindowClass = Class.create({
                        var sort_param = sorting.split(':');
                        var col = parseInt(sort_param[0], 10);
                        var order = -(parseInt(sort_param[1], 10));
-                       this.sortTable(col, order);
+                       this.sortTable(this.gridEl, col, order);
                }
        },
 
index 474318dcf0f15f6c83bc11b88903bd566a4d349a..5fc682c7ea10c41ed624c79ae0377c94da642390 100644 (file)
Binary files a/gui/baculum/protected/Lang/en/messages.mo and b/gui/baculum/protected/Lang/en/messages.mo differ
index 08e8266ff8e53f11baab89408c7f7763c40c058b..3b630625d77c349d67e6469d5cf192f4ef32983c 100644 (file)
@@ -1136,3 +1136,9 @@ msgstr "Please note that for each user (excluding administrator) there should ex
 msgid "Invalid login value. Login may contain a-z A-Z 0-9 characters."
 msgstr "Invalid login value. Login may contain a-z A-Z 0-9 characters."
 
+msgid "Jobs on Volume"
+msgstr "Jobs on Volume"
+
+msgid "No jobs on the volume."
+msgstr "No jobs on the volume."
+
index a309360e0563e0f73bc15b459d9e3197c026ea6f..7b2fe042425bd7a416099080fe27f25ec150b643 100644 (file)
Binary files a/gui/baculum/protected/Lang/pl/messages.mo and b/gui/baculum/protected/Lang/pl/messages.mo differ
index f04920467f2ba06b96db59be0dce5fc753b94fa1..6b6f6c04f03dd6cd85905418b5c221db999d5db1 100644 (file)
@@ -1137,3 +1137,9 @@ msgstr "Uwaga! Dla każdego użytkownika (wyłączając administratora) powinien
 msgid "Invalid login value. Login may contain a-z A-Z 0-9 characters."
 msgstr "Niepoprawny login. Login może zawierać znaki z zakresu: a-z A-Z 0-9"
 
+msgid "Jobs on Volume"
+msgstr "Zadania na volumenie"
+
+msgid "No jobs on the volume."
+msgstr "Na wolumenie nie ma żadnych zadań."
+
index 53e55e53d5bcfc8ef750a847ef16fc5491b3081c..73e8e97cac9d677ef35a3e7d4984e21a4c946200 100644 (file)
Binary files a/gui/baculum/protected/Lang/pt/messages.mo and b/gui/baculum/protected/Lang/pt/messages.mo differ
index 5493c2ef22cc79518cb55105a1095aa7ddb5a374..75c6eedc527dd2e813eed913ddc03fd68347c1b5 100644 (file)
@@ -1139,3 +1139,9 @@ msgstr "Atenção, cada usuário (com excessão do usuário administrador) preci
 msgid "Invalid login value. Login may contain a-z A-Z 0-9 characters."
 msgstr "Usuário inválido! O usuário deve conter apenas os seguintes caracteres [a-z A-Z 0-9]."
 
+msgid "Jobs on Volume"
+msgstr "Jobs on Volume"
+
+msgid "No jobs on the volume."
+msgstr "No jobs on the volume."
+
diff --git a/gui/baculum/protected/Pages/API/JobsOnVolume.php b/gui/baculum/protected/Pages/API/JobsOnVolume.php
new file mode 100644 (file)
index 0000000..ef785a1
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum   - Bacula web interface
+ *
+ * Copyright (C) 2013-2016 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+class JobsOnVolume extends BaculumAPI {
+       public function get() {
+               $allowed = array();
+               $mediaid = intval($this->Request['id']);
+               $error = false;
+               if (!is_null($this->user)) {
+                       $allowed_jobs = $this->getModule('bconsole')->bconsoleCommand($this->director, array('.jobs'), $this->user);
+                       if ($allowed_jobs->exitcode === 0) {
+                               $allowed = $allowed_jobs->output;
+                       } else {
+                               $error = true;
+                               $this->output = $allowed_jobs->output;
+                               $this->error = $allowed_jobs->exitcode;
+                       }
+               }
+
+               if ($error === false) {
+                       $jobs = $this->getModule('job')->getJobsOnVolume($mediaid, $allowed);
+                       $this->output = $jobs;
+                       $this->error = JobError::ERROR_NO_ERRORS;
+               }
+       }
+}
+?>
index efa8fc14cd505e2196875c0c797ef325f777b7e7..e9e0215528da6b45c7eeae45fece8bbb11141090 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList');
+Prado::using('System.Web.UI.ActiveControls.TActiveDataGrid');
 Prado::using('System.Web.UI.ActiveControls.TActiveLabel');
 Prado::using('System.Web.UI.ActiveControls.TActiveTextBox');
 Prado::using('System.Web.UI.ActiveControls.TActiveCheckBox');
@@ -65,6 +66,10 @@ class VolumeConfiguration extends Portlets {
                $this->Pool->dataSource = $poolList;
                $this->Pool->SelectedValue = $voldata->poolid;
                $this->Pool->dataBind();
+
+               $jobs_on_volume = $this->Application->getModule('api')->get(array('volumes', 'jobs', $voldata->mediaid))->output;
+               $this->JobsOnVolume->DataSource = $this->Application->getModule('misc')->objectToArray($jobs_on_volume);
+               $this->JobsOnVolume->dataBind();
        }
 
        public function prune($sender, $param) {
@@ -96,6 +101,11 @@ class VolumeConfiguration extends Portlets {
                $this->Application->getModule('api')->set(array('volumes', $voldata['mediaid']), $voldata);
        }
 
+       public function openJob($sender, $param) {
+               $jobid = $param->CallbackParameter;
+               $this->getPage()->JobConfiguration->configure($jobid);
+       }
+
        public function getVolumeStates($forSetOnly = false) {
                $states = ($forSetOnly === true ) ? $this->volumeStatesForSet : array_merge($this->volumeStatesByDirectorOnly, $this->volumeStatesForSet);
                return $states;
index 584f80e00ca683a966dcaad0ad6e2a1e02982b6a..4b7070295ee0e8bc74c3ac6dba497aa8dcfe1fdc 100644 (file)
 <com:TContent ID="ConfigurationWindowContent">
        <com:TActivePanel DefaultButton="Apply">
                <strong><%[ Volume name: ]%> <com:TActiveLabel ID="VolumeName" /><com:TActiveLabel ID="VolumeID" Visible="false" /></strong>
-               <hr />
-               <com:TValidationSummary
-                       ID="ValidationSummary"
-                       CssClass="validation-error-summary"
-                       ValidationGroup="VolumeGroup"
-                       AutoUpdate="true"
-                       Display="Dynamic"
-                       HeaderText="<%[ There is not possible to run selected action because: ]%>" />
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="VolumeStatus" Text="<%[ Volume status: ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveDropDownList ID="VolumeStatus" CssClass="textbox-auto" AutoPostBack="false" />
+               <span class="text tab tab_active" rel="volume_actions_tab"><%[ Actions ]%></span>
+               <span class="text tab" rel="volume_jobs_tab"><%[ Jobs on Volume ]%></span>
+               <hr class="tabs" />
+               <div id="volume_actions_tab">
+                       <com:TValidationSummary
+                               ID="ValidationSummary"
+                               CssClass="validation-error-summary"
+                               ValidationGroup="VolumeGroup"
+                               AutoUpdate="true"
+                               Display="Dynamic"
+                               HeaderText="<%[ There is not possible to run selected action because: ]%>" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="VolumeStatus" Text="<%[ Volume status: ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveDropDownList ID="VolumeStatus" CssClass="textbox-auto" AutoPostBack="false" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="RetentionPeriod" Text="<%[ Retention period (in hours): ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveTextBox ID="RetentionPeriod" MaxLength="20" CssClass="textbox-auto" AutoPostBack="false" />
-                               <com:TActiveCustomValidator ID="RetentionPeriodValidator" ValidationGroup="VolumeGroup" ControlToValidate="RetentionPeriod" ErrorMessage="<%[ Retention period value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="retentionPeriodValidator" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="RetentionPeriod" Text="<%[ Retention period (in hours): ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveTextBox ID="RetentionPeriod" MaxLength="20" CssClass="textbox-auto" AutoPostBack="false" />
+                                       <com:TActiveCustomValidator ID="RetentionPeriodValidator" ValidationGroup="VolumeGroup" ControlToValidate="RetentionPeriod" ErrorMessage="<%[ Retention period value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="retentionPeriodValidator" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="Pool" Text="<%[ Pool: ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveDropDownList ID="Pool" AutoPostBack="false" CssClass="textbox-auto" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="Pool" Text="<%[ Pool: ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveDropDownList ID="Pool" AutoPostBack="false" CssClass="textbox-auto" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="UseDuration" Text="<%[ Vol. use duration (in hours): ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveTextBox ID="UseDuration" AutoPostBack="false" CssClass="textbox-auto" />
-                               <com:TActiveCustomValidator ID="UseDurationValidator" ValidationGroup="VolumeGroup" ControlToValidate="UseDuration" ErrorMessage="<%[ Vol. use duration value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="useDurationValidator" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="UseDuration" Text="<%[ Vol. use duration (in hours): ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveTextBox ID="UseDuration" AutoPostBack="false" CssClass="textbox-auto" />
+                                       <com:TActiveCustomValidator ID="UseDurationValidator" ValidationGroup="VolumeGroup" ControlToValidate="UseDuration" ErrorMessage="<%[ Vol. use duration value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="useDurationValidator" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="MaxVolJobs" Text="<%[ Max vol. jobs: ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveTextBox ID="MaxVolJobs" AutoPostBack="false" CssClass="textbox-auto" />
-                               <com:TActiveCustomValidator ID="MaxVolJobsValidator" ValidationGroup="VolumeGroup" ControlToValidate="MaxVolJobs" ErrorMessage="<%[ Max vol. jobs value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="maxVolJobsValidator" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="MaxVolJobs" Text="<%[ Max vol. jobs: ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveTextBox ID="MaxVolJobs" AutoPostBack="false" CssClass="textbox-auto" />
+                                       <com:TActiveCustomValidator ID="MaxVolJobsValidator" ValidationGroup="VolumeGroup" ControlToValidate="MaxVolJobs" ErrorMessage="<%[ Max vol. jobs value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="maxVolJobsValidator" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="MaxVolFiles" Text="<%[ Max vol. files: ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveTextBox ID="MaxVolFiles" AutoPostBack="false" CssClass="textbox-auto" />
-                               <com:TActiveCustomValidator ID="MaxVolFilesValidator" ValidationGroup="VolumeGroup" ControlToValidate="MaxVolFiles" ErrorMessage="<%[ Max vol. files value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="maxVolFilesValidator" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="MaxVolFiles" Text="<%[ Max vol. files: ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveTextBox ID="MaxVolFiles" AutoPostBack="false" CssClass="textbox-auto" />
+                                       <com:TActiveCustomValidator ID="MaxVolFilesValidator" ValidationGroup="VolumeGroup" ControlToValidate="MaxVolFiles" ErrorMessage="<%[ Max vol. files value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="maxVolFilesValidator" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="MaxVolBytes" Text="<%[ Max vol. bytes: ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveTextBox ID="MaxVolBytes" AutoPostBack="false" CssClass="textbox-auto" />
-                               <com:TActiveCustomValidator ID="MaxVolBytesValidator" ValidationGroup="VolumeGroup" ControlToValidate="MaxVolBytes" ErrorMessage="<%[ Max vol. bytes value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="maxVolBytesValidator" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="MaxVolBytes" Text="<%[ Max vol. bytes: ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveTextBox ID="MaxVolBytes" AutoPostBack="false" CssClass="textbox-auto" />
+                                       <com:TActiveCustomValidator ID="MaxVolBytesValidator" ValidationGroup="VolumeGroup" ControlToValidate="MaxVolBytes" ErrorMessage="<%[ Max vol. bytes value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="maxVolBytesValidator" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="Slot" Text="<%[ Slot number: ]%>" /></div>
-                       <div class="field">
-                               <com:TActiveTextBox ID="Slot" AutoPostBack="false" CssClass="textbox-auto" />
-                               <com:TActiveCustomValidator ID="SlotValidator" ValidationGroup="VolumeGroup" ControlToValidate="Slot" ErrorMessage="<%[ Slot value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="slotValidator" />
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="Slot" Text="<%[ Slot number: ]%>" /></div>
+                               <div class="field">
+                                       <com:TActiveTextBox ID="Slot" AutoPostBack="false" CssClass="textbox-auto" />
+                                       <com:TActiveCustomValidator ID="SlotValidator" ValidationGroup="VolumeGroup" ControlToValidate="Slot" ErrorMessage="<%[ Slot value must be integer. ]%>" ControlCssClass="validation-error" Display="None" OnServerValidate="slotValidator" />
+                               </div>
                        </div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="Recycle" Text="<%[ Recycle: ]%>" /></div>
-                       <div class="field"><com:TActiveCheckBox ID="Recycle" AutoPostBack="false" /></div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="Enabled" Text="<%[ Enabled: ]%>" /></div>
-                       <div class="field"><com:TActiveCheckBox ID="Enabled" AutoPostBack="false" /></div>
-               </div>
-               <div class="line">
-                       <div class="text"><com:TLabel ForControl="InChanger" Text="<%[ In changer: ]%>" /></div>
-                       <div class="field"><com:TActiveCheckBox ID="InChanger" AutoPostBack="false" /></div>
-               </div>
-               <com:TCallback ID="ReloadVolumes" OnCallback="Page.VolumeWindow.prepareData" ClientSide.OnComplete="SlideWindow.getObj('VolumeWindow').setLoadRequest();" />
-               <script type="text/javascript">
-                       var volume_callback_func = function() {
-                               /*
-                                * Check if Volume list window is open and if any checkbox from actions is not checked.
-                                * Also check if toolbar is open.
-                                * If yes, then is possible to refresh Volume list window.
-                                */
-                               var obj = SlideWindow.getObj('VolumeWindow');
-                               if (obj.isWindowOpen() === false || obj.areCheckboxesChecked() === true || obj.isToolbarOpen() === true) {
-                                       return;
-                               }
-                               var mainForm = Prado.Validation.getForm();
-                               var callback = <%=$this->ReloadVolumes->ActiveControl->Javascript%>;
-                               if (Prado.Validation.managers[mainForm].getValidatorsWithError('VolumeGroup').length == 0) {
-                                       obj.markAllChecked(false);
-                                       callback.dispatch();
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="Recycle" Text="<%[ Recycle: ]%>" /></div>
+                               <div class="field"><com:TActiveCheckBox ID="Recycle" AutoPostBack="false" /></div>
+                       </div>
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="Enabled" Text="<%[ Enabled: ]%>" /></div>
+                               <div class="field"><com:TActiveCheckBox ID="Enabled" AutoPostBack="false" /></div>
+                       </div>
+                       <div class="line">
+                               <div class="text"><com:TLabel ForControl="InChanger" Text="<%[ In changer: ]%>" /></div>
+                               <div class="field"><com:TActiveCheckBox ID="InChanger" AutoPostBack="false" /></div>
+                       </div>
+                       <com:TCallback ID="ReloadVolumes" OnCallback="Page.VolumeWindow.prepareData" ClientSide.OnComplete="SlideWindow.getObj('VolumeWindow').setLoadRequest();" />
+                       <script type="text/javascript">
+                               var volume_callback_func = function() {
+                                       /*
+                                        * Check if Volume list window is open and if any checkbox from actions is not checked.
+                                        * Also check if toolbar is open.
+                                        * If yes, then is possible to refresh Volume list window.
+                                        */
+                                       var obj = SlideWindow.getObj('VolumeWindow');
+                                       if (obj.isWindowOpen() === false || obj.areCheckboxesChecked() === true || obj.isToolbarOpen() === true) {
+                                               return;
+                                       }
+                                       var mainForm = Prado.Validation.getForm();
+                                       var callback = <%=$this->ReloadVolumes->ActiveControl->Javascript%>;
+                                       if (Prado.Validation.managers[mainForm].getValidatorsWithError('VolumeGroup').length == 0) {
+                                               obj.markAllChecked(false);
+                                               callback.dispatch();
+                                       }
                                }
-                       }
-               </script>
-               <div class="button">
-                       <com:Application.Portlets.BActiveButton ID="Purge" Text="<%[ Purge ]%>" OnClick="purge" ClientSide.OnSuccess="ConfigurationWindow.getObj('VolumeWindow').progress(false);volume_callback_func()" />
-                       <com:Application.Portlets.BActiveButton ID="Prune" Text="<%[ Prune ]%>" OnClick="prune" ClientSide.OnSuccess="ConfigurationWindow.getObj('VolumeWindow').progress(false);volume_callback_func()" />
-                       <com:Application.Portlets.BActiveButton ValidationGroup="VolumeGroup" CausesValidation="true" ID="Apply" Text="<%[ Apply ]%>" OnClick="apply" ClientSide.OnSuccess="ConfigurationWindow.getObj('VolumeWindow').progress(false);volume_callback_func()" />
+                       </script>
+                       <div class="button">
+                               <com:Application.Portlets.BActiveButton ID="Purge" Text="<%[ Purge ]%>" OnClick="purge" ClientSide.OnSuccess="ConfigurationWindow.getObj('VolumeWindow').progress(false);volume_callback_func()" />
+                               <com:Application.Portlets.BActiveButton ID="Prune" Text="<%[ Prune ]%>" OnClick="prune" ClientSide.OnSuccess="ConfigurationWindow.getObj('VolumeWindow').progress(false);volume_callback_func()" />
+                               <com:Application.Portlets.BActiveButton ValidationGroup="VolumeGroup" CausesValidation="true" ID="Apply" Text="<%[ Apply ]%>" OnClick="apply" ClientSide.OnSuccess="ConfigurationWindow.getObj('VolumeWindow').progress(false);volume_callback_func()" />
+                       </div>
+               </div>
+               <div id="volume_jobs_tab" style="display: none">
+                       <div style="max-height: 500px; overflow-y: auto;">
+                               <com:TActiveDataGrid
+                                       ID="JobsOnVolume"
+                                       EnableViewState="false"
+                                       AutoGenerateColumns="false"
+                                       AllowSorting="false"
+                                       OnSortCommand="sortDataGrid"
+                                       CellPadding="5px"
+                                       CssClass="window-section-detail"
+                                       ItemStyle.CssClass="slide-window-element"
+                                       AlternatingItemStyle.CssClass="slide-window-element-alternating"
+                                       >
+                                       <com:TActiveBoundColumn HeaderText="ID" DataField="jobid" />
+                                       <com:TActiveTemplateColumn HeaderText="<%[ Job name ]%>" SortExpression="name">
+                                               <prop:ItemTemplate>
+                                                       <div title="<%=$this->getParent()->Data['name']%>"><%=$this->getPage()->JobWindow->formatJobName($this->getParent()->Data['name'])%></div>
+                                                       <input type="hidden" name="<%=$this->getParent()->ClientID%>" value="<%=$this->getParent()->Data['jobid']%>" />
+                                               </prop:ItemTemplate>
+                                       </com:TActiveTemplateColumn>
+                                       <com:TActiveTemplateColumn>
+                                               <prop:HeaderText>
+                                                       <span title="<%=Prado::localize('Type')%>" style="cursor: help">T</span>
+                                               </prop:HeaderText>
+                                               <prop:ItemTemplate>
+                                                       <%=$this->getParent()->Data['type']%>
+                                               </prop:ItemTemplate>
+                                       </com:TActiveTemplateColumn>
+                                       <com:TActiveTemplateColumn>
+                                               <prop:HeaderText>
+                                                       <span title="<%=Prado::localize('Level')%>" style="cursor: help">L</span>
+                                               </prop:HeaderText>
+                                               <prop:ItemTemplate>
+                                                       <%=$this->getParent()->Data['level']%>
+                                               </prop:ItemTemplate>
+                                       </com:TActiveTemplateColumn>
+                                       <com:TActiveTemplateColumn HeaderText="<%[ Job status ]%>" SortExpression="jobstatus">
+                                               <prop:ItemTemplate>
+                                                       <div class="job-status-<%=$this->getPage()->JobWindow->getJobStatusLetter($this->getParent()->Data)%>" title="<%=$this->getPage()->JobWindow->getJobStatusDescription($this->getParent()->Data)%>"><%=$this->getPage()->JobWindow->getJobStatusValue($this->getParent()->Data)%></div>
+                                               </prop:ItemTemplate>
+                                       </com:TActiveTemplateColumn>
+                                       <com:TActiveTemplateColumn HeaderText="<%[ Size ]%>" SortExpression="jobbytes">
+                                               <prop:ItemTemplate>
+                                                       <div class="size" rel="<%=$this->getParent()->Data['jobbytes']%>"><%=$this->getParent()->Data['jobbytes']%></div>
+                                               </prop:ItemTemplate>
+                                       </com:TActiveTemplateColumn>
+                                       <com:TActiveBoundColumn SortExpression="jobfiles" HeaderText="<%[ Files ]%>" DataField="jobfiles" />
+                                       <com:TActiveTemplateColumn HeaderText="<%[ End time ]%>" SortExpression="endtime">
+                                               <prop:ItemTemplate>
+                                                       <%=$this->getParent()->Data['endtime']%>
+                                                       <%=in_array($this->getParent()->Data['jobstatus'], $this->getPage()->JobWindow->runningJobStates) ? '<img src="' . $this->getPage()->getTheme()->getBaseUrl() . '/loader-alter.gif" />' : ''%>
+                                               </prop:ItemTemplate>
+                                       </com:TActiveTemplateColumn>
+                               </com:TActiveDataGrid>
+                       </div>
+                       <p class="center bold" id="no_jobs_on_volume" style="display: none"><%[ No jobs on the volume. ]%></p>
+                       <script type="text/javascript">
+                               var bind_jobs_on_volume_action = function() {
+                                       var grid_id = '<%=$this->JobsOnVolume->ClientID%>';
+                                       var no_jobs_msg_id = 'no_jobs_on_volume';
+                                       if (!document.getElementById(grid_id)) {
+                                               $(no_jobs_msg_id).show();
+                                               return;
+                                       }
+                                       $(no_jobs_msg_id).hide();
+                                       SlideWindow.makeSortable(grid_id);
+                                       var odd_rows = ['#' + grid_id, 'tr.' + SlideWindow.elements.contentItems].join(' ');
+                                       var even_rows = ['#' + grid_id, 'tr.' + SlideWindow.elements.contentAlternatingItems].join(' ');
+                                       var callback = <%=$this->OpenJobCall->ActiveControl->Javascript%>;
+                                       $$(odd_rows, even_rows).each(function(el) {
+                                               el.observe('click', function(e) {
+                                                       var el = $(e.srcElement||e.target);
+                                                       if (el) {
+                                                               el = el.up('tr').down('input[type=hidden]')
+                                                               var val = el.getValue();
+                                                               callback.ActiveControl.CallbackParameter = val;
+                                                               callback.dispatch();
+                                                               ConfigurationWindow.getObj('VolumeWindow').progress(true);
+                                                       }
+                                               }.bind(this));
+                                       }.bind(this));
+                               }.bind(this);
+                       </script>
+                       <com:TCallback ID="OpenJobCall" OnCallback="openJob">
+                               <prop:ClientSide.OnComplete>
+                                       ConfigurationWindow.getObj('VolumeWindow').progress(false);
+                                       ConfigurationWindow.getObj('JobWindow').switchTabByNo(2);
+                                       ConfigurationWindow.getObj('JobWindow').show();
+                               </prop:ClientSide.OnComplete>
+                       </com:TCallback>
                </div>
        </com:TActivePanel>
 </com:TContent>
index 59570fed82674201a75066e7363ce1430c779f08..382e05588d377aae709b1b8a71f9651c3990760f 100644 (file)
@@ -72,6 +72,8 @@
        <com:TCallback ID="DataElementCall" OnCallback="Page.VolumeWindow.configure">
                <prop:ClientSide.OnComplete>
                        ConfigurationWindow.getObj('VolumeWindow').show();
+                       Formatters.set_formatters();
+                       bind_jobs_on_volume_action();
                        ConfigurationWindow.getObj('VolumeWindow').progress(false);
                </prop:ClientSide.OnComplete>
        </com:TCallback>
index 7f4c77477b8d97b086f865f68f43b2b286879275..38cf9708941bffa835bd9d945fb1efd406748364 100644 (file)
@@ -45,6 +45,7 @@
                        <url ServiceParameter="API.Volumes" pattern="volumes/limit/{limit}/" parameters.limit="\d+" />
                        <url ServiceParameter="API.VolumePrune" pattern="volumes/prune/{id}/" parameters.id="\d+" />
                        <url ServiceParameter="API.VolumePurge" pattern="volumes/purge/{id}/" parameters.id="\d+" />
+                       <url ServiceParameter="API.JobsOnVolume" pattern="volumes/jobs/{id}/" parameters.id="\d+" />
                        <!-- END Volumes (media) -->
                        <!-- START Pools -->
                        <url ServiceParameter="API.Pools" pattern="pools/" />