return JobRecord::finder()->findAllBySql($sql);
}
+ /**
+ * Get jobs for given client.
+ *
+ * @param string $clientid client identifier
+ * @param array $allowed_jobs jobs allowed to show
+ * @return array jobs for specific client
+ */
+ public function getJobsForClient($clientid, $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 Client, Job WHERE Client.ClientId='$clientid' AND Client.ClientId=Job.ClientId $jobs_criteria";
+ return JobRecord::finder()->findAllBySql($sql);
+ }
}
?>
msgid "No jobs on the volume."
msgstr "No jobs on the volume."
+msgid "Jobs for Client"
+msgstr "Jobs for Client"
+
+msgid "No jobs for the client."
+msgstr "No jobs for the client."
+
msgid "No jobs on the volume."
msgstr "Na wolumenie nie ma żadnych zadań."
+msgid "Jobs for Client"
+msgstr "Zadania dla klienta"
+
+msgid "No jobs for the client."
+msgstr "Nie ma żadnych zadań dla klienta."
+
msgid "No jobs on the volume."
msgstr "No jobs on the volume."
+msgid "Jobs for Client"
+msgstr "Jobs for Client"
+
+msgid "No jobs for the client."
+msgstr "No jobs for the client."
+
--- /dev/null
+<?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 JobsForClient extends BaculumAPI {
+ public function get() {
+ $allowed = array();
+ $clientid = 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')->getJobsForClient($clientid, $allowed);
+ $this->output = $jobs;
+ $this->error = JobError::ERROR_NO_ERRORS;
+ }
+ }
+}
+?>
*/
Prado::using('System.Web.UI.ActiveControls.TActiveCustomValidator');
+Prado::using('System.Web.UI.ActiveControls.TActiveDataGrid');
Prado::using('Application.Portlets.Portlets');
class ClientConfiguration extends Portlets {
$this->FileRetention->Text = intval($client->fileretention / 86400); // conversion to days
$this->JobRetention->Text = intval($client->jobretention / 86400); // conversion to days
$this->AutoPrune->Checked = $client->autoprune == 1;
+
+ $jobs_for_client = $this->Application->getModule('api')->get(array('clients', 'jobs', $client->clientid))->output;
+ $this->JobsForClient->DataSource = $this->Application->getModule('misc')->objectToArray($jobs_for_client);
+ $this->JobsForClient->dataBind();
}
public function status($sender, $param) {
$isValid = preg_match('/^\d+$/', $this->JobRetention->Text) && $this->JobRetention->Text >= 0;
$param->setIsValid($isValid);
}
+
+ public function openJob($sender, $param) {
+ $jobid = $param->CallbackParameter;
+ $this->getPage()->JobConfiguration->configure($jobid);
+ }
}
?>
<com:TActiveLabel ID="ClientDescription" CssClass="description" />
<span class="text tab tab_active" rel="client_actions_tab"><%[ Actions ]%></span>
<span class="text tab" rel="client_console_tab"><%[ Console status ]%></span>
+ <span class="text tab" rel="client_jobs_tab"><%[ Jobs for Client ]%></span>
<hr class="tabs" />
<div id="client_actions_tab">
<com:TValidationSummary
<com:TActiveTextBox ID="ShowClient" TextMode="MultiLine" CssClass="textbox-auto" Style="height: 440px" ReadOnly="true" />
</div>
</div>
+ <div id="client_jobs_tab" style="display: none">
+ <div style="max-height: 444px; overflow-y: auto;">
+ <com:TActiveDataGrid
+ ID="JobsForClient"
+ EnableViewState="false"
+ AutoGenerateColumns="false"
+ AllowSorting="false"
+ 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_for_client" style="display: none"><%[ No jobs for the client. ]%></p>
+ <script type="text/javascript">
+ var bind_jobs_for_client_action = function() {
+ var grid_id = '<%=$this->JobsForClient->ClientID%>';
+ var no_jobs_msg_id = 'no_jobs_for_client';
+ 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('ClientWindow').progress(true);
+ }
+ }.bind(this));
+ }.bind(this));
+ SlideWindow.sortTable(grid_id, 0, true);
+ }.bind(this);
+ </script>
+ <com:TCallback ID="OpenJobCall" OnCallback="openJob">
+ <prop:ClientSide.OnComplete>
+ ConfigurationWindow.getObj('ClientWindow').progress(false);
+ ConfigurationWindow.getObj('JobWindow').switchTabByNo(2);
+ ConfigurationWindow.getObj('JobWindow').show();
+ </prop:ClientSide.OnComplete>
+ </com:TCallback>
+ </div>
</com:TActivePanel>
</com:TContent>
<com:TCallback ID="DataElementCall" OnCallback="Page.ClientWindow.configure">
<prop:ClientSide.OnComplete>
ConfigurationWindow.getObj('ClientWindow').show();
+ Formatters.set_formatters();
+ bind_jobs_for_client_action();
ConfigurationWindow.getObj('ClientWindow').progress(false);
</prop:ClientSide.OnComplete>
</com:TCallback>
<url ServiceParameter="API.ClientsShow" pattern="clients/show/" />
<url ServiceParameter="API.ClientShow" pattern="clients/show/{id}/" parameters.id="\d+" />
<url ServiceParameter="API.ClientStatus" pattern="clients/status/{id}/" parameters.id="\d+" />
+ <url ServiceParameter="API.JobsForClient" pattern="clients/jobs/{id}/" parameters.id="\d+" />
<!-- END Clients (file daemons) -->
<!-- START Storages (storage daemons) -->
<url ServiceParameter="API.Storages" pattern="storages/" />