partkeepr

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

DataApplicator.js (18314B)


      1 Ext.define("PartKeepr.Components.OctoPart.DataApplicator", {
      2     extend: "Ext.Base",
      3     mixins: ['Ext.mixin.Observable'],
      4 
      5     import: {},
      6 
      7     constructor: function (config)
      8     {
      9         this.setImport("parameters", true);
     10         this.setImport("distributors", true);
     11         this.setImport("bestDatasheet", true);
     12         this.setImport("cadModels", true);
     13         this.setImport("referenceDesigns", true);
     14         this.setImport("images", true);
     15 
     16         this.mixins.observable.constructor.call(this, config);
     17     },
     18     setImport: function (item, flag) {
     19         this.import[item] = flag;
     20     },
     21     setPart: function (part)
     22     {
     23         this.part = part;
     24     },
     25     /**
     26      * Loads the data via the PartKeepr API from Octopart.
     27      *
     28      * @param {String} id The Octopart UID to load
     29      */
     30     loadData: function (id)
     31     {
     32         Ext.Ajax.request({
     33             url: PartKeepr.getBasePath() + '/api/octopart/get/' + id,
     34             success: this.onPartDataLoaded,
     35             scope: this
     36         });
     37     },
     38     /**
     39      * Called after the Octopart Part data has been loaded.
     40      *
     41      * @param {Object} response The response data
     42      */
     43     onPartDataLoaded: function (response)
     44     {
     45         this.data = Ext.decode(response.responseText);
     46 
     47         this.applyData();
     48     },
     49     checkRequirements: function ()
     50     {
     51         var i, unit, file, image, distributor;
     52 
     53         var manufacturer = PartKeepr.getApplication().getManufacturerStore().findRecord("name",
     54             this.data.manufacturer.name);
     55         if (manufacturer === null)
     56         {
     57             this.displayWaitWindow(i18n("Creating Manufacturer…"), this.data.manufacturer.name);
     58             manufacturer = Ext.create("PartKeepr.ManufacturerBundle.Entity.Manufacturer");
     59             manufacturer.set("name", this.data.manufacturer.name);
     60             manufacturer.save({
     61                 success: function ()
     62                 {
     63                     PartKeepr.getApplication().getManufacturerStore().load({
     64                         callback: this.applyData,
     65                         scope: this
     66                     });
     67                 },
     68                 scope: this
     69 
     70             });
     71             return false;
     72         }
     73 
     74         if (this.import.parameters)
     75         {
     76             for (i in this.data["specs"])
     77             {
     78                 var q_value, q_unit, q_siPrefix;
     79                 [q_value,q_unit] = this.parseQuantity( this.data.specs[i].display_value );
     80                 [q_value,q_unit2,q_siPrefix] = this.SIUnitPrefix(q_value, q_unit);
     81                 if (q_unit2 === null && q_unit)
     82                 {
     83                     // there is a unit (q_unit), but we do not know about it or the prefix of the unit is disabled
     84                     unit = PartKeepr.getApplication().getUnitStore().findRecord("symbol",
     85                         q_unit, 0, false, true, true);
     86                     if (unit === null)
     87                     {
     88                         this.displayWaitWindow(i18n("Creating Unit…"), q_unit);
     89                         unit = Ext.create("PartKeepr.UnitBundle.Entity.Unit");
     90                         unit.set("name", q_unit); // v4 API does not have that anymore
     91                         unit.set("symbol", q_unit);
     92                         unit.save({
     93                             success: function ()
     94                             {
     95                                 PartKeepr.getApplication().getUnitStore().load({
     96                                     callback: this.applyData,
     97                                     scope: this
     98                                 });
     99                             },
    100                             scope: this
    101 
    102                         });
    103                         return false;
    104                     }
    105                 }
    106             }
    107         }
    108 
    109         if (this.import.distributors)
    110         {
    111             for (i in this.data['sellers'])
    112             {
    113                 distributor = PartKeepr.getApplication().getDistributorStore().findRecord("name",
    114                     this.data.sellers[i].company.name, 0, false, true, true);
    115 
    116                 if (distributor === null)
    117                 {
    118                     this.displayWaitWindow(i18n("Creating Distributor…"), this.data.sellers[i].company.name);
    119                     distributor = Ext.create("PartKeepr.DistributorBundle.Entity.Distributor");
    120                     distributor.set("name", this.data.sellers[i].company.name);
    121                     distributor.set("url", this.data.sellers[i].company.homepage_url);
    122                     distributor.save({
    123                         success: function ()
    124                         {
    125                             PartKeepr.getApplication().getDistributorStore().load({
    126                                 callback: this.applyData,
    127                                 scope: this
    128                             });
    129                         },
    130                         scope: this
    131 
    132                     });
    133                     return false;
    134                 }
    135             }
    136         }
    137 
    138         if (this.import.bestDatasheet)
    139         {
    140             if (this.data['best_datasheet'])
    141             {
    142                 file = this.data.best_datasheet;
    143                 delete this.data.best_datasheet;
    144                 this.displayWaitWindow(i18n("Uploading datasheet…"), file.url);
    145 
    146                 if (!this.checkIfAttachmentFilenameExists(file.url))
    147                 {
    148                     PartKeepr.getApplication().uploadFileFromURL(file.url, i18n("Datasheet"), this.onFileUploaded,
    149                         this);
    150                 } else
    151                 {
    152                     this.applyData();
    153                 }
    154 
    155                 return false;
    156             }
    157         }
    158 
    159         if (this.import.cadModels)
    160         {
    161             if (this.data['cad'])
    162             {
    163                 file = this.data.cad;
    164                 delete this.data.cad;
    165                 this.displayWaitWindow(i18n("Uploading CAD Model…"), file.add_to_library_url);
    166                 if (!this.checkIfAttachmentFilenameExists(file.add_to_library_url))
    167                 {
    168                     PartKeepr.getApplication().uploadFileFromURL(file.add_to_library_url, i18n("CAD Model"), this.onFileUploaded,
    169                         this);
    170                 } else
    171                 {
    172                     this.applyData();
    173                 }
    174                 return false;
    175             }
    176         }
    177 
    178         if (this.import.referenceDesigns)
    179         {
    180             if (this.data.reference_designs.length > 0)
    181             {
    182                 file = this.data.reference_designs.shift();
    183                 this.displayWaitWindow(i18n("Uploading Reference Designs…"), file.url);
    184                 if (!this.checkIfAttachmentFilenameExists(file.url))
    185                 {
    186                     PartKeepr.getApplication().uploadFileFromURL(file.url, i18n("Reference Design"),
    187                         this.onFileUploaded,
    188                         this);
    189                 } else
    190                 {
    191                     this.applyData();
    192                 }
    193                 return false;
    194             }
    195         }
    196 
    197         if (this.import.images)
    198         {
    199             if (this.data['best_image'])
    200             {
    201                 image = this.data.best_image;
    202                 delete this.data.best_image;
    203 
    204                 this.displayWaitWindow(i18n("Uploading Image…"), image.url);
    205                 if (!this.checkIfAttachmentFilenameExists(image.url))
    206                 {
    207                     PartKeepr.getApplication().uploadFileFromURL(image.url, i18n("Image"), this.onFileUploaded,
    208                         this);
    209                 } else
    210                 {
    211                     this.applyData();
    212                 }
    213 
    214                 return false;
    215             }
    216         }
    217 
    218 
    219         return true;
    220     },
    221     checkIfAttachmentFilenameExists: function (uri)
    222     {
    223         var k, found, filename = uri.split(/[\\/]/).pop();
    224 
    225         found = false;
    226 
    227         for (k = 0; k < this.part.attachments().count(); k++)
    228         {
    229             if (this.part.attachments().getAt(k).get("originalFilename") === filename)
    230             {
    231                 found = true;
    232             }
    233         }
    234 
    235         return found;
    236     },
    237     onFileUploaded: function (options, success, response)
    238     {
    239         if (success)
    240         {
    241             var result = Ext.decode(response.responseText);
    242 
    243             var uploadedFile = Ext.create("PartKeepr.UploadedFileBundle.Entity.TempUploadedFile", result.response);
    244 
    245             this.part.attachments().add(uploadedFile);
    246         }
    247 
    248         this.applyData();
    249     },
    250     displayWaitWindow: function (text, value)
    251     {
    252         this.waitMessage = Ext.MessageBox.show({
    253             msg: text + "<br/>" + value,
    254             progressText: value,
    255             width: 300,
    256             wait: {
    257                 interval: 100
    258             }
    259         });
    260     },
    261     applyData: function ()
    262     {
    263         var spec, i, unit, value, siPrefix, distributor, j, partDistributor, currency, k, found;
    264 
    265         if (this.waitMessage instanceof Ext.window.MessageBox)
    266         {
    267             this.waitMessage.hide();
    268         }
    269 
    270         if (!this.checkRequirements())
    271         {
    272             return;
    273         }
    274 
    275         this.part.set("name", this.data.mpn);
    276         this.part.set("description", this.data.short_description);
    277 
    278         var manufacturer = PartKeepr.getApplication().getManufacturerStore().findRecord("name",
    279             this.data.manufacturer.name);
    280         var partManufacturer;
    281 
    282         if (manufacturer === null)
    283         {
    284             // @todo put out error message
    285         }
    286 
    287         partManufacturer = Ext.create("PartKeepr.PartBundle.Entity.PartManufacturer");
    288         partManufacturer.setManufacturer(manufacturer);
    289         partManufacturer.set("partNumber", this.data.mpn);
    290 
    291         found = null;
    292 
    293         for (k = 0; k < this.part.manufacturers().count(); k++)
    294         {
    295             if (this.part.manufacturers().getAt(k).isPartiallyEqualTo(partManufacturer,
    296                     ["manufacturer.name"]))
    297             {
    298                 found = this.part.manufacturers().getAt(k);
    299             }
    300         }
    301 
    302         if (found !== null)
    303         {
    304             found.set("partNumber", this.data.mpn);
    305         } else
    306         {
    307             this.part.manufacturers().add(partManufacturer);
    308         }
    309 
    310         if (this.import.distributors)
    311         {
    312             for (i in this.data['sellers'])
    313             {
    314                 distributor = PartKeepr.getApplication().getDistributorStore().findRecord("name",
    315                     this.data.sellers[i].company.name, 0, false, true, true);
    316                 if (distributor === null)
    317                 {
    318                     // @todo put out error message
    319                     continue;
    320                 }
    321 
    322                 for (o in this.data.sellers[i]['offers'])
    323                 {
    324                     for (p in this.data.sellers[i].offers[o].prices)
    325                     {
    326                         partDistributor = Ext.create("PartKeepr.PartBundle.Entity.PartDistributor");
    327                         partDistributor.setDistributor(distributor);
    328                         partDistributor.set("sku", this.data.sellers[i].offers[o].sku);
    329                         partDistributor.set("packagingUnit", this.data.sellers[i].offers[o].prices[p].quantity);
    330                         partDistributor.set("currency", this.data.sellers[i].offers[o].prices[p].currency);
    331                         partDistributor.set("price", this.data.sellers[i].offers[o].prices[p].price);
    332 
    333                         found = null;
    334 
    335                         for (k = 0; k < this.part.distributors().count(); k++)
    336                         {
    337                             if (partDistributor.isPartiallyEqualTo(
    338                                     this.part.distributors().getAt(k),
    339                                     ["sku", "packagingUnit", "currency", "distributor.name"]
    340                                 ))
    341                             {
    342                                 found = this.part.distributors().getAt(k);
    343                             }
    344                         }
    345 
    346                         if (found !== null)
    347                         {
    348                             found.set("price", this.data.sellers[i].offers[o].prices[p].price);
    349                         } else
    350                         {
    351                             this.part.distributors().add(partDistributor);
    352                         }
    353                     }
    354                 }
    355             }
    356         }
    357 
    358         if (this.import.parameters)
    359         {
    360             for (i in this.data["specs"])
    361             {
    362                 spec = Ext.create("PartKeepr.PartBundle.Entity.PartParameter");
    363                 spec.set("name", this.data.specs[i].attribute.name);
    364 
    365                 var q_value, q_unit;
    366                 [q_value,q_unit] = this.parseQuantity( this.data.specs[i].display_value );
    367 
    368                 // some fields need to be treated as strings
    369                 if (this.data.specs[i].attribute.name == "Case/Package" ||
    370                     this.data.specs[i].attribute.name == "Case Code (Imperial)" ||
    371                     this.data.specs[i].attribute.name == "Case Code (Metric)") {
    372                     q_value = null; // force string interpretation
    373                     q_unit = null; // force string interpretation
    374                 }
    375             
    376                 if (q_value != null && q_unit != null)
    377                 {
    378                     [value,unit,siPrefix] = this.SIUnitPrefix(q_value, q_unit);
    379                     if (value && unit && siPrefix) {
    380                         spec.setUnit(unit);
    381                         spec.set("value", value);
    382                         spec.setSiPrefix(siPrefix);
    383                     } else {
    384                         unit = PartKeepr.getApplication().getUnitStore().findRecord("symbol",
    385                             q_unit, 0, false, true, true);
    386                         spec.setUnit(unit);
    387                         siPrefix = this.findSiPrefixForValueAndUnit(q_value, unit);
    388                         spec.set("value", this.applySiPrefix(q_value, siPrefix));
    389                         spec.setSiPrefix(siPrefix);
    390                     }
    391                     spec.set("valueType", "numeric");
    392                 }
    393                 else if (q_value != null) {
    394                     spec.set("valueType", "numeric");
    395                     spec.set("value", q_value);
    396                 }
    397                 else
    398                 {
    399                     spec.set("valueType", "string");
    400                     spec.set("stringValue", this.data.specs[i].display_value);
    401                 }
    402 
    403                 found = null;
    404 
    405                 for (k = 0; k < this.part.parameters().count(); k++)
    406                 {
    407                     if (spec.isPartiallyEqualTo(
    408                             this.part.parameters().getAt(k),
    409                             ["name"]
    410                         ))
    411                     {
    412                         found = this.part.parameters().getAt(k);
    413                     }
    414                 }
    415 
    416                 if (found === null)
    417                 {
    418                     this.part.parameters().add(spec);
    419                 }
    420             }
    421         }
    422 
    423         this.fireEvent("refreshData");
    424     },
    425     applySiPrefix: function (value, siPrefix)
    426     {
    427         return Ext.util.Format.round(value / Math.pow(siPrefix.get("base"), siPrefix.get("exponent")), 3);
    428     },
    429     findSiPrefixForValueAndUnit: function (value, unit)
    430     {
    431         var i, prefixedValue, siPrefix;
    432 
    433         siPrefix = PartKeepr.getApplication().getSiPrefixStore().findRecord("exponent", 0, 0, false, false, true);
    434 
    435         if (!(unit instanceof PartKeepr.UnitBundle.Entity.Unit))
    436         {
    437             return siPrefix;
    438         }
    439 
    440         unit.prefixes().sort("exponent", "desc");
    441 
    442         for (i = 0; i < unit.prefixes().getCount(); i++)
    443         {
    444             siPrefix = unit.prefixes().getAt(i);
    445             prefixedValue = Math.abs(this.applySiPrefix(value, siPrefix));
    446 
    447             if (prefixedValue < 1000 && prefixedValue > 0.9)
    448             {
    449                 break;
    450             }
    451         }
    452 
    453         return siPrefix;
    454     },
    455     parseQuantity: function( quantity )
    456     {
    457         try {
    458             quantity = quantity.trim();
    459             const regex = /[^\d+-.]/g;
    460             var idx = quantity.search(regex);
    461             if (idx == -1) {
    462                 // no unit, but maybe value only
    463                 var value = parseFloat(quantity);
    464                 if (!isNaN(value)) {
    465                     return [value,null];
    466                 }
    467             } else {
    468                 var value = parseFloat(quantity.slice(0,idx));
    469                 if (isNaN(value))
    470                     return [null,null];
    471                 var unit = quantity.slice(idx).trim();
    472                 return [value,unit];
    473             }
    474         }
    475         finally {}
    476         return [null,null];
    477     },
    478     SIUnitPrefix: function( q_value, q_unit )
    479     {
    480         // the new Octopart API returns quantities as display strings: e.g. "12 mm"
    481         // try to recognize SI-unit and SI-prefix
    482         
    483         // check if the unit as a whole is already known
    484         var unit = PartKeepr.getApplication().getUnitStore().findRecord("symbol", q_unit, 0, false, true, true);
    485         if (unit) {
    486             var siPrefix = PartKeepr.getApplication().getSiPrefixStore().findRecord("exponent", 0, 0, false, false, true);
    487             return [q_value, unit, siPrefix];
    488         }
    489 
    490         // assume the first character is an SI-prefix
    491         if (q_unit && q_unit.length >= 2) {
    492             unit = PartKeepr.getApplication().getUnitStore().findRecord("symbol", q_unit.substring(1), 0, false, true, true);
    493             if (unit) {
    494                 // now check that the first character is a valid SI-prefix
    495                 console.log(unit);
    496                 var siPrefix;
    497                 for (var i=0; i<unit.prefixes().getData().length; i++) {
    498                     var temp = unit.prefixes().getData().getAt(i);
    499                     var prefixChar = temp.get("symbol");
    500                     if (prefixChar == "μ")
    501                     prefixChar = "µ"; // convert upper case µ to lower case µ
    502                     if (q_unit[0] == prefixChar) {
    503                         siPrefix = temp;
    504                         break;
    505                     }
    506                 }
    507                 if (siPrefix) {
    508                     return [q_value, unit, siPrefix];
    509                 }
    510             }
    511         }
    512 
    513         // no matching unit found
    514         return [null, null, null];
    515     }
    516 });