partkeepr

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

commit babc0bda4405839690d73b9bf1353d05f8cb2e12
parent 7dd3ef8f2395097b3659bbe0587eac70b6ff7671
Author: Felicia Hummel <felicia@drachenkatze.org>
Date:   Sat, 30 Jun 2018 19:04:22 +0200

Added notification bar above the parts grid if a category description was given. To see this in action, to to https://demo.partkeepr.org and go to the category "Free Space".

Diffstat:
Msrc/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css | 12++++++++++++
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/CategoryEditor/CategoryEditorForm.js | 2+-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/CategoryEditor/CategoryEditorWindow.js | 28+++++++++++++---------------
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Editor/EditorGrid.js | 102+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js | 89+++++++++++++++++++++++++++++++------------------------------------------------
5 files changed, 124 insertions(+), 109 deletions(-)

diff --git a/src/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css b/src/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css @@ -223,3 +223,14 @@ margin-left: -75px; width: 217px; background-image: url(../images/become_a_patron_button.png); } + +.x-panel-notification { + padding: 2px; +} + +.x-panel-body-notification { + background-color: #cce5ff; + border: 1px solid #b8daff; + border-radius: .25rem; + padding: .25rem .75rem; +}+ \ No newline at end of file diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/CategoryEditor/CategoryEditorForm.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/CategoryEditor/CategoryEditorForm.js @@ -13,7 +13,7 @@ Ext.define('PartKeepr.CategoryEditorForm', { enableKeyEvents: true, fieldLabel: i18n("Name") }, { - xtype: 'textarea', + xtype: 'htmleditor', name: 'description', anchor: '100%', enableKeyEvents: true, diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/CategoryEditor/CategoryEditorWindow.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/CategoryEditor/CategoryEditorWindow.js @@ -1,7 +1,7 @@ Ext.define('PartKeepr.CategoryEditorWindow', { extend: 'Ext.window.Window', border: false, - width: 400, + width: 650, categoryModel: null, layout: 'fit', items: [ @@ -9,8 +9,7 @@ Ext.define('PartKeepr.CategoryEditorWindow', { xtype: "CategoryEditorForm" } ], - initComponent: function () - { + initComponent: function () { this.buttons = [ { text: i18n("Save"), @@ -23,9 +22,11 @@ Ext.define('PartKeepr.CategoryEditorWindow', { this.callParent(); - if (!this.record.phantom) { + if (!this.record.phantom) + { this.setTitle(i18n("Edit Category")); - } else { + } else + { this.record.set("parent", this.parentRecord.getId()); this.setTitle(i18n("Add Category")); } @@ -33,33 +34,30 @@ Ext.define('PartKeepr.CategoryEditorWindow', { this.down("CategoryEditorForm").loadRecord(this.record); this.down("textfield[name=name]").on("keypress", this.onEnter, this); - this.down("textfield[name=description]").on("keypress", this.onEnter, this); + this.down("htmleditor[name=description]").on("keypress", this.onEnter, this); this.on("show", Ext.bind(this._onShow, this)); }, - onEnter: function (field, e) - { - if (e.getKey() == e.ENTER) { + onEnter: function (field, e) { + if (e.getKey() == e.ENTER) + { this.onSave(); } }, _onShow: function () { this.down("CategoryEditorForm").items.first().focus(); }, - onSave: function () - { + onSave: function () { this.down("CategoryEditorForm").updateRecord(this.record); this.record.save({ - success: Ext.bind(function (response) - { + success: Ext.bind(function (response) { this.fireEvent("save", response); this.destroy(); }, this) }); }, - onCancel: function () - { + onCancel: function () { this.destroy(); } }); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Editor/EditorGrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Editor/EditorGrid.js @@ -105,8 +105,7 @@ Ext.define('PartKeepr.EditorGrid', { * Fires if a record was selected within the grid. * @param {Object} Ext.data.Record The selected record */ - initComponent: function () - { + initComponent: function () { /** * @event itemDeselect @@ -137,8 +136,7 @@ Ext.define('PartKeepr.EditorGrid', { tooltip: this.deleteButtonText, icon: this.deleteButtonIcon, iconCls: this.deleteButtonIconCls, - handler: Ext.bind(function () - { + handler: Ext.bind(function () { this.fireEvent("itemDelete"); }, this), disabled: true @@ -149,8 +147,7 @@ Ext.define('PartKeepr.EditorGrid', { tooltip: this.addButtonText, icon: this.addButtonIcon, iconCls: this.addButtonIconCls, - handler: Ext.bind(function () - { + handler: Ext.bind(function () { this.fireEvent("itemAdd"); }, this) }); @@ -168,7 +165,8 @@ Ext.define('PartKeepr.EditorGrid', { var topToolbarItems = []; - if (this.enableEditing) { + if (this.enableEditing) + { topToolbarItems.push(this.addButton); topToolbarItems.push(this.deleteButton); } @@ -195,37 +193,48 @@ Ext.define('PartKeepr.EditorGrid', { targetStore: this.store }); + this.notificationBar = Ext.create("Ext.panel.Panel", { + dock: 'top', + hidden: true, + ui: 'notification' + }); + this.dockedItems = new Array(); this.dockedItems.push(this.bottomToolbar); this.dockedItems.push(this.appliedFiltersToolbar); - if (this.enableTopToolbar) { + if (this.enableTopToolbar) + { this.dockedItems.push(this.topToolbar); } - if (!Ext.isArray(this.plugins)) { + if (!Ext.isArray(this.plugins)) + { this.plugins = []; } this.callParent(); + this.addDocked(this.notificationBar); this.getSelectionModel().on("select", this._onItemSelect, this); this.getSelectionModel().on("deselect", this._onItemDeselect, this); this.getView().on("itemkeydown", this._onItemKeyPress, this); this.getStore().on("filterchange", this._onFilterChange, this); - if (this.automaticPageSize) { + if (this.automaticPageSize) + { this.on("resize", this.reassignPageSize, this); } }, - _onFilterChange: function () - { + _onFilterChange: function () { var filters = this.getStore().getFilters(); - if (filters.length > 0) { + if (filters.length > 0) + { this.bottomToolbar.down("#resetFilter").show(); - } else { + } else + { this.bottomToolbar.down("#resetFilter").hide(); } @@ -233,22 +242,38 @@ Ext.define('PartKeepr.EditorGrid', { }, /** + * Sets a notification which is displayed on the grid's top dock + * @param message + */ + setNotification: function (message) { + this.notificationBar.setHtml(message); + this.notificationBar.show(); + }, + /** + * Removes a previously set notification + */ + removeNotification: function () { + this.notificationBar.hide(); + }, + /** * Re-calculates and re-assigns the page size for the assigned store. * * Automatically reloads the store. */ - reassignPageSize: function () - { - if (this.store.isLoading()) { + reassignPageSize: function () { + if (this.store.isLoading()) + { return; } - if (this.getView().getHeight() === 0) { + if (this.getView().getHeight() === 0) + { return; } var numRecords = Math.floor(this.getView().getHeight() / this.automaticPageSizeRowHeight); - if (numRecords < 1) { + if (numRecords < 1) + { numRecords = 1; } @@ -258,65 +283,64 @@ Ext.define('PartKeepr.EditorGrid', { var newStartPage = Math.floor(oldStartIndex / numRecords); - if (newStartPage < 1) { + if (newStartPage < 1) + { newStartPage = 1; } this.store.loadPage(newStartPage); }, - onReconfigure: function (me, store) - { + onReconfigure: function (me, store) { this.searchField.setStore(store); this.bottomToolbar.setStore(store); }, - syncChanges: function () - { + syncChanges: function () { // Simply reload the store for now this.store.load(); }, /** * Called when an item was selected. Enables/disables the delete button. */ - _updateDeleteButton: function () - { + _updateDeleteButton: function () { /* Right now, we support delete on a single record only */ - if (this.getSelectionModel().getCount() == 1) { + if (this.getSelectionModel().getCount() == 1) + { this.deleteButton.enable(); - } else { + } else + { this.deleteButton.disable(); } }, - _onItemKeyPress: function (view, record, item, index, e) - { - if (e.getKey() == e.ENTER || e.getKey() == e.TAB) { + _onItemKeyPress: function (view, record, item, index, e) { + if (e.getKey() == e.ENTER || e.getKey() == e.TAB) + { this._onItemEdit(view, record); } }, /** * Called when an item should be edited */ - _onItemEdit: function (view, record) - { - if (this.editItemAsObject) { + _onItemEdit: function (view, record) { + if (this.editItemAsObject) + { this.fireEvent("itemEdit", record); - } else { + } else + { this.fireEvent("itemEdit", record.getId()); } }, /** * Called when an item was selected */ - _onItemSelect: function (selectionModel, record) - { + _onItemSelect: function (selectionModel, record) { this._updateDeleteButton(selectionModel, record); this.fireEvent("itemSelect", record); }, /** * Called when an item was deselected */ - _onItemDeselect: function (selectionModel, record) - { + _onItemDeselect: function (selectionModel, record) { this._updateDeleteButton(selectionModel, record); this.fireEvent("itemDeselect", record); } diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js @@ -25,8 +25,7 @@ Ext.define('PartKeepr.PartManager', { selectedCategory: null, - initComponent: function () - { + initComponent: function () { /** * Create the store with the default sorter "name ASC" @@ -162,8 +161,7 @@ Ext.define('PartKeepr.PartManager', { } }); - this.thumbnailView.on("selectionchange", function (selModel, selection) - { + this.thumbnailView.on("selectionchange", function (selModel, selection) { var parts = []; for (var i = 0; i < selection.length; i++) @@ -174,16 +172,14 @@ Ext.define('PartKeepr.PartManager', { this.grid.getSelectionModel().select(parts); }, this); - this.grid.store.on("update", function (store, record) - { + this.grid.store.on("update", function (store, record) { if (this.detail.record !== null && this.detail.record.getId() == record.getId()) { this.detail.setValues(record); } }, this); - this.grid.store.on("load", function () - { + this.grid.store.on("load", function () { this.thumbnailView.getStore().removeAll(); var data = this.grid.store.getData(), @@ -238,8 +234,7 @@ Ext.define('PartKeepr.PartManager', { items: [this.grid, this.thumbnailPanel] }); - this.thumbnailView.on("render", function () - { + this.thumbnailView.on("render", function () { this.loadMask = Ext.create("Ext.LoadMask", { store: this.grid.store, target: this.thumbnailPanel @@ -293,8 +288,7 @@ Ext.define('PartKeepr.PartManager', { * @param {Ext.tree.View} tree The tree view * @param {Ext.data.Model} record the selected record */ - onCategoryClick: function (tree, record) - { + onCategoryClick: function (tree, record) { this.selectedCategory = record; var filter = Ext.create("PartKeepr.util.Filter", { @@ -304,6 +298,14 @@ Ext.define('PartKeepr.PartManager', { value: this.getChildrenIds(record) }); + if (record.get("description").trim() != "") + { + this.grid.setNotification(record.get("description")); + } else { + this.grid.removeNotification(); + } + + if (record.parentNode.isRoot()) { // Workaround for big installations: Passing all child categories for the root node @@ -315,8 +317,7 @@ Ext.define('PartKeepr.PartManager', { this.store.addFilter(filter); } }, - getSelectedCategory: function () - { + getSelectedCategory: function () { return this.selectedCategory; }, /** @@ -325,8 +326,7 @@ Ext.define('PartKeepr.PartManager', { * @param {Ext.data.Model} node The node * @return Array */ - getChildrenIds: function (node) - { + getChildrenIds: function (node) { var childNodes = [node]; if (node.hasChildNodes()) @@ -344,8 +344,7 @@ Ext.define('PartKeepr.PartManager', { * of the selected part for a short time. We can't select the category * as this would affect the parts grid. */ - onSyncCategory: function () - { + onSyncCategory: function () { var r = this.grid.getSelectionModel().getSelection(); if (r.length != 1) @@ -369,8 +368,7 @@ Ext.define('PartKeepr.PartManager', { * * Prompts the user if he really wishes to delete the part. If yes, it calls deletePart. */ - onItemDelete: function () - { + onItemDelete: function () { var r = this.grid.getSelectionModel().getLastSelected(); Ext.Msg.confirm(i18n("Delete Part"), sprintf(i18n("Do you really wish to delete the part %s?"), r.get("name")), @@ -380,8 +378,7 @@ Ext.define('PartKeepr.PartManager', { * Creates a duplicate with the basic data only from the selected item. Loads the selected part and calls * createPartDuplicate after the part was loaded. */ - onDuplicateItemWithBasicData: function () - { + onDuplicateItemWithBasicData: function () { var r = this.grid.getSelectionModel().getLastSelected(); this.loadPart(r.getId(), Ext.bind(this.createPartDuplicate, this)); @@ -390,8 +387,7 @@ Ext.define('PartKeepr.PartManager', { * Creates a full duplicate from the selected item. Loads the selected part and calls createPartDuplicate * after the part was loaded. */ - onDuplicateItemWithAllData: function () - { + onDuplicateItemWithAllData: function () { var r = this.grid.getSelectionModel().getLastSelected(); this.loadPart(r.getId(), Ext.bind(this.createFullPartDuplicate, this)); @@ -400,8 +396,7 @@ Ext.define('PartKeepr.PartManager', { * Creates a part duplicate from the given record and opens the editor window. * @param rec The record to duplicate */ - createPartDuplicate: function (rec) - { + createPartDuplicate: function (rec) { var data = rec.getData(); var associationData = rec.getAssociationData(); @@ -422,8 +417,7 @@ Ext.define('PartKeepr.PartManager', { j.editor.editItem(newItem); j.show(); }, - onAddMetaPart: function () - { + onAddMetaPart: function () { var defaults = {}; var j = Ext.create("PartKeepr.Components.Part.Editor.MetaPartEditorWindow", {}); @@ -453,8 +447,7 @@ Ext.define('PartKeepr.PartManager', { * Creates a part duplicate from the given record and opens the editor window. * @param rec The record to duplicate */ - createFullPartDuplicate: function (rec) - { + createFullPartDuplicate: function (rec) { var data = rec.getData(); var newItem = Ext.create("PartKeepr.PartBundle.Entity.Part"); @@ -476,8 +469,7 @@ Ext.define('PartKeepr.PartManager', { * @todo We use the current selection of the grid. If for some reason the selection changes during the user is prompted, * we delete the wrong part. Fix that to pass the selected item to the onItemDelete then to this function. */ - deletePart: function (btn) - { + deletePart: function (btn) { var r = this.grid.getSelectionModel().getLastSelected(); if (btn == "yes") @@ -490,8 +482,7 @@ Ext.define('PartKeepr.PartManager', { /** * Creates a new, empty part editor window */ - onItemAdd: function (defaults) - { + onItemAdd: function (defaults) { var j = Ext.create("PartKeepr.PartEditorWindow", { partMode: 'create' }); @@ -521,8 +512,7 @@ Ext.define('PartKeepr.PartManager', { /** * Called when a part was edited. Refreshes the grid. */ - onEditPart: function (part) - { + onEditPart: function (part) { var editorWindow; if (part.get("metaPart") === true) @@ -537,19 +527,16 @@ Ext.define('PartKeepr.PartManager', { editorWindow.editor.editItem(part); editorWindow.show(); }, - onNewPartSaved: function () - { + onNewPartSaved: function () { this.grid.getStore().reload(); }, - onPartSaved: function (record) - { + onPartSaved: function (record) { this.detail.setValues(record); }, /** * Called when a part was selected in the grid. Displays the details for this part. */ - onItemSelect: function () - { + onItemSelect: function () { if (this.grid.getSelection().length > 1) { this.detailPanel.collapse(); @@ -580,8 +567,7 @@ Ext.define('PartKeepr.PartManager', { * @param {Integer} id The ID of the part to load * @param {Function} handler The callback to call when the part was loaded */ - loadPart: function (id, handler) - { + loadPart: function (id, handler) { // @todo we have this method duplicated in PartEditor PartKeepr.PartBundle.Entity.Part.load(id, { @@ -592,8 +578,7 @@ Ext.define('PartKeepr.PartManager', { /** * Creates the store */ - createStore: function (config) - { + createStore: function (config) { Ext.Object.merge(config, { autoLoad: true, autoSync: false, // Do not change. If true, new (empty) records would be immediately commited to the database. @@ -605,13 +590,11 @@ Ext.define('PartKeepr.PartManager', { this.store = Ext.create('Ext.data.Store', config); // Workaround for bug http://www.sencha.com/forum/showthread.php?133767-Store.sync()-does-not-update-dirty-flag&p=607093#post607093 - this.store.on('write', function (store, operation) - { + this.store.on('write', function (store, operation) { var success = operation.wasSuccessful(); if (success) { - Ext.each(operation.records, function (record) - { + Ext.each(operation.records, function (record) { if (record.dirty) { record.commit(); @@ -623,13 +606,11 @@ Ext.define('PartKeepr.PartManager', { /** * Returns the store */ - getStore: function () - { + getStore: function () { return this.store; }, statics: { - formatParameter: function (partParameter) - { + formatParameter: function (partParameter) { var minSiPrefix = "", siPrefix = "", maxSiPrefix = "", unit = "", minValue = "", maxValue = "", value = "", minMaxCombined = "";