partkeepr

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

commit f7859ae1bb1c5499945c6b147516127163dc2e5e
parent 761cb6e861c2e1f4b3493c9f5e4b1f927367b279
Author: Timo A. Hummel <timo@netraver.de>
Date:   Thu,  9 Jun 2011 19:26:52 +0200

Added initial part parameter implementation

Diffstat:
Mfrontend/index.php | 4++++
Mfrontend/js/Components/Part/PartEditor.js | 8+++++++-
Mfrontend/js/Components/Part/PartEditorWindow.js | 7++++++-
Afrontend/js/Components/Part/PartParameterGrid.js | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afrontend/js/Components/Widgets/PartParameterComboBox.js | 39+++++++++++++++++++++++++++++++++++++++
Afrontend/js/Components/Widgets/UnitComboBox.js | 27+++++++++++++++++++++++++++
Afrontend/js/Models/PartParameter.js | 12++++++++++++
Mfrontend/js/PartDB2.js | 14++++++++++++++
Mfrontend/rest.php | 36++++++++++++++++++++++++++++++++++++
Msrc/de/RaumZeitLabor/PartDB2/Part/Part.php | 23+++++++++++++++++++++--
Msrc/de/RaumZeitLabor/PartDB2/Part/PartManufacturer.php | 4++++
Msrc/de/RaumZeitLabor/PartDB2/Part/PartService.php | 7++++++-
Msrc/de/RaumZeitLabor/PartDB2/PartDB2.php | 3++-
Asrc/de/RaumZeitLabor/PartDB2/PartParameter/PartParameter.php | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/de/RaumZeitLabor/PartDB2/Service/ServiceManager.php | 4++++
Mtesting/SetupDatabase.php | 22++++++++++++++++++++++
16 files changed, 520 insertions(+), 6 deletions(-)

