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 });