mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-25 05:34:06 -08:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
commit
29c584289f
|
@ -55,11 +55,11 @@ Since the release of the JSON REST API, several third-party developers have been
|
|||
|
||||
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
|
||||
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
|
||||
- [InQRy](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
|
||||
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
|
||||
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
|
||||
- [Snipe-IT plugin for Jira Service Desk (beta)](https://marketplace.atlassian.com/apps/1220379/snipe-it-for-jira-service-desk-beta?hosting=cloud&tab=overview) - for the upcoming Snipe-IT v5 only
|
||||
- [Snipe-IT plugin for Jira Service Desk)](https://marketplace.atlassian.com/apps/1220964/snipe-it-for-jira)
|
||||
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
|
||||
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it.
|
||||
|
|
|
@ -51,6 +51,10 @@ class AccessoriesController extends Controller
|
|||
$accessories->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$accessories->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
|
||||
|
@ -167,9 +171,13 @@ class AccessoriesController extends Controller
|
|||
|
||||
if ($request->filled('search')) {
|
||||
$accessory_users = $accessory->users()
|
||||
->where('first_name', 'like', '%'.$request->input('search').'%')
|
||||
->orWhere('last_name', 'like', '%'.$request->input('search').'%')
|
||||
->get();
|
||||
->where(function ($query) use ($request) {
|
||||
$search_str = '%' . $request->input('search') . '%';
|
||||
$query->where('first_name', 'like', $search_str)
|
||||
->orWhere('last_name', 'like', $search_str)
|
||||
->orWhere('note', 'like', $search_str);
|
||||
})
|
||||
->get();
|
||||
$total = $accessory_users->count();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use App\Http\Requests\AssetCheckoutRequest;
|
|||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
|
@ -640,6 +641,39 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v5.1.18]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function restore($assetId = null)
|
||||
{
|
||||
// Get asset information
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$this->authorize('delete', $asset);
|
||||
if (isset($asset->id)) {
|
||||
// Restore the asset
|
||||
Asset::withTrashed()->where('id', $assetId)->restore();
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Asset::class;
|
||||
$logaction->item_id = $asset->id;
|
||||
$logaction->created_at = date("Y-m-d H:i:s");
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restored');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.restore.success')));
|
||||
|
||||
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,6 +46,10 @@ class ConsumablesController extends Controller
|
|||
$consumables->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$consumables->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
|
|
|
@ -20,9 +20,9 @@ class DepreciationsController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Depreciation::class);
|
||||
$allowed_columns = ['id','name','months','created_at'];
|
||||
$allowed_columns = ['id','name','months','depreciation_min','created_at'];
|
||||
|
||||
$depreciations = Depreciation::select('id','name','months','user_id','created_at','updated_at');
|
||||
$depreciations = Depreciation::select('id','name','months','depreciation_min','user_id','created_at','updated_at');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$depreciations = $depreciations->TextSearch($request->input('search'));
|
||||
|
|
|
@ -61,7 +61,7 @@ class ForgotPasswordController extends Controller
|
|||
$request->validate([
|
||||
'username' => ['required', 'max:255'],
|
||||
]);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -71,13 +71,21 @@ class ForgotPasswordController extends Controller
|
|||
* Once we have attempted to send the link, we will examine the response
|
||||
* then see the message we need to show to the user. Finally, we'll send out a proper response.
|
||||
*/
|
||||
$response = $this->broker()->sendResetLink(
|
||||
array_merge(
|
||||
$request->only('username'),
|
||||
['activated' => '1'],
|
||||
['ldap_import' => '0']
|
||||
)
|
||||
);
|
||||
|
||||
$response = null;
|
||||
|
||||
try {
|
||||
$response = $this->broker()->sendResetLink(
|
||||
array_merge(
|
||||
$request->only('username'),
|
||||
['activated' => '1'],
|
||||
['ldap_import' => '0']
|
||||
)
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
\Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
|
||||
}
|
||||
|
||||
|
||||
if ($response === \Password::RESET_LINK_SENT) {
|
||||
\Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
|
||||
|
|
|
@ -69,6 +69,7 @@ class DepreciationsController extends Controller
|
|||
// Depreciation data
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
$depreciation->depreciations_min= $request->input('depreciation_min');
|
||||
$depreciation->user_id = Auth::id();
|
||||
|
||||
// Was the asset created?
|
||||
|
@ -125,8 +126,9 @@ class DepreciationsController extends Controller
|
|||
$this->authorize('update', $depreciation);
|
||||
|
||||
// Depreciation data
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
$depreciation->depreciation_min = $request->input('depreciation_min');
|
||||
|
||||
// Was the asset created?
|
||||
if ($depreciation->save()) {
|
||||
|
|
|
@ -24,6 +24,7 @@ class DepreciationsTransformer
|
|||
'id' => (int) $depreciation->id,
|
||||
'name' => e($depreciation->name),
|
||||
'months' => $depreciation->months . ' '. trans('general.months'),
|
||||
'depreciation_min' => $depreciation->depreciation_min,
|
||||
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime'),
|
||||
];
|
||||
|
|
|
@ -14,7 +14,7 @@ class AccessoryImporter extends ItemImporter
|
|||
protected function handle($row)
|
||||
{
|
||||
parent::handle($row); // TODO: Change the autogenerated stub
|
||||
$this->createAccessoryIfNotExists();
|
||||
$this->createAccessoryIfNotExists($row);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ class AccessoryImporter extends ItemImporter
|
|||
* @author Daniel Melzter
|
||||
* @since 3.0
|
||||
*/
|
||||
public function createAccessoryIfNotExists()
|
||||
public function createAccessoryIfNotExists($row)
|
||||
{
|
||||
$accessory = Accessory::where('name', $this->item['name'])->first();
|
||||
if ($accessory) {
|
||||
|
@ -33,12 +33,14 @@ class AccessoryImporter extends ItemImporter
|
|||
}
|
||||
|
||||
$this->log('Updating Accessory');
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$accessory->update($this->sanitizeItemForUpdating($accessory));
|
||||
$accessory->save();
|
||||
return;
|
||||
}
|
||||
$this->log("No Matching Accessory, Creating a new one");
|
||||
$accessory = new Accessory();
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$accessory->fill($this->sanitizeItemForStoring($accessory));
|
||||
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
|
|
|
@ -226,26 +226,26 @@ $factory->state(App\Models\AssetModel::class, 'tab3-model', function ($faker) {
|
|||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$factory->state(App\Models\AssetModel::class, 'iphone6s-model', function ($faker) {
|
||||
$factory->state(App\Models\AssetModel::class, 'iphone11-model', function ($faker) {
|
||||
return [
|
||||
'name' => 'iPhone 6s',
|
||||
'name' => 'iPhone 11',
|
||||
'category_id' => 4,
|
||||
'manufacturer_id' => 1,
|
||||
'eol' => '12',
|
||||
'depreciation_id' => 3,
|
||||
'image' => 'iphone6.jpg',
|
||||
'image' => 'iphone11.jpeg',
|
||||
'fieldset_id' => 1,
|
||||
];
|
||||
});
|
||||
|
||||
$factory->state(App\Models\AssetModel::class, 'iphone7-model', function ($faker) {
|
||||
$factory->state(App\Models\AssetModel::class, 'iphone12-model', function ($faker) {
|
||||
return [
|
||||
'name' => 'iPhone 7',
|
||||
'name' => 'iPhone 12',
|
||||
'category_id' => 4,
|
||||
'manufacturer_id' => 1,
|
||||
'eol' => '12',
|
||||
'depreciation_id' => 1,
|
||||
'image' => 'iphone7.jpg',
|
||||
'image' => 'iphone12.jpeg',
|
||||
'fieldset_id' => 1,
|
||||
];
|
||||
});
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddDepreciationMinimumValue extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('depreciations', function (Blueprint $table) {
|
||||
$table->decimal('depreciation_min', 8,2)->after('months')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('depreciations', function (Blueprint $table) {
|
||||
$table->dropColumn('depreciation_min');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -33,8 +33,8 @@ class AssetModelSeeder extends Seeder
|
|||
factory(AssetModel::class, 1)->states('tab3-model')->create(); // 14
|
||||
|
||||
// Phones
|
||||
factory(AssetModel::class, 1)->states('iphone6s-model')->create(); // 15
|
||||
factory(AssetModel::class, 1)->states('iphone7-model')->create(); // 16
|
||||
factory(AssetModel::class, 1)->states('iphone11-model')->create(); // 15
|
||||
factory(AssetModel::class, 1)->states('iphone12-model')->create(); // 16
|
||||
|
||||
// Displays
|
||||
factory(AssetModel::class, 1)->states('ultrafine')->create(); // 17
|
||||
|
|
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -11629,7 +11629,8 @@
|
|||
"picomatch": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
|
||||
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||
"optional": true
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
|
@ -14235,6 +14236,7 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
||||
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
|
@ -14248,7 +14250,8 @@
|
|||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"optional": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.4.0",
|
||||
|
@ -18323,7 +18326,8 @@
|
|||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
|
|
BIN
public/img/demo/models/iphone11.jpeg
Normal file
BIN
public/img/demo/models/iphone11.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
public/img/demo/models/iphone12.jpeg
Normal file
BIN
public/img/demo/models/iphone12.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
|
@ -141,6 +141,9 @@
|
|||
{id: 'username', text: 'Username' },
|
||||
{id: 'department', text: 'Department' },
|
||||
],
|
||||
accessories:[
|
||||
{id: 'model_number', text: 'Model Number'},
|
||||
],
|
||||
assets: [
|
||||
{id: 'asset_tag', text: 'Asset Tag' },
|
||||
{id: 'asset_model', text: 'Model Name' },
|
||||
|
@ -208,7 +211,10 @@
|
|||
.concat(this.columnOptions.assets)
|
||||
.concat(this.columnOptions.customFields)
|
||||
.sort(sorter);
|
||||
|
||||
case 'accessory':
|
||||
return this.columnOptions.general
|
||||
.concat(this.columnOptions.accessories)
|
||||
.sort(sorter);
|
||||
case 'consumable':
|
||||
return this.columnOptions.general
|
||||
.concat(this.columnOptions.consumables)
|
||||
|
|
|
@ -8,5 +8,6 @@ return array(
|
|||
'depreciation_name' => 'Depreciation Name',
|
||||
'number_of_months' => 'Number of Months',
|
||||
'update' => 'Update Depreciation',
|
||||
'depreciation_min' => 'Minimum Value after Depreciation'
|
||||
|
||||
);
|
||||
|
|
|
@ -22,5 +22,14 @@
|
|||
</div>
|
||||
{!! $errors->first('months', '<span class="alert-msg" aria-hidden="true"><i class="fa fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- Depreciation Minimum -->
|
||||
<div class="form-group {{ $errors->has('depreciation_min') ? ' has-error' : '' }}">
|
||||
<label for="depreciation_min" class="col-md-3 control-label">
|
||||
{{ trans('admin/depreciations/general.depreciation_min') }}
|
||||
</label>
|
||||
<div class="col-md-2" style="padding-left:0px">
|
||||
<input class="form-control" name="depreciation_min" id="depreciation_min" value="{{ Request::old('depreciation_min', $item->depreciation_min) }}" style="width: 80px; margin-left:15px" />
|
||||
</div>
|
||||
{!! $errors->first('depreciation_min', '<span class="alert-msg" aria-hidden="true"><i class="fa fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@stop
|
||||
|
|
|
@ -445,6 +445,20 @@ Route::group(['prefix' => 'v1','namespace' => 'Api', 'middleware' => 'auth:api']
|
|||
]
|
||||
);
|
||||
|
||||
Route::post('{asset_id}/restore',
|
||||
[
|
||||
'as' => 'api.assets.restore',
|
||||
'uses' => 'AssetsController@restore'
|
||||
]
|
||||
);
|
||||
|
||||
Route::post('{asset_id}/destroy',
|
||||
[
|
||||
'as' => 'api.assets.destroy',
|
||||
'uses' => 'AssetsController@destroy'
|
||||
]
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
/*--- Asset Maintenances API ---*/
|
||||
|
|
Loading…
Reference in a new issue