mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
Custom field import repair (#3968)
* There is no notes field on accessories. Fixes Importer Test. * Fix notification test. We should see a checkout not allowed exception when trying to check out to a location if the asset requires acceptance. * Fix Custom field import. Add a test for custom field import, and fix a few issues related to importing custom fields. This will restore v3 functionality. * Add UI support for mapping custom fields. This still requires the field mappings to be created/assigned in advance, but will fetch all custom field names and allow them to be selected when setting up custom field mappings. This commit also updates laravel-mix to v1.4.3 and other node dependencies to fix some build issues. * Fix some requestable asset page/assetloc issues. I'd love to know why laravel expections relationships to be in lower case... but thats a question for another day.
This commit is contained in:
parent
c53dae4b72
commit
922d6937ae
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Transformers\CustomFieldsTransformer;
|
||||||
|
use App\Models\CustomField;
|
||||||
use App\Models\CustomFieldset;
|
use App\Models\CustomFieldset;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class CustomFieldsController extends Controller
|
class CustomFieldsController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -16,6 +18,15 @@ class CustomFieldsController extends Controller
|
||||||
* @since [v3.0]
|
* @since [v3.0]
|
||||||
* @return Array
|
* @return Array
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$this->authorize('index', CustomFields::class);
|
||||||
|
$fields = CustomField::get();
|
||||||
|
|
||||||
|
$total = count($fields);
|
||||||
|
return (new CustomFieldsTransformer)->transformCustomFields($fields, $total);
|
||||||
|
}
|
||||||
public function postReorder(Request $request, $id)
|
public function postReorder(Request $request, $id)
|
||||||
{
|
{
|
||||||
$fieldset = CustomFieldset::find($id);
|
$fieldset = CustomFieldset::find($id);
|
||||||
|
|
|
@ -25,7 +25,7 @@ class CustomFieldsTransformer
|
||||||
'name' => e($field->name),
|
'name' => e($field->name),
|
||||||
'db_column_name' => e($field->db_column_name()),
|
'db_column_name' => e($field->db_column_name()),
|
||||||
'format' => e($field->format),
|
'format' => e($field->format),
|
||||||
'required' => $field->pivot->required,
|
'required' => $field->pivot ? $field->pivot->required : false,
|
||||||
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
|
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
|
||||||
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
|
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
|
||||||
];
|
];
|
||||||
|
|
|
@ -109,7 +109,15 @@ abstract class Importer
|
||||||
{
|
{
|
||||||
$headerRow = $this->csv->fetchOne();
|
$headerRow = $this->csv->fetchOne();
|
||||||
$results = $this->normalizeInputArray($this->csv->fetchAssoc());
|
$results = $this->normalizeInputArray($this->csv->fetchAssoc());
|
||||||
$this->customFields = CustomField::All(['name']);
|
|
||||||
|
// Stolen From https://adamwathan.me/2016/07/14/customizing-keys-when-mapping-collections/
|
||||||
|
// This 'inverts' the fields such that we have a collection of fields indexed by name.
|
||||||
|
$cFs = CustomField::All();
|
||||||
|
$this->customFields = $cFs->reduce(function ($nameLookup, $field) {
|
||||||
|
$nameLookup[$field['name']] = $field;
|
||||||
|
return $nameLookup;
|
||||||
|
});
|
||||||
|
|
||||||
DB::transaction(function () use (&$results) {
|
DB::transaction(function () use (&$results) {
|
||||||
Model::unguard();
|
Model::unguard();
|
||||||
$resultsCount = sizeof($results);
|
$resultsCount = sizeof($results);
|
||||||
|
@ -161,8 +169,6 @@ abstract class Importer
|
||||||
*/
|
*/
|
||||||
public function lookupCustomKey($key)
|
public function lookupCustomKey($key)
|
||||||
{
|
{
|
||||||
// dd($this->fieldMap);
|
|
||||||
|
|
||||||
if (array_key_exists($key, $this->fieldMap)) {
|
if (array_key_exists($key, $this->fieldMap)) {
|
||||||
$this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
|
$this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
|
||||||
return $this->fieldMap[$key];
|
return $this->fieldMap[$key];
|
||||||
|
|
|
@ -61,7 +61,6 @@ class Accessory extends SnipeModel
|
||||||
'purchase_date',
|
'purchase_date',
|
||||||
'model_number',
|
'model_number',
|
||||||
'manufacturer_id',
|
'manufacturer_id',
|
||||||
'notes',
|
|
||||||
'qty',
|
'qty',
|
||||||
'requestable'
|
'requestable'
|
||||||
];
|
];
|
||||||
|
|
|
@ -253,8 +253,9 @@ class Asset extends Depreciable
|
||||||
public function assetLoc()
|
public function assetLoc()
|
||||||
{
|
{
|
||||||
if (!empty($this->assignedType())) {
|
if (!empty($this->assignedType())) {
|
||||||
|
// dd($this->assignedType());
|
||||||
if ($this->assignedType() == self::ASSET) {
|
if ($this->assignedType() == self::ASSET) {
|
||||||
return $this->assignedTo->assetloc(); // Recurse until we have a final location
|
return $this->assignedto->assetloc(); // Recurse until we have a final location
|
||||||
}
|
}
|
||||||
if ($this->assignedType() == self::LOCATION) {
|
if ($this->assignedType() == self::LOCATION) {
|
||||||
return $this->assignedTo();
|
return $this->assignedTo();
|
||||||
|
|
File diff suppressed because one or more lines are too long
6880
build/css/app.css
6880
build/css/app.css
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,23 +1,8 @@
|
||||||
{
|
{
|
||||||
"/build/vue.js": "/build/vue.js",
|
"/vue.js": "/vue.js",
|
||||||
"/mix.js": "/mix.js",
|
"/css/AdminLTE.css": "/css/AdminLTE.css",
|
||||||
"/build/app.css": "/build/app.535d8af1016a2377e449920c617f0197.css",
|
"/css/app.css": "/css/app.css",
|
||||||
"/build/AdminLTE.css": "/build/AdminLTE.3d8a2b2e33baa060b1b324363ad5e1c2.css",
|
"/css/overrides.css": "/css/overrides.css",
|
||||||
"/build/overrides.css": "/build/overrides.617623c6a96be3e0cbd11c5d4039ec10.css",
|
"/public/css/dist/all.css": "/public/css/dist/all.css",
|
||||||
"/css/all.css": "/css/all.css",
|
"/public/js/dist/all.js": "/public/js/dist/all.js"
|
||||||
"/js/all.js": "/js/all.js",
|
|
||||||
"/css/app.css": "/css/app.css",
|
|
||||||
"/css/dist/all.css": "/css/dist/all.css",
|
|
||||||
"/js/dist/all.js": "/js/dist/all.js",
|
|
||||||
"/css/AdminLTE.css": "/css/AdminLTE.css",
|
|
||||||
"/css/overrides.css": "/css/overrides.css",
|
|
||||||
"/css/skin-blue.css": "/css/skin-blue.css",
|
|
||||||
"/vue.js": "/vue.js",
|
|
||||||
"/vue.js.map": "/vue.js.map",
|
|
||||||
"/mix.js.map": "/mix.js.map",
|
|
||||||
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map",
|
|
||||||
"/css/app.css.map": "/css/app.css.map",
|
|
||||||
"/css/overrides.css.map": "/css/overrides.css.map",
|
|
||||||
"public/css/dist/all.css": "public/css/dist/all.css",
|
|
||||||
"public/js/dist/all.js": "public/js/dist/all.js"
|
|
||||||
}
|
}
|
112
build/mix.js
112
build/mix.js
|
@ -1,2 +1,110 @@
|
||||||
!function(n){function t(e){if(r[e])return r[e].exports;var o=r[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var r={};t.m=n,t.c=r,t.i=function(n){return n},t.d=function(n,r,e){t.o(n,r)||Object.defineProperty(n,r,{configurable:!1,enumerable:!0,get:e})},t.n=function(n){var r=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(r,"a",r),r},t.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},t.p="",t(t.s=62)}({6:function(n,t){},62:function(n,t,r){r(9),r(7),r(8),n.exports=r(6)},7:function(n,t){},8:function(n,t){},9:function(n,t){}});
|
/******/ (function(modules) { // webpackBootstrap
|
||||||
//# sourceMappingURL=mix.js.map
|
/******/ // The module cache
|
||||||
|
/******/ var installedModules = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ if(installedModules[moduleId])
|
||||||
|
/******/ return installedModules[moduleId].exports;
|
||||||
|
/******/
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = installedModules[moduleId] = {
|
||||||
|
/******/ i: moduleId,
|
||||||
|
/******/ l: false,
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Flag the module as loaded
|
||||||
|
/******/ module.l = true;
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // expose the modules object (__webpack_modules__)
|
||||||
|
/******/ __webpack_require__.m = modules;
|
||||||
|
/******/
|
||||||
|
/******/ // expose the module cache
|
||||||
|
/******/ __webpack_require__.c = installedModules;
|
||||||
|
/******/
|
||||||
|
/******/ // identity function for calling harmony imports with the correct context
|
||||||
|
/******/ __webpack_require__.i = function(value) { return value; };
|
||||||
|
/******/
|
||||||
|
/******/ // define getter function for harmony exports
|
||||||
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||||
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||||
|
/******/ Object.defineProperty(exports, name, {
|
||||||
|
/******/ configurable: false,
|
||||||
|
/******/ enumerable: true,
|
||||||
|
/******/ get: getter
|
||||||
|
/******/ });
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||||
|
/******/ __webpack_require__.n = function(module) {
|
||||||
|
/******/ var getter = module && module.__esModule ?
|
||||||
|
/******/ function getDefault() { return module['default']; } :
|
||||||
|
/******/ function getModuleExports() { return module; };
|
||||||
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||||
|
/******/ return getter;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Object.prototype.hasOwnProperty.call
|
||||||
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||||
|
/******/
|
||||||
|
/******/ // __webpack_public_path__
|
||||||
|
/******/ __webpack_require__.p = "";
|
||||||
|
/******/
|
||||||
|
/******/ // Load entry module and return exports
|
||||||
|
/******/ return __webpack_require__(__webpack_require__.s = 15);
|
||||||
|
/******/ })
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ ({
|
||||||
|
|
||||||
|
/***/ 15:
|
||||||
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
__webpack_require__(6);
|
||||||
|
__webpack_require__(4);
|
||||||
|
__webpack_require__(5);
|
||||||
|
module.exports = __webpack_require__(3);
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 3:
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
eval("// removed by extract-text-webpack-plugin//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3Jlc291cmNlcy9hc3NldHMvbGVzcy9vdmVycmlkZXMubGVzcz9lNDcxIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9yZXNvdXJjZXMvYXNzZXRzL2xlc3Mvb3ZlcnJpZGVzLmxlc3Ncbi8vIG1vZHVsZSBpZCA9IDNcbi8vIG1vZHVsZSBjaHVua3MgPSAxIl0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIifQ==");
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 4:
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
eval("// removed by extract-text-webpack-plugin//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3Jlc291cmNlcy9hc3NldHMvbGVzcy9BZG1pbkxURS5sZXNzP2U4YTYiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3Jlc291cmNlcy9hc3NldHMvbGVzcy9BZG1pbkxURS5sZXNzXG4vLyBtb2R1bGUgaWQgPSA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMSJdLCJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VSb290IjoiIn0=");
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 5:
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
eval("// removed by extract-text-webpack-plugin//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3Jlc291cmNlcy9hc3NldHMvbGVzcy9hcHAubGVzcz80OTY1Il0sInNvdXJjZXNDb250ZW50IjpbIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9yZXNvdXJjZXMvYXNzZXRzL2xlc3MvYXBwLmxlc3Ncbi8vIG1vZHVsZSBpZCA9IDVcbi8vIG1vZHVsZSBjaHVua3MgPSAxIl0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIifQ==");
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 6:
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
eval("//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNi5qcyIsInNvdXJjZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZVJvb3QiOiIifQ==");
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ });
|
52888
build/vue.js
52888
build/vue.js
File diff suppressed because one or more lines are too long
17
database/factories/CustomFieldsFactory.php
Normal file
17
database/factories/CustomFieldsFactory.php
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
$factory->define(App\Models\CustomField::class, function (Faker\Generator $faker) {
|
||||||
|
return [
|
||||||
|
'name' => $faker->catchPhrase,
|
||||||
|
'format' => 'IP',
|
||||||
|
'element' => 'text',
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$factory->define(App\Models\CustomFieldset::class, function (Faker\Generator $faker) {
|
||||||
|
return [
|
||||||
|
'name' => $faker->catchPhrase,
|
||||||
|
'user_id' => Auth::id()
|
||||||
|
];
|
||||||
|
});
|
|
@ -97,14 +97,6 @@ $factory->define(App\Models\Consumable::class, function (Faker\Generator $faker)
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
$factory->define(App\Models\CustomField::class, function (Faker\Generator $faker) {
|
|
||||||
return [
|
|
||||||
'name' => $faker->catchPhrase,
|
|
||||||
'format' => 'IP',
|
|
||||||
'element' => 'text',
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
$factory->define(App\Models\Department::class, function (Faker\Generator $faker) {
|
$factory->define(App\Models\Department::class, function (Faker\Generator $faker) {
|
||||||
return [
|
return [
|
||||||
'name' => $faker->catchPhrase,
|
'name' => $faker->catchPhrase,
|
||||||
|
|
12
package.json
12
package.json
|
@ -10,14 +10,14 @@
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"axios": "^0.15.3",
|
"axios": "^0.16.2",
|
||||||
"babel-preset-latest": "^6.24.1",
|
"babel-preset-latest": "^6.24.1",
|
||||||
"cross-env": "^3.2.4",
|
"cross-env": "^5.0.5",
|
||||||
"jquery": "^3.1.1",
|
"jquery": "^3.1.1",
|
||||||
"laravel-mix": "0.12.1",
|
"laravel-mix": "1.4.3",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"vue": "2.3.3",
|
"vue": "2.4.4",
|
||||||
"vue-template-compiler": "2.3.3"
|
"vue-template-compiler": "2.4.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"blueimp-file-upload": "^9.18.0",
|
"blueimp-file-upload": "^9.18.0",
|
||||||
|
@ -32,6 +32,8 @@
|
||||||
"jquery-ui": "^1.12.1",
|
"jquery-ui": "^1.12.1",
|
||||||
"jquery-ui-bundle": "^1.12.1",
|
"jquery-ui-bundle": "^1.12.1",
|
||||||
"jquery.iframe-transport": "^1.0.0",
|
"jquery.iframe-transport": "^1.0.0",
|
||||||
|
"less": "^2.7.2",
|
||||||
|
"less-loader": "^4.0.5",
|
||||||
"papaparse": "^4.3.3",
|
"papaparse": "^4.3.3",
|
||||||
"select2": "^4.0.3",
|
"select2": "^4.0.3",
|
||||||
"tether": "^1.4.0",
|
"tether": "^1.4.0",
|
||||||
|
|
BIN
public/css/dist/all.css
vendored
BIN
public/css/dist/all.css
vendored
Binary file not shown.
BIN
public/js/dist/all.js
vendored
BIN
public/js/dist/all.js
vendored
Binary file not shown.
|
@ -130,12 +130,14 @@ tr {
|
||||||
{id: 'jobtitle', text: 'Job Title' },
|
{id: 'jobtitle', text: 'Job Title' },
|
||||||
{id: 'phone_number', text: 'Phone Number' },
|
{id: 'phone_number', text: 'Phone Number' },
|
||||||
],
|
],
|
||||||
|
customFields: [],
|
||||||
},
|
},
|
||||||
columnMappings: this.file.field_map || {},
|
columnMappings: this.file.field_map || {},
|
||||||
activeColumn: null,
|
activeColumn: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.fetchCustomFields();
|
||||||
window.eventHub.$on('showDetails', this.toggleExtendedDisplay)
|
window.eventHub.$on('showDetails', this.toggleExtendedDisplay)
|
||||||
this.populateSelect2ActiveItems();
|
this.populateSelect2ActiveItems();
|
||||||
},
|
},
|
||||||
|
@ -143,7 +145,7 @@ tr {
|
||||||
columns() {
|
columns() {
|
||||||
switch(this.options.importType) {
|
switch(this.options.importType) {
|
||||||
case 'asset':
|
case 'asset':
|
||||||
return this.columnOptions.general.concat(this.columnOptions.assets);
|
return this.columnOptions.general.concat(this.columnOptions.assets).concat(this.columnOptions.customFields);
|
||||||
case 'license':
|
case 'license':
|
||||||
return this.columnOptions.general.concat(this.columnOptions.licenses);
|
return this.columnOptions.general.concat(this.columnOptions.licenses);
|
||||||
case 'user':
|
case 'user':
|
||||||
|
@ -153,6 +155,18 @@ tr {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
fetchCustomFields() {
|
||||||
|
this.$http.get('/api/v1/fields')
|
||||||
|
.then( ({data}) => {
|
||||||
|
data = data.rows;
|
||||||
|
data.forEach((item) => {
|
||||||
|
this.columnOptions.customFields.push({
|
||||||
|
'id': item.db_column_name,
|
||||||
|
'text': item.name,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
},
|
||||||
postSave() {
|
postSave() {
|
||||||
this.statusText = "Processing...";
|
this.statusText = "Processing...";
|
||||||
this.$http.post('/api/v1/imports/process/'+this.file.id, {
|
this.$http.post('/api/v1/imports/process/'+this.file.id, {
|
||||||
|
@ -208,4 +222,4 @@ tr {
|
||||||
select2: require('../select2.vue')
|
select2: require('../select2.vue')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -51,16 +51,16 @@
|
||||||
<tr>
|
<tr>
|
||||||
<form action="{{route('account/request-item', ['itemType' => 'asset', 'itemId' => $asset->id])}}" method="POST" accept-charset="utf-8">
|
<form action="{{route('account/request-item', ['itemType' => 'asset', 'itemId' => $asset->id])}}" method="POST" accept-charset="utf-8">
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
<td>{{ $asset->model->name }}</td>
|
<td>{!! $asset->model->present()->nameUrl() !!}</td>
|
||||||
|
|
||||||
@if ($snipeSettings->display_asset_name)
|
@if ($snipeSettings->display_asset_name)
|
||||||
<td>{{ $asset->name }}</td>
|
<td>{{ $asset->name }}</td>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<td>{{ $asset->serial }}</td>
|
<td><a href="{{ $asset->present()->viewUrl() }}">{{ $asset->serial }}</a></td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{{ $asset->assetloc->name }}
|
{!! $asset->assetLoc->present()->nameUrl() !!}
|
||||||
</td>
|
</td>
|
||||||
@if ($asset->assigned_to != '' && $asset->assigned_to > 0)
|
@if ($asset->assigned_to != '' && $asset->assigned_to > 0)
|
||||||
<td>Checked out</td>
|
<td>Checked out</td>
|
||||||
|
|
|
@ -175,6 +175,13 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () {
|
||||||
'uses' => 'CustomFieldsController@postReorder'
|
'uses' => 'CustomFieldsController@postReorder'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Route::get('/',
|
||||||
|
[
|
||||||
|
'as' => 'api.customfields.index',
|
||||||
|
'uses' => 'CustomFieldsController@index'
|
||||||
|
]
|
||||||
|
);
|
||||||
}); // Fields group
|
}); // Fields group
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
use App\Importer\AccessoryImporter;
|
use App\Importer\AccessoryImporter;
|
||||||
use App\Importer\AssetImporter;
|
use App\Importer\AssetImporter;
|
||||||
use App\Importer\LicenseImporter;
|
|
||||||
use App\Importer\ConsumableImporter;
|
use App\Importer\ConsumableImporter;
|
||||||
|
use App\Importer\LicenseImporter;
|
||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
|
use App\Models\Asset;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
use App\Models\Category;
|
use App\Models\Category;
|
||||||
|
use App\Models\CustomField;
|
||||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
|
@ -18,14 +20,15 @@ class ImporterTest extends BaseTest
|
||||||
*/
|
*/
|
||||||
protected $tester;
|
protected $tester;
|
||||||
|
|
||||||
public function testDefaultImportAsset()
|
public function testDefaultImportAssetWithCustomFields()
|
||||||
{
|
{
|
||||||
$csv = <<<'EOT'
|
$csv = <<<'EOT'
|
||||||
Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
|
Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier,Weight
|
||||||
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
|
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan,35
|
||||||
EOT;
|
EOT;
|
||||||
|
|
||||||
|
$this->initializeCustomFields();
|
||||||
$this->import(new AssetImporter($csv));
|
$this->import(new AssetImporter($csv));
|
||||||
// Did we create a user?
|
|
||||||
|
|
||||||
$this->tester->seeRecord('users', [
|
$this->tester->seeRecord('users', [
|
||||||
'first_name' => 'Bonnie',
|
'first_name' => 'Bonnie',
|
||||||
|
@ -67,16 +70,19 @@ EOT;
|
||||||
'notes' => "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
|
'notes' => "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
|
||||||
'purchase_date' => '2016-04-05 00:00:01',
|
'purchase_date' => '2016-04-05 00:00:01',
|
||||||
'purchase_cost' => 133289.59,
|
'purchase_cost' => 133289.59,
|
||||||
'warranty_months' => 14
|
'warranty_months' => 14,
|
||||||
|
'_snipeit_weight_2' => 35
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateAsset()
|
public function testUpdateAssetIncludingCustomFields()
|
||||||
{
|
{
|
||||||
$csv = <<<'EOT'
|
$csv = <<<'EOT'
|
||||||
Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
|
Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier,weight
|
||||||
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
|
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan,95
|
||||||
EOT;
|
EOT;
|
||||||
|
|
||||||
|
$this->initializeCustomFields();
|
||||||
$this->import(new AssetImporter($csv));
|
$this->import(new AssetImporter($csv));
|
||||||
$updatedCSV = <<<'EOT'
|
$updatedCSV = <<<'EOT'
|
||||||
item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
|
item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
|
||||||
|
@ -124,10 +130,24 @@ EOT;
|
||||||
'notes' => "I have no notes",
|
'notes' => "I have no notes",
|
||||||
'purchase_date' => '2018-04-05 00:00:01',
|
'purchase_date' => '2018-04-05 00:00:01',
|
||||||
'purchase_cost' => 25.59,
|
'purchase_cost' => 25.59,
|
||||||
'warranty_months' => 18
|
'warranty_months' => 18,
|
||||||
]);
|
'_snipeit_weight_2' => 95
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function initializeCustomFields()
|
||||||
|
{
|
||||||
|
$customField = factory(App\Models\CustomField::class)->create(['name' => 'Weight']);
|
||||||
|
$customFieldSet = factory(App\Models\CustomFieldset::class)->create(['name' => 'Default']);
|
||||||
|
$customFieldSet->fields()->attach($customField, [
|
||||||
|
'required' => false,
|
||||||
|
'order' => 'asc']);
|
||||||
|
|
||||||
|
$am = factory(App\Models\AssetModel::class)->create([
|
||||||
|
'name' => 'massa id',
|
||||||
|
'fieldset_id' => $customFieldSet->id
|
||||||
|
]);
|
||||||
|
}
|
||||||
public function testCustomMappingImport()
|
public function testCustomMappingImport()
|
||||||
{
|
{
|
||||||
$csv = <<<'EOT'
|
$csv = <<<'EOT'
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
use App\Exceptions\CheckoutNotAllowed;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
use App\Models\Category;
|
use App\Models\Category;
|
||||||
|
@ -38,6 +39,7 @@ class NotificationTest extends BaseTest
|
||||||
$this->signIn();
|
$this->signIn();
|
||||||
$asset = factory(Asset::class)->states('requires-acceptance')->create();
|
$asset = factory(Asset::class)->states('requires-acceptance')->create();
|
||||||
|
|
||||||
|
$this->expectException(CheckoutNotAllowed::class);
|
||||||
$location = factory(Location::class)->create();
|
$location = factory(Location::class)->create();
|
||||||
Notification::fake();
|
Notification::fake();
|
||||||
$asset->checkOut($location, 1);
|
$asset->checkOut($location, 1);
|
||||||
|
|
Loading…
Reference in a new issue