diff --git a/frontend/index.php b/frontend/index.php @@ -38,6 +38,8 @@ <script type="text/javascript" src="js/Components/Widgets/ManufacturerComboBox.js"></script> <script type="text/javascript" src="js/Components/Widgets/DistributorComboBox.js"></script> <script type="text/javascript" src="js/Components/Widgets/PartUnitComboBox.js"></script> + <script type="text/javascript" src="js/Components/Widgets/UnitComboBox.js"></script> + <script type="text/javascript" src="js/Components/Widgets/PartParameterComboBox.js"></script> <script type="text/javascript" src="js/Util/ServiceCall.js"></script> @@ -57,6 +59,7 @@ <script type="text/javascript" src="js/Models/Part.js"></script> <script type="text/javascript" src="js/Models/PartUnit.js"></script> <script type="text/javascript" src="js/Models/PartDistributor.js"></script> + <script type="text/javascript" src="js/Models/PartParameter.js"></script> <script type="text/javascript" src="js/Models/Unit.js"></script> <script type="text/javascript" src="js/Models/SiPrefix.js"></script> <script type="text/javascript" src="js/Models/StockEntry.js"></script> @@ -115,6 +118,7 @@ <script type="text/javascript" src="js/Components/Part/PartsManager.js"></script> <script type="text/javascript" src="js/Components/Part/PartsGrid.js"></script> + <script type="text/javascript" src="js/Components/Part/PartParameterGrid.js"></script> <script type="text/javascript" src="js/Components/Part/PartDistributorGrid.js"></script> <script type="text/javascript" src="js/Components/Part/PartManufacturerGrid.js"></script> <script type="text/javascript" src="js/Components/Part/PartEditorWindow.js"></script> diff --git a/frontend/js/Components/Part/PartEditor.js b/frontend/js/Components/Part/PartEditor.js @@ -52,6 +52,11 @@ Ext.define('PartDB2.PartEditor', { layout: 'fit' }); + this.partParameterGrid = Ext.create("PartDB2.PartParameterGrid", { + title: i18n("Parameters"), + layout: 'fit' + }); + this.items = { xtype: 'tabpanel', border: false, @@ -70,7 +75,8 @@ Ext.define('PartDB2.PartEditor', { items: basicEditorFields }, this.partDistributorGrid, - this.partManufacturerGrid + this.partManufacturerGrid, + this.partParameterGrid ] }; diff --git a/frontend/js/Components/Part/PartEditorWindow.js b/frontend/js/Components/Part/PartEditorWindow.js @@ -4,7 +4,7 @@ Ext.define('PartDB2.PartEditorWindow', { width: 500, minWidth: 500, minHeight: 300, - height: 320, + height: 350, layout: 'fit', title: i18n("Add Part"), initComponent: function () { @@ -33,7 +33,12 @@ Ext.define('PartDB2.PartEditorWindow', { r.manufacturers = []; } + if (!r.parameters) { + r.parameters = []; + } + this.editor.partDistributorGrid.getStore().loadData(r.distributors); this.editor.partManufacturerGrid.getStore().loadData(r.manufacturers); + this.editor.partParameterGrid.getStore().loadData(r.parameters) } }); \ No newline at end of file diff --git a/frontend/js/Components/Part/PartParameterGrid.js b/frontend/js/Components/Part/PartParameterGrid.js @@ -0,0 +1,147 @@ +Ext.define('PartDB2.PartParameterGrid', { + extend: 'Ext.grid.Panel', + alias: 'widget.PartParameterGrid', + border: false, + initComponent: function () { + this.store = Ext.create("Ext.data.Store", { + model: 'PartParameter', + proxy: { + type: 'memory', + reader: { + type: 'json' + } + } + + }); + + this.editing = Ext.create('Ext.grid.plugin.RowEditing', { + clicksToEdit: 1 + }); + + this.plugins = [ this.editing ]; + + this.deleteButton = Ext.create("Ext.button.Button", { + text: 'Delete', + disabled: true, + itemId: 'delete', + scope: this, + icon: 'resources/silkicons/building_delete.png', + handler: this.onDeleteClick + }); + + this.dockedItems = [{ + xtype: 'toolbar', + items: [{ + text: 'Add', + scope: this, + icon: 'resources/silkicons/building_add.png', + handler: this.onAddClick + }, this.deleteButton] + }]; + + this.columns = [ + { + header: i18n("Parameter"), + dataIndex: 'name', + flex: 0.2, + editor: { + xtype:'PartParameterComboBox', + allowBlank:true + } + }, + { + header: i18n("Description"), + dataIndex: 'description', + flex: 0.3, + editor: { + xtype:'textfield', + allowBlank:true + } + }, + { + header: i18n("Unit"), + flex: 0.2, + dataIndex: 'unit_id', + renderer: function (val,p,rec) { + var foundRec = PartDB2.getApplication().getUnitStore().findRecord("id", val); + + if (foundRec) { + return foundRec.get("name"); + } else { + return ""; + } + }, + editor: { + xtype:'UnitComboBox', + allowBlank:true + } + }, + { + header: i18n("Value"), + flex: 0.2, + dataIndex: "value", + renderer: function (val,p,rec) { + /* Convert the value into a "nice" si-prefixed unit */ + + var foundRec = PartDB2.getApplication().getUnitStore().findRecord("id", rec.get("unit_id")); + var allowedSiPrefixes = foundRec.prefixes().getRange(); + + console.log(allowedSiPrefixes.length); + finalValue = null; + + for (var i=0;i<allowedSiPrefixes.length;i++) { + var test = val / Math.pow(10, allowedSiPrefixes[i].get("power")); + + if (test >= 1 && test < 1000) { + finalValue = test.toPrecision(6) + " "+allowedSiPrefixes[i].get("symbol")+foundRec.get("symbol"); + } + } + + if (finalValue === null) { + finalValue = val.toPrecision(6) + foundRec.get("symbol"); + } + + return finalValue; + }, + editor: { + xtype: 'numberfield', + decimalPrecision: 20 + } + } + ]; + + this.callParent(); + + this.getSelectionModel().on('selectionchange', this.onSelectChange, this); + this.on("edit", this.onEdit, this); + }, + onEdit: function (data) { + /*var id = data.record.get("unit_id"); + + var rec = PartDB2.getApplication().getManufacturerStore().findRecord("id", id); + + if (rec) { + data.record.set("manufacturer_name", rec.get("name")); + }*/ + }, + onAddClick: function () { + this.editing.cancelEdit(); + + /*var rec = new PartDB2.PartManufacturer({ + packagingUnit: 1 + }); + + this.store.insert(0, rec); + + this.editing.startEdit(0,0);*/ + }, + onDeleteClick: function () { + var selection = this.getView().getSelectionModel().getSelection()[0]; + if (selection) { + this.store.remove(selection); + } + }, + onSelectChange: function(selModel, selections){ + this.deleteButton.setDisabled(selections.length === 0); + } +});+ \ No newline at end of file diff --git a/frontend/js/Components/Widgets/PartParameterComboBox.js b/frontend/js/Components/Widgets/PartParameterComboBox.js @@ -0,0 +1,39 @@ +Ext.define("PartDB2.PartParameterComboBox",{ + extend:"Ext.form.field.ComboBox", + alias: 'widget.PartParameterComboBox', + displayField: 'name', + valueField: 'name', + autoSelect: false, + queryMode: 'remote', + triggerAction: 'all', + forceSelection: false, + editable: true, + initComponent: function () { + //this.store = PartDB2.getApplication().getPartUnitStore(); + + this.store = Ext.create("Ext.data.Store", { + fields: [{ name: 'name' }], + proxy: { + type: 'ajax', + url: PartDB2.getBasePath() + "/Part/getPartParameterNames", + reader: { + type: 'json', + root: 'response.data' + } + } + }); + + /* Workaround to remember the value when loading */ + this.store.on("beforeload", function () { + this._oldValue = this.getValue(); + }, this); + + /* Set the old value when load is complete */ + this.store.on("load", function () { + this.setValue(this._oldValue); + }, this); + + this.callParent(); + } +}); + diff --git a/frontend/js/Components/Widgets/UnitComboBox.js b/frontend/js/Components/Widgets/UnitComboBox.js @@ -0,0 +1,27 @@ +Ext.define("PartDB2.UnitComboBox",{ + extend:"Ext.form.field.ComboBox", + alias: 'widget.UnitComboBox', + displayField: 'name', + valueField: 'id', + autoSelect: true, + queryMode: 'local', + triggerAction: 'all', + forceSelection: true, + editable: false, + initComponent: function () { + this.store = PartDB2.getApplication().getUnitStore(); + + /* Workaround to remember the value when loading */ + this.store.on("beforeload", function () { + this._oldValue = this.getValue(); + }, this); + + /* Set the old value when load is complete */ + this.store.on("load", function () { + this.setValue(this._oldValue); + }, this); + + this.callParent(); + } +}); + diff --git a/frontend/js/Models/PartParameter.js b/frontend/js/Models/PartParameter.js @@ -0,0 +1,12 @@ +PartDB2.PartParameter = Ext.define("PartParameter", { + extend: "Ext.data.Model", + fields: [ + { id: 'id', name: 'id', type: 'int' }, + { name: 'part_id', type: 'int' }, + { name: 'name', type: 'string' }, + { name: 'description', type: 'string' }, + { name: 'unit_id', type: 'int' }, + { name: 'value', type: 'float' } + ], + proxy: PartDB2.getRESTProxy("PartParameter") +}); diff --git a/frontend/js/PartDB2.js b/frontend/js/PartDB2.js @@ -63,6 +63,16 @@ Ext.application({ pageSize: -1, autoLoad: false }); + + this.unitStore = Ext.create("Ext.data.Store", + { + model: 'Unit', + pageSize: -1, + autoLoad: false + }); + }, + getUnitStore: function () { + return this.unitStore; }, getPartUnitStore: function () { return this.partUnitStore; @@ -91,6 +101,9 @@ Ext.application({ * If the user pulls down the storage location combo box, * reload it. * + * YES, this is becoming nasty. We have now 6 stores, each + * reloading every minute. This NEEDS to be fixed soon! + * */ reloadStores: function () { this.storageLocationStore.load(); @@ -98,6 +111,7 @@ Ext.application({ this.manufacturerStore.load(); this.distributorStore.load(); this.partUnitStore.load(); + this.unitStore.load(); Ext.defer(PartDB2.getApplication().reloadStores, 100000, this); }, createLayout: function () { diff --git a/frontend/rest.php b/frontend/rest.php @@ -8,6 +8,42 @@ use de\RaumZeitLabor\PartDB2\PartDB2, include("../src/de/RaumZeitLabor/PartDB2/PartDB2.php"); PartDB2::initialize(""); +/** + * This script dispatches the request to the ServiceManager. + * + * You have a few options how to define which service and call you wish to request: + * + * + * DIRECT SPECIFICATION + * ==================== + * + * You have a few options to specify the call directly: + * + * - You can specify the call via a HTTP header. Set the header named "call" to the call you wish to execute. + * - You can specify the call via a HTTP POST or GET variable. Set the variable named "call" to the call you wish + * to execute. + * - You can specify the call as second parameter in the URL, e.g. if your service is "Part" and your call is + * "getParts", you would invoke rest.php/Part/getParts + * + * If you specify the call, the ServiceManager ignores the HTTP verb. + * + * SERVICE + * ======= + * + * The service is specified via an URL attached to the rest.php file. Example: + * + * rest.php/Part + * + * /Part specifies that you wish to call the Part service. The service manager automatically extends the short "Part" + * name to the class de\RaumZeitLabor\PartDB2\Part\PartService. + * + * REST + * ==== + * + * Each service which implements the RESTful interface operates on the POST, PUT, GET and DELETE + * HTTP verbs. Those are mapped to the get(), create(), update() and destroy() methods. + * + */ try { $response = array(); $response["status"] = "ok"; diff --git a/src/de/RaumZeitLabor/PartDB2/Part/Part.php b/src/de/RaumZeitLabor/PartDB2/Part/Part.php @@ -77,11 +77,16 @@ class Part { /** * @OneToMany(targetEntity="de\RaumZeitLabor\PartDB2\Stock\StockEntry",mappedBy="part",cascade={"persist", "remove"}) - * Enter description here ... - * @var unknown_type + * @var ArrayCollection */ private $stockLevels; + /** + * @OneToMany(targetEntity="de\RaumZeitLabor\PartDB2\PartParameter\PartParameter",mappedBy="part") + * @var ArrayCollection + */ + private $parameters; + public function __construct () { $this->distributors = new \Doctrine\Common\Collections\ArrayCollection(); $this->manufacturers = new \Doctrine\Common\Collections\ArrayCollection(); @@ -158,6 +163,14 @@ class Part { return $this->manufacturers; } + /** + * Returns the parameters assigned to this part + * @return array An array of PartParameter objects + */ + public function getParameters () { + return $this->parameters; + } + public function getStockLevel () { $query = PartDB2::getEM()->createQuery("SELECT SUM(s.stockLevel) FROM de\RaumZeitLabor\PartDB2\Stock\StockEntry s WHERE s.part = :part"); $query->setParameter("part", $this); @@ -183,6 +196,11 @@ class Part { $aDistributors[] = $distributor->serialize(); } + $aParameters = array(); + foreach ($this->getParameters() as $parameter) { + $aParameters[] = $parameter->serialize(); + } + return array( "id" => $this->id, "name" => $this->name, @@ -198,6 +216,7 @@ class Part { "partUnit_shortName" => is_object($this->partUnit) ? $this->getPartUnit()->getId() : "", "manufacturers" => $aManufacturers, "distributors" => $aDistributors, + "parameters" => $aParameters ); } diff --git a/src/de/RaumZeitLabor/PartDB2/Part/PartManufacturer.php b/src/de/RaumZeitLabor/PartDB2/Part/PartManufacturer.php @@ -64,6 +64,10 @@ class PartManufacturer { return $this->id; } + /** + * Returns the data of this object in a serialized form. + * @return array The result array + */ public function serialize () { return array( "id" => $this->getId(), diff --git a/src/de/RaumZeitLabor/PartDB2/Part/PartService.php b/src/de/RaumZeitLabor/PartDB2/Part/PartService.php @@ -49,7 +49,12 @@ class PartService extends Service implements RestfulService { throw new \Exception("Not yet implemented"); } - + public function getPartParameterNames () { + $dql = "SELECT pp.name FROM de\RaumZeitLabor\PartDB2\PartParameter\PartParameter pp GROUP BY pp.name"; + $query = PartDB2::getEM()->createQuery($dql); + + return array("data" => $query->getArrayResult()); + } // Old stuff below public function getParts () { diff --git a/src/de/RaumZeitLabor/PartDB2/PartDB2.php b/src/de/RaumZeitLabor/PartDB2/PartDB2.php @@ -185,7 +185,8 @@ class PartDB2 { 'de\RaumZeitLabor\PartDB2\Statistic\StatisticSnapshot', 'de\RaumZeitLabor\PartDB2\Statistic\StatisticSnapshotUnit', 'de\RaumZeitLabor\PartDB2\SiPrefix\SiPrefix', - 'de\RaumZeitLabor\PartDB2\Unit\Unit' + 'de\RaumZeitLabor\PartDB2\Unit\Unit', + 'de\RaumZeitLabor\PartDB2\PartParameter\PartParameter' ); } diff --git a/src/de/RaumZeitLabor/PartDB2/PartParameter/PartParameter.php b/src/de/RaumZeitLabor/PartDB2/PartParameter/PartParameter.php @@ -0,0 +1,167 @@ +<?php +namespace de\RaumZeitLabor\PartDB2\PartParameter; +declare(encoding = 'UTF-8'); + +use de\RaumZeitLabor\PartDB2\PartDB2, + de\RaumZeitLabor\PartDB2\Util\Exceptions\OutOfRangeException, + de\RaumZeitLabor\PartDB2\Unit\Unit, + de\RaumZeitLabor\PartDB2\Part\Part, + de\RaumZeitLabor\PartDB2\SiPrefix\SiPrefix; + + +/** + * This object represents a parameter. Each parameter can have an unit (defined by the class "Unit") associated with + * a numeric value. + * + * @Entity + **/ +class PartParameter { + /** + * @Id @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + * @var integer + */ + private $id; + + /** + * @ManyToOne(targetEntity="de\RaumZeitLabor\PartDB2\Part\Part") + * The part this parameter is bound to + * @var Part + */ + private $part; + + /** + * The name of the parameter (e.g. Resistance, Voltage) + * @Column(type="string") + * @var string + */ + private $name; + + /** + * A description for this parameter + * @Column(type="string") + * @var string + */ + private $description; + + /** + * The unit for this type. May be null. + * + * @ManyToOne(targetEntity="de\RaumZeitLabor\PartDB2\Unit\Unit") + * @var Unit + */ + private $unit; + + /** + * The value of the unit. + * @Column(type="float") + * @var float + */ + private $value; + + /** + * Sets the name for this parameter + * @param string $name The name + */ + public function setName ($name) { + $this->name = $name; + } + + /** + * Returns the name for this parameter + * @return string The name for this parameter + */ + public function getName () { + return $this->name; + } + + /** + * Sets the description for this parameter + * @param string $description The description + */ + public function setDescription ($description) { + $this->description = $description; + } + + /** + * Returns the description + * @return string The description + */ + public function getDescription () { + return $this->description; + } + + /** + * Sets the unit + * @param Unit $unit The unit to set + */ + public function setUnit (Unit $unit = null) { + $this->unit = $unit; + } + + /** + * Returns the unit + * @return Unit the unit + */ + public function getUnit () { + return $this->unit; + } + + /** + * Sets the part + * @param Part $part The part to set + */ + public function setPart (Part $part) { + $this->part = $part; + } + + /** + * Returns the part + * @return Part the part + */ + public function getPart () { + return $this->part; + } + + /** + * Sets the value + * @param float $value The value to set + */ + public function setValue ($value) { + $this->value = $value; + } + + /** + * Returns the value + * @return float The value + */ + public function getValue () { + return $this->value; + } + + /** + * Returns the ID for this object. + * @param none + * @return int The ID for this object + */ + public function getId () { + return $this->id; + } + + /** + * Returns the data of this object in a serialized form. + * @return array The result array + */ + public function serialize () { + return array( + "id" => $this->getId(), + "name" => $this->getName(), + "description" => $this->getDescription(), + "value" => $this->getValue(), + "part_id" => $this->getPart()->getId(), + "unit_id" => is_object($this->getUnit()) ? $this->getUnit()->getId() : null + + ); + } +} + + \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartDB2/Service/ServiceManager.php b/src/de/RaumZeitLabor/PartDB2/Service/ServiceManager.php @@ -13,10 +13,14 @@ class ServiceManager { $request = new Request(array('restful' => true)); $service = $request->getService(); + //print_r($request->action); + if ($service->hasHeader("call")) { $call = $service->getHeader("call"); } elseif (array_key_exists("call", $_REQUEST) && $_REQUEST["call"] != "") { $call = $_REQUEST["call"]; + } elseif ($request->action != "") { + $call = $request->action; } else { switch (strtoupper($request->getMethod())) { case "POST": diff --git a/testing/SetupDatabase.php b/testing/SetupDatabase.php @@ -1,5 +1,7 @@ <?php namespace de\RaumZeitLabor\PartDB2\Tests; +use de\RaumZeitLabor\PartDB2\PartParameter\PartParameter; + declare(encoding = 'UTF-8'); use de\RaumZeitLabor\PartDB2\Unit\Unit; @@ -178,6 +180,8 @@ PartDB2::getEM()->flush(); /* Add units */ $data = \Symfony\Component\Yaml\Yaml::load("../setup/data/units.yaml"); +$aUnits = array(); + foreach ($data as $unitName => $data) { $unit = new Unit(); $unit->setName($unitName); @@ -197,6 +201,7 @@ foreach ($data as $unitName => $data) { } PartDB2::getEM()->persist($unit); + $aUnits[] = $unit; } @@ -237,6 +242,7 @@ PartDB2::getEM()->flush(); $r = mysql_query("SELECT * FROM parts"); +$aRandomUnitNames = array("Spannung", "Strom", "Leitfähigkeit", "Viskosität", "Nessis"); while ($part = mysql_fetch_assoc($r)) { $oPart = new Part(); $oPart->setName(convertText($part["name"])); @@ -272,6 +278,22 @@ while ($part = mysql_fetch_assoc($r)) { } PartDB2::getEM()->persist($oStock); + + /* Add some random parameters */ + + + for ($i=0;$i<rand(1,15);$i++) { + $val = rand(0,999) * (pow(10,(rand(-20,20)))); + $oPartParameter = new PartParameter(); + $oPartParameter->setName($aRandomUnitNames[array_rand($aRandomUnitNames)]); + $oPartParameter->setDescription("Testbeschreibung"); + $oPartParameter->setPart($oPart); + $oPartParameter->setUnit($aUnits[array_rand($aUnits)]); + $oPartParameter->setValue($val); + PartDB2::getEM()->persist($oPartParameter); + } + + }