commit 903389118b7f2400e7d35c9573771f1b16ab9adb
parent 324cbdbf7a366143b3abf2b6afbb02695781bdbd
Author: Felicitus <felicitus@felicitus.org>
Date: Wed, 29 Jun 2011 17:45:29 +0200
Added multi-create dialog for storage locations
Diffstat:
5 files changed, 348 insertions(+), 35 deletions(-)
diff --git a/frontend/js/Components/StorageLocation/StorageLocationGrid.js b/frontend/js/Components/StorageLocation/StorageLocationGrid.js
@@ -5,5 +5,39 @@ Ext.define('PartKeepr.StorageLocationGrid', {
{header: i18n("Storage Location"), dataIndex: 'name', flex: 1}
],
addButtonText: i18n("Add Storage Location"),
- deleteButtonText: i18n("Delete Storage Location")
+ deleteButtonText: i18n("Delete Storage Location"),
+ initComponent: function () {
+ this.callParent();
+
+ // Adds a button which shows the multi-create window
+ this.multiCreateButton = Ext.create("Ext.button.Button", {
+ icon: 'resources/silkicons/table_multiple.png',
+ tooltip: i18n("Multi-create storage locations"),
+ handler: this.onMultiCreateClick,
+ scope: this
+ });
+
+ this.topToolbar.insert(2, {xtype: 'tbseparator'});
+ this.topToolbar.insert(3, this.multiCreateButton);
+ },
+ /**
+ * Creates a new storage location multi-create window.
+ */
+ onMultiCreateClick: function () {
+ var j = Ext.create("PartKeepr.StorageLocationMultiCreateWindow", {
+ listeners: {
+ destroy: {
+ fn: this.onMultiCreateWindowDestroy,
+ scope: this
+ }
+ }
+ });
+ j.show();
+ },
+ /**
+ * Reloads the store after the multi-create window was closed
+ */
+ onMultiCreateWindowDestroy: function () {
+ this.store.load();
+ }
});
\ No newline at end of file
diff --git a/frontend/js/Components/StorageLocation/StorageLocationMultiAddDialog.js b/frontend/js/Components/StorageLocation/StorageLocationMultiAddDialog.js
@@ -0,0 +1,206 @@
+/**
+ * Represents a form which is used to create multiple storage locations at once.
+ * @class PartKeepr.StorageLocationMultiAddDialog
+ */
+Ext.define('PartKeepr.StorageLocationMultiAddDialog', {
+ extend: 'Ext.form.Panel',
+
+ // Layout settings
+ layout: 'anchor',
+ defaults: {
+ anchor: '100%'
+ },
+
+ // Styling
+ border: false,
+ bodyStyle: 'background:#DFE8F6;padding: 10px;',
+
+ /**
+ * Initializes the component. Adds all form fields
+ */
+ initComponent: function () {
+
+ /**
+ * The prefix represents the first part of the storage location name,
+ * e.g. "A" for storage locations "A0001".
+ */
+ this.storageLocationPrefix = Ext.create("Ext.form.field.Text", {
+ fieldLabel: i18n("Name Prefix"),
+ listeners: {
+ change: {
+ fn: this.onFormChange,
+ scope: this
+ }
+ }
+ });
+
+ /**
+ * Specifies the start of the numeric range.
+ */
+ this.storageLocationStart = Ext.create("Ext.form.field.Number", {
+ fieldLabel: i18n("Start"),
+ value: 1,
+ minValue: 0,
+ columnWidth: 0.5,
+ listeners: {
+ change: {
+ fn: this.onFormChange,
+ scope: this
+ }
+ }
+ });
+
+ /**
+ * Specifies the end of the numeric range.
+ */
+ this.storageLocationEnd = Ext.create("Ext.form.field.Number", {
+ fieldLabel: i18n("End"),
+ value: 10,
+ minValue: 1,
+ columnWidth: 0.5,
+ margin: "0 0 0 5",
+ listeners: {
+ change: {
+ fn: this.onFormChange,
+ scope: this
+ }
+ }
+ });
+
+ /**
+ * Specifies if the storage locations should be prefixed with a zero (e.g. creates A0001 instead of A1).
+ */
+ this.storageLocationZeroPrefix = Ext.create("Ext.form.field.Checkbox", {
+ boxLabel: i18n("Prefix with zeroes"),
+ hideEmptyLabel: false,
+ columnWidth: 0.5,
+ listeners: {
+ change: {
+ fn: this.onFormChange,
+ scope: this
+ }
+ }
+ });
+
+ /**
+ * Specifies the overall length of the storage location name. If you have a prefix "A" and numbers up to
+ * 100, you can set the overall length to 5 to achieve "A0100", or to 6 to achieve "A00100".
+ */
+ this.storageLocationOverallLength = Ext.create("Ext.form.field.Number", {
+ fieldLabel: i18n("Length"),
+ columnWidth: 0.5,
+ margin: "0 0 0 5",
+ disabled: true,
+ listeners: {
+ change: {
+ fn: this.onFormChange,
+ scope: this
+ }
+ }
+ });
+
+ /**
+ * Creates a field which displays the storage locations to be created.
+ */
+ this.outputField = Ext.create("Ext.form.field.TextArea", {
+ fieldLabel: i18n("Sample"),
+ readOnly: true,
+ anchor: '100% -70'
+ });
+
+ this.items = [
+ this.storageLocationPrefix,
+ {
+ layout: 'column',
+ border: false,
+ bodyStyle: 'background:#DFE8F6;',
+ items: [
+ this.storageLocationStart,
+ this.storageLocationEnd
+ ]
+ },
+ {
+ layout: 'column',
+ border: false,
+ plain: true,
+ bodyStyle: 'background:#DFE8F6;',
+ items: [
+ this.storageLocationZeroPrefix,
+ this.storageLocationOverallLength
+ ]
+ },
+ this.outputField
+ ];
+
+ this.callParent();
+
+ this.recalculateDemo();
+ },
+ /**
+ * Called when something in the form has changed.
+ */
+ onFormChange: function () {
+ /**
+ * If the overall length is less than the prefix plus the length of the highest number, update it
+ */
+ if (this.storageLocationOverallLength.getValue() < this.getMinLength()) {
+ this.storageLocationOverallLength.setValue(this.getMinLength());
+ }
+
+ /**
+ * Make sure that the end value is bigger than the start value.
+ */
+ if (this.storageLocationStart.getValue() > this.storageLocationEnd.getValue()) {
+ this.storageLocationEnd.setValue(this.storageLocationStart.getValue());
+ }
+
+ /**
+ * Enable/Disable the length field if zero prefix is wanted
+ */
+ if (this.storageLocationZeroPrefix.getValue()) {
+ this.storageLocationOverallLength.enable();
+ } else {
+ this.storageLocationOverallLength.disable();
+ }
+
+ this.recalculateDemo();
+ },
+ /**
+ * Calculates the minimum length possible
+ * @returns int The minimum length possible
+ */
+ getMinLength: function () {
+ return strlen(this.storageLocationPrefix.getValue()) +
+ strlen((this.storageLocationEnd.getValue()).toString());
+ },
+ /**
+ * Updates the sample field
+ */
+ recalculateDemo: function () {
+ this.outputField.setValue(implode("\n", this.getStorageLocations()));
+ },
+ /**
+ * Returns all storage locations which are to be created
+ * @returns {Array} The storage locations
+ */
+ getStorageLocations: function () {
+ var j = [];
+
+ for (var i=this.storageLocationStart.getValue();i<this.storageLocationEnd.getValue()+1;i++) {
+ if (!this.storageLocationZeroPrefix.getValue()) {
+ // No padding wanted
+ j.push(this.storageLocationPrefix.getValue()+i);
+ } else {
+ var padLength = this.storageLocationOverallLength.getValue() -
+ ( strlen(this.storageLocationPrefix.getValue()) +
+ strlen(i));
+
+ j.push(this.storageLocationPrefix.getValue() + str_repeat("0", padLength)+ i);
+ }
+
+ }
+
+ return j;
+ }
+
+});+
\ No newline at end of file
diff --git a/frontend/js/Components/StorageLocation/StorageLocationMultiAddWindow.js b/frontend/js/Components/StorageLocation/StorageLocationMultiAddWindow.js
@@ -0,0 +1,77 @@
+/**
+ * Represents the multi create window.
+ * @class PartKeepr.StorageLocationMultiCreateWindow
+ */
+Ext.define("PartKeepr.StorageLocationMultiCreateWindow", {
+ extend: 'Ext.Window',
+
+ // Layout stuff
+ layout: 'fit',
+ width: 500,
+ height: 250,
+
+ // Title
+ title: i18n("Multi-Create Storage Locations"),
+
+ /**
+ * Initializes the window by adding the buttons and the form
+ */
+ initComponent: function () {
+ this.form = Ext.create("PartKeepr.StorageLocationMultiAddDialog");
+
+ this.items = [ this.form ];
+
+ // Creates the add button as instance, so we can disable it easily.
+ this.addButton = Ext.create("Ext.button.Button", {
+ text: i18n("Create Storage Locations"),
+ icon: 'resources/silkicons/add.png',
+ handler: this.onAddClick,
+ scope: this
+ });
+
+ this.bbar = [
+ this.addButton,
+ {
+ text: i18n("Close"),
+ handler: this.onCloseClick,
+ scope: this,
+ icon: 'resources/silkicons/cancel.png'
+ }];
+
+ this.callParent();
+ },
+ /**
+ * Called when the "Add" button was clicked. Sends a call to the server
+ * to create the storage locations
+ */
+ onAddClick: function () {
+ this.addButton.disable();
+ var call = new PartKeepr.ServiceCall("StorageLocation", "massCreate");
+ call.setParameter("storageLocations", this.form.getStorageLocations());
+ call.setHandler(Ext.bind(this.onAdded, this));
+ call.doCall();
+
+ },
+ /**
+ * Called when the service call was completed. Displays an error dialog
+ * if something went wrong.
+ * @param response The server response
+ */
+ onAdded: function (response) {
+ this.addButton.enable();
+
+
+ if (response.data.length > 0) {
+ Ext.Msg.alert(i18n("Errors occured"), implode("<br>", response.data));
+ } else {
+ this.close();
+ }
+ },
+ /**
+ * Close the dialog
+ */
+ onCloseClick: function () {
+ this.close();
+ }
+
+});+
\ No newline at end of file
diff --git a/src/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationManager.php b/src/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationManager.php
@@ -55,6 +55,13 @@ class StorageLocationManager extends Singleton {
}
}
+ public function getStorageLocationByName ($name) {
+ $query = PartKeepr::getEM()->createQuery("SELECT s FROM de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation s WHERE s.name = :name");
+ $query->setParameter("name", $name);
+
+ return $query->getSingleResult();
+ }
+
public function addStorageLocation ($name) {
$storageLocation = new StorageLocation();
$storageLocation->setName($name);
diff --git a/src/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationService.php b/src/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationService.php
@@ -66,44 +66,31 @@ class StorageLocationService extends Service implements RestfulService {
return array("data" => null);
}
- // Old Stuff below
- public function getStorageLocations() {
- return StorageLocationManager::getInstance()->getStorageLocations(
- $this->getParameter("start", 0),
- $this->getParameter("limit", 10),
- $this->getParameter("sortby", "name"),
- $this->getParameter("dir", "asc"),
- $this->getParameter("filter", ""));
- }
-
- public function addStorageLocation () {
- $this->requireParameter("name");
-
- StorageLocationManager::getInstance()->addStorageLocation($this->getParameter("name"));
- }
-
- public function deleteStorageLocation () {
- $this->requireParameter("id");
-
- StorageLocationManager::getInstance()->deleteStorageLocation($this->getParameter("id"));
- }
-
- public function getStorageLocation () {
- $this->requireParameter("id");
-
- return StorageLocationManager::getInstance()->getStorageLocation($this->getParameter("id"))->serialize();
- }
-
- public function saveStorageLocation () {
- $this->requireParameter("id");
- $this->requireParameter("name");
+ /**
+ * Creates multiple storage locations at once.
+ *
+ * Requires that the parameter "storageLocations" is set to an array with the names of the storage locations.
+ * Returns all error messages as "data" index in the result array.
+ */
+ public function massCreate () {
+ $this->requireParameter("storageLocations");
- $storageLocation = StorageLocationManager::getInstance()->getStorageLocation($this->getParameter("id"));
+ $aMessages = array();
- $storageLocation->setName($this->getParameter("name"));
+ foreach ($this->getParameter("storageLocations") as $storageLocation) {
+ try {
+ $obj = StorageLocationManager::getInstance()->getStorageLocationByName($storageLocation);
+ $aMessages[] = sprintf(PartKeepr::i18n("Storage Location %s already exists"), $storageLocation);
+ } catch (\Exception $e) {
+ $obj = new StorageLocation();
+ $obj->setName($storageLocation);
+ PartKeepr::getEM()->persist($obj);
+ }
+
+ }
PartKeepr::getEM()->flush();
- return $storageLocation->serialize();
+ return array("data" => $aMessages);
}
}
\ No newline at end of file