mirror of
				https://git.proxmox.com/git/proxmox-backup
				synced 2025-11-02 15:18:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
Ext.define('pbs-file-tree', {
 | 
						|
    extend: 'Ext.data.Model',
 | 
						|
 | 
						|
    fields: ['filepath', 'text', 'type', 'size',
 | 
						|
	{
 | 
						|
	    name: 'mtime',
 | 
						|
	    type: 'date',
 | 
						|
	    dateFormat: 'timestamp',
 | 
						|
	},
 | 
						|
	{
 | 
						|
	    name: 'iconCls',
 | 
						|
	    calculate: function(data) {
 | 
						|
		let icon = 'file-o';
 | 
						|
		switch (data.type) {
 | 
						|
		    case 'b': // block device
 | 
						|
			icon = 'cube';
 | 
						|
			break;
 | 
						|
		    case 'c': // char device
 | 
						|
			icon = 'tty';
 | 
						|
			break;
 | 
						|
		    case 'd':
 | 
						|
			icon = data.expanded ? 'folder-open-o' : 'folder-o';
 | 
						|
			break;
 | 
						|
		    case 'f': //regular file
 | 
						|
			icon = 'file-text-o';
 | 
						|
			break;
 | 
						|
		    case 'h': // hardlink
 | 
						|
			icon = 'file-o';
 | 
						|
			break;
 | 
						|
		    case 'l': // softlink
 | 
						|
			icon = 'link';
 | 
						|
			break;
 | 
						|
		    case 'p': // pipe/fifo
 | 
						|
			icon = 'exchange';
 | 
						|
			break;
 | 
						|
		    case 's': // socket
 | 
						|
			icon = 'plug';
 | 
						|
			break;
 | 
						|
		    default:
 | 
						|
			icon = 'file-o';
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
		return `fa fa-${icon}`;
 | 
						|
	    },
 | 
						|
	},
 | 
						|
    ],
 | 
						|
    idProperty: 'filepath',
 | 
						|
});
 | 
						|
 | 
						|
Ext.define("PBS.window.FileBrowser", {
 | 
						|
    extend: "Ext.window.Window",
 | 
						|
 | 
						|
    width: 800,
 | 
						|
    height: 600,
 | 
						|
 | 
						|
    modal: true,
 | 
						|
 | 
						|
    controller: {
 | 
						|
	xclass: 'Ext.app.ViewController',
 | 
						|
 | 
						|
	buildUrl: function(baseurl, params) {
 | 
						|
	    let url = new URL(baseurl, window.location.origin);
 | 
						|
	    for (const [key, value] of Object.entries(params)) {
 | 
						|
		url.searchParams.append(key, value);
 | 
						|
	    }
 | 
						|
 | 
						|
	    return url.href;
 | 
						|
	},
 | 
						|
 | 
						|
	downloadFile: function() {
 | 
						|
	    let me = this;
 | 
						|
	    let view = me.getView();
 | 
						|
	    let tree = me.lookup('tree');
 | 
						|
	    let selection = tree.getSelection();
 | 
						|
	    if (!selection || selection.length < 1) return;
 | 
						|
 | 
						|
	    let data = selection[0].data;
 | 
						|
 | 
						|
	    let atag = document.createElement('a');
 | 
						|
 | 
						|
	    atag.download = data.text;
 | 
						|
	    let params = {
 | 
						|
		'backup-id': view['backup-id'],
 | 
						|
		'backup-type': view['backup-type'],
 | 
						|
		'backup-time': view['backup-time'],
 | 
						|
	    };
 | 
						|
	    params.filepath = data.filepath;
 | 
						|
	    atag.download = data.text;
 | 
						|
	    atag.href = me
 | 
						|
	        .buildUrl(`/api2/json/admin/datastore/${view.datastore}/pxar-file-download`, params);
 | 
						|
	    atag.click();
 | 
						|
	},
 | 
						|
 | 
						|
	fileChanged: function() {
 | 
						|
	    let me = this;
 | 
						|
	    let tree = me.lookup('tree');
 | 
						|
	    let selection = tree.getSelection();
 | 
						|
	    if (!selection || selection.length < 1) return;
 | 
						|
 | 
						|
	    let data = selection[0].data;
 | 
						|
 | 
						|
	    let canDownload = false;
 | 
						|
	    switch (data.type) {
 | 
						|
		case 'h':
 | 
						|
		case 'f':
 | 
						|
		    canDownload = true;
 | 
						|
		    break;
 | 
						|
		default: break;
 | 
						|
	    }
 | 
						|
 | 
						|
	    me.lookup('downloadBtn').setDisabled(!canDownload);
 | 
						|
	},
 | 
						|
 | 
						|
	init: function(view) {
 | 
						|
	    let me = this;
 | 
						|
	    let tree = me.lookup('tree');
 | 
						|
 | 
						|
	    if (!view['backup-id']) {
 | 
						|
		throw "no backup-id given";
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (!view['backup-type']) {
 | 
						|
		throw "no backup-id given";
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (!view['backup-time']) {
 | 
						|
		throw "no backup-id given";
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (!view.datastore) {
 | 
						|
		throw "no datastore given";
 | 
						|
	    }
 | 
						|
 | 
						|
	    let store = tree.getStore();
 | 
						|
	    let proxy = store.getProxy();
 | 
						|
 | 
						|
	    Proxmox.Utils.monStoreErrors(tree, store, true);
 | 
						|
	    proxy.setUrl(`/api2/json/admin/datastore/${view.datastore}/catalog`);
 | 
						|
	    proxy.setExtraParams({
 | 
						|
		'backup-id': view['backup-id'],
 | 
						|
		'backup-type': view['backup-type'],
 | 
						|
		'backup-time': view['backup-time'],
 | 
						|
	    });
 | 
						|
	    store.load(() => {
 | 
						|
		let root = store.getRoot();
 | 
						|
		root.expand(); // always expand invisible root node
 | 
						|
		if (view.archive) {
 | 
						|
		    let child = root.findChild('text', view.archive);
 | 
						|
		    if (child) {
 | 
						|
			child.expand();
 | 
						|
			setTimeout(function() {
 | 
						|
			    tree.setSelection(child);
 | 
						|
			    tree.getView().focusRow(child);
 | 
						|
			}, 10);
 | 
						|
		    }
 | 
						|
		} else if (root.childNodes.length === 1) {
 | 
						|
		    root.firstChild.expand();
 | 
						|
		}
 | 
						|
	    });
 | 
						|
	},
 | 
						|
 | 
						|
	control: {
 | 
						|
	    'treepanel': {
 | 
						|
		selectionchange: 'fileChanged',
 | 
						|
	    },
 | 
						|
	},
 | 
						|
    },
 | 
						|
 | 
						|
    layout: 'fit',
 | 
						|
    items: [
 | 
						|
	{
 | 
						|
	    xtype: 'treepanel',
 | 
						|
	    scrollable: true,
 | 
						|
	    rootVisible: false,
 | 
						|
	    reference: 'tree',
 | 
						|
	    store: {
 | 
						|
		autoLoad: false,
 | 
						|
		model: 'pbs-file-tree',
 | 
						|
		nodeParam: 'filepath',
 | 
						|
		sorters: 'text',
 | 
						|
		proxy: {
 | 
						|
		    appendId: false,
 | 
						|
		    type: 'proxmox',
 | 
						|
		},
 | 
						|
	    },
 | 
						|
 | 
						|
	    columns: [
 | 
						|
		{
 | 
						|
		    text: gettext('Name'),
 | 
						|
		    xtype: 'treecolumn',
 | 
						|
		    flex: 1,
 | 
						|
		    dataIndex: 'text',
 | 
						|
		    renderer: Ext.String.htmlEncode,
 | 
						|
		},
 | 
						|
		{
 | 
						|
		    text: gettext('Size'),
 | 
						|
		    dataIndex: 'size',
 | 
						|
		    renderer: value => value === undefined ? '' : Proxmox.Utils.format_size(value),
 | 
						|
		    sorter: {
 | 
						|
			sorterFn: function(a, b) {
 | 
						|
			    let asize = a.data.size || 0;
 | 
						|
			    let bsize = b.data.size || 0;
 | 
						|
 | 
						|
			    return asize - bsize;
 | 
						|
			},
 | 
						|
		    },
 | 
						|
		},
 | 
						|
		{
 | 
						|
		    text: gettext('Modified'),
 | 
						|
		    dataIndex: 'mtime',
 | 
						|
		    minWidth: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
		    text: gettext('Type'),
 | 
						|
		    dataIndex: 'type',
 | 
						|
		    renderer: function(value) {
 | 
						|
			switch (value) {
 | 
						|
			    case 'b': return gettext('Block Device');
 | 
						|
			    case 'c': return gettext('Character Device');
 | 
						|
			    case 'd': return gettext('Directory');
 | 
						|
			    case 'f': return gettext('File');
 | 
						|
			    case 'h': return gettext('Hardlink');
 | 
						|
			    case 'l': return gettext('Softlink');
 | 
						|
			    case 'p': return gettext('Pipe/Fifo');
 | 
						|
			    case 's': return gettext('Socket');
 | 
						|
			    default: return Proxmox.Utils.unknownText;
 | 
						|
			}
 | 
						|
		    },
 | 
						|
		},
 | 
						|
	    ],
 | 
						|
	},
 | 
						|
    ],
 | 
						|
 | 
						|
    buttons: [
 | 
						|
	{
 | 
						|
	    text: gettext('Download'),
 | 
						|
	    handler: 'downloadFile',
 | 
						|
	    reference: 'downloadBtn',
 | 
						|
	    disabled: true,
 | 
						|
	},
 | 
						|
    ],
 | 
						|
});
 |