+++ /dev/null
-// require("js/omv/tree/Panel.js")
-// require("js/omv/module/admin/service/zfs/TreePanel.js")
-// require("js/omv/workspace/window/Grid.js")
-
-Ext.define("OMV.module.admin.services.zfs.AddObject", {
- extend: "OMV.workspace.window.Form",
- uses: [
- "OMV.data.Store",
- "OMV.data.Model",
- "OMV.data.proxy.Rpc",
- "OMV.data.reader.RpcArray"
- ],
-
- rpcService: "ZFS",
- rpcSetMethod: "addObject",
- width: 420,
-
- getFormItems: function() {
- var me = this;
- return [{
- xtype: "combo",
- name: "type",
- fieldLabel: _("Object Type"),
- queryMode: "local",
- store: [
- [ "filesystem", "Filesystem" ],
- [ "snapshot", "Snapshot" ],
- [ "volume", "Volume" ]
- ],
- allowBlank: true,
- editable: false,
- triggerAction: "all",
- value: "filesystem",
- listeners: {
- scope: me,
- change: function(combo, value) {
- var sizeField = this.findField("size");
- switch(value) {
- case "volume":
- sizeField.show();
- sizeField.allowBlank = false;
- break;
- default:
- sizeField.hide();
- sizeField.allowBlank = true;
- break;
- }
- sizeField.validate();
- }
- }
- },{
- xtype: "textfield",
- name: "path",
- fieldLabel: _("Prefix"),
- allowBlank: false,
- readOnly: true
- },{
- xtype: "textfield",
- name: "name",
- fieldLabel: _("Name"),
- allowBlank: false,
- plugins: [{
- ptype: "fieldinfo",
- text: _("Name of the new object. Prefix will prepend the name. Please omit leading /")
- }]
- },{
- xtype: "textfield",
- name: "size",
- hidden: true,
- fieldLabel: _("Size"),
- allowBlank: true,
- plugins: [{
- ptype: "fieldinfo",
- text: _("Size of the volume e.g. 5mb,100gb,1tb etc")
- }]
- }];
- }
-});
-
-
-
-Ext.define("OMV.module.admin.service.zfs.EditProperties", {
- extend: "OMV.workspace.window.Grid",
- requires: [
- "OMV.data.Store",
- "OMV.data.Model",
- "OMV.data.proxy.Rpc"
- ],
-
- rpcService: "ZFS",
- rpcSetMethod: "setProperties",
-
- title: _("Edit properties"),
- width: 500,
- height: 305,
-
- getGridConfig: function() {
- var me = this;
-
- var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
- clicksToEdit: 1,
- pluginId: 'rowEditing',
- listeners: {
- validateedit: function(editor, e, eOpts) {
- e.record.set("modified", "true");
- },
- beforeedit: function(editor, e, eOpts) {
- if (e.record.get("property") === "mountpoint") {
- e.grid.getPlugin('rowEditing').editor.form.findField("value").disable();
- e.grid.getPlugin('rowEditing').editor.form.findField("property").disable();
- } else if (e.record.get("newproperty") === "false") {
- e.grid.getPlugin('rowEditing').editor.form.findField("value").enable();
- e.grid.getPlugin('rowEditing').editor.form.findField("property").disable();
- } else {
- e.grid.getPlugin('rowEditing').editor.form.findField("value").enable();
- e.grid.getPlugin('rowEditing').editor.form.findField("property").enable();
- }
- }
-
- }
- });
-
- var store = Ext.create("OMV.data.Store", {
- autoLoad: true,
- model: OMV.data.Model.createImplicit({
- fields: [
- { name: "property", type: "string" },
- { name: "value", type: "string" },
- { name: "source", type: "string" },
- { name: "modified", type: "string" },
- { name: "newproperty", type: "string", defaultValue: "false" }
- ]
- }),
- proxy: {
- type: "rpc",
- rpcData: {
- service: "ZFS",
- method: "getProperties",
- params: {
- name: me.name,
- type: me.type
- }
- }
- }
- });
-
- return {
- border: false,
- stateful: true,
- stateId: "8c3dc800-bdbb-11e3-b1b6-0800200c9a66",
- selType: 'rowmodel',
- plugins: [rowEditing],
- store: store,
- tbar: [{
- text: "Add property",
- icon: "images/add.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- handler: function(view) {
- Ext.define('Property', {
- extend: 'Ext.data.Model',
- fields: [
- "property",
- "value",
- "source",
- "modified",
- "newproperty"
- ]
- });
- var newProperty = Ext.create("Property", {
- property: "",
- value: "",
- source: "local",
- modified: "true",
- newproperty: "true"
- });
- rowEditing.cancelEdit();
- store.insert(0, newProperty);
- rowEditing.startEdit();
- }
- }],
- columns: [{
- text: _("Property"),
- sortable: true,
- dataIndex: "property",
- stateId: "property",
- editor: {
- xtype: "textfield",
- allowBlank: false,
- }
- },{
- text: _("Value"),
- sortable: true,
- dataIndex: "value",
- stateId: "value",
- flex: 1,
- readOnly: true,
- editor: {
- xtype: "textfield",
- allowBlank: false,
- }
- },{
- text: _("Source"),
- sortable: true,
- dataIndex: "source",
- stateId: "source",
- },{
- xtype: 'actioncolumn',
- header: 'Inherit',
- icon: "images/checkmark.png",
- tooltip: "Inherit",
- handler: function(view, rowIndex, colIndex, item, e, record, row) {
- OMV.RpcObserver.request({
- msg : _("Updating property..."),
- rpcData : {
- service: "ZFS",
- method: "inherit",
- params: {
- name: me.name,
- type: me.type,
- property: record.get("property")
- }
- },
- finish : function() {
- view.getStore().reload();
- }
- });
- },
- isDisabled: function(view, rowIdx, colIdx, item, record) {
- var src = record.get("source");
- if(src === "local") {
- return false;
- } else {
- return true;
- }
- }
- },{
- text: _("New"),
- dataIndex: "newproperty",
- stateId: "newproperty",
- sortable: false,
- hidden: true
- },{
- text: _("Modified"),
- sortable: false,
- dataIndex: "modified",
- stateId: "modified",
- hidden: true
- }],
- };
- },
-
- getRpcSetParams: function() {
- var me = this;
- var properties = [];
- var values = me.getValues();
- Ext.Array.each(values, function(value) {
- if(value.modified === "false")
- return;
- properties.push({
- "property": value.property,
- "value": value.value,
- });
- });
- return {
- name: me.name,
- type: me.type,
- properties: properties
- };
- }
-
-});
-
-
-Ext.define("OMV.module.admin.services.zfs.CreateShare", {
- extend: "OMV.workspace.window.Form",
- uses: [
- "OMV.data.Store",
- "OMV.data.Model",
- "OMV.data.proxy.Rpc",
- "OMV.data.reader.RpcArray"
- ],
-
- rpcService: "ZFS",
- rpcSetMethod: "createShare",
- width: 500,
-
- getFormItems: function() {
- var me = this;
- return [{
- xtype: "textfield",
- name: "sharename",
- fieldLabel: _("Name"),
- allowBlank: false,
- },{
- xtype: "textfield",
- name: "mountpoint",
- fieldLabel: _("Path"),
- allowBlank: false,
- readOnly: true
- },{
- xtype: "combo",
- name: "mode",
- fieldLabel: _("Permissions"),
- queryMode: "local",
- store: Ext.create("Ext.data.ArrayStore", {
- fields: [ "value", "text" ],
- data: [
- [ "700", _("Administrator: read/write, Users: no access, Others: no access") ],
- [ "750", _("Administrator: read/write, Users: read-only, Others: no access") ],
- [ "770", _("Administrator: read/write, Users: read/write, Others: no access") ],
- [ "755", _("Administrator: read/write, Users: read-only, Others: read-only") ],
- [ "775", _("Administrator: read/write, Users: read/write, Others: read-only") ],
- [ "777", _("Everyone: read/write") ]
- ]
- }),
- displayField: "text",
- valueField: "value",
- allowBlank: false,
- editable: false,
- showItemTooltip: true,
- triggerAction: "all",
- value: "775",
- plugins: [{
- ptype: "fieldinfo",
- text: _("The file mode of the shared folder path.")
- }]
- },{
- xtype: "textarea",
- name: "comment",
- fieldLabel: _("Comment"),
- allowBlank: true
- },{
- xtype: "textarea",
- name: "name",
- hidden: true
- },{
- xtype: "textarea",
- name: "type",
- hidden: true
- }];
- }
-});
-
-
-
-Ext.define("OMV.module.admin.service.zfs.Overview", {
- extend: "OMV.module.admin.services.zfs.TreePanel",
-
- rpcService: "ZFS",
- rpcGetMethod: "getObjectTree",
- requires: [
- "OMV.data.Store",
- "OMV.data.Model",
- "OMV.data.proxy.Rpc"
- ],
-
- rootVisible: false,
- stateful: true,
- stateId: "cec54550-bc2a-11e3-a5e2-0800200c9a66",
-
- columns: [{
- text: _("Name"),
- xtype: 'treecolumn',
- dataIndex: 'name',
- sortable: true,
- flex: 2,
- stateId: 'name'
- },{
- text: _("Type"),
- dataIndex: 'type',
- sortable: true,
- flex: 1,
- stateId: 'type'
- },{
- text: _("Share"),
- xtype: 'actioncolumn',
- tooltip: 'Create shared folder',
- align: 'center',
- icon: 'images/checkmark.png',
- handler: function(view, rowIndex, colIndex, item, e, record, row) {
- var me = this;
- Ext.create("OMV.module.admin.services.zfs.CreateShare", {
- title: _("Create shared folder"),
- rpcGetMethod: "getSharedParams",
- rpcGetParams: {
- name: record.get('path'),
- type: record.get('type')
- }
- }).show();
- },
- isDisabled: function(view, rowIdx, colIdx, item, record) {
- var src = record.get("type");
- if((src === "Filesystem") && (record.get("shared") === "false")) {
- return false;
- } else {
- return true;
- }
- }
-
-
- },{
- text: _("Details"),
- xtype: 'actioncolumn',
- tooltip: 'Details',
- align: 'center',
- icon: 'images/zfs_mag.png'
- },{
- text: _("Shared"),
- dataIndex: 'shared',
- sortable: false,
- stateId: 'shared',
- hidden: true
- }],
-
- initComponent: function() {
- var me = this;
- this.width = 600;
- Ext.apply(me, {
- store: Ext.create("Ext.data.TreeStore", {
- autoLoad: true,
- model: OMV.data.Model.createImplicit({
- fields: [
- { name: "name", type: "string" },
- { name: "type", type: "string" },
- { name: "id", type: "string" },
- { name: "path", type: "string" },
- { name: "origin", type: "string", defaultValue: "none" },
- { name: "shared", type: "string", defaultValue: "false" }
- ]
- }),
- proxy: {
- type: "rpc",
- rpcData: {
- service: "ZFS",
- method: "getObjectTree",
- }
- },
- folderSort: true
- })
- });
- me.callParent(arguments);
- },
-
- onAddObjButton: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var records = sm.getSelection();
- var record = records[0];
- Ext.create("OMV.module.admin.services.zfs.AddObject", {
- title: _("Add Object"),
- rpcGetMethod: "passParam",
- rpcGetParams: {
- key: "path",
- value: record.get('path')
- },
- listeners: {
- scope: me,
- submit: function() {
- this.doReload();
- }
- }
- }).show();
- },
-
- onEditButton: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var records = sm.getSelection();
- var record = records[0];
- Ext.create("OMV.module.admin.service.zfs.EditProperties", {
- name: record.get("path"),
- type: record.get("type")
- }).show();
- },
-
- doDeletion: function(record) {
- var me = this;
- OMV.Rpc.request({
- scope: me,
- callback: me.onDeletion,
- rpcData: {
- service: "ZFS",
- method: "deleteObject",
- params: {
- name: record.get('path'),
- type: record.get('type')
- }
- }
- });
- }
-
-});
-
-OMV.WorkspaceManager.registerPanel({
- id: "overview",
- path: "/service/zfs",
- text: _("Overview"),
- position: 10,
- className: "OMV.module.admin.service.zfs.Overview"
-});
-
-
-
+++ /dev/null
-/**
- * This file is part of OpenMediaVault.
- *
- * @license http://www.gnu.org/licenses/gpl.html GPL Version 3
- * @author Volker Theile <volker.theile@openmediavault.org>
- * @copyright Copyright (c) 2009-2014 Volker Theile
- *
- * OpenMediaVault is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * any later version.
- *
- * OpenMediaVault is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenMediaVault. If not, see <http://www.gnu.org/licenses/>.
- */
-// require("js/omv/tree/Panel.js")
-// require("js/omv/grid/Panel.js")
-// require("js/omv/grid/column/BinaryUnit.js")
-// require("js/omv/grid/column/BooleanIcon.js")
-// require("js/omv/grid/column/BooleanText.js")
-// require("js/omv/grid/column/Empty.js")
-// require("js/omv/grid/column/Hyperlink.js")
-// require("js/omv/grid/column/UnixTimestamp.js")
-// require("js/omv/grid/column/WhiteSpace.js")
-// require("js/omv/window/MessageBox.js")
-
-/**
- * @ingroup webgui
- * @class OMV.workspace.grid.Panel
- * @derived OMV.grid.Panel
- * An enhanced grid panel. This grid provides 'Add', 'Edit' and 'Delete'
- * buttons in the toolbar by default. The basic delete functionality is also
- * implemented, simply overwrite the 'doDeletion' and 'afterDeletion'
- * functions to implement fit your requirements. To implement the 'Add' and
- * 'Edit' functionality overwrite the 'onAdd' and 'onEdit' callback
- * functions. A paging toolbar which is displayed at the bottom of the grid
- * can be displayed also. It is also possible to reload the grid
- * automatically in a given interval.
- * @param hideTopToolbar TRUE to hide the whole toolbar. Defaults to FALSE.
- * @param hidePagingToolbar TRUE to hide the paging toolbar at the bottom of
- * the grid. Defaults to TRUE.
- * @param hideAddButton Hide the 'Add' button in the top toolbar.
- * Defaults to FALSE.
- * @param hideEditButton Hide the 'Edit' button in the top toolbar.
- * Defaults to FALSE.
- * @param hideDeleteButton Hide the 'Delete' button in the top toolbar.
- * Defaults to FALSE.
- * @param hideUpButton Hide the 'Up' button in the top toolbar.
- * Defaults to TRUE.
- * @param hideDownButton Hide the 'Down' button in the top toolbar.
- * Defaults to TRUE.
- * @param hideApplyButton Hide the 'Apply' button in the top toolbar.
- * Defaults to TRUE.
- * @param hideRefreshButton Hide the 'Refresh' button in the top toolbar.
- * Defaults to TRUE.
- * @param addButtonText The button text. Defaults to 'Add'.
- * @param editButtonText The button text. Defaults to 'Edit'.
- * @param deleteButtonText The button text. Defaults to 'Delete'.
- * @param upButtonText The button text. Defaults to 'Up'.
- * @param downButtonText The button text. Defaults to 'Down'.
- * @param applyButtonText The button text. Defaults to 'Save'.
- * @param refreshButtonText The button text. Defaults to 'Refresh'.
- * @param deletionConfirmRequired Set to TRUE to force the user to confirm
- * the deletion request. Defaults to TRUE.
- * @param deletionWaitMsg The message displayed during the deletion process.
- * @param mode The mode how to retrieve the data displayed in the grid panel.
- * This can be 'local' or 'remote' which means the data is requested via
- * RPC. Defaults to 'remote'.
- * @param rememberSelected TRUE to reselect the previous selected rows
- * after the grid content has been reloaded/refreshed. Defaults to FALSE.
- */
-Ext.define("OMV.module.admin.services.zfs.TreePanel", {
- extend: "OMV.tree.Panel",
- requires: [
- "OMV.window.MessageBox",
- "OMV.grid.column.BinaryUnit",
- "OMV.grid.column.BooleanIcon",
- "OMV.grid.column.BooleanText",
- "OMV.grid.column.Empty",
- "OMV.grid.column.Hyperlink",
- "OMV.grid.column.UnixTimestamp",
- "OMV.grid.column.WhiteSpace"
- ],
-
- border: false,
- rowLines: false,
- columnLines: true,
- selModel: {
- allowDeselect: true,
- mode: "SINGLE"
- },
-
- hideTopToolbar: false,
- hidePagingToolbar: true,
- hideAddButton: false,
- hideAddObjButton: false,
- hideEditButton: false,
- hideDeleteButton: false,
- hideUpButton: true,
- hideDownButton: true,
- hideApplyButton: true,
- hideRefreshButton: true,
- addButtonText: _("Add Pool"),
- addObjButtonText: _("Add Object"),
- editButtonText: _("Edit"),
- deleteButtonText: _("Delete"),
- upButtonText: _("Up"),
- downButtonText: _("Down"),
- applyButtonText: _("Save"),
- refreshButtonText: _("Refresh"),
- deletionConfirmRequired: true,
- deletionWaitMsg: _("Deleting selected item(s)"),
- mode: "remote",
- rememberSelected: false,
-
- initComponent: function() {
- var me = this;
- // Initialize toolbars.
- me.dockedItems = [];
- if(!me.hideTopToolbar) {
- me.dockedItems.push(me.topToolbar = Ext.widget({
- xtype: "toolbar",
- dock: "top",
- items: me.getTopToolbarItems(me)
- }));
- }
- if(!me.hidePagingToolbar) {
- me.dockedItems.push({
- xtype: "toolbar",
- dock: "bottom",
- items: [ me.pagingToolbar = Ext.widget({
- xtype: "pagingtoolbar",
- store: me.store,
- displayInfo: true,
- displayMsg: _("Displaying items {0} - {1} of {2}"),
- emptyMsg: _("No items to display")
- }) ]
- });
- }
- me.callParent(arguments);
- // Register event handler.
- // Process double clicks in grid.
- me.on("itemdblclick", me.onItemDblClick, me);
- // Process selections in grid, e.g. to update the toolbar.
- var selModel = me.getSelectionModel();
- selModel.on("selectionchange", me.onSelectionChange, me);
- // Remember selection to restore it after the grid has been
- // refreshed.
- if(me.rememberSelected) {
- me.getStore().on("beforeload", function() {
- if(!me.rendered || Ext.isEmpty(me.getEl()))
- return;
- if(!selModel.hasSelection())
- return;
- me.previousSelected = selModel.getSelection();
- });
- me.getView().on("refresh", function(view) {
- if(Ext.isEmpty(me.previousSelected))
- return;
- var select = [];
- Ext.Array.each(me.previousSelected, function(r) {
- var record = me.getStore().getById(r.getId());
- if(!Ext.isEmpty(record))
- select.push(record);
- });
- delete me.previousSelected;
- if(select.length > 0) {
- selModel.select(select, false, false);
- selModel.view.focusNode(select[0]);
- }
- });
- }
- },
-
- /**
- * Returns the items displayed in the top toolbar.
- * @param c This component object.
- * @return An array of buttons displayed in the top toolbar.
- */
- getTopToolbarItems: function(c) {
- var me = this;
- return [{
- id: me.getId() + "-add",
- xtype: "button",
- text: me.addButtonText,
- icon: "images/add.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideAddButton,
- handler: Ext.Function.bind(me.onAddButton, me, [ me ]),
- scope: me
- },{
- id: me.getId() + "-addobj",
- xtype: "button",
- text: me.addObjButtonText,
- icon: "images/add.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideAddObjButton,
- handler: Ext.Function.bind(me.onAddObjButton, me, [ me ]),
- scope: me,
- disabled: true
- },{
- id: me.getId() + "-edit",
- xtype: "button",
- text: me.editButtonText,
- icon: "images/edit.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideEditButton,
- handler: Ext.Function.bind(me.onEditButton, me, [ me ]),
- scope: me,
- disabled: true
- },{
- id: me.getId() + "-delete",
- xtype: "button",
- text: me.deleteButtonText,
- icon: "images/delete.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideDeleteButton,
- handler: Ext.Function.bind(me.onDeleteButton, me, [ me ]),
- scope: me,
- disabled: true
- },{
- id: me.getId() + "-up",
- xtype: "button",
- text: me.upButtonText,
- icon: "images/arrow-up.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideUpButton,
- handler: Ext.Function.bind(me.onUpButton, me, [ me ]),
- scope: me,
- disabled: true
- },{
- id: me.getId() + "-down",
- xtype: "button",
- text: me.downButtonText,
- icon: "images/arrow-down.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideDownButton,
- handler: Ext.Function.bind(me.onDownButton, me, [ me ]),
- scope: me,
- disabled: true
- },{
- id: me.getId() + "-apply",
- xtype: "button",
- text: me.applyButtonText,
- icon: "images/checkmark.png",
- hidden: me.hideApplyButton,
- handler: Ext.Function.bind(me.onApplyButton, me, [ me ]),
- scope: me
- },{
- id: me.getId() + "-refresh",
- xtype: "button",
- text: me.refreshButtonText,
- icon: "images/refresh.png",
- iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
- hidden: me.hideRefreshButton,
- handler: Ext.Function.bind(me.onRefreshButton, me, [ me ]),
- scope: me
- }]
- },
-
- /**
- * Handler that is called whenever the selection in the grid has
- * been changed. The top toolbar buttons will be enabled/disabled
- * depending on how much rows has been selected.
- * @param model The selection model
- */
- onSelectionChange: function(model, records) {
- var me = this;
- if(me.hideTopToolbar)
- return;
- var tbarBtnName = [ "addobj", "edit", "delete", "up", "down" ];
- var tbarBtnDisabled = {
- "addobj": false,
- "edit": false,
- "delete": false,
- "up": true,
- "down": true
- };
- // Enable/disable buttons depending on the number of selected rows.
- if(records.length <= 0) {
- tbarBtnDisabled["addobj"] = true;
- tbarBtnDisabled["edit"] = true;
- tbarBtnDisabled["delete"] = true;
- tbarBtnDisabled["up"] = true;
- tbarBtnDisabled["down"] = true;
- } else if(records.length == 1) {
- tbarBtnDisabled["addobj"] = false;
- tbarBtnDisabled["edit"] = false;
- tbarBtnDisabled["delete"] = false;
- tbarBtnDisabled["up"] = false;
- tbarBtnDisabled["down"] = false;
- } else {
- tbarBtnDisabled["addobj"] = true;
- tbarBtnDisabled["edit"] = true;
- tbarBtnDisabled["delete"] = false;
- tbarBtnDisabled["up"] = false;
- tbarBtnDisabled["down"] = false;
- }
- //Disable 'AddObj' button if selected row is a Poool or a Snapshot
- Ext.Array.each(records, function(record) {
- if(("Pool" == record.get("type")) ||
- ("Snapshot" == record.get("type"))) {
- tbarBtnDisabled["addobj"] = true;
- return false;
- }
- });
-
- // Disable 'Delete' button if a selected node is not a leaf
- Ext.Array.each(records, function(record) {
- if((false == record.get("leaf"))) {
- tbarBtnDisabled["delete"] = true;
- return false;
- }
- });
-
- // Update the button controls.
- Ext.Array.each(tbarBtnName, function(name) {
- var tbarBtnCtrl = me.queryById(me.getId() + "-" + name);
- if(!Ext.isEmpty(tbarBtnCtrl)) {
- if(true == tbarBtnDisabled[name]) {
- tbarBtnCtrl.disable();
- } else {
- tbarBtnCtrl.enable();
- }
- }
- });
- },
-
- onItemDblClick: function() {
- var me = this;
- if(!me.hideTopToolbar && !me.hideEditButton) {
- me.onEditButton(me);
- }
- },
-
- /**
- * Load the grid content.
- */
- doLoad: function() {
- var me = this;
- if(me.mode === "remote") {
- me.store.load();
- }
- },
-
- /**
- * Reload the grid content.
- */
- doReload: function() {
- var me = this;
- if(me.mode === "remote") {
- me.store.reload();
- }
- },
-
- /**
- * Handler that is called when the 'Add' button in the top toolbar
- * is pressed. Override this method to customize the default behaviour.
- * @param this The grid itself.
- */
- onAddButton: function() {
- // Nothing to do here
- },
-
- /**
- * * Handler that is called when the 'AddObj' button in the top toolbar
- * is pressed. Override this method to customize the default behaviour.
- * @param this The grid itself.
- */
- onAddObjButton: function() {
- // Nothing to do here
- },
-
-
- /**
- * Handler that is called when the 'Edit' button in the top toolbar
- * is pressed. Override this method to customize the default behaviour.
- * @param this The grid itself.
- */
- onEditButton: function() {
- // Nothing to do here
- },
-
- /**
- * Handler that is called when the 'Up' button in the top toolbar
- * is pressed. Override this method to customize the default behaviour.
- * @param this The grid itself.
- */
- onUpButton: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var records = sm.getSelection();
- if(records.length > 0) {
- // Find the smallest index of the selected rows.
- var ltIndex = me.store.indexOf(records[0]);
- Ext.Array.each(records, function(record) {
- var index = me.store.indexOf(record);
- if(ltIndex > index)
- ltIndex = index;
- });
- // Calculate the index where to insert the rows.
- var index = ltIndex - 1;
- if(index < 0)
- index = 0;
- me.doMoveRows(records, index);
- }
- },
-
- /**
- * Handler that is called when the 'Down' button in the top toolbar
- * is pressed.
- * @param this The grid itself.
- */
- onDownButton: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var records = sm.getSelection();
- if(records.length > 0) {
- // Find the smallest index of the selected rows.
- var ltIndex = me.store.indexOf(records[0]);
- Ext.Array.each(records, function(record) {
- var index = me.store.indexOf(record);
- if(ltIndex > index)
- ltIndex = index;
- });
- // Calculate the index where to insert the rows.
- var index = ltIndex + records.length;
- var count = me.store.getCount() - 1;
- if(index > count)
- index = count;
- me.doMoveRows(records, index);
- }
- },
-
- /**
- * Handler that is called when the 'Apply' button in the top toolbar
- * is pressed. Override this method to customize the default behaviour.
- * @param this The grid itself.
- */
- onApplyButton: function() {
- // Nothing to do here
- },
-
- /**
- * Handler that is called when the 'Refresh' button in the top toolbar
- * is pressed. Override this method to customize the default behaviour.
- * @param this The grid itself.
- */
- onRefreshButton: function() {
- this.doReload();
- },
-
- /**
- * Move the given rows to the given index.
- * @param records The records to move.
- * @param index The index where to insert the rows to be moved.
- */
- doMoveRows: function(records, index) {
- var me = this;
- if(!Ext.isNumber(index))
- return;
- records = Ext.Array.from(records);
- me.store.suspendEvents();
- Ext.Array.each(records, function(record) {
- me.store.remove(record);
- me.store.insert(index, record);
- });
- me.store.resumeEvents();
- me.afterMoveRows(records, index);
- me.getView().refresh();
- },
-
- /**
- * Function that is called after the selected rows have been moved.
- * Override this method to customize the default behaviour.
- * @param records The records that have been move.
- * @param index The index where the rows have been inserted.
- */
- afterMoveRows: function(records, index) {
- var sm = this.getSelectionModel();
- sm.select(records);
- },
-
- /**
- * Handler that is called when the 'Delete' button in the top toolbar
- * is pressed.
- */
- onDeleteButton: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var records = sm.getSelection();
- if(me.deletionConfirmRequired === true) {
- var msg = _("Do you really want to delete the selected item(s)?");
- OMV.MessageBox.show({
- title: _("Confirmation"),
- msg: msg,
- buttons: Ext.Msg.YESNO,
- fn: function(answer) {
- if(answer !== "yes")
- return;
- me.startDeletion(records);
- },
- scope: me,
- icon: Ext.Msg.QUESTION
- });
- } else {
- me.startDeletion(records);
- }
- },
-
- /**
- * @private
- * Private method that is called when the deletion of the selected records
- * has been aggreed.
- * @param records The records to delete.
- */
- startDeletion: function(records) {
- var me = this;
- if(records.length <= 0)
- return;
- // Store selected records in a local variable
- me.delActionInfo = {
- records: records,
- count: records.length
- }
- // Get first record to be deleted
- var record = me.delActionInfo.records.pop();
- // Display progress dialog
- OMV.MessageBox.progress("", me.deletionWaitMsg, "");
- me.updateDeletionProgress();
- // Execute deletion function
- me.doDeletion(record);
- },
-
- /**
- * The method that is called to delete a selected record. Override this
- * method to customize the default behaviour. This is necessary in
- * 'remote' mode.
- */
- doDeletion: function(record) {
- var me = this;
- if(me.mode === "local") {
- // Remove record from store
- me.store.remove(record);
- // Continue deletion process
- me.onDeletion(null, true, null);
- }
- },
-
- /**
- * The method that is called by the 'doDeletion' method. The progress
- * bar will be updated and the deletion progress will be continued if
- * there are still records to delete.
- */
- onDeletion: function(id, success, response) {
- var me = this;
- if(!success) {
- // Remove temporary local variables
- delete me.delActionInfo;
- // Hide progress dialog
- OMV.MessageBox.hide();
- // Display error message
- OMV.MessageBox.error(null, response);
- } else {
- if(me.delActionInfo.records.length > 0) {
- var record = me.delActionInfo.records.pop();
- // Update progress dialog
- me.updateDeletionProgress();
- // Execute deletion function
- me.doDeletion(record);
- } else {
- // Remove temporary local variables
- delete me.delActionInfo;
- // Update and hide progress dialog
- OMV.MessageBox.updateProgress(1, _("100% completed ..."));
- OMV.MessageBox.hide();
- me.afterDeletion();
- }
- }
- },
-
- /**
- * Function that is called after the deletion has been successful finished.
- */
- afterDeletion: function() {
- var me = this;
- if(me.mode === "remote") {
- me.doReload();
- }
- },
-
- /**
- * @private
- * Private helper function to update the progress dialog.
- */
- updateDeletionProgress: function() {
- var me = this;
- // Calculate percentage
- var p = (me.delActionInfo.count - me.delActionInfo.records.length) /
- me.delActionInfo.count;
- // Create message text
- var text = Math.round(100 * p) + _("% completed ...");
- // Update progress dialog
- OMV.MessageBox.updateProgress(p, text);
- },
-
- /**
- * Convenience function for setting the given toolbar button
- * disabled/enabled.
- * @param name The name of the toolbar button.
- * @param disabled TRUE to disable the button, FALSE to enable.
- * @return The button component, otherwise FALSE.
- */
- setToolbarButtonDisabled: function(name, disabled) {
- var me = this;
- var result = false;
- var btnCtrl = me.queryById(me.getId() + "-" + name);
- if(!Ext.isEmpty(btnCtrl) && btnCtrl.isButton)
- result = btnCtrl.setDisabled(disabled);
- return result;
- },
-
- /**
- * Helper function to get the top toolbar object.
- * @return The paging toolbar object or NULL.
- */
- getTopToolbar: function() {
- return this.topToolbar;
- },
-
- /**
- * Helper function to get the paging toolbar object.
- * @return The paging toolbar object or NULL.
- */
- getPagingToolbar: function() {
- return this.pagingToolbar;
- }
-});
-
-
-
+++ /dev/null
-OMV.WorkspaceManager.registerNode({
- id : "zfs",
- path : "/storage",
- text : _("ZFS"),
- icon16 : "images/zfs.png",
- iconSvg : "images/zfs.svg"
-});
-
--- /dev/null
+// require("js/omv/tree/Panel.js")
+// require("js/omv/module/admin/service/zfs/TreePanel.js")
+// require("js/omv/workspace/window/Grid.js")
+
+Ext.define("OMV.module.admin.services.zfs.AddObject", {
+ extend: "OMV.workspace.window.Form",
+ uses: [
+ "OMV.data.Store",
+ "OMV.data.Model",
+ "OMV.data.proxy.Rpc",
+ "OMV.data.reader.RpcArray"
+ ],
+
+ rpcService: "ZFS",
+ rpcSetMethod: "addObject",
+ width: 420,
+
+ getFormItems: function() {
+ var me = this;
+ return [{
+ xtype: "combo",
+ name: "type",
+ fieldLabel: _("Object Type"),
+ queryMode: "local",
+ store: [
+ [ "filesystem", "Filesystem" ],
+ [ "snapshot", "Snapshot" ],
+ [ "volume", "Volume" ]
+ ],
+ allowBlank: true,
+ editable: false,
+ triggerAction: "all",
+ value: "filesystem",
+ listeners: {
+ scope: me,
+ change: function(combo, value) {
+ var sizeField = this.findField("size");
+ switch(value) {
+ case "volume":
+ sizeField.show();
+ sizeField.allowBlank = false;
+ break;
+ default:
+ sizeField.hide();
+ sizeField.allowBlank = true;
+ break;
+ }
+ sizeField.validate();
+ }
+ }
+ },{
+ xtype: "textfield",
+ name: "path",
+ fieldLabel: _("Prefix"),
+ allowBlank: false,
+ readOnly: true
+ },{
+ xtype: "textfield",
+ name: "name",
+ fieldLabel: _("Name"),
+ allowBlank: false,
+ plugins: [{
+ ptype: "fieldinfo",
+ text: _("Name of the new object. Prefix will prepend the name. Please omit leading /")
+ }]
+ },{
+ xtype: "textfield",
+ name: "size",
+ hidden: true,
+ fieldLabel: _("Size"),
+ allowBlank: true,
+ plugins: [{
+ ptype: "fieldinfo",
+ text: _("Size of the volume e.g. 5mb,100gb,1tb etc")
+ }]
+ }];
+ }
+});
+
+
+
+Ext.define("OMV.module.admin.service.zfs.EditProperties", {
+ extend: "OMV.workspace.window.Grid",
+ requires: [
+ "OMV.data.Store",
+ "OMV.data.Model",
+ "OMV.data.proxy.Rpc"
+ ],
+
+ rpcService: "ZFS",
+ rpcSetMethod: "setProperties",
+
+ title: _("Edit properties"),
+ width: 500,
+ height: 305,
+
+ getGridConfig: function() {
+ var me = this;
+
+ var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
+ clicksToEdit: 1,
+ pluginId: 'rowEditing',
+ listeners: {
+ validateedit: function(editor, e, eOpts) {
+ e.record.set("modified", "true");
+ },
+ beforeedit: function(editor, e, eOpts) {
+ if (e.record.get("property") === "mountpoint") {
+ e.grid.getPlugin('rowEditing').editor.form.findField("value").disable();
+ e.grid.getPlugin('rowEditing').editor.form.findField("property").disable();
+ } else if (e.record.get("newproperty") === "false") {
+ e.grid.getPlugin('rowEditing').editor.form.findField("value").enable();
+ e.grid.getPlugin('rowEditing').editor.form.findField("property").disable();
+ } else {
+ e.grid.getPlugin('rowEditing').editor.form.findField("value").enable();
+ e.grid.getPlugin('rowEditing').editor.form.findField("property").enable();
+ }
+ }
+
+ }
+ });
+
+ var store = Ext.create("OMV.data.Store", {
+ autoLoad: true,
+ model: OMV.data.Model.createImplicit({
+ fields: [
+ { name: "property", type: "string" },
+ { name: "value", type: "string" },
+ { name: "source", type: "string" },
+ { name: "modified", type: "string" },
+ { name: "newproperty", type: "string", defaultValue: "false" }
+ ]
+ }),
+ proxy: {
+ type: "rpc",
+ rpcData: {
+ service: "ZFS",
+ method: "getProperties",
+ params: {
+ name: me.name,
+ type: me.type
+ }
+ }
+ }
+ });
+
+ return {
+ border: false,
+ stateful: true,
+ stateId: "8c3dc800-bdbb-11e3-b1b6-0800200c9a66",
+ selType: 'rowmodel',
+ plugins: [rowEditing],
+ store: store,
+ tbar: [{
+ text: "Add property",
+ icon: "images/add.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ handler: function(view) {
+ Ext.define('Property', {
+ extend: 'Ext.data.Model',
+ fields: [
+ "property",
+ "value",
+ "source",
+ "modified",
+ "newproperty"
+ ]
+ });
+ var newProperty = Ext.create("Property", {
+ property: "",
+ value: "",
+ source: "local",
+ modified: "true",
+ newproperty: "true"
+ });
+ rowEditing.cancelEdit();
+ store.insert(0, newProperty);
+ rowEditing.startEdit();
+ }
+ }],
+ columns: [{
+ text: _("Property"),
+ sortable: true,
+ dataIndex: "property",
+ stateId: "property",
+ editor: {
+ xtype: "textfield",
+ allowBlank: false,
+ }
+ },{
+ text: _("Value"),
+ sortable: true,
+ dataIndex: "value",
+ stateId: "value",
+ flex: 1,
+ readOnly: true,
+ editor: {
+ xtype: "textfield",
+ allowBlank: false,
+ }
+ },{
+ text: _("Source"),
+ sortable: true,
+ dataIndex: "source",
+ stateId: "source",
+ },{
+ xtype: 'actioncolumn',
+ header: 'Inherit',
+ icon: "images/checkmark.png",
+ tooltip: "Inherit",
+ handler: function(view, rowIndex, colIndex, item, e, record, row) {
+ OMV.RpcObserver.request({
+ msg : _("Updating property..."),
+ rpcData : {
+ service: "ZFS",
+ method: "inherit",
+ params: {
+ name: me.name,
+ type: me.type,
+ property: record.get("property")
+ }
+ },
+ finish : function() {
+ view.getStore().reload();
+ }
+ });
+ },
+ isDisabled: function(view, rowIdx, colIdx, item, record) {
+ var src = record.get("source");
+ if(src === "local") {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ },{
+ text: _("New"),
+ dataIndex: "newproperty",
+ stateId: "newproperty",
+ sortable: false,
+ hidden: true
+ },{
+ text: _("Modified"),
+ sortable: false,
+ dataIndex: "modified",
+ stateId: "modified",
+ hidden: true
+ }],
+ };
+ },
+
+ getRpcSetParams: function() {
+ var me = this;
+ var properties = [];
+ var values = me.getValues();
+ Ext.Array.each(values, function(value) {
+ if(value.modified === "false")
+ return;
+ properties.push({
+ "property": value.property,
+ "value": value.value,
+ });
+ });
+ return {
+ name: me.name,
+ type: me.type,
+ properties: properties
+ };
+ }
+
+});
+
+
+Ext.define("OMV.module.admin.services.zfs.CreateShare", {
+ extend: "OMV.workspace.window.Form",
+ uses: [
+ "OMV.data.Store",
+ "OMV.data.Model",
+ "OMV.data.proxy.Rpc",
+ "OMV.data.reader.RpcArray"
+ ],
+
+ rpcService: "ZFS",
+ rpcSetMethod: "createShare",
+ width: 500,
+
+ getFormItems: function() {
+ var me = this;
+ return [{
+ xtype: "textfield",
+ name: "sharename",
+ fieldLabel: _("Name"),
+ allowBlank: false,
+ },{
+ xtype: "textfield",
+ name: "mountpoint",
+ fieldLabel: _("Path"),
+ allowBlank: false,
+ readOnly: true
+ },{
+ xtype: "combo",
+ name: "mode",
+ fieldLabel: _("Permissions"),
+ queryMode: "local",
+ store: Ext.create("Ext.data.ArrayStore", {
+ fields: [ "value", "text" ],
+ data: [
+ [ "700", _("Administrator: read/write, Users: no access, Others: no access") ],
+ [ "750", _("Administrator: read/write, Users: read-only, Others: no access") ],
+ [ "770", _("Administrator: read/write, Users: read/write, Others: no access") ],
+ [ "755", _("Administrator: read/write, Users: read-only, Others: read-only") ],
+ [ "775", _("Administrator: read/write, Users: read/write, Others: read-only") ],
+ [ "777", _("Everyone: read/write") ]
+ ]
+ }),
+ displayField: "text",
+ valueField: "value",
+ allowBlank: false,
+ editable: false,
+ showItemTooltip: true,
+ triggerAction: "all",
+ value: "775",
+ plugins: [{
+ ptype: "fieldinfo",
+ text: _("The file mode of the shared folder path.")
+ }]
+ },{
+ xtype: "textarea",
+ name: "comment",
+ fieldLabel: _("Comment"),
+ allowBlank: true
+ },{
+ xtype: "textarea",
+ name: "name",
+ hidden: true
+ },{
+ xtype: "textarea",
+ name: "type",
+ hidden: true
+ }];
+ }
+});
+
+
+
+Ext.define("OMV.module.admin.service.zfs.Overview", {
+ extend: "OMV.module.admin.services.zfs.TreePanel",
+
+ rpcService: "ZFS",
+ rpcGetMethod: "getObjectTree",
+ requires: [
+ "OMV.data.Store",
+ "OMV.data.Model",
+ "OMV.data.proxy.Rpc"
+ ],
+
+ rootVisible: false,
+ stateful: true,
+ stateId: "cec54550-bc2a-11e3-a5e2-0800200c9a66",
+
+ columns: [{
+ text: _("Name"),
+ xtype: 'treecolumn',
+ dataIndex: 'name',
+ sortable: true,
+ flex: 2,
+ stateId: 'name'
+ },{
+ text: _("Type"),
+ dataIndex: 'type',
+ sortable: true,
+ flex: 1,
+ stateId: 'type'
+ },{
+ text: _("Share"),
+ xtype: 'actioncolumn',
+ tooltip: 'Create shared folder',
+ align: 'center',
+ icon: 'images/checkmark.png',
+ handler: function(view, rowIndex, colIndex, item, e, record, row) {
+ var me = this;
+ Ext.create("OMV.module.admin.services.zfs.CreateShare", {
+ title: _("Create shared folder"),
+ rpcGetMethod: "getSharedParams",
+ rpcGetParams: {
+ name: record.get('path'),
+ type: record.get('type')
+ }
+ }).show();
+ },
+ isDisabled: function(view, rowIdx, colIdx, item, record) {
+ var src = record.get("type");
+ if((src === "Filesystem") && (record.get("shared") === "false")) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ },{
+ text: _("Details"),
+ xtype: 'actioncolumn',
+ tooltip: 'Details',
+ align: 'center',
+ icon: 'images/zfs_mag.png'
+ },{
+ text: _("Shared"),
+ dataIndex: 'shared',
+ sortable: false,
+ stateId: 'shared',
+ hidden: true
+ }],
+
+ initComponent: function() {
+ var me = this;
+ this.width = 600;
+ Ext.apply(me, {
+ store: Ext.create("Ext.data.TreeStore", {
+ autoLoad: true,
+ model: OMV.data.Model.createImplicit({
+ fields: [
+ { name: "name", type: "string" },
+ { name: "type", type: "string" },
+ { name: "id", type: "string" },
+ { name: "path", type: "string" },
+ { name: "origin", type: "string", defaultValue: "none" },
+ { name: "shared", type: "string", defaultValue: "false" }
+ ]
+ }),
+ proxy: {
+ type: "rpc",
+ rpcData: {
+ service: "ZFS",
+ method: "getObjectTree",
+ }
+ },
+ folderSort: true
+ })
+ });
+ me.callParent(arguments);
+ },
+
+ onAddObjButton: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+ var records = sm.getSelection();
+ var record = records[0];
+ Ext.create("OMV.module.admin.services.zfs.AddObject", {
+ title: _("Add Object"),
+ rpcGetMethod: "passParam",
+ rpcGetParams: {
+ key: "path",
+ value: record.get('path')
+ },
+ listeners: {
+ scope: me,
+ submit: function() {
+ this.doReload();
+ }
+ }
+ }).show();
+ },
+
+ onEditButton: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+ var records = sm.getSelection();
+ var record = records[0];
+ Ext.create("OMV.module.admin.service.zfs.EditProperties", {
+ name: record.get("path"),
+ type: record.get("type")
+ }).show();
+ },
+
+ doDeletion: function(record) {
+ var me = this;
+ OMV.Rpc.request({
+ scope: me,
+ callback: me.onDeletion,
+ rpcData: {
+ service: "ZFS",
+ method: "deleteObject",
+ params: {
+ name: record.get('path'),
+ type: record.get('type')
+ }
+ }
+ });
+ }
+
+});
+
+OMV.WorkspaceManager.registerPanel({
+ id: "overview",
+ path: "/service/zfs",
+ text: _("Overview"),
+ position: 10,
+ className: "OMV.module.admin.service.zfs.Overview"
+});
+
+
+
--- /dev/null
+/**
+ * This file is part of OpenMediaVault.
+ *
+ * @license http://www.gnu.org/licenses/gpl.html GPL Version 3
+ * @author Volker Theile <volker.theile@openmediavault.org>
+ * @copyright Copyright (c) 2009-2014 Volker Theile
+ *
+ * OpenMediaVault is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * OpenMediaVault is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OpenMediaVault. If not, see <http://www.gnu.org/licenses/>.
+ */
+// require("js/omv/tree/Panel.js")
+// require("js/omv/grid/Panel.js")
+// require("js/omv/grid/column/BinaryUnit.js")
+// require("js/omv/grid/column/BooleanIcon.js")
+// require("js/omv/grid/column/BooleanText.js")
+// require("js/omv/grid/column/Empty.js")
+// require("js/omv/grid/column/Hyperlink.js")
+// require("js/omv/grid/column/UnixTimestamp.js")
+// require("js/omv/grid/column/WhiteSpace.js")
+// require("js/omv/window/MessageBox.js")
+
+/**
+ * @ingroup webgui
+ * @class OMV.workspace.grid.Panel
+ * @derived OMV.grid.Panel
+ * An enhanced grid panel. This grid provides 'Add', 'Edit' and 'Delete'
+ * buttons in the toolbar by default. The basic delete functionality is also
+ * implemented, simply overwrite the 'doDeletion' and 'afterDeletion'
+ * functions to implement fit your requirements. To implement the 'Add' and
+ * 'Edit' functionality overwrite the 'onAdd' and 'onEdit' callback
+ * functions. A paging toolbar which is displayed at the bottom of the grid
+ * can be displayed also. It is also possible to reload the grid
+ * automatically in a given interval.
+ * @param hideTopToolbar TRUE to hide the whole toolbar. Defaults to FALSE.
+ * @param hidePagingToolbar TRUE to hide the paging toolbar at the bottom of
+ * the grid. Defaults to TRUE.
+ * @param hideAddButton Hide the 'Add' button in the top toolbar.
+ * Defaults to FALSE.
+ * @param hideEditButton Hide the 'Edit' button in the top toolbar.
+ * Defaults to FALSE.
+ * @param hideDeleteButton Hide the 'Delete' button in the top toolbar.
+ * Defaults to FALSE.
+ * @param hideUpButton Hide the 'Up' button in the top toolbar.
+ * Defaults to TRUE.
+ * @param hideDownButton Hide the 'Down' button in the top toolbar.
+ * Defaults to TRUE.
+ * @param hideApplyButton Hide the 'Apply' button in the top toolbar.
+ * Defaults to TRUE.
+ * @param hideRefreshButton Hide the 'Refresh' button in the top toolbar.
+ * Defaults to TRUE.
+ * @param addButtonText The button text. Defaults to 'Add'.
+ * @param editButtonText The button text. Defaults to 'Edit'.
+ * @param deleteButtonText The button text. Defaults to 'Delete'.
+ * @param upButtonText The button text. Defaults to 'Up'.
+ * @param downButtonText The button text. Defaults to 'Down'.
+ * @param applyButtonText The button text. Defaults to 'Save'.
+ * @param refreshButtonText The button text. Defaults to 'Refresh'.
+ * @param deletionConfirmRequired Set to TRUE to force the user to confirm
+ * the deletion request. Defaults to TRUE.
+ * @param deletionWaitMsg The message displayed during the deletion process.
+ * @param mode The mode how to retrieve the data displayed in the grid panel.
+ * This can be 'local' or 'remote' which means the data is requested via
+ * RPC. Defaults to 'remote'.
+ * @param rememberSelected TRUE to reselect the previous selected rows
+ * after the grid content has been reloaded/refreshed. Defaults to FALSE.
+ */
+Ext.define("OMV.module.admin.services.zfs.TreePanel", {
+ extend: "OMV.tree.Panel",
+ requires: [
+ "OMV.window.MessageBox",
+ "OMV.grid.column.BinaryUnit",
+ "OMV.grid.column.BooleanIcon",
+ "OMV.grid.column.BooleanText",
+ "OMV.grid.column.Empty",
+ "OMV.grid.column.Hyperlink",
+ "OMV.grid.column.UnixTimestamp",
+ "OMV.grid.column.WhiteSpace"
+ ],
+
+ border: false,
+ rowLines: false,
+ columnLines: true,
+ selModel: {
+ allowDeselect: true,
+ mode: "SINGLE"
+ },
+
+ hideTopToolbar: false,
+ hidePagingToolbar: true,
+ hideAddButton: false,
+ hideAddObjButton: false,
+ hideEditButton: false,
+ hideDeleteButton: false,
+ hideUpButton: true,
+ hideDownButton: true,
+ hideApplyButton: true,
+ hideRefreshButton: true,
+ addButtonText: _("Add Pool"),
+ addObjButtonText: _("Add Object"),
+ editButtonText: _("Edit"),
+ deleteButtonText: _("Delete"),
+ upButtonText: _("Up"),
+ downButtonText: _("Down"),
+ applyButtonText: _("Save"),
+ refreshButtonText: _("Refresh"),
+ deletionConfirmRequired: true,
+ deletionWaitMsg: _("Deleting selected item(s)"),
+ mode: "remote",
+ rememberSelected: false,
+
+ initComponent: function() {
+ var me = this;
+ // Initialize toolbars.
+ me.dockedItems = [];
+ if(!me.hideTopToolbar) {
+ me.dockedItems.push(me.topToolbar = Ext.widget({
+ xtype: "toolbar",
+ dock: "top",
+ items: me.getTopToolbarItems(me)
+ }));
+ }
+ if(!me.hidePagingToolbar) {
+ me.dockedItems.push({
+ xtype: "toolbar",
+ dock: "bottom",
+ items: [ me.pagingToolbar = Ext.widget({
+ xtype: "pagingtoolbar",
+ store: me.store,
+ displayInfo: true,
+ displayMsg: _("Displaying items {0} - {1} of {2}"),
+ emptyMsg: _("No items to display")
+ }) ]
+ });
+ }
+ me.callParent(arguments);
+ // Register event handler.
+ // Process double clicks in grid.
+ me.on("itemdblclick", me.onItemDblClick, me);
+ // Process selections in grid, e.g. to update the toolbar.
+ var selModel = me.getSelectionModel();
+ selModel.on("selectionchange", me.onSelectionChange, me);
+ // Remember selection to restore it after the grid has been
+ // refreshed.
+ if(me.rememberSelected) {
+ me.getStore().on("beforeload", function() {
+ if(!me.rendered || Ext.isEmpty(me.getEl()))
+ return;
+ if(!selModel.hasSelection())
+ return;
+ me.previousSelected = selModel.getSelection();
+ });
+ me.getView().on("refresh", function(view) {
+ if(Ext.isEmpty(me.previousSelected))
+ return;
+ var select = [];
+ Ext.Array.each(me.previousSelected, function(r) {
+ var record = me.getStore().getById(r.getId());
+ if(!Ext.isEmpty(record))
+ select.push(record);
+ });
+ delete me.previousSelected;
+ if(select.length > 0) {
+ selModel.select(select, false, false);
+ selModel.view.focusNode(select[0]);
+ }
+ });
+ }
+ },
+
+ /**
+ * Returns the items displayed in the top toolbar.
+ * @param c This component object.
+ * @return An array of buttons displayed in the top toolbar.
+ */
+ getTopToolbarItems: function(c) {
+ var me = this;
+ return [{
+ id: me.getId() + "-add",
+ xtype: "button",
+ text: me.addButtonText,
+ icon: "images/add.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideAddButton,
+ handler: Ext.Function.bind(me.onAddButton, me, [ me ]),
+ scope: me
+ },{
+ id: me.getId() + "-addobj",
+ xtype: "button",
+ text: me.addObjButtonText,
+ icon: "images/add.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideAddObjButton,
+ handler: Ext.Function.bind(me.onAddObjButton, me, [ me ]),
+ scope: me,
+ disabled: true
+ },{
+ id: me.getId() + "-edit",
+ xtype: "button",
+ text: me.editButtonText,
+ icon: "images/edit.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideEditButton,
+ handler: Ext.Function.bind(me.onEditButton, me, [ me ]),
+ scope: me,
+ disabled: true
+ },{
+ id: me.getId() + "-delete",
+ xtype: "button",
+ text: me.deleteButtonText,
+ icon: "images/delete.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideDeleteButton,
+ handler: Ext.Function.bind(me.onDeleteButton, me, [ me ]),
+ scope: me,
+ disabled: true
+ },{
+ id: me.getId() + "-up",
+ xtype: "button",
+ text: me.upButtonText,
+ icon: "images/arrow-up.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideUpButton,
+ handler: Ext.Function.bind(me.onUpButton, me, [ me ]),
+ scope: me,
+ disabled: true
+ },{
+ id: me.getId() + "-down",
+ xtype: "button",
+ text: me.downButtonText,
+ icon: "images/arrow-down.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideDownButton,
+ handler: Ext.Function.bind(me.onDownButton, me, [ me ]),
+ scope: me,
+ disabled: true
+ },{
+ id: me.getId() + "-apply",
+ xtype: "button",
+ text: me.applyButtonText,
+ icon: "images/checkmark.png",
+ hidden: me.hideApplyButton,
+ handler: Ext.Function.bind(me.onApplyButton, me, [ me ]),
+ scope: me
+ },{
+ id: me.getId() + "-refresh",
+ xtype: "button",
+ text: me.refreshButtonText,
+ icon: "images/refresh.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideRefreshButton,
+ handler: Ext.Function.bind(me.onRefreshButton, me, [ me ]),
+ scope: me
+ }]
+ },
+
+ /**
+ * Handler that is called whenever the selection in the grid has
+ * been changed. The top toolbar buttons will be enabled/disabled
+ * depending on how much rows has been selected.
+ * @param model The selection model
+ */
+ onSelectionChange: function(model, records) {
+ var me = this;
+ if(me.hideTopToolbar)
+ return;
+ var tbarBtnName = [ "addobj", "edit", "delete", "up", "down" ];
+ var tbarBtnDisabled = {
+ "addobj": false,
+ "edit": false,
+ "delete": false,
+ "up": true,
+ "down": true
+ };
+ // Enable/disable buttons depending on the number of selected rows.
+ if(records.length <= 0) {
+ tbarBtnDisabled["addobj"] = true;
+ tbarBtnDisabled["edit"] = true;
+ tbarBtnDisabled["delete"] = true;
+ tbarBtnDisabled["up"] = true;
+ tbarBtnDisabled["down"] = true;
+ } else if(records.length == 1) {
+ tbarBtnDisabled["addobj"] = false;
+ tbarBtnDisabled["edit"] = false;
+ tbarBtnDisabled["delete"] = false;
+ tbarBtnDisabled["up"] = false;
+ tbarBtnDisabled["down"] = false;
+ } else {
+ tbarBtnDisabled["addobj"] = true;
+ tbarBtnDisabled["edit"] = true;
+ tbarBtnDisabled["delete"] = false;
+ tbarBtnDisabled["up"] = false;
+ tbarBtnDisabled["down"] = false;
+ }
+ //Disable 'AddObj' button if selected row is a Poool or a Snapshot
+ Ext.Array.each(records, function(record) {
+ if(("Pool" == record.get("type")) ||
+ ("Snapshot" == record.get("type"))) {
+ tbarBtnDisabled["addobj"] = true;
+ return false;
+ }
+ });
+
+ // Disable 'Delete' button if a selected node is not a leaf
+ Ext.Array.each(records, function(record) {
+ if((false == record.get("leaf"))) {
+ tbarBtnDisabled["delete"] = true;
+ return false;
+ }
+ });
+
+ // Update the button controls.
+ Ext.Array.each(tbarBtnName, function(name) {
+ var tbarBtnCtrl = me.queryById(me.getId() + "-" + name);
+ if(!Ext.isEmpty(tbarBtnCtrl)) {
+ if(true == tbarBtnDisabled[name]) {
+ tbarBtnCtrl.disable();
+ } else {
+ tbarBtnCtrl.enable();
+ }
+ }
+ });
+ },
+
+ onItemDblClick: function() {
+ var me = this;
+ if(!me.hideTopToolbar && !me.hideEditButton) {
+ me.onEditButton(me);
+ }
+ },
+
+ /**
+ * Load the grid content.
+ */
+ doLoad: function() {
+ var me = this;
+ if(me.mode === "remote") {
+ me.store.load();
+ }
+ },
+
+ /**
+ * Reload the grid content.
+ */
+ doReload: function() {
+ var me = this;
+ if(me.mode === "remote") {
+ me.store.reload();
+ }
+ },
+
+ /**
+ * Handler that is called when the 'Add' button in the top toolbar
+ * is pressed. Override this method to customize the default behaviour.
+ * @param this The grid itself.
+ */
+ onAddButton: function() {
+ // Nothing to do here
+ },
+
+ /**
+ * * Handler that is called when the 'AddObj' button in the top toolbar
+ * is pressed. Override this method to customize the default behaviour.
+ * @param this The grid itself.
+ */
+ onAddObjButton: function() {
+ // Nothing to do here
+ },
+
+
+ /**
+ * Handler that is called when the 'Edit' button in the top toolbar
+ * is pressed. Override this method to customize the default behaviour.
+ * @param this The grid itself.
+ */
+ onEditButton: function() {
+ // Nothing to do here
+ },
+
+ /**
+ * Handler that is called when the 'Up' button in the top toolbar
+ * is pressed. Override this method to customize the default behaviour.
+ * @param this The grid itself.
+ */
+ onUpButton: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+ var records = sm.getSelection();
+ if(records.length > 0) {
+ // Find the smallest index of the selected rows.
+ var ltIndex = me.store.indexOf(records[0]);
+ Ext.Array.each(records, function(record) {
+ var index = me.store.indexOf(record);
+ if(ltIndex > index)
+ ltIndex = index;
+ });
+ // Calculate the index where to insert the rows.
+ var index = ltIndex - 1;
+ if(index < 0)
+ index = 0;
+ me.doMoveRows(records, index);
+ }
+ },
+
+ /**
+ * Handler that is called when the 'Down' button in the top toolbar
+ * is pressed.
+ * @param this The grid itself.
+ */
+ onDownButton: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+ var records = sm.getSelection();
+ if(records.length > 0) {
+ // Find the smallest index of the selected rows.
+ var ltIndex = me.store.indexOf(records[0]);
+ Ext.Array.each(records, function(record) {
+ var index = me.store.indexOf(record);
+ if(ltIndex > index)
+ ltIndex = index;
+ });
+ // Calculate the index where to insert the rows.
+ var index = ltIndex + records.length;
+ var count = me.store.getCount() - 1;
+ if(index > count)
+ index = count;
+ me.doMoveRows(records, index);
+ }
+ },
+
+ /**
+ * Handler that is called when the 'Apply' button in the top toolbar
+ * is pressed. Override this method to customize the default behaviour.
+ * @param this The grid itself.
+ */
+ onApplyButton: function() {
+ // Nothing to do here
+ },
+
+ /**
+ * Handler that is called when the 'Refresh' button in the top toolbar
+ * is pressed. Override this method to customize the default behaviour.
+ * @param this The grid itself.
+ */
+ onRefreshButton: function() {
+ this.doReload();
+ },
+
+ /**
+ * Move the given rows to the given index.
+ * @param records The records to move.
+ * @param index The index where to insert the rows to be moved.
+ */
+ doMoveRows: function(records, index) {
+ var me = this;
+ if(!Ext.isNumber(index))
+ return;
+ records = Ext.Array.from(records);
+ me.store.suspendEvents();
+ Ext.Array.each(records, function(record) {
+ me.store.remove(record);
+ me.store.insert(index, record);
+ });
+ me.store.resumeEvents();
+ me.afterMoveRows(records, index);
+ me.getView().refresh();
+ },
+
+ /**
+ * Function that is called after the selected rows have been moved.
+ * Override this method to customize the default behaviour.
+ * @param records The records that have been move.
+ * @param index The index where the rows have been inserted.
+ */
+ afterMoveRows: function(records, index) {
+ var sm = this.getSelectionModel();
+ sm.select(records);
+ },
+
+ /**
+ * Handler that is called when the 'Delete' button in the top toolbar
+ * is pressed.
+ */
+ onDeleteButton: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+ var records = sm.getSelection();
+ if(me.deletionConfirmRequired === true) {
+ var msg = _("Do you really want to delete the selected item(s)?");
+ OMV.MessageBox.show({
+ title: _("Confirmation"),
+ msg: msg,
+ buttons: Ext.Msg.YESNO,
+ fn: function(answer) {
+ if(answer !== "yes")
+ return;
+ me.startDeletion(records);
+ },
+ scope: me,
+ icon: Ext.Msg.QUESTION
+ });
+ } else {
+ me.startDeletion(records);
+ }
+ },
+
+ /**
+ * @private
+ * Private method that is called when the deletion of the selected records
+ * has been aggreed.
+ * @param records The records to delete.
+ */
+ startDeletion: function(records) {
+ var me = this;
+ if(records.length <= 0)
+ return;
+ // Store selected records in a local variable
+ me.delActionInfo = {
+ records: records,
+ count: records.length
+ }
+ // Get first record to be deleted
+ var record = me.delActionInfo.records.pop();
+ // Display progress dialog
+ OMV.MessageBox.progress("", me.deletionWaitMsg, "");
+ me.updateDeletionProgress();
+ // Execute deletion function
+ me.doDeletion(record);
+ },
+
+ /**
+ * The method that is called to delete a selected record. Override this
+ * method to customize the default behaviour. This is necessary in
+ * 'remote' mode.
+ */
+ doDeletion: function(record) {
+ var me = this;
+ if(me.mode === "local") {
+ // Remove record from store
+ me.store.remove(record);
+ // Continue deletion process
+ me.onDeletion(null, true, null);
+ }
+ },
+
+ /**
+ * The method that is called by the 'doDeletion' method. The progress
+ * bar will be updated and the deletion progress will be continued if
+ * there are still records to delete.
+ */
+ onDeletion: function(id, success, response) {
+ var me = this;
+ if(!success) {
+ // Remove temporary local variables
+ delete me.delActionInfo;
+ // Hide progress dialog
+ OMV.MessageBox.hide();
+ // Display error message
+ OMV.MessageBox.error(null, response);
+ } else {
+ if(me.delActionInfo.records.length > 0) {
+ var record = me.delActionInfo.records.pop();
+ // Update progress dialog
+ me.updateDeletionProgress();
+ // Execute deletion function
+ me.doDeletion(record);
+ } else {
+ // Remove temporary local variables
+ delete me.delActionInfo;
+ // Update and hide progress dialog
+ OMV.MessageBox.updateProgress(1, _("100% completed ..."));
+ OMV.MessageBox.hide();
+ me.afterDeletion();
+ }
+ }
+ },
+
+ /**
+ * Function that is called after the deletion has been successful finished.
+ */
+ afterDeletion: function() {
+ var me = this;
+ if(me.mode === "remote") {
+ me.doReload();
+ }
+ },
+
+ /**
+ * @private
+ * Private helper function to update the progress dialog.
+ */
+ updateDeletionProgress: function() {
+ var me = this;
+ // Calculate percentage
+ var p = (me.delActionInfo.count - me.delActionInfo.records.length) /
+ me.delActionInfo.count;
+ // Create message text
+ var text = Math.round(100 * p) + _("% completed ...");
+ // Update progress dialog
+ OMV.MessageBox.updateProgress(p, text);
+ },
+
+ /**
+ * Convenience function for setting the given toolbar button
+ * disabled/enabled.
+ * @param name The name of the toolbar button.
+ * @param disabled TRUE to disable the button, FALSE to enable.
+ * @return The button component, otherwise FALSE.
+ */
+ setToolbarButtonDisabled: function(name, disabled) {
+ var me = this;
+ var result = false;
+ var btnCtrl = me.queryById(me.getId() + "-" + name);
+ if(!Ext.isEmpty(btnCtrl) && btnCtrl.isButton)
+ result = btnCtrl.setDisabled(disabled);
+ return result;
+ },
+
+ /**
+ * Helper function to get the top toolbar object.
+ * @return The paging toolbar object or NULL.
+ */
+ getTopToolbar: function() {
+ return this.topToolbar;
+ },
+
+ /**
+ * Helper function to get the paging toolbar object.
+ * @return The paging toolbar object or NULL.
+ */
+ getPagingToolbar: function() {
+ return this.pagingToolbar;
+ }
+});
+
+
+
--- /dev/null
+OMV.WorkspaceManager.registerNode({
+ id : "zfs",
+ path : "/storage",
+ text : _("ZFS"),
+ icon16 : "images/zfs.png",
+ iconSvg : "images/zfs.svg"
+});
+