partkeepr

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

EditorComponent.js (6372B)


      1 /**
      2  * @class PartKeepr.EditorComponent
      3 
      4  * <p>The EditorComponent encapsulates an editing workflow. In general, we have four actions
      5  * for each object: create, update, delete, view. These actions stay exactly the same for each
      6  * distinct object.</p>
      7  * <p>The EditorComponent is a border layout, which has a navigation and an editor area.</p>
      8  * @todo Document the editor system a bit better
      9  */
     10 Ext.define('PartKeepr.EditorComponent', {
     11     extend: 'Ext.panel.Panel',
     12     alias: 'widget.EditorComponent',
     13 
     14     /**
     15      * Misc layout settings
     16      */
     17     layout: 'border',
     18     padding: 5,
     19     border: false,
     20 
     21     /**
     22      * Specifies the class name of the navigation. The navigation is placed in the "west" region
     23      * and needs to fire the event "itemSelect". The component listens on that event and
     24      * creates an editor based on the selected record.
     25      */
     26     navigationClass: null,
     27 
     28     /**
     29      * Specifies the class name of the editor.
     30      */
     31     editorClass: null,
     32 
     33     /**
     34      * Contains the store for the item overview.
     35      */
     36     store: null,
     37 
     38     /**
     39      * Contains the associated model to load a record for.
     40      */
     41     model: null,
     42 
     43     /**
     44      * Defines the store to use. Defaults to {Ext.data.Store}
     45      */
     46     storeType: "Ext.data.Store",
     47 
     48     /**
     49      * Some default text messages. Can be overridden by sub classes.
     50      */
     51     deleteMessage: i18n("Do you really wish to delete the item %s?"),
     52     deleteTitle: i18n("Delete Item"),
     53     newItemText: i18n("New Item"),
     54 
     55     /**
     56      * @var {string} The record field to read the title property from
     57      */
     58     titleProperty: 'name',
     59 
     60     initComponent: function ()
     61     {
     62 
     63         /**
     64          * Create the navigation panel
     65          */
     66         this.navigation = Ext.create(this.navigationClass, {
     67             region: 'west',
     68             width: 300,
     69             split: true,
     70             store: this.store,
     71             titleProperty: this.titleProperty
     72         });
     73 
     74         this.navigation.on("itemAdd", this.newRecord, this);
     75         this.navigation.on("itemDelete", this.confirmDelete, this);
     76         this.navigation.on("itemEdit", this.startEdit, this);
     77 
     78         /**
     79          * Create the editor panel
     80          */
     81         this.editorTabPanel = Ext.create("Ext.tab.Panel", {
     82             region: "center",
     83             layout: 'fit',
     84             plugins: Ext.create('Ext.ux.TabCloseMenu')
     85         });
     86 
     87         this.items = [this.navigation, this.editorTabPanel];
     88 
     89         this.callParent();
     90     },
     91     /**
     92      * Creates a new record. Creates a new instance of the editor.
     93      */
     94     newRecord: function (defaults)
     95     {
     96         Ext.apply(defaults, {});
     97 
     98         var editor = this.createEditor(this.newItemText);
     99         editor.newItem(defaults);
    100         this.editorTabPanel.add(editor).show();
    101     },
    102     /**
    103      * Instructs the component to edit a new record.
    104      * @param {Record} record The record to edit
    105      */
    106     startEdit: function (id)
    107     {
    108         /* Search for an open editor for the current record. If we
    109          * already have an editor, show the editor instead of loading
    110          * a new record.
    111          */
    112         var editor = this.findEditor(id);
    113 
    114         if (editor !== null) {
    115             editor.show();
    116             return;
    117         }
    118 
    119         // Still here? OK, we don't have an editor open. Create a new one
    120         var model = Ext.ClassManager.get(this.model);
    121 
    122         model.load(id, {
    123             scope: this,
    124             success: function (record, operation)
    125             {
    126                 editor = this.createEditor(record.get(this.titleProperty));
    127                 editor.editItem(record);
    128                 this.editorTabPanel.add(editor).show();
    129             }
    130         });
    131     },
    132     findEditor: function (id)
    133     {
    134         for (var i = 0; i < this.editorTabPanel.items.getCount(); i++) {
    135             if (this.editorTabPanel.items.getAt(i).getRecordId() == id) {
    136                 return this.editorTabPanel.items.getAt(i);
    137             }
    138         }
    139 
    140         return null;
    141     },
    142     createEditor: function (title)
    143     {
    144         var editor = Ext.create(this.editorClass, {
    145             store: this.store,
    146             title: title,
    147             model: this.model,
    148             closable: true,
    149             titleProperty: this.titleProperty,
    150             listeners: {
    151                 editorClose: Ext.bind(function (m)
    152                 {
    153                     this.editorTabPanel.remove(m);
    154                 }, this)
    155             }
    156         });
    157 
    158         editor.on("itemSaved", this.onItemSaved, this);
    159         return editor;
    160     },
    161     confirmDelete: function ()
    162     {
    163         var r = this.navigation.getSelectionModel().getLastSelected();
    164         var recordName;
    165 
    166         recordName = r.get(this.titleProperty);
    167 
    168         Ext.Msg.confirm(
    169             this.deleteTitle,
    170             sprintf(this.deleteMessage, recordName),
    171             function (but)
    172             {
    173                 if (but == "yes") {
    174                     this.deleteRecord(r);
    175                 }
    176             }, this);
    177     },
    178     deleteRecord: function (r)
    179     {
    180         var editor = this.findEditor(r.getId());
    181 
    182         if (editor !== null) {
    183             this.editorTabPanel.remove(editor);
    184         }
    185 
    186         r.erase();
    187         this.store.load();
    188     },
    189     // Creates a store. To be called from child's initComponent
    190     createStore: function (config)
    191     {
    192         Ext.applyIf(config, {
    193             autoLoad: true,
    194             model: this.model,
    195             autoSync: false, // Do not change. If true, new (empty) records would be immediately committed to the database.
    196             remoteFilter: true,
    197             remoteSort: true,
    198             pageSize: 15
    199         });
    200 
    201         this.store = Ext.create(this.storeType, config);
    202 
    203         // Workaround for bug http://www.sencha.com/forum/showthread.php?133767-Store.sync()-does-not-update-dirty-flag&p=607093#post607093
    204         this.store.on('write', function (store, operation)
    205         {
    206             var success = operation.wasSuccessful();
    207             if (success) {
    208                 Ext.each(operation.records, function (record)
    209                 {
    210                     if (record.dirty) {
    211                         record.commit();
    212                     }
    213                 });
    214             }
    215         });
    216     },
    217     getStore: function ()
    218     {
    219         return this.store;
    220     },
    221     onItemSaved: function (record)
    222     {
    223         this.navigation.syncChanges(record);
    224     }
    225 });