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',
127 path:Ext.brestore.path,
133 tree.on('beforeload', function(e) {
134 file_store.removeAll();
139 ////////////////////////////////////////////////////////////////
141 var file_store = new Ext.data.Store({
142 proxy: new Ext.data.HttpProxy({
143 url: '/cgi-bin/bweb/bresto.pl',
148 reader: new Ext.data.ArrayReader({
149 }, Ext.data.Record.create([
151 {name: 'filenameid'},
155 {name: 'size', type: 'int' },
156 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
160 var cm = new Ext.grid.ColumnModel([{
161 id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
165 css: 'white-space:normal;'
169 renderer: human_size,
174 renderer: Ext.util.Format.dateRenderer('Y-m-d h:i'),
180 dataIndex: 'filenameid',
191 // by default columns are sortable
192 cm.defaultSortable = true;
194 var files_grid = new Ext.grid.Grid('div-files', {
199 enableDragDrop: true,
200 selModel: new Ext.grid.RowSelectionModel(),
202 autoSizeColumns: true,
206 // when we reload the view,
207 // we clear the file version box
208 file_store.on('beforeload', function(e) {
209 file_versions_store.removeAll();
213 // TODO: selection only when using dblclick
214 files_grid.selModel.on('rowselect', function(e,i,r) {
215 if (r.json[4] == '.') {
218 Ext.brestore.filename = r.json[4];
219 file_versions_store.load({params:init_params({action: 'list_versions',
220 vafv: Ext.brestore.option_vafv,
222 filenameid: r.json[1]
228 //////////////////////////////////////////////////////////////:
230 var file_selection_store = new Ext.data.Store({
231 proxy: new Ext.data.MemoryProxy(),
233 reader: new Ext.data.ArrayReader({
234 }, Ext.data.Record.create([
237 {name: 'filenameid'},
240 {name: 'size', type: 'int' },
241 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
245 var file_selection_cm = new Ext.grid.ColumnModel([{
246 id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
257 renderer: human_size,
262 renderer: Ext.util.Format.dateRenderer('Y-m-d h:i'),
269 dataIndex: 'filenameid',
280 var file_selection_grid = new Ext.grid.Grid('div-file-selection', {
281 cm: file_selection_cm,
282 ds: file_selection_store,
286 selModel: new Ext.grid.RowSelectionModel(),
291 var file_selection_record = Ext.data.Record.create(
294 {name: 'filenameid'},
299 // data.selections[0].json[]
301 // http://extjs.com/forum/showthread.php?t=12582&highlight=drag+drop
302 var ddrow = new Ext.dd.DropTarget(file_selection_grid.container, {
305 notifyDrop : function(dd, e, data){
307 if (data.selections) {
308 if (data.grid.id == 'div-files') {
309 for(var i=0;i<data.selections.length;i++) {
310 r = new file_selection_record({
311 jobid: data.selections[0].json[3],
312 fileid: data.selections[i].json[0],
313 filenameid:data.selections[i].json[1],
314 pathid: data.selections[i].json[2],
315 name: Ext.brestore.path + data.selections[i].json[4],
316 size: data.selections[i].json[5],
317 mtime: data.selections[i].json[6]
319 file_selection_store.add(r)
323 if (data.grid.id == 'div-file-versions') {
324 r = new file_selection_record({
325 jobid: data.selections[0].json[3],
326 fileid: data.selections[0].json[0],
327 filenameid:data.selections[0].json[1],
328 pathid: data.selections[0].json[2],
329 name: Ext.brestore.path + Ext.brestore.filename,
330 size: data.selections[0].json[7],
331 mtime: data.selections[0].json[8]
333 file_selection_store.add(r)
338 var path= get_node_path(data.node);
339 r = new file_selection_record({
340 jobid: data.node.attributes.jobid,
343 pathid: data.node.id,
348 file_selection_store.add(r)
354 file_selection_grid.on('enddrag', function(dd,e) {
355 alert(e) ; return true;
357 file_selection_grid.on('notifyDrop', function(dd,e) {
358 alert(e) ; return true;
360 func1 = function(e,b,c) {
361 if (e.browserEvent.keyCode == 46) {
362 for (elt in file_selection_grid.getSelectionModel().getSelections()) {
364 // file_selection_store.remove(elt);
368 file_selection_grid.on('keypress', func1);
369 ///////////////////////////////////////////////////////
371 var file_versions_store = new Ext.data.Store({
372 proxy: new Ext.data.HttpProxy({
373 url: '/cgi-bin/bweb/bresto.pl',
375 params:{offset:0, limit:50 }
378 reader: new Ext.data.ArrayReader({
379 }, Ext.data.Record.create([
381 {name: 'filenameid'},
385 {name: 'inchanger' },
387 {name: 'size', type: 'int' },
388 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
392 var file_versions_cm = new Ext.grid.ColumnModel([{
393 id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
398 dataIndex: 'inchanger',
400 renderer: rd_vol_is_online
411 renderer: human_size,
416 renderer: Ext.util.Format.dateRenderer('Y-m-d h:i'),
427 header: "filenameid",
428 dataIndex: 'filenameid',
437 // by default columns are sortable
438 file_versions_cm.defaultSortable = true;
441 var file_versions_grid = new Ext.grid.Grid('div-file-versions', {
442 ds: file_versions_store,
443 cm: file_versions_cm,
447 selModel: new Ext.grid.RowSelectionModel(),
453 file_versions_grid.on('rowdblclick', function(e) {
454 alert(e) ; file_versions_store.removeAll(); return true;
457 //////////////////////////////////////////////////////////////:
460 var client_store = new Ext.data.Store({
461 proxy: new Ext.data.HttpProxy({
462 url: '/cgi-bin/bweb/bresto.pl',
464 params:{action:'list_client'}
467 reader: new Ext.data.ArrayReader({
468 }, Ext.data.Record.create([
473 var client_combo = new Ext.form.ComboBox({
474 fieldLabel: 'Clients',
479 triggerAction: 'all',
480 emptyText:'Select a client...',
482 forceSelection: true,
486 client_combo.on('valid', function(e) {
487 Ext.brestore.client = e.getValue();
488 Ext.brestore.jobid=0;
489 Ext.brestore.jobdate = '';
490 Ext.brestore.root_path='';
491 job_combo.clearValue();
492 file_store.removeAll();
493 file_versions_store.removeAll();
494 root.collapse(false, false);
495 while(root.firstChild){
496 root.removeChild(root.firstChild);
498 job_store.load( {params:{action: 'list_job',
499 client:Ext.brestore.client}});
503 //////////////////////////////////////////////////////////////:
505 var job_store = new Ext.data.Store({
506 proxy: new Ext.data.HttpProxy({
507 url: '/cgi-bin/bweb/bresto.pl',
509 params:{offset:0, limit:50 }
512 reader: new Ext.data.ArrayReader({
513 }, Ext.data.Record.create([
520 var job_combo = new Ext.form.ComboBox({
523 displayField:'jobname',
526 triggerAction: 'all',
527 emptyText:'Select a job...',
530 forceSelection: true,
534 job_combo.on('select', function(e,c) {
535 Ext.brestore.jobid = c.json[0];
536 Ext.brestore.jobdate = c.json[1];
537 Ext.brestore.root_path='';
538 root.setText("Root");
539 tree_loader.baseParams = init_params({init:1, action: 'list_dirs'});
543 ////////////////////////////////////////////////////////////////
545 function sel_option(item, check)
547 if (item.id == 'id_vosb') {
548 Ext.brestore.option_vosb = check;
550 if (item.id == 'id_vafv') {
551 Ext.brestore.option_vafv = check;
555 var menu = new Ext.menu.Menu({
558 new Ext.menu.CheckItem({
560 text: 'View only selected backup',
561 checked: Ext.brestore.option_vosb,
562 checkHandler: sel_option
564 new Ext.menu.CheckItem({
566 text: 'View all file versions',
567 checked: Ext.brestore.option_vafv,
568 checkHandler: sel_option
572 ////////////////////////////////////////////////////////////////:
574 // create the primary toolbar
575 var tb2 = new Ext.Toolbar('div-tb-sel');
577 var where_field = new Ext.form.TextField({
578 fieldLabel: 'Location',
584 var tb = new Ext.Toolbar('div-toolbar', [
590 // icon: '/bweb/up.gif',
591 text: 'Change location',
592 cls:'x-btn-text-icon',
593 handler: function() {
594 var where = where_field.getValue();
595 Ext.brestore.root_path=where;
597 tree_loader.baseParams = init_params({ action:'list_dirs', path: where });
604 cls: 'x-btn-text-icon bmenu', // icon and text class
606 menu: menu // assign menu by instance
609 icon: '/bweb/mR.png', // icons can also be specified inline
612 handler: function() {
613 if (Ext.brestore.dlglaunch) {
614 Ext.brestore.dlglaunch.show();
617 Ext.brestore.dlglaunch = new Ext.LayoutDialog("div-resto-dlg", {
631 // collapsible: true,
636 // tabPosition: 'top',
638 // alwaysShowTabs: true
642 var fs = new Ext.form.Form({
647 // var resto_store = new Ext.data.Store({
648 // proxy: new Ext.data.HttpProxy({
649 // url: '/cgi-bin/bweb/bresto.pl',
651 // params:{action:'list_resto'}
654 // reader: new Ext.data.ArrayReader({
655 // }, Ext.data.Record.create([
660 var rclient_combo = new Ext.form.ComboBox({
661 value: Ext.brestore.client,
662 fieldLabel: 'Client',
668 triggerAction: 'all',
669 emptyText:'Select a client...',
673 var where_text = new Ext.form.TextField({
676 value: '/tmp/bacula-restore',
679 var stripprefix_text = new Ext.form.TextField({
680 fieldLabel: 'Strip prefix',
681 name: 'strip_prefix',
686 var addsuffix_text = new Ext.form.TextField({
687 fieldLabel: 'Add suffix',
693 var addprefix_text = new Ext.form.TextField({
694 fieldLabel: 'Add prefix',
700 var rwhere_text = new Ext.form.TextField({
701 fieldLabel: 'Where regexp',
702 name: 'regexp_where',
707 var usefilerelocation_bp = new Ext.form.Checkbox({
708 fieldLabel: 'Use file relocation',
709 name: 'use_relocation',
712 var useregexp_bp = new Ext.form.Checkbox({
713 fieldLabel: 'Use regexp',
718 usefilerelocation_bp.on('check', function(bp,state) {
720 where_text.disable();
721 useregexp_bp.enable();
722 if (useregexp_bp.getValue()) {
723 addsuffix_text.disable();
724 addprefix_text.disable();
725 stripprefix_text.disable();
726 rwhere_text.enable();
728 addsuffix_text.enable();
729 addprefix_text.enable();
730 stripprefix_text.enable();
731 rwhere_text.disable();
735 addsuffix_text.disable();
736 addprefix_text.disable();
737 stripprefix_text.disable();
738 useregexp_bp.disable();
739 rwhere_text.disable();
743 useregexp_bp.on('check', function(bp,state) {
745 addsuffix_text.disable();
746 addprefix_text.disable();
747 stripprefix_text.disable();
748 rwhere_text.enable();
750 addsuffix_text.enable();
751 addprefix_text.enable();
752 stripprefix_text.enable();
753 rwhere_text.disable();
758 var storage_store = new Ext.data.Store({
759 proxy: new Ext.data.HttpProxy({
760 url: '/cgi-bin/bweb/bresto.pl',
762 params:{action:'list_storage'}
765 reader: new Ext.data.ArrayReader({
766 }, Ext.data.Record.create([
770 var storage_combo = new Ext.form.ComboBox({
771 fieldLabel: 'Storage',
772 hiddenName:'storage',
773 store: storage_store,
777 triggerAction: 'all',
778 emptyText:'Select a storage...',
782 ////////////////////////////////////////////////////////////////
783 var media_store = new Ext.data.Store({
784 proxy: new Ext.data.HttpProxy({
785 url: '/cgi-bin/bweb/bresto.pl',
787 params:{offset:0, limit:50 }
790 reader: new Ext.data.ArrayReader({
791 }, Ext.data.Record.create([
792 {name: 'volumename'},
798 var media_cm = new Ext.grid.ColumnModel([{
800 dataIndex: 'inchanger',
802 renderer: rd_vol_is_online
806 dataIndex: 'volumename',
812 var media_grid = new Ext.grid.Grid('div-media', {
822 var items = file_selection_store.data.items;
823 var tab_fileid=new Array();
824 var tab_jobid=new Array();
825 for(var i=0;i<items.length;i++) {
826 if (items[i].data['fileid']) {
827 tab_fileid.push(items[i].data['fileid']);
829 tab_jobid.push(items[i].data['jobid']);
831 var res = tab_fileid.join(",");
832 var res2 = tab_jobid.join(",");
834 ////////////////////////////////////////////////////////////////
836 {legend:'Media needed'},
840 {legend:'Restore options'},
841 new Ext.form.ComboBox({
842 fieldLabel: 'Replace',
843 hiddenName:'replace',
844 store: new Ext.data.SimpleStore({
846 data : [['always'],['never'],['if newer']]
848 displayField:'replace',
851 triggerAction: 'all',
857 // new Ext.form.ComboBox({
858 // fieldLabel: 'job',
860 // store: resto_store,
861 // displayField:'name',
864 // triggerAction: 'all',
865 // emptyText:'Select a job...',
866 // selectOnFocus:true,
875 {legend:'File relocation'},
876 usefilerelocation_bp,
883 media_store.baseParams = init_params({action: 'get_media', jobid: res2, fileid: res});
885 storage_store.load({params:{action: 'list_storage'}});
886 // resto_store.load({params:{action: 'list_resto'}});
887 fs.render('div-resto-form');
889 // var f = new Ext.form.BasicForm('div-resto-form', {url: '/bweb/test', method: 'GET',
890 // baseParams: {init: 1}
894 var launch_restore = function() {
895 var items = file_selection_store.data.items;
896 var tab_fileid=new Array();
897 var tab_dirid=new Array();
898 var tab_jobid=new Array();
899 for(var i=0;i<items.length;i++) {
900 if (items[i].data['fileid']) {
901 tab_fileid.push(items[i].data['fileid']);
903 tab_dirid.push(items[i].data['pathid']);
905 tab_jobid.push(items[i].data['jobid']);
907 var res = ';fileid=' + tab_fileid.join(";fileid=");
908 var res2 = ';dirid=' + tab_dirid.join(";dirid=");
909 var res3 = ';jobid=' + tab_jobid.join(";jobid=");
911 var res4 = ';client=' + rclient_combo.getValue();
912 if (storage_combo.getValue()) {
913 res4 = res4 + ';storage=' + storage_combo.getValue();
915 if (usefilerelocation_bp.getValue()) {
916 if (useregexp_bp.getValue()) {
917 res4 = res4 + ';regexwhere=' + rwhere_text.getValue();
919 var reg = new Array();
920 if (stripprefix_text.getValue()) {
921 reg.push('!' + stripprefix_text.getValue() + '!!i');
923 if (addprefix_text.getValue()) {
924 reg.push('!^!' + addprefix_text.getValue() + '!');
926 if (addsuffix_text.getValue()) {
927 reg.push('!([^/])$!$1' + addsuffix_text.getValue() + '!');
929 res4 = res4 + ';regexwhere=' + reg.join(',');
932 res4 = res4 + ';where=' + where_text.getValue();
934 window.location='/cgi-bin/bweb/bresto.pl?action=restore' + res + res2 + res3 + res4;
935 } // end launch_restore
937 var dialog = Ext.brestore.dlglaunch;
938 dialog.addKeyListener(27, dialog.hide, dialog);
939 dialog.addButton('Submit', launch_restore);
940 dialog.addButton('Close', dialog.hide, dialog);
942 var layout = dialog.getLayout();
943 layout.beginUpdate();
944 layout.add('center', new Ext.ContentPanel('div-resto-form', {
945 autoCreate:true, title: 'Third Tab', closable:true, background:true}));
953 ////////////////////////////////////////////////////////////////
955 var layout = new Ext.BorderLayout(document.body, {
960 split: true, initialSize: 300
963 split: true, initialSize: 550
966 split: true, initialSize: 300
974 layout.beginUpdate();
975 layout.add('north', new Ext.ContentPanel('div-toolbar', {
976 fitToFrame: true, autoCreate:true,closable: false
978 layout.add('south', new Ext.ContentPanel('div-file-selection', {
979 toolbar: tb2,resizeEl:'div-file-selection',
980 fitToFrame: true, autoCreate:true,closable: false
982 layout.add('east', new Ext.ContentPanel('div-file-versions', {
983 fitToFrame: true, autoCreate:true,closable: false
985 layout.add('west', new Ext.ContentPanel('div-tree', {
986 autoScroll:true, fitToFrame: true,
987 autoCreate:true,closable: false
989 layout.add('center', new Ext.ContentPanel('div-files', {
990 autoScroll:true,autoCreate:true,fitToFrame: true
995 ////////////////////////////////////////////////////////////////
998 client_store.load({params:{action: 'list_client'}});
999 // file_store.load({params:{offset:0, limit:50}});
1000 // file_versions_store.load({params:{offset:0, limit:50}});
1001 // file_selection_store.load();
1002 files_grid.render();
1003 file_selection_grid.render();
1004 file_versions_grid.render();
1007 Ext.onReady( ext_init );