mirror of
https://github.com/snipe/snipe-it.git
synced 2025-02-21 03:15:45 -08:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
commit
93e038006c
|
@ -1584,4 +1584,68 @@ class AssetsController extends Controller
|
|||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getBulkCheckout()
|
||||
{
|
||||
// Get the dropdown of users and then pass it to the checkout view
|
||||
$users_list = Helper::usersList();
|
||||
// Filter out assets that are not deployable.
|
||||
$assets = Asset::RTD()->get();
|
||||
|
||||
$assets_list = Company::scopeCompanyables($assets, 'assets.company_id')->lists('detailed_name', 'id')->toArray();
|
||||
|
||||
return View::make('hardware/bulk-checkout')->with('users_list', $users_list)->with('assets_list', $assets_list);
|
||||
}
|
||||
|
||||
public function postBulkCheckout(Request $request)
|
||||
{
|
||||
|
||||
$this->validate($request, [
|
||||
"assigned_to" => 'required'
|
||||
]);
|
||||
|
||||
$user = User::find(e(Input::get('assigned_to')));
|
||||
$admin = Auth::user();
|
||||
|
||||
$asset_ids = array_filter(Input::get('selected_assets'));
|
||||
|
||||
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
|
||||
$checkout_at = e(Input::get('checkout_at'));
|
||||
} else {
|
||||
$checkout_at = date("Y-m-d H:i:s");
|
||||
}
|
||||
|
||||
if (Input::has('expected_checkin')) {
|
||||
$expected_checkin = e(Input::get('expected_checkin'));
|
||||
} else {
|
||||
$expected_checkin = '';
|
||||
}
|
||||
|
||||
$has_errors = false;
|
||||
$errors = [];
|
||||
DB::transaction(function() use ($user, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids)
|
||||
{
|
||||
foreach($asset_ids as $asset_id)
|
||||
{
|
||||
$asset = Asset::find($asset_id);
|
||||
|
||||
$error = $asset->checkOutToUser($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), null);
|
||||
|
||||
if($error)
|
||||
{
|
||||
$has_errors = true;
|
||||
array_merge_recursive($errors, $asset->getErrors()->toArray());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!$errors) {
|
||||
// Redirect to the new asset page
|
||||
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->to("hardware/bulk-checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -275,6 +275,13 @@ Route::group(
|
|||
]
|
||||
);
|
||||
|
||||
# Bulk checkout / checkin
|
||||
Route::get(
|
||||
'bulkcheckout',
|
||||
[ 'as' => 'hardware/bulkcheckout', 'uses' => 'AssetsController@getBulkCheckout' ]
|
||||
);
|
||||
Route::post('bulkcheckout', 'AssetsController@postBulkCheckout');
|
||||
|
||||
# Asset Model Management
|
||||
Route::group([ 'prefix' => 'models', 'middleware' => 'auth' ], function () {
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
return array (
|
||||
'app_version' => 'v3.0',
|
||||
'hash_version' => 'v3.0-67-gf31637a',
|
||||
'hash_version' => 'v3.0-79-gfcb1d6a',
|
||||
);
|
|
@ -3,6 +3,7 @@
|
|||
return array(
|
||||
'archived' => 'Archived',
|
||||
'asset' => 'Asset',
|
||||
'bulk_checkout' => 'Checkout Assets to User',
|
||||
'checkin' => 'Checkin Asset',
|
||||
'checkout' => 'Checkout Asset to User',
|
||||
'clone' => 'Clone Asset',
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
'avatar_upload' => 'Upload Avatar',
|
||||
'back' => 'Back',
|
||||
'bad_data' => 'Nothing found. Maybe bad data?',
|
||||
'bulk_checkout' => 'Bulk Checkout',
|
||||
'cancel' => 'Cancel',
|
||||
'categories' => 'Categories',
|
||||
'category' => 'Category',
|
||||
|
@ -105,6 +106,7 @@
|
|||
'moreinfo' => 'More Info',
|
||||
'name' => 'Name',
|
||||
'next' => 'Next',
|
||||
'new' => 'new!',
|
||||
'no_depreciation' => 'No Depreciation',
|
||||
'no_results' => 'No Results.',
|
||||
'no' => 'No',
|
||||
|
|
280
resources/views/hardware/bulk-checkout.blade.php
Normal file
280
resources/views/hardware/bulk-checkout.blade.php
Normal file
|
@ -0,0 +1,280 @@
|
|||
@extends('layouts/default')
|
||||
|
||||
{{-- Page title --}}
|
||||
@section('title')
|
||||
{{ trans('admin/hardware/general.bulk_checkout') }}
|
||||
@parent
|
||||
@stop
|
||||
|
||||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.input-group {
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<!-- left column -->
|
||||
<div class="col-md-7">
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title"> {{ trans('admin/hardware/form.tag') }} </h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<form class="form-horizontal" method="post" action="" autocomplete="off">
|
||||
<!-- CSRF Token -->
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
|
||||
|
||||
|
||||
<!-- User -->
|
||||
<div id="assigned_user" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
|
||||
|
||||
{{ Form::label('assigned_to', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
|
||||
|
||||
<div class="col-md-7 required">
|
||||
{{ Form::select('assigned_to', $users_list , Input::old('assigned_to'), array('class'=>'select2', 'id'=>'assigned_to', 'style'=>'width:100%')) }}
|
||||
|
||||
{!! $errors->first('assigned_to', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
<div class="col-md-1 col-sm-1 text-left">
|
||||
<a href='#' data-toggle="modal" data-target="#createModal" data-dependency="user" data-select='assigned_to' class="btn btn-sm btn-default">New</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Checkout/Checkin Date -->
|
||||
<div class="form-group {{ $errors->has('checkout_at') ? 'error' : '' }}">
|
||||
|
||||
{{ Form::label('name', trans('admin/hardware/form.checkout_date'), array('class' => 'col-md-3 control-label')) }}
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="col-md-4 input-group required">
|
||||
<input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" name="checkout_at" id="checkout_at" value="{{ Input::old('checkout_at', date('Y-m-d')) }}">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
</div>
|
||||
{!! $errors->first('checkout_at', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Expected Checkin Date -->
|
||||
<div class="form-group {{ $errors->has('expected_checkin') ? 'error' : '' }}">
|
||||
|
||||
{{ Form::label('name', trans('admin/hardware/form.expected_checkin'), array('class' => 'col-md-3 control-label')) }}
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="col-md-4 input-group">
|
||||
<input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" name="expected_checkin" id="expected_checkin" value="{{ Input::old('expected_checkin') }}">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
</div>
|
||||
{!! $errors->first('expected_checkin', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Note -->
|
||||
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
|
||||
|
||||
{{ Form::label('note', trans('admin/hardware/form.notes'), array('class' => 'col-md-3 control-label')) }}
|
||||
|
||||
<div class="col-md-8">
|
||||
<textarea class="col-md-6 form-control" id="note" name="note">{{ Input::old('note') }}</textarea>
|
||||
{!! $errors->first('note', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('selected_asset') ? ' has-error' : '' }}">
|
||||
|
||||
{{ Form::label('selected_asset', trans('general.assets'), array('class' => 'col-md-3 control-label')) }}
|
||||
|
||||
<div class="col-md-8 required">
|
||||
{{ Form::select('selected_assets[]', $assets_list , Input::old('selected_asset'), array('class'=>'select2', 'id'=>'selected_asset', 'style'=>'width:100%', 'multiple'=>'multiple')) }}
|
||||
|
||||
{!! $errors->first('selected_asset', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<a class="btn btn-link" href="{{ URL::previous() }}"> {{ trans('button.cancel') }}</a>
|
||||
<button type="submit" class="btn btn-success pull-right"><i class="fa fa-check icon-white"></i> {{ trans('general.checkout') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- right column -->
|
||||
<div class="col-md-5" id="current_assets_box" style="display:none;">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('admin/users/general.current_assets') }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div id="current_assets_content">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@section('moar_scripts')
|
||||
|
||||
{{-- Some room for the modals --}}
|
||||
<div class="modal fade" id="createModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Modal title</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12"><label for="modal-first_name">{{ trans('general.first_name') }}:</label></div>
|
||||
<div class="col-md-8 col-xs-12 required"><input type='text' id='modal-first_name' class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12"><label for="modal-last_name">{{ trans('general.last_name') }}:</label></div>
|
||||
<div class="col-md-8 col-xs-12"><input type='text' id='modal-last_name' class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12"><label for="modal-username">{{ trans('admin/users/table.username') }}:</label></div>
|
||||
<div class="col-md-8 col-xs-12 required"><input type='text' id='modal-username' class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12"><label for="modal-email">{{ trans('admin/users/table.email') }}:</label></div>
|
||||
<div class="col-md-8 col-xs-12"><input type='email' id='modal-email' class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12"><label for="modal-password">{{ trans('admin/users/table.password') }}:</label></div>
|
||||
<div class="col-md-8 col-xs-12 required"><input type='password' id='modal-password' class="form-control"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('button.cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary" id="modal-save">{{ trans('general.save') }}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Ajax call to retrieve user assets -->
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
var model,select;
|
||||
$('#createModal').on("show.bs.modal",function (event) {
|
||||
console.warn('modal ran');
|
||||
var link = $(event.relatedTarget);
|
||||
model=link.data("dependency");
|
||||
select=link.data("select");
|
||||
var modal = $(this);
|
||||
modal.find('.modal-title').text('Add a new ' + model);
|
||||
$('.dynamic-form-row').hide();
|
||||
function show_er(selector) {
|
||||
$(selector).parent().parent().show();
|
||||
}
|
||||
show_er('#modal-name');
|
||||
switch(model) {
|
||||
case 'user':
|
||||
$('.dynamic-form-row').hide(); //we don't want a generic "name"
|
||||
show_er("#modal-first_name");
|
||||
show_er("#modal-last_name");
|
||||
show_er("#modal-username");
|
||||
show_er("#modal-email");
|
||||
show_er("#modal-password");
|
||||
show_er("#modal-password_confirm");
|
||||
break;
|
||||
//do nothing, they just need 'name'
|
||||
}
|
||||
//console.warn("The Model is: "+model+" and the select is: "+select);
|
||||
});
|
||||
$('#modal-save').on('click',function () {
|
||||
var data={};
|
||||
//console.warn("We are about to SAVE!!! for model: "+model+" and select ID: "+select);
|
||||
$('.modal-body input:visible').each(function (index,elem) {
|
||||
//console.warn("["+index+"]: "+elem.id+" = "+$(elem).val());
|
||||
var bits=elem.id.split("-");
|
||||
if(bits[0]==="modal") {
|
||||
data[bits[1]]=$(elem).val();
|
||||
}
|
||||
});
|
||||
$('.modal-body select:visible').each(function (index,elem) {
|
||||
var bits=elem.id.split("-");
|
||||
data[bits[1]]=$(elem).val();
|
||||
});
|
||||
data._token = '{{ csrf_token() }}',
|
||||
// console.dir(data);
|
||||
$.post("{{config('app.url') }}/api/"+model+"s",data,function (result) {
|
||||
var id=result.id;
|
||||
var name=result.name || (result.first_name+" "+result.last_name);
|
||||
$('.modal-body input:visible').val("");
|
||||
$('#createModal').modal('hide');
|
||||
//console.warn("The select ID thing we're going for is: "+select);
|
||||
var selector=document.getElementById(select);
|
||||
selector.options[selector.length] = new Option(name,id);
|
||||
selector.selectedIndex=selector.length-1;
|
||||
$(selector).trigger("change");
|
||||
}).fail(function (result) {
|
||||
//console.dir(result.responseJSON);
|
||||
msg=result.responseJSON.error.message || result.responseJSON.error;
|
||||
window.alert("Unable to add new "+model+" - error: "+msg);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$('#assigned_to').on("change",function () {
|
||||
// console.warn("Model Id has changed!");
|
||||
var userid=$('#assigned_to').val();
|
||||
if(userid=='') {
|
||||
console.warn('no user selected');
|
||||
$('#current_assets_box').fadeOut();
|
||||
$('#current_assets_content').html("");
|
||||
} else {
|
||||
$.get("{{config('app.url') }}/api/users/"+userid+"/assets",{_token: "{{ csrf_token() }}"},function (data) {
|
||||
// console.warn("Ajax call came back okay for user " + userid + "! " + data.length + " Data is: "+data);
|
||||
if (data.length > 0) {
|
||||
$('#current_assets_box').fadeIn();
|
||||
var table_html = '<div class="row"><div class="col-md-12"><table class="table table-striped"><thead><tr><td>{{ trans('admin/hardware/form.name') }}</td><td>{{ trans('admin/hardware/form.tag') }}</td></tr></thead><tbody>';
|
||||
$('#current_assets_content').append('');
|
||||
for (var i in data) {
|
||||
var asset = data[i];
|
||||
table_html += "<tr><td class=\"col-md-8\"><a href=\"{{ config('app.url') }}/hardware/" + asset.id + "/view\">" + asset.name;
|
||||
if (asset.model.name!='') {
|
||||
table_html += " (" + asset.model.name + ")";
|
||||
}
|
||||
table_html += "</a></td><td class=\"col-md-4\">" + asset.asset_tag + "</td></tr>";
|
||||
}
|
||||
$('#current_assets_content').html(table_html + '</tbody></table></div></div>');
|
||||
} else {
|
||||
$('#current_assets_box').fadeOut();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@stop
|
||||
|
||||
@stop
|
|
@ -206,6 +206,7 @@
|
|||
</ul>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@can('admin')
|
||||
<!-- Tasks: style can be found in dropdown.less -->
|
||||
<?php $alert_items = \App\Helpers\Helper::checkLowInventory(); ?>
|
||||
|
@ -389,24 +390,28 @@
|
|||
<li>
|
||||
<a href="{{ URL::to('hardware') }}">@lang('general.list_all')</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ URL::to('hardware?status=Deployed') }}" {!! (Request::query('status') == 'Deployed' ? ' class="active"' : '') !!} >@lang('general.deployed')
|
||||
<li{!! (Request::query('status') == 'Deployed' ? ' class="active"' : '') !!}>
|
||||
<a href="{{ URL::to('hardware?status=Deployed') }}">@lang('general.deployed')
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ URL::to('hardware?status=RTD') }}" {!! (Request::query('status') == 'RTD' ? ' class="active"' : '') !!}>
|
||||
<li{!! (Request::query('status') == 'RTD' ? ' class="active"' : '') !!}>
|
||||
<a href="{{ URL::to('hardware?status=RTD') }}">
|
||||
@lang('general.ready_to_deploy')</a>
|
||||
</li>
|
||||
<li><a href="{{ URL::to('hardware?status=Pending') }}"
|
||||
{!! (Request::query('status') == 'Pending' ? ' class="active"' : '') !!} >@lang('general.pending')</a></li>
|
||||
<li><a href="{{ URL::to('hardware?status=Undeployable') }}" {!! (Request::query('status') == 'Undeployable' ? ' class="active"' : '') !!} >@lang('general.undeployable')</a></li>
|
||||
<li><a href="{{ URL::to('hardware?status=Archived') }}" {!! (Request::query('status') == 'Archived' ? ' class="active"' : '') !!} >@lang('admin/hardware/general.archived')</a></li>
|
||||
<li><a href="{{ URL::to('hardware?status=Requestable') }}" {!! (Request::query('status') == 'Requestable' ? ' class="active"' : '') !!} >@lang('admin/hardware/general.requestable')</a></li>
|
||||
<li{!! (Request::query('status') == 'Pending' ? ' class="active"' : '') !!}><a href="{{ URL::to('hardware?status=Pending') }}">@lang('general.pending')</a></li>
|
||||
<li{!! (Request::query('status') == 'Undeployable' ? ' class="active"' : '') !!} ><a href="{{ URL::to('hardware?status=Undeployable') }}">@lang('general.undeployable')</a></li>
|
||||
<li{!! (Request::query('status') == 'Archived' ? ' class="active"' : '') !!} >@lang('admin/hardware/general.archived')</a></li>
|
||||
<li><a href="{{ URL::to('hardware?status=Requestable') }}" {!! (Request::query('status') == 'Requestable' ? ' class="active"' : '') !!}><a href="{{ URL::to('hardware?status=Archived') }}" >@lang('admin/hardware/general.requestable')</a></li>
|
||||
|
||||
<li class="divider"> </li>
|
||||
<li><a href="{{ URL::to('hardware/models') }}" {!! (Request::is('hardware/models*') ? ' class="active"' : '') !!} >@lang('general.asset_models')</a></li>
|
||||
<li{!! (Request::is('hardware/bulkcheckout') ? ' class="active>"' : '') !!}>
|
||||
<small class="label pull-right bg-orange">{{ trans('general.new') }}</small>
|
||||
<a href="{{ route('hardware/bulkcheckout') }}">
|
||||
{{ trans('general.bulk_checkout') }}</a>
|
||||
</li>
|
||||
<li{!! (Request::is('hardware/models*') ? ' class="active"' : '') !!}><a href="{{ URL::to('hardware/models') }}">@lang('general.asset_models')</a></li>
|
||||
<li><a href="{{ URL::to('admin/settings/categories') }}" {!! (Request::is('admin/settings/categories*') ? ' class="active"' : '') !!} >@lang('general.categories')</a></li>
|
||||
<li><a href="{{ URL::to('hardware?status=Deleted') }}" {!! (Request::query('Deleted') ? ' class="active"' : '') !!} >@lang('general.deleted')</a></li>
|
||||
<li{!! (Request::query('Deleted') ? ' class="active"' : '') !!}><a href="{{ URL::to('hardware?status=Deleted') }}">@lang('general.deleted')</a></li>
|
||||
<li><a href="{{ URL::to('admin/asset_maintenances') }}" >@lang('general.asset_maintenances') </a></li>
|
||||
<li><a href="{{ URL::to('hardware/import') }}" >@lang('general.import') </a></li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in a new issue