Integrate ajax select2 menus in all asset checkouts

This commit is contained in:
snipe 2017-10-26 02:28:17 -07:00
parent 75b527ab59
commit 82690e1fd7
17 changed files with 274 additions and 127 deletions

View file

@ -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

View file

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

View file

@ -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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/js/dist/all.js vendored

Binary file not shown.

View file

@ -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"
}

View file

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

View file

@ -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");

View file

@ -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();

View file

@ -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

View file

@ -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',