for (var i = 0; i < tab_btns.length; i++) {
if (tab_btns[i].id === btn_id && !tab_btns[i].classList.contains(this.css.tab_item_hover)) {
tab_btns[i].classList.add(this.css.tab_item_hover);
- } else if (tab_btns[i].classList.contains(this.css.tab_item_hover)) {
+ } else if (tab_btns[i].id !== btn_id && tab_btns[i].classList.contains(this.css.tab_item_hover)) {
tab_btns[i].classList.remove(this.css.tab_item_hover);
}
}
msgid "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
msgstr "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
+
+msgid "Offset:"
+msgstr "Offset:"
+
+msgid "List type:"
+msgstr "List type:"
+
+msgid "saved items"
+msgstr "saved items"
+
+msgid "deleted items"
+msgstr "deleted items"
+
+msgid "all"
+msgstr "all"
+
+msgid "Find file or directory"
+msgstr "Find file or directory"
+
+msgid "Find"
+msgstr "Find"
+
+msgid "Item count:"
+msgstr "Item count:"
+
+msgid "No item result"
+msgstr "No item result"
msgid "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
msgstr "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
+
+msgid "Offset:"
+msgstr "Offset:"
+
+msgid "List type:"
+msgstr "List type:"
+
+msgid "saved items"
+msgstr "saved items"
+
+msgid "deleted items"
+msgstr "deleted items"
+
+msgid "all"
+msgstr "all"
+
+msgid "Find file or directory"
+msgstr "Find file or directory"
+
+msgid "Find"
+msgstr "Find"
+
+msgid "Item count:"
+msgstr "Item count:"
+
+msgid "No item result"
+msgstr "No item result"
msgid "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
msgstr "Graficzny status zadania jest wspierany dla zadań uruchomionych na klientach Bacula w wersji 9.0 lub wyższych."
+
+msgid "Offset:"
+msgstr "Offset:"
+
+msgid "List type:"
+msgstr "Typ listy:"
+
+msgid "saved items"
+msgstr "zapisane elementy"
+
+msgid "deleted items"
+msgstr "skasowane elementy"
+
+msgid "all"
+msgstr "wszystko"
+
+msgid "Find file or directory"
+msgstr "Znajdź plik lub katalog"
+
+msgid "Find"
+msgstr "Znajdź"
+
+msgid "Item count:"
+msgstr "Ilość elementów:"
+
+msgid "No item result"
+msgstr "Brak wyniku"
msgid "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
msgstr "Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater."
+
+msgid "Offset:"
+msgstr "Offset:"
+
+msgid "List type:"
+msgstr "List type:"
+
+msgid "saved items"
+msgstr "saved items"
+
+msgid "deleted items"
+msgstr "deleted items"
+
+msgid "all"
+msgstr "all"
+
+msgid "Find file or directory"
+msgstr "Find file or directory"
+
+msgid "Find"
+msgstr "Find"
+
+msgid "Item count:"
+msgstr "Item count:"
+
+msgid "No item result"
+msgstr "No item result"
OnCallback="runningJobStatus"
ClientSide.OnComplete="oRunningJobStatus.init_refresh();"
/>
- <com:TConditional
- ID="RunningJobStatus"
- Condition="$this->allow_graph_mode"
- >
- <prop:TrueTemplate>
<div class="w3-row">
- <a href="javascript:void(0)" onclick="W3SubTabs.open('status_running_job_subtab_graphical', 'status_running_job_graphical_output');">
+ <a href="javascript:void(0)" onclick="W3SubTabs.open('status_running_job_subtab_graphical', 'status_running_job_graphical_output');"<%=!$this->allow_graph_mode ? ' style="display: none"' : ''%>>
<div id="status_running_job_subtab_graphical" class="subtab_btn w3-half w3-bottombar w3-hover-light-grey w3-border-red w3-padding"><%[ Running job status ]%></div>
- </a>
+ </a>
<a href="javascript:void(0)" onclick="W3SubTabs.open('joblog_subtab_text', 'joblog_text_output');">
<div id="joblog_subtab_text" class="subtab_btn w3-half w3-bottombar w3-hover-light-grey w3-padding"><%[ Raw job log ]%></div>
</a>
+ <a href="javascript:void(0)" onclick="W3SubTabs.open('jobfiles_subtab_text', 'jobfiles_list'); load_job_list_files();"<%=!$this->allow_list_files_mode ? ' style="display: none"' : ''%>>
+ <div id="jobfiles_subtab_text" class="subtab_btn w3-half w3-bottombar w3-hover-light-grey w3-padding"><%[ Job files ]%></div>
+ </a>
</div>
- <div id="status_running_job_graphical_output" class="subtab_item">
+ <div id="status_running_job_graphical_output" class="subtab_item" style="display: none">
<h4 id="status_running_job_status_not_supported" style="display: none"><%[ Graphical job status is supported for jobs running on Bacula clients version 9.0 and greater. ]%></h4>
<div id="status_running_job_graphical_container">
<div class="w3-right w3-margin-top w3-margin-right" title="<%[ To disable refreshing please type 0. ]%>">
$('#' + this.ids.refresh_interval).parent().hide();
var graphical_container = document.getElementById(this.ids.graphical_container);
graphical_container.style.display = 'none';
- W3SubTabs.open('joblog_subtab_text', 'joblog_text_output');
+ if (document.getElementById('jobfiles_list').style.display == 'none') {
+ W3SubTabs.open('joblog_subtab_text', 'joblog_text_output');
+ }
}
},
add_running_job: function(job, full_refresh) {
}
}
-function init_graphical_running_job_status(data) {
+function init_graphical_running_job_status(data, tab_data) {
oRunningJobStatus.update(data);
+ var tabs = Object.keys(tab_data);
+ for (var i = 0; i < tabs.length; i++) {
+ document.getElementById(tabs[i]).parentNode.style.display = (tab_data[tabs[i]] ? '' : 'none');
+ }
+ if (document.getElementById('status_running_job_subtab_graphical').classList.contains(W3SubTabs.css.tab_item_hover)) {
+ W3SubTabs.open('status_running_job_subtab_graphical', 'status_running_job_graphical_output');
+ }
}
oRunningJobStatus.init();
});
</script>
</div>
- <div id="joblog_text_output" class="subtab_item" style="display: none">
- </prop:TrueTemplate>
+ <com:TConditional
+ Condition="$this->allow_graph_mode"
+ >
+ <prop:FalseTemplate>
+ <script>
+ $(function() {
+ W3SubTabs.open('joblog_subtab_text', 'joblog_text_output');
+ });
+ </script>
+ </prop:FalseTemplate>
</com:TConditional>
+ <div id="joblog_text_output" class="subtab_item" style="display: none">
<div class="w3-code">
<pre><com:TActiveLabel ID="JobLog" /></pre>
</div>
- <com:TConditional Condition="$this->allow_graph_mode">
- <prop:TrueTemplate>
</div>
+ <div id="jobfiles_list" class="subtab_item" style="display: none">
+ <com:Application.Web.Portlets.JobListFiles
+ ID="FileList"
+ />
+ </div>
+ <com:TConditional
+ Condition="$this->allow_list_files_mode"
+ >
+ <prop:TrueTemplate>
+ <script>
+ $(function() {
+ W3SubTabs.open('joblog_subtab_text', 'joblog_text_output');
+ });
+ </script>
</prop:TrueTemplate>
</com:TConditional>
</div>
* Bacula(R) - The Network Backup Solution
* Baculum - Bacula web interface
*
- * Copyright (C) 2013-2018 Kern Sibbald
+ * Copyright (C) 2013-2019 Kern Sibbald
*
* The main author of Baculum is Marcin Haba.
* The original author of Bacula is Kern Sibbald, with contributions
const JOBID = 'JobId';
const JOB_NAME = 'JobName';
const JOB_UNAME = 'JobUname';
- const CLIENTID = 'ClientId';
+ const JOB_LEVEL = 'JobLevel';
const JOB_TYPE = 'JobType';
+ const CLIENTID = 'ClientId';
const USE_CACHE = true;
public $is_running = false;
public $allow_graph_mode = false;
+ public $allow_list_files_mode = false;
private $no_graph_mode_types = array('M', 'D', 'C', 'c', 'g');
+ private $no_graph_mode_verify_levels = array('O');
+ private $list_files_types = array('B', 'C', 'V');
+ private $list_files_mode_verify_levels = array('V');
public function onPreInit($param) {
parent::onPreInit($param);
$this->setJobName($jobdata->name);
$this->setJobUname($jobdata->job);
$this->setJobType($jobdata->type);
+ $this->setJobLevel($jobdata->level);
$this->setClientId($jobdata->clientid);
$this->is_running = $this->getModule('misc')->isJobRunning($jobdata->jobstatus);
$this->allow_graph_mode = ($this->is_running && !in_array($jobdata->type, $this->no_graph_mode_types));
+ $this->allow_list_files_mode = (!$this->is_running && in_array($jobdata->type, $this->list_files_types));
+ if ($jobdata->type === 'V') {
+ // Verify job requires special treating here
+ if (in_array($jobdata->level, $this->no_graph_mode_verify_levels)) {
+ $this->allow_graph_mode = false;
+ }
+ if (!in_array($jobdata->level, $this->list_files_mode_verify_levels)) {
+ $this->allow_list_files_mode = false;
+ }
+ }
}
public function onInit($param) {
parent::onInit($param);
$this->RunJobModal->setJobId($this->getJobId());
$this->RunJobModal->setJobName($this->getJobName());
+ $this->FileList->setJobId($this->getJobId());
}
public function onLoad($param) {
public function runningJobStatus($sender, $param) {
$running_job_status = $this->getRunningJobStatus($this->getClientId());
- $this->getCallbackClient()->callClientFunction('init_graphical_running_job_status', array($running_job_status));
+ $tabs = array(
+ 'joblog_subtab_text' => true,
+ 'status_running_job_subtab_graphical' => false,
+ 'jobfiles_subtab_text' => false
+ );
+ if ($this->allow_graph_mode) {
+ $tabs['status_running_job_subtab_graphical'] = true;
+ } elseif ($this->allow_list_files_mode) {
+ $tabs['jobfiles_subtab_text'] = true;
+ }
+ $this->getCallbackClient()->callClientFunction('init_graphical_running_job_status', array($running_job_status, $tabs));
}
public function getRunningJobStatus($clientid) {
return $this->getViewState(self::JOB_TYPE);
}
+ /**
+ * Set job level.
+ *
+ * @return none;
+ */
+ public function setJobLevel($job_level) {
+ $this->setViewState(self::JOB_LEVEL, $job_level);
+ }
+
+ /**
+ * Get job level.
+ *
+ * @return string job level
+ */
+ public function getJobLevel() {
+ return $this->getViewState(self::JOB_LEVEL);
+ }
+
/**
* Refresh job log page and load latest logs.
*
--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2019 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.
+ */
+
+
+Prado::using('System.Web.UI.ActiveControls.TActiveLabel');
+Prado::using('System.Web.UI.ActiveControls.TActiveTextBox');
+Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList');
+Prado::using('System.Web.UI.ActiveControls.TActiveRepeater');
+Prado::using('System.Web.UI.ActiveControls.TCallback');
+Prado::using('System.Web.UI.WebControls.TListItem');
+Prado::using('Application.Web.Portlets.Portlets');
+
+class JobListFiles extends Portlets {
+
+ const JOBID = 'JobId';
+
+ const DEFAULT_PAGE_SIZE = 100;
+
+ public function onLoad($param) {
+ parent::onLoad($param);
+ if ($this->getPage()->IsPostBack || $this->getPage()->IsCallBack) {
+ return;
+ }
+ $this->FileListOffset->Text = 0;
+ $this->FileListLimit->Text = self::DEFAULT_PAGE_SIZE;
+ }
+
+ public function loadFileList($sender, $param) {
+ $params = array(
+ 'offset' => intval($this->FileListOffset->Text),
+ 'limit' => intval($this->FileListLimit->Text)
+ );
+ if (!empty($this->FileListType->SelectedValue)) {
+ $params['type'] = $this->FileListType->SelectedValue;
+ }
+ if (!empty($this->FileListSearch->Text)) {
+ $params['search'] = $this->FileListSearch->Text;
+ }
+ $query = '?' . http_build_query($params);
+ $result = $this->getModule('api')->get(
+ array('jobs', $this->getJobId(), 'files', $query)
+ );
+ if ($result->error === 0) {
+ $file_list = $result->output->items;
+ if (!empty($this->FileListSearch->Text)) {
+ $file_list = $this->findFileListItems($file_list, $this->FileListSearch->Text);
+ }
+ $this->FileList->DataSource = $file_list;
+ $this->FileList->dataBind();
+ $this->FileListCount->Text = $result->output->total;
+ } else {
+ $this->FileList->DataSource = array();
+ $this->FileList->dataBind();
+ $this->FileListCount->Text = 0;
+ }
+ }
+
+ private function findFileListItems($file_list, $keyword) {
+ $result = array();
+ for ($i = 0; $i < count($file_list); $i++) {
+ $pos = stripos($file_list[$i], $keyword);
+ $str1 = substr($file_list[$i], 0, $pos);
+ $key_len = strlen($keyword);
+ $key = substr($file_list[$i], $pos, $key_len);
+ $str2 = substr($file_list[$i], ($pos + $key_len));
+ $result[] = $str1 . '<strong class="w3-text-red">' . $key . '</strong>' . $str2;
+ }
+ return $result;
+ }
+
+ /**
+ * Set job identifier to show files.
+ *
+ * @return none
+ */
+ public function setJobId($jobid) {
+ $jobid = intval($jobid);
+ $this->setViewState(self::JOBID, $jobid, 0);
+ }
+
+ /**
+ * Get job identifier to show files.
+ *
+ * @return integer job identifier
+ */
+ public function getJobId() {
+ return $this->getViewState(self::JOBID, 0);
+ }
+}
+?>
--- /dev/null
+<div class="w3-panel">
+ <button type="button" class="w3-button w3-dark-grey w3-right w3-margin-left" onclick="get_job_list_files(1);"><%[ Next ]%> <i class="fa fa-arrow-right"></i></button>
+ <button type="button" class="w3-button w3-dark-grey w3-right w3-margin-left" onclick="get_job_list_files(-1);"><i class="fa fa-arrow-left"></i> <%[ Previous ]%></button>
+ <button type="button" class="w3-button w3-dark-grey w3-right" onclick="load_job_list_files();"><i class="fa fa-check"></i> <%[ Apply ]%></button>
+ <div style="display: inline-block;" class="w3-right w3-margin-right">
+ <span><%[ Offset: ]%></span> <com:TActiveTextBox ID="FileListOffset" Width="70px" CssClass="w3-input w3-border" Style="display: inline-block" />
+ <span><%[ Limit: ]%></span> <com:TActiveTextBox ID="FileListLimit" Width="70px" CssClass="w3-input w3-border" Style="display: inline-block" />
+ </div>
+ <div style="display: inline-block;" class="w3-right w3-margin-right">
+ <%[ List type: ]%> <com:TActiveDropDownList ID="FileListType" CssClass="w3-select w3-border" style="width: 150px;">
+ <com:TListItem Value="" Text="<%[ saved items ]%>" />
+ <com:TListItem Value="deleted" Text="<%[ deleted items ]%>" />
+ <com:TListItem Value="all" Text="<%[ all ]%>" />
+ </com:TActiveDropDownList>
+ </div>
+ <div style="display: inline-block; margin-right: 5px;" class="w3-left">
+ <%[ Search: ]%> <com:TActiveTextBox
+ ID="FileListSearch"
+ CssClass="w3-input w3-border"
+ Style="width: 200px; display: inline-block;"
+ Attributes.placeholder="<%[ Find file or directory ]%>"
+ Attributes.onkeyup="var keycode = event.keyCode || event.which; if (keycode === 13) { find_job_list_items(); }"
+ />
+ <button type="button" class="w3-button w3-dark-grey" onclick="find_job_list_items();"><i class="fas fa-search"></i> <%[ Find ]%></button>
+ <button type="button" class="w3-button w3-dark-grey" onclick="clear_job_list_items();" title="<%[ Clear ]%>"><i class="fas fa-times"></i></button>
+ <span class="w3-margin-left"><%[ Item count: ]%> <com:TActiveLabel ID="FileListCount" /></span>
+ <i id="jobfiles_loading" class="fa fa-sync w3-spin w3-margin-left" style="display: none;"></i>
+ </div>
+</div>
+<div class="w3-container">
+ <div id="job_list_files_no_result" class="w3-panel w3-center" style="display: none"><strong><%[ No item result ]%></strong></div>
+ <com:TActiveRepeater ID="FileList">
+ <prop:HeaderTemplate>
+ <ul>
+ </prop:HeaderTemplate>
+ <prop:ItemTemplate>
+ <li><%=$this->Data%></li>
+ </prop:ItemTemplate>
+ <prop:FooterTemplate>
+ </ul>
+ </prop:FooterTemplate>
+ </com:TActiveRepeater>
+</div>
+<com:TCallback
+ ID="LoadJobFileList"
+ OnCallback="loadFileList"
+ ClientSide.OnLoading="show_job_list_files_loader(true)"
+ ClientSide.OnComplete="job_list_files_msg(); show_job_list_files_loader(false)"
+/>
+<script>
+function get_job_list_files(page_direction) {
+ var ofs = document.getElementById('<%=$this->FileListOffset->ClientID%>');
+ var lmt = document.getElementById('<%=$this->FileListLimit->ClientID%>');
+ var ofs_val = (parseInt(lmt.value, 10) * page_direction) + parseInt(ofs.value, 10);
+ ofs.value = (ofs_val > 0) ? ofs_val : 0;
+ load_job_list_files();
+}
+function find_job_list_items() {
+ document.getElementById('<%=$this->FileListOffset->ClientID%>').value = 0;
+ document.getElementById('<%=$this->FileListLimit->ClientID%>').value = <%=JobListFiles::DEFAULT_PAGE_SIZE%>;
+ load_job_list_files();
+}
+function clear_job_list_items() {
+ document.getElementById('<%=$this->FileListSearch->ClientID%>').value = '';
+ find_job_list_items();
+}
+function load_job_list_files() {
+ var request = <%=$this->LoadJobFileList->ActiveControl->Javascript%>;
+ request.dispatch();
+}
+function job_list_files_msg() {
+ var flc = document.getElementById('<%=$this->FileListCount->ClientID%>');
+ var item_count = parseInt(flc.textContent, 10);
+ document.getElementById('job_list_files_no_result').style.display = item_count == 0 ? '' : 'none';
+}
+function show_job_list_files_loader(show) {
+ document.getElementById('jobfiles_loading').style.display = (show ? '' : 'none');
+}
+job_list_files_msg();
+</script>
const DEFAULT_JOB_PRIORITY = 10;
- public $job_to_verify = array('C', 'O', 'd');
+ public $job_to_verify = array('C', 'O', 'd', 'A');
public $verify_options = array('jobname' => 'Verify by Job Name', 'jobid' => 'Verify by JobId');