mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-24 21:24:13 -08:00
Integrate ajax select2 menus in all asset checkouts
This commit is contained in:
parent
75b527ab59
commit
82690e1fd7
|
@ -263,6 +263,61 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a formatted JSON response for the select2 menus
|
||||
*
|
||||
* @todo: create a transformer for handling these responses
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$assets = Company::scopeCompanyables(Asset::select([
|
||||
'assets.id',
|
||||
'assets.name',
|
||||
'assets.asset_tag',
|
||||
'assets.model_id',
|
||||
]))->with('model')->RTD();
|
||||
|
||||
|
||||
if ($request->has('search')) {
|
||||
$assets = $assets->where('assets.name', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('assets.asset_tag', 'LIKE', '%'.$request->get('search').'%')
|
||||
->join('models AS assets_models',function ($join) use ($request) {
|
||||
$join->on('assets_models.id', "=", "assets.model_id");
|
||||
})->orWhere('assets_models.name','LIKE','%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
$assets = $assets->paginate(50);
|
||||
$assets_array = [];
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
$assets_array[] =
|
||||
[
|
||||
'id' => (int) $asset->id,
|
||||
'text' => e($asset->present()->fullName),
|
||||
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
|
||||
];
|
||||
}
|
||||
$results = [
|
||||
'items' => $assets_array,
|
||||
'pagination' =>
|
||||
[
|
||||
'more' => ($assets->currentPage() >= $assets->lastPage()) ? false : true,
|
||||
'per_page' => $assets->perPage()
|
||||
],
|
||||
'total_count' => $assets->total(),
|
||||
'page' => $assets->currentPage(),
|
||||
'page_count' => $assets->lastPage()
|
||||
];
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a POST request to create a new asset
|
||||
|
|
|
@ -139,4 +139,55 @@ class LocationsController extends Controller
|
|||
$location->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/locations/message.delete.success')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a formatted JSON response for the select2 menus
|
||||
*
|
||||
* @todo: create a transformer for handling these responses
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
$this->authorize('view', Location::class);
|
||||
|
||||
$locations = Location::select([
|
||||
'locations.id',
|
||||
'locations.name',
|
||||
'locations.image',
|
||||
]);
|
||||
|
||||
|
||||
if ($request->has('search')) {
|
||||
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
$locations = $locations->paginate(50);
|
||||
$locations_array = [];
|
||||
|
||||
foreach ($locations as $location) {
|
||||
$locations_array[] =
|
||||
[
|
||||
'id' => (int) $location->id,
|
||||
'text' => e($location->name),
|
||||
'image' => ($location->image) ? url('/').'/uploads/locations/'.$location->image : null,
|
||||
];
|
||||
}
|
||||
$results = [
|
||||
'items' => $locations_array,
|
||||
'pagination' =>
|
||||
[
|
||||
'more' => ($locations->currentPage() >= $locations->lastPage()) ? false : true,
|
||||
'per_page' => $locations->perPage()
|
||||
],
|
||||
'total_count' => $locations->total(),
|
||||
'page' => $locations->currentPage(),
|
||||
'page_count' => $locations->lastPage()
|
||||
];
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -273,14 +273,16 @@ class AssetPresenter extends Presenter
|
|||
**/
|
||||
public function name()
|
||||
{
|
||||
if (empty($this->name)) {
|
||||
if (isset($this->model)) {
|
||||
return $this->model->name.' ('.$this->asset_tag.')';
|
||||
|
||||
if (empty($this->model->name)) {
|
||||
if (isset($this->model->model)) {
|
||||
return $this->model->model->name.' ('.$this->model->asset_tag.')';
|
||||
}
|
||||
return $this->asset_tag;
|
||||
return $this->model->asset_tag;
|
||||
} else {
|
||||
return $this->name.' ('.$this->asset_tag.')';
|
||||
return $this->model->name . ' (' . $this->model->asset_tag . ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,7 +291,18 @@ class AssetPresenter extends Presenter
|
|||
*/
|
||||
public function fullName()
|
||||
{
|
||||
return $this->name();
|
||||
$str = '';
|
||||
if ($this->model->name) {
|
||||
$str .= $this->name;
|
||||
}
|
||||
|
||||
if ($this->asset_tag) {
|
||||
$str .= ' ('.$this->model->asset_tag.')';
|
||||
}
|
||||
if ($this->model->model) {
|
||||
$str .= ' - '.$this->model->model->name;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
/**
|
||||
* Returns the date this item hits EOL.
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/css/dist/all.css
vendored
BIN
public/css/dist/all.css
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/js/dist/all.js
vendored
BIN
public/js/dist/all.js
vendored
Binary file not shown.
|
@ -1,14 +1,10 @@
|
|||
{
|
||||
"/js/build/vue.js": "/js/build/vue.js?id=e6804371942215bd1d7d",
|
||||
"/css/AdminLTE.css": "/css/AdminLTE.css?id=b8be19a285eaf44eec37",
|
||||
"/css/app.css": "/css/app.css?id=407edb63cc6b6dc62405",
|
||||
"/css/overrides.css": "/css/overrides.css?id=9ae1a3c861441320c5a1",
|
||||
"/js/build/vue.js.map": "/js/build/vue.js.map?id=3b3d417664a61dcce3e9",
|
||||
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map?id=99f5a5a03c4155cf69f6",
|
||||
"/css/app.css.map": "/css/app.css.map?id=bdbe05e6ecd70ccfac72",
|
||||
"/css/overrides.css.map": "/css/overrides.css.map?id=898c91d4a425b01b589b",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=7c3842d2639193ac7e88",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=f14abfc2506d42ffb0f5",
|
||||
"/css/build/all.css": "/css/build/all.css?id=7c3842d2639193ac7e88",
|
||||
"/js/build/all.js": "/js/build/all.js?id=f14abfc2506d42ffb0f5"
|
||||
"/js/build/vue.js": "/js/build/vue.js?id=e9504cad01a748f9b0fa",
|
||||
"/css/AdminLTE.css": "/css/AdminLTE.css?id=889dc040f2ddfca6efde",
|
||||
"/css/app.css": "/css/app.css?id=3a1e8c168fa8714043a6",
|
||||
"/css/overrides.css": "/css/overrides.css?id=3911514a8a64a4247483",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=f2d4896e67e878a47434",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=b967aad5fdaca0a91359",
|
||||
"/css/build/all.css": "/css/build/all.css?id=f2d4896e67e878a47434",
|
||||
"/js/build/all.js": "/js/build/all.js?id=b967aad5fdaca0a91359"
|
||||
}
|
|
@ -180,14 +180,78 @@ $(document).ready(function () {
|
|||
}
|
||||
$('.datepicker').datepicker();
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#toggle_nav").toggle(function() {
|
||||
var datepicker = $.fn.datepicker.noConflict(); // return $.fn.datepicker to previously assigned value
|
||||
$.fn.bootstrapDP = datepicker;
|
||||
$('.datepicker').datepicker();
|
||||
|
||||
|
||||
// Crazy select2 rich dropdowns with images!
|
||||
$('.js-data-ajax').each( function (i,item) {
|
||||
var link = $(item);
|
||||
var endpoint = link.data("endpoint");
|
||||
var select = link.data("select");
|
||||
|
||||
link.select2({
|
||||
|
||||
ajax: {
|
||||
url: baseUrl + '/api/v1/' + endpoint + '/selectlist',
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
headers: {
|
||||
"X-Requested-With": 'XMLHttpRequest',
|
||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr('content')
|
||||
},
|
||||
data: function (params) {
|
||||
var data = {
|
||||
search: params.term,
|
||||
page: params.page || 1
|
||||
};
|
||||
return data;
|
||||
},
|
||||
processResults: function (data, params) {
|
||||
|
||||
params.page = params.page || 1;
|
||||
|
||||
var answer = {
|
||||
results: data.items,
|
||||
pagination: {
|
||||
more: "true" //(params.page < data.page_count)
|
||||
}
|
||||
};
|
||||
|
||||
return answer;
|
||||
},
|
||||
cache: true
|
||||
},
|
||||
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
|
||||
templateResult: formatDatalist,
|
||||
templateSelection: formatDataSelection
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function formatDatalist (datalist) {
|
||||
var loading_markup = '<i class="fa fa-spinner fa-spin" aria-hidden="true"></i> Loading...';
|
||||
if (datalist.loading) {
|
||||
return loading_markup;
|
||||
}
|
||||
|
||||
var markup = "<div class='clearfix'>" ;
|
||||
markup +="<div class='pull-left' style='padding-right: 10px;'>";
|
||||
if (datalist.image) {
|
||||
markup += "<img src='" + datalist.image + "' style='max-height: 20px'>";
|
||||
} else {
|
||||
markup += "<div style='height: 20px; width: 20px;'></div>";
|
||||
}
|
||||
|
||||
markup += "</div><div>" + datalist.text + "</div>";
|
||||
markup += "</div>";
|
||||
return markup;
|
||||
}
|
||||
|
||||
function formatDataSelection (datalist) {
|
||||
return datalist.text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -95,10 +95,14 @@
|
|||
// clicked 'add' on to add a new 'thing'
|
||||
// this code adds the newly created object to that select
|
||||
var selector = document.getElementById(select);
|
||||
console.warn("The selector we should've selecte dis: "+select);
|
||||
console.dir(selector);
|
||||
if(!selector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.warn("onChange Selector Thing should've activated? Here's the selector");
|
||||
console.dir(selector);
|
||||
selector.options[selector.length] = new Option(name, id);
|
||||
selector.selectedIndex = selector.length - 1;
|
||||
$(selector).trigger("change");
|
||||
|
|
|
@ -47,45 +47,58 @@
|
|||
|
||||
|
||||
|
||||
<div id="assigned_user" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
|
||||
|
||||
|
||||
|
||||
<div id="assigned_user" class="form-group{{ $errors->has('assigned_user') ? ' has-error' : '' }}">
|
||||
|
||||
{{ Form::label('assigned_user', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
|
||||
|
||||
<div class="col-md-7 required">
|
||||
<select class="js-data-user-ajax" name="assigned_user" style="width: 350px;">
|
||||
<select class="js-data-ajax" data-endpoint="users" name="assigned_user" style="width: 100%" id="assigned_user_select">
|
||||
<option value="">{{ trans('general.select_user') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{!! $errors->first('assigned_user', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
|
||||
<div class="col-md-1 col-sm-1 text-left">
|
||||
@can('create', \App\Models\User::class)
|
||||
<a href='{{ route('modal.user') }}' data-toggle="modal" data-target="#createModal" data-dependency="user" data-select='assigned_user_select' class="btn btn-sm btn-default">New</a>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
@if (!$asset->requireAcceptance())
|
||||
<!-- Assets -->
|
||||
<div id="assigned_asset" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
|
||||
{{ Form::label('assigned_asset', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
|
||||
<div class="col-md-7 required">
|
||||
{{ Form::select('assigned_asset', $assets_list , Input::old('assigned_asset', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_asset', 'style'=>'width:100%')) }}
|
||||
{!! $errors->first('assigned_asset', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Locations -->
|
||||
<div id="assigned_location" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
|
||||
{{ Form::label('assigned_location', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
|
||||
<div class="col-md-7 required">
|
||||
{{ Form::select('assigned_location', $locations_list , Input::old('assigned_location', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_location', 'style'=>'width:100%')) }}
|
||||
{!! $errors->first('assigned_location', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
{!! $errors->first('assigned_user', '<div class="col-md-8 col-md-offset-3"><span class="alert-msg"><i class="fa fa-times"></i> :message</span></div>') !!}
|
||||
|
||||
</div>
|
||||
|
||||
@if (!$asset->requireAcceptance())
|
||||
|
||||
<!-- Asset -->
|
||||
<div id="assigned_asset" class="form-group{{ $errors->has('assigned_asset') ? ' has-error' : '' }}">
|
||||
{{ Form::label('assigned_asset', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
|
||||
<div class="col-md-7 required">
|
||||
<select class="js-data-ajax" data-endpoint="hardware" name="assigned_asset" style="width: 100%" id="assigned_asset_select">
|
||||
<option value="">{{ trans('general.select_asset') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
{!! $errors->first('assigned_asset', '<div class="col-md-8 col-md-offset-3"><span class="alert-msg"><i class="fa fa-times"></i> :message</span></div>') !!}
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Location -->
|
||||
<div id="assigned_location" class="form-group{{ $errors->has('assigned_location') ? ' has-error' : '' }}">
|
||||
{{ Form::label('assigned_location', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
|
||||
<div class="col-md-7 required">
|
||||
<select class="js-data-ajax" data-endpoint="locations" name="assigned_location" style="width: 100%" id="assigned_location_select">
|
||||
<option value="">{{ trans('general.select_location') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-1 col-sm-1 text-left">
|
||||
@can('create', \App\Models\Location::class)
|
||||
<a href='{{ route('modal.location') }}' data-toggle="modal" data-target="#createModal" data-dependency="location" data-select='assigned_location_select' class="btn btn-sm btn-default">New</a>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
{!! $errors->first('assigned_location', '<div class="col-md-8 col-md-offset-3"><span class="alert-msg"><i class="fa fa-times"></i> :message</span></div>') !!}
|
||||
|
||||
</div>
|
||||
@endif
|
||||
<!-- Checkout/Checkin Date -->
|
||||
<div class="form-group {{ $errors->has('checkout_at') ? 'error' : '' }}">
|
||||
|
@ -164,9 +177,12 @@
|
|||
|
||||
@section('moar_scripts')
|
||||
<script nonce="{{ csrf_token() }}">
|
||||
|
||||
// create the assigned assets listing box for the right side of the screen
|
||||
$(function() {
|
||||
$('#assigned_user').on("change",function () {
|
||||
var userid = $('#assigned_user option:selected').val();
|
||||
|
||||
if(userid=='') {
|
||||
console.warn('no user selected');
|
||||
$('#current_assets_box').fadeOut();
|
||||
|
|
|
@ -658,73 +658,6 @@
|
|||
|
||||
|
||||
<script src="{{ url(mix('js/dist/all.js')) }}" nonce="{{ csrf_token() }}"></script>
|
||||
<script nonce="{{ csrf_token() }}">
|
||||
$(function () {
|
||||
var datepicker = $.fn.datepicker.noConflict(); // return $.fn.datepicker to previously assigned value
|
||||
$.fn.bootstrapDP = datepicker;
|
||||
$('.datepicker').datepicker();
|
||||
});
|
||||
|
||||
// Crazy select2 rich dropdowns with images!
|
||||
$(".js-data-user-ajax").select2({
|
||||
ajax: {
|
||||
url: '{{ route('api.users.selectlist') }}',
|
||||
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
headers: {
|
||||
"X-Requested-With": 'XMLHttpRequest',
|
||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr('content')
|
||||
},
|
||||
data: function (params) {
|
||||
var data = {
|
||||
search: params.term,
|
||||
page: params.page || 1
|
||||
};
|
||||
return data;
|
||||
},
|
||||
processResults: function (data, params) {
|
||||
|
||||
params.page = params.page || 1;
|
||||
|
||||
var answer = {
|
||||
results: data.items,
|
||||
pagination: {
|
||||
more: "true" //(params.page < data.page_count)
|
||||
}
|
||||
};
|
||||
|
||||
return answer;
|
||||
},
|
||||
cache: true
|
||||
},
|
||||
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
|
||||
templateResult: formatUserlist,
|
||||
templateSelection: formatUserSelection
|
||||
});
|
||||
|
||||
function formatUserlist (userlist) {
|
||||
var loading_markup = '<i class="fa fa-spinner fa-spin" aria-hidden="true"></i> Loading...';
|
||||
if (userlist.loading) {
|
||||
return loading_markup;
|
||||
}
|
||||
|
||||
var markup = "<div class='clearfix'>" ;
|
||||
markup +="<div class='pull-left' style='padding-right: 10px;'>";
|
||||
markup += "<img src='" + userlist.image + "' style='max-height: 20px'></div>";
|
||||
markup += "<div>" + userlist.text + "</div>";
|
||||
markup += "</div>";
|
||||
return markup;
|
||||
}
|
||||
|
||||
function formatUserSelection (userlist) {
|
||||
return userlist.text;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
@section('moar_scripts')
|
||||
@show
|
||||
|
|
|
@ -226,6 +226,12 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () {
|
|||
|
||||
Route::group(['prefix' => 'hardware'], function () {
|
||||
|
||||
Route::get( 'selectlist', [
|
||||
'as' => 'assets.selectlist',
|
||||
'uses' => 'AssetsController@selectlist'
|
||||
]);
|
||||
|
||||
|
||||
Route::post('audit', [
|
||||
'as' => 'api.asset.audit',
|
||||
'uses' => 'AssetsController@audit'
|
||||
|
@ -331,21 +337,6 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () {
|
|||
|
||||
/*--- Locations API ---*/
|
||||
|
||||
Route::resource('locations', 'LocationsController',
|
||||
[
|
||||
'names' =>
|
||||
[
|
||||
'index' => 'api.locations.index',
|
||||
'show' => 'api.locations.show',
|
||||
'store' => 'api.locations.store',
|
||||
'update' => 'api.locations.update',
|
||||
'destroy' => 'api.locations.destroy'
|
||||
],
|
||||
'except' => ['create', 'edit'],
|
||||
'parameters' => ['location' => 'location_id']
|
||||
]
|
||||
); // Locations resource
|
||||
|
||||
Route::group(['prefix' => 'locations'], function () {
|
||||
|
||||
Route::get('{location}/users',
|
||||
|
@ -369,9 +360,33 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () {
|
|||
'uses' => 'LocationsController@show'
|
||||
]
|
||||
);
|
||||
|
||||
Route::get( 'selectlist', [
|
||||
'as' => 'locations.selectlist',
|
||||
'uses' => 'LocationsController@selectlist'
|
||||
]);
|
||||
}); // Locations group
|
||||
|
||||
|
||||
|
||||
Route::resource('locations', 'LocationsController',
|
||||
[
|
||||
'names' =>
|
||||
[
|
||||
'index' => 'api.locations.index',
|
||||
'show' => 'api.locations.show',
|
||||
'store' => 'api.locations.store',
|
||||
'update' => 'api.locations.update',
|
||||
'destroy' => 'api.locations.destroy'
|
||||
],
|
||||
'except' => ['create', 'edit'],
|
||||
'parameters' => ['location' => 'location_id']
|
||||
]
|
||||
); // Locations resource
|
||||
|
||||
|
||||
|
||||
|
||||
/*--- Manufacturers API ---*/
|
||||
|
||||
Route::resource('manufacturers', 'ManufacturersController',
|
||||
|
|
Loading…
Reference in a new issue