partkeepr

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

commit a919f65ce60fb13ce8bec38b92cd34b329d6faec
parent 53badb86f5a9b4e9b622fdaa7372a324027c57a4
Author: Felicitus <felicitus@felicitus.org>
Date:   Thu, 16 Jun 2011 23:19:21 +0200

Merge branch 'UPLOAD'

Diffstat:
Mfrontend/file.php | 7++++++-
Mfrontend/image.php | 2+-
Mfrontend/js/Components/CategoryEditor/CategoryEditorTree.js | 66++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mfrontend/js/Components/Editor/Editor.js | 6+++---
Mfrontend/js/Components/Editor/EditorComponent.js | 4++--
Mfrontend/js/Components/Editor/EditorGrid.js | 14++++++++++++--
Afrontend/js/Components/Footprint/FootprintAttachmentGrid.js | 7+++++++
Mfrontend/js/Components/Footprint/FootprintEditor.js | 37+++++++++++++++++++++++++++++++------
Mfrontend/js/Components/Footprint/FootprintEditorComponent.js | 2+-
Mfrontend/js/Components/Part/PartAttachmentGrid.js | 152++-----------------------------------------------------------------------------
Mfrontend/js/Components/Part/PartsGrid.js | 10++++++++++
Mfrontend/js/Components/Part/PartsManager.js | 18+++++++++++++-----
Afrontend/js/Components/Widgets/AttachmentGrid.js | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfrontend/js/Dialogs/FileUploadDialog.js | 41+++++++++++++++++++++++++++++++++--------
Mfrontend/js/Models/Category.js | 2+-
Mfrontend/js/Models/Distributor.js | 2+-
Mfrontend/js/Models/Footprint.js | 3++-
Afrontend/js/Models/FootprintAttachment.js | 16++++++++++++++++
Mfrontend/js/Models/Manufacturer.js | 2+-
Mfrontend/js/Models/ManufacturerICLogo.js | 8++++----
Mfrontend/js/Models/Part.js | 5+----
Mfrontend/js/Models/PartAttachment.js | 2+-
Mfrontend/js/Models/PartUnit.js | 2+-
Mfrontend/js/Models/StorageLocation.js | 2+-
Mfrontend/js/Models/Unit.js | 2+-
Mfrontend/js/Models/User.js | 2+-
Msrc/de/RaumZeitLabor/PartKeepr/Footprint/Footprint.php | 30+++++++++++++++++++++++++++++-
Asrc/de/RaumZeitLabor/PartKeepr/Footprint/FootprintAttachment.php | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentService.php | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerICLogo.php | 2+-
Msrc/de/RaumZeitLabor/PartKeepr/Part/PartService.php | 25++++++++++++++++++++++++-
Msrc/de/RaumZeitLabor/PartKeepr/PartKeepr.php | 1+
Msrc/de/RaumZeitLabor/PartKeepr/TempFile/TempFileService.php | 15+++++++++++----
Msrc/de/RaumZeitLabor/PartKeepr/TempImage/TempImageService.php | 18++++++++++++------
Mtesting/SetupDatabase.php | 7++++---
36 files changed, 705 insertions(+), 225 deletions(-)

