partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

commit 3477e8e87e7776cd6086b08a8093828f427633da
parent 302831192e05cd04396eb7bba0d8868f3f70138a
Author: Felicitus <felicitus@felicitus.org>
Date:   Tue,  6 Sep 2011 09:22:50 +0200

Added user preferences menu item + password change function

Diffstat:
Mfrontend/css/PartKeepr.css | 3+++
Mfrontend/js/Components/MenuBar.js | 31++++++++++++++++++++++++++++++-
Afrontend/js/Components/User/UserPasswordChangePanel.js | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afrontend/js/Components/User/UserPreferences.js | 14++++++++++++++
Afrontend/js/Components/Widgets/ResistorCalculator.js | 30++++++++++++++++++++++++++++++
Afrontend/js/Components/Widgets/ResistorDisplay.js | 25+++++++++++++++++++++++++
Afrontend/js/Components/Widgets/UserPreferenceGrid.js | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfrontend/js/bugfixes.js | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreferenceService.php | 9+++++++++
9 files changed, 360 insertions(+), 1 deletion(-)

diff --git a/frontend/css/PartKeepr.css b/frontend/css/PartKeepr.css @@ -106,6 +106,9 @@ td.o2 { background-image: url(../resources/fugue-icons/icons/ruler.png) !important; } +.icon-gear { + background-image: url(../resources/fugue-icons/icons/gear.png) !important; +} diff --git a/frontend/js/Components/MenuBar.js b/frontend/js/Components/MenuBar.js @@ -46,8 +46,25 @@ Ext.define('PartKeepr.MenuBar', { }] }); + this.systemMenu = Ext.create('Ext.menu.Menu', { + items: [ + { + text: i18n('Disconnect'), + icon: 'resources/silkicons/disconnect.png', + handler: this.disconnect + },{ + text: i18n("User Preferences"), + icon: 'resources/fugue-icons/icons/gear.png', + handler: this.showUserPreferences + } + ] + }); + this.items = [{ - text: 'Menu', + text: i18n("System"), + menu: this.systemMenu + },{ + text: i18n('Menu'), menu: this.menu }, '->', @@ -62,6 +79,18 @@ Ext.define('PartKeepr.MenuBar', { this.callParent(); }, + showUserPreferences: function () { + var j = new PartKeepr.UserPreferencePanel({ + iconCls: 'icon-gear', + closable: true + }); + + PartKeepr.getApplication().addItem(j); + j.show(); + }, + disconnect: function () { + PartKeepr.getApplication().logout(); + }, /** * Shows the system information window */ diff --git a/frontend/js/Components/User/UserPasswordChangePanel.js b/frontend/js/Components/User/UserPasswordChangePanel.js @@ -0,0 +1,75 @@ +Ext.define('PartKeepr.UserPasswordChangePanel', { + extend: 'Ext.form.FormPanel', + title: i18n("Change Password"), + bodyStyle: 'background:#DBDBDB;padding: 10px;', + initComponent: function () { + + this.oldPassword = Ext.create("Ext.form.field.Text", { + inputType: "password", + name: 'password', + labelWidth: 150, + style: 'border-bottom: 1px solid grey; padding-bottom: 10px;', + width: 300, + fieldLabel: i18n("Current Password") + }); + + this.newPassword = Ext.create("Ext.form.field.Text", { + style: 'margin-top: 10px', + inputType: "password", + name: 'password', + labelWidth: 150, + width: 300, + fieldLabel: i18n("New Password") + }); + + this.newPasswordConfirm = Ext.create("Ext.form.field.Text", { + inputType: "password", + name: 'password', + labelWidth: 150, + width: 300, + validator: Ext.bind(this.validatePassword, this), + fieldLabel: i18n("New Password (Confirm)") + }); + + this.items = [ + this.oldPassword, + this.newPassword, + this.newPasswordConfirm, + { + xtype: 'fieldcontainer', + hideEmptyLabel: false, + width: 300, + labelWidth: 150, + items: { + xtype: 'button', + handler: this.onChangePassword, + scope: this, + width: 145, + icon: 'resources/silkicons/accept.png', + text: i18n("Change Password") + } + }]; + + this.callParent(); + }, + onChangePassword: function () { + if (this.getForm().isValid()) { + + var call = new PartKeepr.ServiceCall("UserPreference", "changePassword"); + call.setParameter("oldpassword", md5(this.oldPassword.getValue())); + call.setParameter("newpassword", md5(this.newPassword.getValue())); + call.setHandler(Ext.bind(this.onAfterPasswordChange, this)); + call.doCall(); + } + }, + onAfterPasswordChange: function (data) { + Ext.Msg.alert(data.data, data.data); + }, + validatePassword: function () { + if (this.newPassword.getValue() != this.newPasswordConfirm.getValue()) { + return i18n("Passwords don't match"); + } + + return true; + } +});+ \ No newline at end of file diff --git a/frontend/js/Components/User/UserPreferences.js b/frontend/js/Components/User/UserPreferences.js @@ -0,0 +1,13 @@ +Ext.define('PartKeepr.UserPreferencePanel', { + extend: 'Ext.tab.Panel', + title: i18n("User Preferences"), + tabPosition: 'bottom', + //bodyStyle: 'background:#DBDBDB;padding: 10px;', + initComponent: function () { + + this.passwordChangePanel = Ext.create("PartKeepr.UserPasswordChangePanel"); + + this.items = [ this.passwordChangePanel ]; + this.callParent(); + } +});+ \ No newline at end of file diff --git a/frontend/js/Components/Widgets/ResistorCalculator.js b/frontend/js/Components/Widgets/ResistorCalculator.js @@ -0,0 +1,29 @@ +Ext.define("PartKeepr.ResistorCalculator",{ + extend:"Ext.window.Window", + alias: 'widget.ResistorCalculator', + + width: 300, + height: 300, + layout: 'fit', + initComponent: function () { + + //this.resistorValueField = Ext.create("Ext.form.field.Number"); + this.resistorDisplay = Ext.create("PartKeepr.ResistorDisplay", { + viewBox: false + }); + + /*this.resistorDisplay = Ext.create('Ext.draw.Component', { + viewBox: false, + items: [{ + type: 'circle', + fill: '#79BB3F', + radius: 100, + x: 100, + y: 100 + }] + });*/ + + this.items = [ this.resistorDisplay ]; + this.callParent(); + } +});+ \ No newline at end of file diff --git a/frontend/js/Components/Widgets/ResistorDisplay.js b/frontend/js/Components/Widgets/ResistorDisplay.js @@ -0,0 +1,24 @@ +Ext.define("PartKeepr.ResistorDisplay",{ + extend:"Ext.draw.Component", + alias: 'widget.ResistorDisplay', + + viewBox: false, + initComponent: function () { + + this.circle = Ext.create("Ext.draw.Sprite", { + type: 'circle', + fill: '#79BB3F', + radius: 100, + x: 100, + y: 100 + }); + + this.items = [ this.circle ]; + + this.callParent(); + + this.circle = this.surface; + + + } +});+ \ No newline at end of file diff --git a/frontend/js/Components/Widgets/UserPreferenceGrid.js b/frontend/js/Components/Widgets/UserPreferenceGrid.js @@ -0,0 +1,71 @@ +Ext.define('PartKeepr.UserPreferenceGrid', { + extend: 'Ext.grid.Panel', + + columnLines: true, + + columns: [{ + header: i18n("Key"), + dataIndex: 'key', + flex: 0.3, + minWidth: 200, + renderer: Ext.util.Format.htmlEncode + },{ + header: i18n("Value"), + dataIndex: 'value', + flex: 0.7, + minWidth: 200, + renderer: Ext.util.Format.htmlEncode + }], + userId: null, + + initComponent: function () { + this.deleteButton = Ext.create("Ext.button.Button", { + text: i18n('Delete'), + disabled: true, + itemId: 'delete', + scope: this, + icon: 'resources/silkicons/delete.png', + handler: this.onDeleteClick + }); + + this.dockedItems = [{ + xtype: 'toolbar', + items: [ + this.deleteButton + ] + }]; + this.store = Ext.create("Ext.data.Store", { + model: 'PartKeepr.UserPreference', + pageSize: -1 + }); + + this.callParent(); + + this.getSelectionModel().on('selectionchange', this.onSelectChange, this); + }, + onDeleteClick: function () { + var selection = this.getView().getSelectionModel().getSelection()[0]; + if (selection) { + // Set phantom to false because ExtJS has problems with PK-less thingies + selection.phantom = false; + this.store.remove(selection); + } + }, + onSelectChange: function(selModel, selections){ + this.deleteButton.setDisabled(selections.length === 0); + }, + syncPreferences: function () { + /* Iterate through all removed records and issue an AJAX + * call. This is necessary because the server side doesn't suport string + * keys and ExtJS can't handle composite keys. + */ + for (var j=0;j<this.store.removed.length;j++) { + var call = new PartKeepr.ServiceCall("UserPreference", "destroy"); + call.setParameter("key", this.store.removed[j].get("key")); + call.setParameter("user_id", this.store.removed[j].get("user_id")); + call.doCall(); + } + + this.store.removed = []; + } +}); diff --git a/frontend/js/bugfixes.js b/frontend/js/bugfixes.js @@ -19,6 +19,108 @@ Ext.override(Ext.panel.Table, { scrollDelta: 100 }); +Ext.panel.Table.override({ + determineScrollbars: function() { + var me = this, + box, + tableEl, + scrollWidth, + clientWidth, + scrollHeight, + clientHeight, + verticalScroller = me.verticalScroller, + horizontalScroller = me.horizontalScroller, + curScrollbars = (verticalScroller && verticalScroller.ownerCt === me ? 1 : 0) | + (horizontalScroller && horizontalScroller.ownerCt === me ? 2 : 0), + reqScrollbars = 0; // 1 = vertical, 2 = horizontal, 3 = both + + + // If we are not collapsed, and the view has been rendered AND filled, then we can determine scrollbars + if (!me.collapsed && me.view && me.view.el && me.view.el.dom.firstChild && !me.changingScrollBars) { + + + // Calculate maximum, *scrollbarless* space which the view has available. + // It will be the Fit Layout's calculated size, plus the widths of any currently shown scrollbars + //####### THIS IS ONLY CHANGE I HAVE MADE, USE VIEW SIZE RATHER THAN FULL PANEL SIZE ####### + box = me.view.getSize(); + + + clientWidth = box.width + ((curScrollbars & 1) ? verticalScroller.width : 0); + clientHeight = box.height + ((curScrollbars & 2) ? horizontalScroller.height : 0); + + + // Calculate the width of the scrolling block + // There will never be a horizontal scrollbar if all columns are flexed. + + + scrollWidth = (me.headerCt.query('[flex]').length && !me.headerCt.layout.tooNarrow) ? 0 : me.headerCt.getFullWidth(); + + + // Calculate the height of the scrolling block + if (verticalScroller && verticalScroller.el) { + scrollHeight = verticalScroller.getSizeCalculation().height; + } else { + tableEl = me.view.el.child('table', true); + scrollHeight = tableEl ? tableEl.offsetHeight : 0; + } + + + // View is too high. + // Definitely need a vertical scrollbar + if (scrollHeight > clientHeight) { + reqScrollbars = 1; + + + // But if scrollable block width goes into the zone required by the vertical scrollbar, we'll also need a horizontal + if (horizontalScroller && ((clientWidth - scrollWidth) < verticalScroller.width)) { + reqScrollbars = 3; + } + } + + + // View height fits. But we stil may need a horizontal scrollbar, and this might necessitate a vertical one. + else { + // View is too wide. + // Definitely need a horizontal scrollbar + if (scrollWidth > clientWidth) { + reqScrollbars = 2; + + + // But if scrollable block height goes into the zone required by the horizontal scrollbar, we'll also need a vertical + if (verticalScroller && ((clientHeight - scrollHeight) < horizontalScroller.height)) { + reqScrollbars = 3; + } + } + } + + + // If scrollbar requirements have changed, change 'em... + if (reqScrollbars !== curScrollbars) { + + + // Suspend component layout while we add/remove the docked scrollers + me.suspendLayout = true; + if (reqScrollbars & 1) { + me.showVerticalScroller(); + } else { + me.hideVerticalScroller(); + } + if (reqScrollbars & 2) { + me.showHorizontalScroller(); + } else { + me.hideHorizontalScroller(); + } + me.suspendLayout = false; + } + // Lay out the Component. + // Set a flag so that afterComponentLayout does not recurse back into here. + me.changingScrollBars = true; + me.doComponentLayout(); + me.changingScrollBars = false; + } + } +}); + Ext.override(Ext.data.Connection, { /** * Inject session header. I haven't found a better way to do diff --git a/src/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreferenceService.php b/src/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreferenceService.php @@ -88,7 +88,16 @@ class UserPreferenceService extends Service implements RestfulService { } else { UserPreference::deletePreference($this->getUser(), $this->getParameter("key")); } + } + + public function changePassword () { + if (!$this->getUser()->compareHashedPassword($this->getParameter("oldpassword"))) { + throw new \Exception("Invalid Password"); + } else { + $this->getUser()->setHashedPassword($this->getParameter("newpassword")); + } + return array("data" => PartKeepr::i18n("Password changed successfully")); } } \ No newline at end of file