2 // Bweb - A Bacula web interface
3 // Bacula® - The Network Backup Solution
5 // Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
7 // The main author of Bweb is Eric Bollengier.
8 // The main author of Bacula is Kern Sibbald, with contributions from
9 // many others, a complete list can be found in the file AUTHORS.
11 // This program is Free Software; you can redistribute it and/or
12 // modify it under the terms of version two of the GNU General Public
13 // License as published by the Free Software Foundation plus additions
14 // that are listed in the file LICENSE.
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 // Bacula® is a registered trademark of John Walker.
27 // The licensor of Bacula is the Free Software Foundation Europe
28 // (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
29 // Switzerland, email:ftf@fsfeurope.org.
31 // render if vol is online/offline
32 function rd_vol_is_online(val)
34 return '<img src="/bweb/inflag' + val + '.png">';
37 // TODO: fichier ou rep
38 function rd_file_or_dir(val)
41 return '<img src="/bweb/A.png">';
43 return '<img src="/bweb/R.png">';
47 Ext.namespace('Ext.brestore');
49 Ext.brestore.jobid=0; // selected jobid
50 Ext.brestore.jobdate=''; // selected date
51 Ext.brestore.client=''; // selected client
52 Ext.brestore.rclient=''; // selected client for resto
53 Ext.brestore.storage=''; // selected storage for resto
54 Ext.brestore.path=''; // current path (without user location)
55 Ext.brestore.root_path=''; // user location
57 Ext.brestore.option_vosb = false;
58 Ext.brestore.option_vafv = false;
59 Ext.brestore.dlglaunch;
60 Ext.BLANK_IMAGE_URL = '/bweb/ext/resources/images/aero/s.gif'; // 1.1
62 function get_node_path(node)
65 for (var p = node; p; p = p.parentNode) {
70 temp = p.text + '/' + temp;
74 return Ext.brestore.root_path + temp;
78 function init_params(baseParams)
80 baseParams['client']= Ext.brestore.client;
82 if (Ext.brestore.option_vosb) {
83 baseParams['jobid'] = Ext.brestore.jobid;
85 baseParams['date'] = Ext.brestore.jobdate;
93 //////////////////////////////////////////////////////////////:
95 var tree_loader = new Ext.tree.TreeLoader({
97 dataUrl:'/cgi-bin/bweb/bresto.pl'
100 var tree = new Ext.tree.TreePanel('div-tree', {
104 enableDragDrop: true,
105 containerScroll: true
109 var root = new Ext.tree.AsyncTreeNode({
110 text: 'Select a client then a job',
114 tree.setRootNode(root);
115 Ext.brestore.tree = root;
121 tree.on('click', function(node, event) {
122 Ext.brestore.path = get_node_path(node);
123 where_field.setValue(Ext.brestore.path);
124 file_store.removeAll();
125 file_versions_store.removeAll();
126 file_store.load({params:init_params({action: 'list_files',
132 tree.on('beforeload', function(e) {
133 file_store.removeAll();
138 ////////////////////////////////////////////////////////////////
140 var file_store = new Ext.data.Store({
141 proxy: new Ext.data.HttpProxy({
142 url: '/cgi-bin/bweb/bresto.pl',
147 reader: new Ext.data.ArrayReader({
148 }, Ext.data.Record.create([
150 {name: 'filenameid'},
154 {name: 'size', type: 'int' },
155 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
159 var cm = new Ext.grid.ColumnModel([{
160 id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
164 css: 'white-space:normal;'
168 renderer: human_size,
178 dataIndex: 'filenameid',
189 // by default columns are sortable
190 cm.defaultSortable = true;
193 var files_grid = new Ext.grid.Grid('div-files', {
198 enableDragDrop: true,
199 selModel: new Ext.grid.RowSelectionModel(),
205 // when we reload the view,
206 // we clear the file version box
207 file_store.on('beforeload', function(e) {
208 file_versions_store.removeAll();
212 // TODO: selection only when using dblclick
213 files_grid.selModel.on('rowselect', function(e,i,r) {
214 Ext.brestore.filename = r.json[3];
215 file_versions_store.load({params:init_params({action: 'list_versions',
216 vafv: Ext.brestore.option_vafv,
218 filenameid: r.json[1]
225 //////////////////////////////////////////////////////////////:
227 var file_selection_store = new Ext.data.Store({
228 proxy: new Ext.data.MemoryProxy(),
230 reader: new Ext.data.ArrayReader({
231 }, Ext.data.Record.create([
234 {name: 'filenameid'},
237 {name: 'size', type: 'int' },
238 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
242 var file_selection_cm = new Ext.grid.ColumnModel([{
243 id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
254 renderer: human_size,
265 dataIndex: 'filenameid',
276 var file_selection_grid = new Ext.grid.Grid('div-file-selection', {
277 cm: file_selection_cm,
278 ds: file_selection_store,
282 selModel: new Ext.grid.RowSelectionModel(),
288 var file_selection_record = Ext.data.Record.create(
291 {name: 'filenameid'},
296 // data.selections[0].json[]
298 // http://extjs.com/forum/showthread.php?t=12582&highlight=drag+drop
299 var ddrow = new Ext.dd.DropTarget(file_selection_grid.container, {
302 notifyDrop : function(dd, e, data){
304 if (data.selections) {
305 if (data.grid.id == 'div-files') {
306 for(var i=0;i<data.selections.length;i++) {
307 r = new file_selection_record({
308 jobid: data.selections[0].json[3],
309 fileid: data.selections[i].json[0],
310 filenameid:data.selections[i].json[1],
311 pathid: data.selections[i].json[2],
312 name: Ext.brestore.path + data.selections[i].json[4],
313 size: data.selections[i].json[5],
314 mtime: data.selections[i].json[6]
316 file_selection_store.add(r)
320 if (data.grid.id == 'div-file-versions') {
321 r = new file_selection_record({
322 jobid: data.selections[0].json[3],
323 fileid: data.selections[0].json[0],
324 filenameid:data.selections[0].json[1],
325 pathid: data.selections[0].json[2],
326 name: Ext.brestore.path + Ext.brestore.filename,
327 size: data.selections[0].json[7],
328 mtime: data.selections[0].json[8]
330 file_selection_store.add(r)
335 var path= get_node_path(data.node);
336 r = new file_selection_record({
337 jobid: data.node.attributes.jobid,
340 pathid: data.node.id,
345 file_selection_store.add(r)
352 file_selection_grid.on('enddrag', function(dd,e) {
353 alert(e) ; return true;
355 file_selection_grid.on('notifyDrop', function(dd,e) {
356 alert(e) ; return true;
358 file_selection_grid.render();
360 ///////////////////////////////////////////////////////
362 var file_versions_store = new Ext.data.Store({
363 proxy: new Ext.data.HttpProxy({
364 url: '/cgi-bin/bweb/bresto.pl',
366 params:{offset:0, limit:50 }
369 reader: new Ext.data.ArrayReader({
370 }, Ext.data.Record.create([
372 {name: 'filenameid'},
376 {name: 'inchanger' },
378 {name: 'size', type: 'int' },
379 {name: 'mtime'} //, type: 'date', dateFormat: 'Y-m-d h:i:s'}
383 var file_versions_cm = new Ext.grid.ColumnModel([{
384 id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
389 dataIndex: 'inchanger',
391 renderer: rd_vol_is_online
402 renderer: human_size,
416 dataIndex: 'filenameid',
424 // by default columns are sortable
425 file_versions_cm.defaultSortable = true;
428 var file_versions_grid = new Ext.grid.Grid('div-file-versions', {
429 ds: file_versions_store,
430 cm: file_versions_cm,
434 selModel: new Ext.grid.RowSelectionModel(),
440 file_versions_grid.on('rowdblclick', function(e) {
441 alert(e) ; file_versions_store.removeAll(); return true;
443 file_versions_grid.render();
445 //////////////////////////////////////////////////////////////:
448 var client_store = new Ext.data.Store({
449 proxy: new Ext.data.HttpProxy({
450 url: '/cgi-bin/bweb/bresto.pl',
452 params:{action:'list_client'}
455 reader: new Ext.data.ArrayReader({
456 }, Ext.data.Record.create([
461 var client_combo = new Ext.form.ComboBox({
462 fieldLabel: 'Clients',
467 triggerAction: 'all',
468 emptyText:'Select a client...',
470 forceSelection: true,
474 client_combo.on('valid', function(e) {
475 Ext.brestore.client = e.getValue();
476 Ext.brestore.jobid=0;
477 Ext.brestore.jobdate = '';
478 Ext.brestore.root_path='';
479 job_combo.clearValue();
480 file_store.removeAll();
481 file_versions_store.removeAll();
482 root.collapse(false, false);
483 while(root.firstChild){
484 root.removeChild(root.firstChild);
486 job_store.load( {params:{action: 'list_job',
487 client:Ext.brestore.client}});
491 //////////////////////////////////////////////////////////////:
493 var job_store = new Ext.data.Store({
494 proxy: new Ext.data.HttpProxy({
495 url: '/cgi-bin/bweb/bresto.pl',
497 params:{offset:0, limit:50 }
500 reader: new Ext.data.ArrayReader({
501 }, Ext.data.Record.create([
508 var job_combo = new Ext.form.ComboBox({
511 displayField:'jobname',
514 triggerAction: 'all',
515 emptyText:'Select a job...',
517 forceSelection: true,
521 job_combo.on('select', function(e,c) {
522 Ext.brestore.jobid = c.json[0];
523 Ext.brestore.jobdate = c.json[1];
524 Ext.brestore.root_path='';
525 root.setText("Root");
526 tree_loader.baseParams = init_params({init:1, action: 'list_dirs'});
530 ////////////////////////////////////////////////////////////////
532 function sel_option(item, check)
534 if (item.id == 'id_vosb') {
535 Ext.brestore.option_vosb = check;
537 if (item.id == 'id_vafv') {
538 Ext.brestore.option_vafv = check;
542 var menu = new Ext.menu.Menu({
545 new Ext.menu.CheckItem({
547 text: 'View only selected backup',
548 checked: Ext.brestore.option_vosb,
549 checkHandler: sel_option
551 new Ext.menu.CheckItem({
553 text: 'View all file versions',
554 checked: Ext.brestore.option_vafv,
555 checkHandler: sel_option
559 ////////////////////////////////////////////////////////////////:
561 // create the primary toolbar
562 var tb2 = new Ext.Toolbar('div-tb-sel');
564 var where_field = new Ext.form.TextField({
565 fieldLabel: 'Location',
571 var tb = new Ext.Toolbar('div-toolbar', [
577 // icon: '/bweb/up.gif',
578 text: 'Change location',
579 cls:'x-btn-text-icon',
580 handler: function() {
581 var where = where_field.getValue();
582 Ext.brestore.root_path=where;
584 tree_loader.baseParams = init_params({ action:'list_dirs', path: where });
591 cls: 'x-btn-text-icon bmenu', // icon and text class
593 menu: menu // assign menu by instance
596 icon: '/bweb/remove.png', // icons can also be specified inline
599 handler: function() {
600 if (Ext.brestore.dlglaunch) {
601 Ext.brestore.dlglaunch.show();
604 Ext.brestore.dlglaunch = new Ext.LayoutDialog("div-resto-dlg", {
618 // collapsible: true,
623 // tabPosition: 'top',
625 // alwaysShowTabs: true
629 var fs = new Ext.form.Form({
634 // var resto_store = new Ext.data.Store({
635 // proxy: new Ext.data.HttpProxy({
636 // url: '/cgi-bin/bweb/bresto.pl',
638 // params:{action:'list_resto'}
641 // reader: new Ext.data.ArrayReader({
642 // }, Ext.data.Record.create([
647 var rclient_combo = new Ext.form.ComboBox({
648 value: Ext.brestore.client,
649 fieldLabel: 'client',
655 triggerAction: 'all',
656 emptyText:'Select a client...',
660 var where_text = new Ext.form.TextField({
663 value: '/tmp/bacula-restore',
666 var storage_store = new Ext.data.Store({
667 proxy: new Ext.data.HttpProxy({
668 url: '/cgi-bin/bweb/bresto.pl',
670 params:{action:'list_storage'}
673 reader: new Ext.data.ArrayReader({
674 }, Ext.data.Record.create([
678 var storage_combo = new Ext.form.ComboBox({
679 fieldLabel: 'storage',
680 hiddenName:'storage',
681 store: storage_store,
685 triggerAction: 'all',
686 emptyText:'Select a storage...',
691 {legend:'Restore job'},
692 // new Ext.form.ComboBox({
693 // fieldLabel: 'Replace',
694 // hiddenName:'replace',
695 // store: new Ext.data.SimpleStore({
696 // fields: ['replace'],
697 // data : [['always'],['never'],['if newer']]
699 // displayField:'replace',
702 // triggerAction: 'all',
703 // emptyText:'never',
704 // selectOnFocus:true,
708 // new Ext.form.ComboBox({
709 // fieldLabel: 'job',
711 // store: resto_store,
712 // displayField:'name',
715 // triggerAction: 'all',
716 // emptyText:'Select a job...',
717 // selectOnFocus:true,
725 storage_store.load({params:{action: 'list_storage'}});
726 // resto_store.load({params:{action: 'list_resto'}});
727 fs.render('div-resto-form');
729 // var f = new Ext.form.BasicForm('div-resto-form', {url: '/bweb/test', method: 'GET',
730 // baseParams: {init: 1}
734 var launch_restore = function() {
735 var items = file_selection_store.data.items;
736 var tab_fileid=new Array();
737 var tab_dirid=new Array();
738 var tab_jobid=new Array();
739 for(var i=0;i<items.length;i++) {
740 if (items[i].data['fileid']) {
741 tab_fileid.push(items[i].data['fileid']);
743 tab_dirid.push(items[i].data['pathid']);
745 tab_jobid.push(items[i].data['jobid']);
747 var res = ';fileid=' + tab_fileid.join(";fileid=");
748 var res2 = ';dirid=' + tab_dirid.join(";dirid=");
749 var res3 = ';jobid=' + tab_jobid.join(";jobid=");
751 var res4 = ';client=' + rclient_combo.getValue() + ';storage=' + storage_combo.getValue() + ';where=' + where_text.getValue();
753 window.location='/cgi-bin/bweb/bresto.pl?action=restore' + res + res2 + res3 + res4;
755 var dialog = Ext.brestore.dlglaunch;
756 dialog.addKeyListener(27, dialog.hide, dialog);
757 dialog.addButton('Submit', launch_restore);
758 dialog.addButton('Close', dialog.hide, dialog);
760 var layout = dialog.getLayout();
761 layout.beginUpdate();
762 layout.add('center', new Ext.ContentPanel('div-resto-form', {
763 autoCreate:true, title: 'Third Tab', closable:true, background:true}));
771 ////////////////////////////////////////////////////////////////
773 var layout = new Ext.BorderLayout(document.body, {
778 split: true, initialSize: 300
781 split: true, initialSize: 550
784 split: true, initialSize: 300
792 layout.beginUpdate();
793 layout.add('north', new Ext.ContentPanel('div-toolbar', {
794 fitToFrame: true, autoCreate:true,closable: false
796 layout.add('south', new Ext.ContentPanel('div-file-selection', {
797 toolbar: tb2,resizeEl:'div-file-selection',
798 fitToFrame: true, autoCreate:true,closable: false
800 layout.add('east', new Ext.ContentPanel('div-file-versions', {
801 fitToFrame: true, autoCreate:true,closable: false
803 layout.add('west', new Ext.ContentPanel('div-tree', {
804 autoScroll:true, fitToFrame: true,
805 autoCreate:true,closable: false
807 layout.add('center', new Ext.ContentPanel('div-files', {
808 autoScroll:true,autoCreate:true,fitToFrame: true
813 ////////////////////////////////////////////////////////////////
816 client_store.load({params:{action: 'list_client'}});
817 // file_store.load({params:{offset:0, limit:50}});
818 // file_versions_store.load({params:{offset:0, limit:50}});
819 // file_selection_store.load();
822 Ext.onReady( ext_init );