diff --git a/frontend/file.php b/frontend/file.php @@ -1,5 +1,7 @@ <?php namespace de\RaumZeitLabor\PartKeepr\Frontend; +use de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment; + use de\RaumZeitLabor\PartKeepr\Part\PartAttachment; use de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile; @@ -22,6 +24,9 @@ try { case "PartAttachment": $file = PartAttachment::loadById($id); break; + case "FootprintAttachment": + $file = FootprintAttachment::loadById($id); + break; default: $file = null; // Add default image? @@ -44,5 +49,5 @@ $fp = fopen($file->getFilename(), "rb"); fpassthru($fp); fclose($fp); -Netraver::getEM()->flush(); +PartKeepr::getEM()->flush(); exit(); \ No newline at end of file diff --git a/frontend/image.php b/frontend/image.php @@ -45,5 +45,5 @@ $fp = fopen($file, "rb"); fpassthru($fp); fclose($fp); -Netraver::getEM()->flush(); +PartKeepr::getEM()->flush(); exit(); \ No newline at end of file diff --git a/frontend/js/Components/CategoryEditor/CategoryEditorTree.js b/frontend/js/Components/CategoryEditor/CategoryEditorTree.js @@ -4,7 +4,8 @@ PartKeepr.CategoryEditorTree = Ext.define("CategoryEditorTree", { viewConfig: { animate: false, plugins: { - ptype: 'treeviewdragdrop' + ptype: 'treeviewdragdrop', + ddGroup: 'CategoryTree' } }, initComponent: function () { @@ -12,30 +13,67 @@ PartKeepr.CategoryEditorTree = Ext.define("CategoryEditorTree", { this.callParent(); this.getView().on("drop", Ext.bind(this.onCategoryDrop, this)); + this.getView().on("beforedrop", this.onBeforeDrop, this); this.getView().on("itemcontextmenu", Ext.bind(this.onItemContextMenu, this)); this.createMenu(); }, - onCategoryDrop: function (node, data, model, pos) { + onBeforeDrop: function (node, data, overModel, dropPosition, dropFunction, options) { var draggedRecord = data.records[0]; - var droppedOn = this.getView().getRecord(node); + + if (draggedRecord.modelName == "Part") { + /* Move Part */ + var call = new PartKeepr.ServiceCall("Part", "movePart"); + + if (data.records.length > 1) { + var sources = []; + + for (var i=0;i<data.records.length;i++) { + sources.push(data.records[i].get("id")); + } + + call.setParameter("parts", sources); + } else { + call.setParameter("part", draggedRecord.get("id")); + } + + call.setParameter("targetCategory", droppedOn.get("id")); + call.setHandler(function () { + data.view.store.load(); + }); + call.doCall(); + + return false; + } - var targetRecord; + }, + onCategoryDrop: function (node, data, model, pos) { + var draggedRecord = data.records[0]; + var droppedOn = this.getView().getRecord(node); - if (pos == "after" || pos == "before") { - targetRecord = droppedOn.parentNode; + if (draggedRecord.modelName == "Part") { + return; } else { - targetRecord = droppedOn; + /* Must be a category */ + + var targetRecord; + + if (pos == "after" || pos == "before") { + targetRecord = droppedOn.parentNode; + } else { + targetRecord = droppedOn; + } + + this.getStore().sort("name", "ASC"); + + var call = new PartKeepr.ServiceCall("Category", "moveCategory"); + call.setLoadMessage(sprintf(i18n("Moving category %s..."), draggedRecord.get("name"))); + call.setParameter("category", draggedRecord.get("id")); + call.setParameter("target", targetRecord.get("id")); + call.doCall(); } - this.getStore().sort("name", "ASC"); - - var call = new PartKeepr.ServiceCall("Category", "moveCategory"); - call.setLoadMessage(sprintf(i18n("Moving category %s..."), draggedRecord.get("name"))); - call.setParameter("category", draggedRecord.get("id")); - call.setParameter("target", targetRecord.get("id")); - call.doCall(); }, onItemContextMenu: function (view, record, item, index, event) { diff --git a/frontend/js/Components/Editor/Editor.js b/frontend/js/Components/Editor/Editor.js @@ -19,7 +19,7 @@ Ext.define('PartKeepr.Editor', { // @todo Finish implementing the dirty flag later /*if (this.change == false) { - this.setTitle(this.record.getName() + "*"); + this.setTitle(this.record.getRecordName() + "*"); } this.change = true;*/ @@ -70,8 +70,8 @@ Ext.define('PartKeepr.Editor', { this.record = record; this.getForm().loadRecord(this.record); this.show(); - if (this.record.getName() !== "") { - this.setTitle(this.record.getName()); + if (this.record.getRecordName() !== "") { + this.setTitle(this.record.getRecordName()); } this.change = false; diff --git a/frontend/js/Components/Editor/EditorComponent.js b/frontend/js/Components/Editor/EditorComponent.js @@ -61,7 +61,7 @@ Ext.define('PartKeepr.EditorComponent', { //this.editor.editItem(r); - editor = this.createEditor(r.getName()); + editor = this.createEditor(r.getRecordName()); editor.editItem(r); this.editorTabPanel.add(editor).show(); @@ -94,7 +94,7 @@ Ext.define('PartKeepr.EditorComponent', { Ext.Msg.confirm( this.deleteTitle, - sprintf(this.deleteMessage, r.getName()), + sprintf(this.deleteMessage, r.getRecordName()), function (but) { if (but == "yes") { var editor = this.findEditor(r.get("id")); diff --git a/frontend/js/Components/Editor/EditorGrid.js b/frontend/js/Components/Editor/EditorGrid.js @@ -58,15 +58,25 @@ Ext.define('PartKeepr.EditorGrid', { this.getSelectionModel().on("select", Ext.bind(function (rsm, r, i) { - this.deleteButton.enable(); + if (this.getSelectionModel().getCount() == 1) { + this.deleteButton.enable(); + } else { + this.deleteButton.disable(); + } + this.fireEvent("itemSelect", r); }, this)); this.getSelectionModel().on("deselect", Ext.bind(function (rsm, r, i) { + if (this.getSelectionModel().getCount() == 1) { + this.deleteButton.enable(); + } else { this.deleteButton.disable(); - this.fireEvent("itemDeselect", r); + } + + this.fireEvent("itemDeselect", r); }, this)); this.deleteButton = Ext.create("Ext.button.Button", { diff --git a/frontend/js/Components/Footprint/FootprintAttachmentGrid.js b/frontend/js/Components/Footprint/FootprintAttachmentGrid.js @@ -0,0 +1,6 @@ +Ext.define('PartKeepr.FootprintAttachmentGrid', { + extend: 'PartKeepr.AttachmentGrid', + alias: 'widget.FootprintAttachmentGrid', + + model: "FootprintAttachment" +});+ \ No newline at end of file diff --git a/frontend/js/Components/Footprint/FootprintEditor.js b/frontend/js/Components/Footprint/FootprintEditor.js @@ -1,11 +1,36 @@ Ext.define('PartKeepr.FootprintEditor', { extend: 'PartKeepr.Editor', alias: 'widget.FootprintEditor', - items: [{ - xtype: 'textfield', - name: 'name', - fieldLabel: i18n("Footprint") - }], saveText: i18n("Save Footprint"), - model: 'PartKeepr.Footprint' + model: 'PartKeepr.Footprint', + initComponent: function () { + this.on("startEdit", this.onEditStart, this, { delay: 50 }); + + this.attachmentGrid = Ext.create("PartKeepr.FootprintAttachmentGrid", { + height: 200, + border: true + }); + + this.items = [{ + xtype: 'textfield', + name: 'name', + fieldLabel: i18n("Footprint") + }, { + xtype: 'fieldcontainer', + fieldLabel: i18n("Attachments"), + items: this.attachmentGrid + }]; + + this.callParent(); + }, + onEditStart: function () { + var store = this.record.attachments(); + store.load(); + this.attachmentGrid.bindStore(store); + }, + onItemSave: function () { + this.callParent(); + + this.attachmentGrid.getStore().sync(); + }, }); \ No newline at end of file diff --git a/frontend/js/Components/Footprint/FootprintEditorComponent.js b/frontend/js/Components/Footprint/FootprintEditorComponent.js @@ -8,7 +8,7 @@ Ext.define('PartKeepr.FootprintEditorComponent', { this.createStore({ model: "Footprint", sorters: [{ - property: 'footprint', + property: 'name', direction:'ASC' }] }); diff --git a/frontend/js/Components/Part/PartAttachmentGrid.js b/frontend/js/Components/Part/PartAttachmentGrid.js @@ -1,152 +1,6 @@ Ext.define('PartKeepr.PartAttachmentGrid', { - extend: 'Ext.grid.Panel', + extend: 'PartKeepr.AttachmentGrid', alias: 'widget.PartAttachmentGrid', - border: false, - initComponent: function () { - this.store = Ext.create("Ext.data.Store", { - model: 'PartAttachment', - proxy: { - type: 'memory', - reader: { - type: 'json' - } - } - - }); - - this.editing = Ext.create('Ext.grid.plugin.CellEditing', { - clicksToEdit: 1 - }); - - this.plugins = [ this.editing ]; - - 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.viewButton = Ext.create("Ext.button.Button", { - text: i18n("View"), - handler: this.onViewClick, - scope: this, - disabled: true - }); - - this.dockedItems = [{ - xtype: 'toolbar', - items: [{ - text: i18n('Add'), - scope: this, - icon: 'resources/silkicons/attach.png', - handler: this.onAddClick - }, - this.viewButton, - this.deleteButton - ] - }]; - - this.columns = [ - { - header: "", - dataIndex: 'extension', - width: 30, - renderer: function (val) { - return '<img src="resources/mimetypes/'+val+'.png"/>'; - } - }, - { - header: i18n("Filename"), - dataIndex: 'originalFilename', - width: 200 - }, - { - header: i18n("Size"), - dataIndex: 'size', - width: 80, - renderer: PartKeepr.bytesToSize - }, - { - header: i18n("Description"), - dataIndex: 'description', - flex: 0.4, - editor: { - xtype:'textfield', - allowBlank:true - } - } - ]; - - this.callParent(); - - this.getSelectionModel().on('selectionchange', this.onSelectChange, this); - this.on("itemdblclick", this.onDoubleClick, this); - }, - onDoubleClick: function (view, record) { - if (record) { - this.viewAttachment(record); - } - }, - onAddClick: function () { - var j = Ext.create("PartKeepr.FileUploadDialog"); - j.on("fileUploaded", this.onFileUploaded, this); - j.show(); - }, - onFileUploaded: function (response) { - this.editing.cancelEdit(); - - this.getStore().add({ - id: 0, - tmp_id: response.id, - extension: response.extension, - size: response.size, - originalFilename: response.originalFilename - }); - - }, - 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); - this.viewButton.setDisabled(selections.length === 0); - }, - onViewClick: function () { - var selection = this.getView().getSelectionModel().getSelection()[0]; - if (selection) { - this.viewAttachment(selection); - } - }, - viewAttachment: function (record) { - var mySrc = "file.php?type=PartAttachment&"; - - if (record.get("id") == 0) { - mySrc += "id=0&tmpId=" + record.get("tmp_id"); - } else { - mySrc += "id=" + record.get("id"); - } - console.log(mySrc); - - new Ext.Window({ - title : i18n("Display File"), - width : 300, - height: 300, - maximizable: true, - constrain: true, - layout : 'fit', - items : [{ - xtype : "component", - autoEl : { - tag : "iframe", - src : mySrc - } - }] - }).show(); - } + + model: "PartAttachment" }); \ No newline at end of file diff --git a/frontend/js/Components/Part/PartsGrid.js b/frontend/js/Components/Part/PartsGrid.js @@ -9,6 +9,16 @@ Ext.define('PartKeepr.PartsGrid', { // We want to display the texts for the add/delete buttons buttonTextMode: 'show', + viewConfig: { + plugins: { + ddGroup: 'CategoryTree', + ptype: 'gridviewdragdrop', + enableDrop: false + } + }, + enableDragDrop : true, + stripeRows : true, + multiSelect : true, initComponent: function () { // Create the columns diff --git a/frontend/js/Components/Part/PartsManager.js b/frontend/js/Components/Part/PartsManager.js @@ -45,6 +45,7 @@ Ext.define('PartKeepr.PartManager', { // Create the grid listeners this.grid.on("itemSelect", this.onItemSelect, this); + this.grid.on("itemDeselect", this.onItemSelect, this); this.grid.on("itemAdd", this.onItemAdd, this); this.grid.on("itemDelete", this.onItemDelete, this); @@ -133,11 +134,18 @@ Ext.define('PartKeepr.PartManager', { /** * Called when a part was selected in the grid. Displays the details for this part. */ - onItemSelect: function (r) { - this.detailPanel.setActiveTab(this.detail); - this.detailPanel.show(); - this.detail.setValues(r); - this.stockLevel.part = r.get("id"); + onItemSelect: function () { + if (this.grid.getSelectionModel().getCount() > 1) { + this.detailPanel.hide(); + } else { + var r = this.grid.getSelectionModel().getLastSelected(); + + this.detailPanel.setActiveTab(this.detail); + this.detailPanel.show(); + this.detail.setValues(r); + this.stockLevel.part = r.get("id"); + } + }, /** * Triggers loading of a part diff --git a/frontend/js/Components/Widgets/AttachmentGrid.js b/frontend/js/Components/Widgets/AttachmentGrid.js @@ -0,0 +1,157 @@ +Ext.define('PartKeepr.AttachmentGrid', { + extend: 'Ext.grid.Panel', + alias: 'widget.AttachmentGrid', + border: false, + model: null, + initComponent: function () { + if (this.model === null) { + alert("Error: Model can't be null!"); + } + + this.store = Ext.create("Ext.data.Store", { + model: this.model, + proxy: { + type: 'memory', + reader: { + type: 'json' + } + } + + }); + + this.editing = Ext.create('Ext.grid.plugin.CellEditing', { + clicksToEdit: 1 + }); + + this.plugins = [ this.editing ]; + + 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.viewButton = Ext.create("Ext.button.Button", { + text: i18n("View"), + handler: this.onViewClick, + scope: this, + disabled: true + }); + + this.dockedItems = [{ + xtype: 'toolbar', + items: [{ + text: i18n('Add'), + scope: this, + icon: 'resources/silkicons/attach.png', + handler: this.onAddClick + }, + this.viewButton, + this.deleteButton + ] + }]; + + this.columns = [ + { + header: "", + dataIndex: 'extension', + width: 30, + renderer: function (val) { + return '<img src="resources/mimetypes/'+val+'.png"/>'; + } + }, + { + header: i18n("Filename"), + dataIndex: 'originalFilename', + width: 200 + }, + { + header: i18n("Size"), + dataIndex: 'size', + width: 80, + renderer: PartKeepr.bytesToSize + }, + { + header: i18n("Description"), + dataIndex: 'description', + flex: 0.4, + editor: { + xtype:'textfield', + allowBlank:true + } + } + ]; + + this.callParent(); + + this.getSelectionModel().on('selectionchange', this.onSelectChange, this); + this.on("itemdblclick", this.onDoubleClick, this); + }, + onDoubleClick: function (view, record) { + if (record) { + this.viewAttachment(record); + } + }, + onAddClick: function () { + var j = Ext.create("PartKeepr.FileUploadDialog"); + j.on("fileUploaded", this.onFileUploaded, this); + j.show(); + }, + onFileUploaded: function (response) { + this.editing.cancelEdit(); + + this.getStore().add({ + id: 0, + tmp_id: response.id, + extension: response.extension, + size: response.size, + originalFilename: response.originalFilename + }); + + }, + 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); + this.viewButton.setDisabled(selections.length === 0); + }, + onViewClick: function () { + var selection = this.getView().getSelectionModel().getSelection()[0]; + if (selection) { + this.viewAttachment(selection); + } + }, + viewAttachment: function (record) { + var mySrc = "file.php?type="+this.model+"&"; + + if (record.get("id") == 0) { + mySrc += "id=0&tmpId=" + record.get("tmp_id"); + } else { + mySrc += "id=" + record.get("id"); + } + console.log(mySrc); + + new Ext.Window({ + title : i18n("Display File"), + width : 640, + height: 600, + maximizable: true, + constrain: true, + layout : 'fit', + items : [{ + xtype : "component", + autoEl : { + tag : "iframe", + src : mySrc + } + }] + }).show(); + } +});+ \ No newline at end of file diff --git a/frontend/js/Dialogs/FileUploadDialog.js b/frontend/js/Dialogs/FileUploadDialog.js @@ -19,6 +19,15 @@ Ext.define('PartKeepr.FileUploadDialog', { text: i18n('Upload'), handler: Ext.bind(function() { var form = this.form.getForm(); + + var values = form.getValues(); + + if (this.fileField.getValue() == "" && this.urlField.getValue() == "") { + Ext.Msg.alert(i18n("Error"), i18n("Please select a file to upload or enter an URL")); + return; + } + + if(form.isValid()){ form.submit({ url: this.uploadURL, @@ -37,6 +46,13 @@ Ext.define('PartKeepr.FileUploadDialog', { }, this) }); + this.urlField = Ext.create("Ext.form.field.Text", { + fieldLabel: i18n("URL"), + labelWidth: 50, + name: "url", + anchor: '100%' + }); + this.tbButtons = [ this.uploadButton ]; if (this.imageUpload) { @@ -54,23 +70,32 @@ Ext.define('PartKeepr.FileUploadDialog', { this.tbButtons.push(this.fileFormatButton); } - this.form = Ext.create('Ext.form.Panel', { - width: 400, - bodyPadding: 10, - border: false, - items: [{ + this.fileField = Ext.create("Ext.form.field.File",{ xtype: 'filefield', name: 'userfile', fieldLabel: this.fileFieldLabel, labelWidth: 50, msgTarget: 'side', - allowBlank: false, anchor: '100%', buttonText: this.uploadButtonText - },{ + }); + + this.form = Ext.create('Ext.form.Panel', { + width: 400, + bodyPadding: 10, + border: false, + items: [{ + html: i18n("Select a file to upload or enter an URL to load the file from"), + border: false, + style: "margin-bottom: 20px;" + }, + this.fileField, + { html: sprintf(i18n("Maximum upload size: %s"), PartKeepr.bytesToSize(PartKeepr.getMaxUploadSize())), + style: 'margin-bottom: 10px;', border: false - }], + }, + this.urlField], buttons: this.tbButtons }); diff --git a/frontend/js/Models/Category.js b/frontend/js/Models/Category.js @@ -7,7 +7,7 @@ PartKeepr.Category = Ext.define("Category", { { name: 'parent', type: 'int' } ], proxy: PartKeepr.getRESTProxy("Category"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); diff --git a/frontend/js/Models/Distributor.js b/frontend/js/Models/Distributor.js @@ -9,7 +9,7 @@ PartKeepr.Distributor = Ext.define("Distributor", { { name: 'email', type: 'string'} ], proxy: PartKeepr.getRESTProxy("Distributor"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); \ No newline at end of file diff --git a/frontend/js/Models/Footprint.js b/frontend/js/Models/Footprint.js @@ -4,8 +4,9 @@ PartKeepr.Footprint = Ext.define("Footprint", { { id: 'id', name: 'id', type: 'int' }, { name: 'name', type: 'string'} ], + hasMany: {model: 'FootprintAttachment', name: 'attachments'}, proxy: PartKeepr.getRESTProxy("Footprint"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); \ No newline at end of file diff --git a/frontend/js/Models/FootprintAttachment.js b/frontend/js/Models/FootprintAttachment.js @@ -0,0 +1,15 @@ +PartKeepr.FootprintAttachment = Ext.define("FootprintAttachment", { + extend: "Ext.data.Model", + fields: [ + { id: 'id', name: 'id', type: 'int' }, + { name: 'originalFilename', type: 'string' }, + { name: 'footprint_id', type: 'int' }, + { name: 'mimetype', type: 'string' }, + { name: 'extension', type: 'string' }, + { name: 'description', type: 'string' }, + { name: 'size', type: 'string' }, + { name: 'tmp_id', type: 'int' } + ], + belongsTo: { type: 'belongsTo', model: 'Footprint', primaryKey: 'id', foreignKey: 'footprint_id'}, + proxy: PartKeepr.getRESTProxy("FootprintAttachment") +});+ \ No newline at end of file diff --git a/frontend/js/Models/Manufacturer.js b/frontend/js/Models/Manufacturer.js @@ -10,7 +10,7 @@ PartKeepr.Manufacturer = Ext.define("Manufacturer", { ], hasMany: {model: 'ManufacturerICLogo', name: 'iclogos'}, proxy: PartKeepr.getRESTProxy("Manufacturer"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); \ No newline at end of file diff --git a/frontend/js/Models/ManufacturerICLogo.js b/frontend/js/Models/ManufacturerICLogo.js @@ -1,10 +1,10 @@ PartKeepr.ManufacturerICLogo = Ext.define("ManufacturerICLogo", { extend: "Ext.data.Model", fields: [ - { id: 'id', name: 'id', type: 'int' }, - { name: 'manufacturer_id', type: 'int' }, - { name: 'type', type: 'string' }, - { name: 'tmp_id', type: 'int' } + { id: 'id', name: 'id', type: 'int' }, + { name: 'manufacturer_id', type: 'int' }, + { name: 'type', type: 'string' }, + { name: 'tmp_id', type: 'int' } ], belongsTo: { type: 'belongsTo', model: 'Manufacturer', primaryKey: 'id', foreignKey: 'manufacturer_id'}, proxy: PartKeepr.getRESTProxy("ManufacturerICLogo") diff --git a/frontend/js/Models/Part.js b/frontend/js/Models/Part.js @@ -37,8 +37,5 @@ PartKeepr.Part = Ext.define("Part", { { model: 'Category', primaryKey: 'id', foreignKey: 'category_id'} ], hasMany: { model: 'PartDistributor', name: 'distributors'}, - proxy: PartKeepr.getRESTProxy("Part"), - getName: function () { - return this.get("name"); - } + proxy: PartKeepr.getRESTProxy("Part") }); \ No newline at end of file diff --git a/frontend/js/Models/PartAttachment.js b/frontend/js/Models/PartAttachment.js @@ -1,4 +1,4 @@ -PartKeepr.PartDistributor = Ext.define("PartAttachment", { +PartKeepr.PartAttachment = Ext.define("PartAttachment", { extend: "Ext.data.Model", fields: [ { id: 'id', name: 'id', type: 'int' }, diff --git a/frontend/js/Models/PartUnit.js b/frontend/js/Models/PartUnit.js @@ -7,7 +7,7 @@ PartKeepr.PartUnit = Ext.define("PartUnit", { { name: 'default', type: 'bool'} ], proxy: PartKeepr.getRESTProxy("PartUnit"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); \ No newline at end of file diff --git a/frontend/js/Models/StorageLocation.js b/frontend/js/Models/StorageLocation.js @@ -5,7 +5,7 @@ PartKeepr.StorageLocation = Ext.define("StorageLocation", { { name: 'name', type: 'string'} ], proxy: PartKeepr.getRESTProxy("StorageLocation"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); \ No newline at end of file diff --git a/frontend/js/Models/Unit.js b/frontend/js/Models/Unit.js @@ -7,7 +7,7 @@ PartKeepr.Unit = Ext.define("Unit", { ], hasMany: { model: 'SiPrefix', name: 'prefixes'}, proxy: PartKeepr.getRESTProxy("Unit"), - getName: function () { + getRecordName: function () { return this.get("name"); } }); \ No newline at end of file diff --git a/frontend/js/Models/User.js b/frontend/js/Models/User.js @@ -5,7 +5,7 @@ PartKeepr.User = Ext.define("User", { { name: 'username', type: 'string'} ], proxy: PartKeepr.getRESTProxy("User"), - getName: function () { + getRecordName: function () { return this.get("username"); } }); \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartKeepr/Footprint/Footprint.php b/src/de/RaumZeitLabor/PartKeepr/Footprint/Footprint.php @@ -17,6 +17,20 @@ class Footprint extends BaseEntity implements Serializable { private $name; /** + * Holds the footprint attachments + * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment",mappedBy="part",cascade={"persist", "remove"}) + * @var FootprintAttachment + */ + private $attachments; + + /** + * Constructs a new Footprint entity + */ + public function __construct () { + $this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** * Sets the name of this footprint * * @param string $name The footprint name @@ -33,11 +47,25 @@ class Footprint extends BaseEntity implements Serializable { return $this->name; } + + /** + * Returns the attachments for this footprint + * @return ArrayCollection The attachments + */ + public function getAttachments () { + return $this->attachments; + } + /** * Serializes the footprint * @return array the serialized footprint */ public function serialize () { - return array("id" => $this->getId(), "name" => $this->getName()); + $aAttachments = array(); + foreach ($this->getAttachments() as $attachment) { + $aAttachments[] = $attachment->serialize(); + } + + return array("id" => $this->getId(), "name" => $this->getName(), "attachments" => $aAttachments); } } \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartKeepr/Footprint/FootprintAttachment.php b/src/de/RaumZeitLabor/PartKeepr/Footprint/FootprintAttachment.php @@ -0,0 +1,82 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Footprint; +use de\RaumZeitLabor\PartKeepr\Util\Serializable; + +declare(encoding = 'UTF-8'); + +use de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile; + +/** + * Holds a footprint attachment + * @Entity + **/ +class FootprintAttachment extends UploadedFile implements Serializable { + /** + * The description of this attachment + * @Column(type="text") + * @var string + */ + private $description; + + /** + * Creates a new footprint attachment + */ + public function __construct () { + parent::__construct(); + $this->setType("FootprintAttachment"); + } + /** + * The footprint object + * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\Footprint") + * @var Footprint + */ + private $footprint = null; + + /** + * Sets the footprint + * @param Footprint $footprint The footprint to set + */ + public function setFootprint (Footprint $footprint) { + $this->footprint = $footprint; + } + + /** + * Returns the footprint + * @return Footprint the footprint + */ + public function getFootprint () { + return $this->footprint; + } + + /** + * Sets the description for this attachment + * @param string $description The attachment description + */ + public function setDescription ($description) { + $this->description = $description; + } + + /** + * Returns the description for this attachment + * @return string The description + */ + public function getDescription () { + return $this->description; + } + + /** + * + * Serializes this footprint attachment + * @return array The serialized footprint attachment + */ + public function serialize () { + return array( + "id" => $this->getId(), + "footprint_id" => $this->getFootprint()->getId(), + "originalFilename" => $this->getOriginalFilename(), + "mimetype" => $this->getMimetype(), + "extension" => $this->getExtension(), + "size" => $this->getSize(), + "description" => $this->getDescription()); + } +}+ \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php b/src/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php @@ -0,0 +1,69 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\FootprintAttachment; +declare(encoding = 'UTF-8'); + +use de\RaumZeitLabor\PartKeepr\Util\Singleton, + de\RaumZeitLabor\PartKeepr\Footprint\Footprint, + de\RaumZeitLabor\PartKeepr\PartKeepr; + +class FootprintAttachmentManager extends Singleton { + /** + * Returns a list of footprint attachments + * + * @param int $start Start of the list, default 0 + * @param int $limit Number of users to list, default 10 + * @param string $sort The field to sort by, default "name" + * @param string $dir The direction to sort (ASC or DESC), default ASC + * @param string $filter The footprint id + */ + public function getFootprintAttachments ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") { + + $qb = PartKeepr::getEM()->createQueryBuilder(); + $qb->select("st")->from("de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment","st") + ->leftJoin('st.footprint', "fp"); + + if ($filter != "") { + $footprint = Footprint::loadById($filter); + $qb = $qb->where("st.footprint = :footprint"); + $qb->setParameter("footprint", $footprint); + } + + if ($limit > -1) { + $qb->setMaxResults($limit); + $qb->setFirstResult($start); + } + + $qb->orderBy("st.".$sort, $dir); + + $query = $qb->getQuery(); + + $result = $query->getResult(); + + $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder(); + $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment","st"); + + + + if ($filter != "") { + $totalQueryBuilder = $totalQueryBuilder->where("st.footprint = :footprint"); + $totalQueryBuilder->setParameter("footprint", $footprint); + } + + $totalQuery = $totalQueryBuilder->getQuery(); + + $aData = array(); + foreach ($result as $item) { + $aData[] = $item->serialize(); + } + return array("data" => $aData, "totalCount" => $totalQuery->getSingleScalarResult()); + } + + /** + * Returns a footprint attachment by id + * @param int $id The footprint attachment id + */ + public function getFootprintAttachment ($id) { + return FootprintAttachment::loadById($id); + } + +}+ \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentService.php b/src/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentService.php @@ -0,0 +1,106 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\FootprintAttachment; +use de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment; + +use de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile; + +use de\RaumZeitLabor\PartKeepr\Service\RestfulService; + +declare(encoding = 'UTF-8'); + +use de\RaumZeitLabor\PartKeepr\Service\Service; +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Footprint\Footprint, + de\RaumZeitLabor\PartKeepr\Session\SessionManager; + +class FootprintAttachmentService extends Service implements RestfulService { + /** + * (non-PHPdoc) + * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get() + */ + public function get () { + if ($this->hasParameter("id")) { + return FootprintAttachmentManager::getInstance()->getFootprintAttachment($this->getParameter("id"))->serialize(); + } else { + if ($this->hasParameter("sort")) { + $tmp = json_decode($this->getParameter("sort"), true); + + $aSortParams = $tmp[0]; + } else { + $aSortParams = array( + "property" => "id", + "direction" => "ASC"); + } + + $filter = ""; + + if ($this->hasParameter("filter")) { + $tmp = json_decode($this->getParameter("filter"), true); + + foreach ($tmp as $item) { + if (array_key_exists("property", $item)) { + if ($item["property"] == "footprint_id") { + if (array_key_exists("value", $item)) { + $filter = $item["value"]; + } + } + } + } + } + return FootprintAttachmentManager::getInstance()->getFootprintAttachments( + $this->getParameter("start", $this->getParameter("start", 0)), + $this->getParameter("limit", $this->getParameter("limit", 25)), + $this->getParameter("sortby", $aSortParams["property"]), + $this->getParameter("dir", $aSortParams["direction"]), + $filter); + } + } + + /** + * (non-PHPdoc) + * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create() + */ + public function create () { + $this->requireParameter("tmp_id"); + $this->requireParameter("footprint_id"); + + $tmpImage = TempUploadedFile::loadById($this->getParameter("tmp_id")); + + $file = new FootprintAttachment(); + + $footprint = Footprint::loadById($this->getParameter("footprint_id")); + + $file->setFootprint($footprint); + $file->replace($tmpImage->getFilename()); + $file->setOriginalFilename($tmpImage->getOriginalFilename()); + $file->setDescription($this->getParameter("description")); + PartKeepr::getEM()->persist($file); + PartKeepr::getEM()->flush(); + + return $file->serialize(); + } + + /** + * (non-PHPdoc) + * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update() + */ + public function update () { + + } + + /** + * (non-PHPdoc) + * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy() + */ + public function destroy () { + $this->requireParameter("id"); + + $file = FootprintAttachment::loadById($this->getParameter("id")); + + PartKeepr::getEM()->remove($file); + PartKeepr::getEM()->flush(); + + return array("data" => null); + } + +}+ \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerICLogo.php b/src/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerICLogo.php @@ -47,6 +47,6 @@ class ManufacturerICLogo extends Image implements Serializable { * @return array The serialized ic logo */ public function serialize () { - return array("id" => $this->getId(), "manufacturer_id" => $this->getMenufacturer()->getId()); + return array("id" => $this->getId(), "manufacturer_id" => $this->getManufacturer()->getId()); } } \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartKeepr/Part/PartService.php b/src/de/RaumZeitLabor/PartKeepr/Part/PartService.php @@ -1,5 +1,5 @@ <?php -namespace de\raumzeitlabor\PartKeepr\Part; +namespace de\RaumZeitLabor\PartKeepr\Part; use de\RaumZeitLabor\PartKeepr\Service\RestfulService; declare(encoding = 'UTF-8'); @@ -8,6 +8,7 @@ use de\RaumZeitLabor\PartKeepr\Service\Service; use de\RaumZeitLabor\PartKeepr\Part\PartManager, de\RaumZeitLabor\PartKeepr\Stock\StockEntry, de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Category\Category, de\RaumZeitLabor\PartKeepr\Session\SessionManager; class PartService extends Service implements RestfulService { @@ -57,6 +58,28 @@ class PartService extends Service implements RestfulService { return array("data" => $query->getArrayResult()); } + public function movePart () { + $this->requireParameter("targetCategory"); + + if ($this->getParameter("parts", false) !== false) { + /* We are moving multiple parts */ + foreach ($this->getParameter("parts") as $part) { + $part = Part::loadById($part); + $category = Category::loadById($this->getParameter("targetCategory")); + + $part->setCategory($category); + } + } else { + $part = Part::loadById($this->getParameter("part")); + $category = Category::loadById($this->getParameter("targetCategory")); + + $part->setCategory($category); + + } + + + PartKeepr::getEM()->flush(); + } // Old stuff below public function getParts () { $aParameters = array( diff --git a/src/de/RaumZeitLabor/PartKeepr/PartKeepr.php b/src/de/RaumZeitLabor/PartKeepr/PartKeepr.php @@ -173,6 +173,7 @@ class PartKeepr { 'de\RaumZeitLabor\PartKeepr\User\User', 'de\RaumZeitLabor\PartKeepr\Session\Session', 'de\RaumZeitLabor\PartKeepr\Footprint\Footprint', + 'de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment', 'de\RaumZeitLabor\PartKeepr\Category\Category', 'de\RaumZeitLabor\PartKeepr\Part\Part', 'de\RaumZeitLabor\PartKeepr\Part\PartUnit', diff --git a/src/de/RaumZeitLabor/PartKeepr/TempFile/TempFileService.php b/src/de/RaumZeitLabor/PartKeepr/TempFile/TempFileService.php @@ -10,11 +10,18 @@ class TempFileService extends Service { public function upload () { $tmpFile = new TempUploadedFile(); - $file = $_FILES['userfile']['tmp_name']; - $filename = $_FILES['userfile']['name']; + if (array_key_exists("userfile", $_FILES) && file_exists($_FILES["userfile"]["tmp_name"])) { + $file = $_FILES['userfile']['tmp_name']; + $filename = $_FILES['userfile']['name']; + + $tmpFile->replace($file); + $tmpFile->setOriginalFilename(basename($filename)); + } elseif (array_key_exists("url", $_REQUEST)) { + $tmpFile->replaceFromURL($_REQUEST["url"]); + } else { + throw new \Exception("Error: No valid file given"); + } - $tmpFile->replace($file); - $tmpFile->setOriginalFilename(basename($filename)); PartKeepr::getEM()->persist($tmpFile); PartKeepr::getEM()->flush(); diff --git a/src/de/RaumZeitLabor/PartKeepr/TempImage/TempImageService.php b/src/de/RaumZeitLabor/PartKeepr/TempImage/TempImageService.php @@ -6,19 +6,25 @@ use de\RaumZeitLabor\PartKeepr\TempImage\TempImage; use de\RaumZeitLabor\PartKeepr\PartKeepr; class TempImageService extends Service { - public function upload () { $image = new TempImage(); - $file = $_FILES['userfile']['tmp_name']; - $filename = $_FILES['userfile']['name']; + if (array_key_exists("userfile", $_FILES) && file_exists($_FILES["userfile"]["tmp_name"])) { + $file = $_FILES['userfile']['tmp_name']; + $filename = $_FILES['userfile']['name']; - $image->replace($file); - $image->setOriginalFilename(basename($filename)); + $image->replace($file); + $image->setOriginalFilename(basename($filename)); + } elseif (array_key_exists("url", $_REQUEST)) { + $image->replaceFromURL($_REQUEST["url"]); + } else { + throw new \Exception("Error: No valid file given"); + } + PartKeepr::getEM()->persist($image); PartKeepr::getEM()->flush(); - return array("id" => $image->getId()); + return array("id" => $image->getId(), "extension" => $image->getExtension(), "size" => $image->getSize(), "originalFilename" => $image->getOriginalFilename()); } } \ No newline at end of file diff --git a/testing/SetupDatabase.php b/testing/SetupDatabase.php @@ -59,10 +59,11 @@ if (!($_SERVER["argc"] == 2 && $_SERVER["argv"][1] == "--yes")) { echo "Performing actions...\n"; -mkdir("../src/Proxies"); -mkdir("../data"); -mkdir("../data/images"); +@mkdir("../src/Proxies"); +@mkdir("../data"); +@mkdir("../data/images"); chmod("../data/images", 0777); +chmod("../data/files", 0777); $tool = new \Doctrine\ORM\Tools\SchemaTool(PartKeepr::getEM());