Merge branch 'checkout-to-location-v2' of https://github.com/dmeltzer/snipe-it into dmeltzer-checkout-to-location-v2

# Conflicts:
#	app/Http/Controllers/Api/UsersController.php
#	app/Http/Transformers/LocationsTransformer.php
#	resources/views/locations/view.blade.php
#	routes/api.php
#	tests/_data/dump.sql
This commit is contained in:
snipe 2017-08-25 06:04:22 -07:00
commit 08f3e78d26
16 changed files with 147 additions and 127 deletions

View file

@ -21,7 +21,7 @@ class LocationsController extends Controller
{
$this->authorize('view', Location::class);
$allowed_columns = ['id','name','address','address2','city','state','country','zip','created_at',
'updated_at','parent_id'];
'updated_at','parent_id', 'manager_id'];
$locations = Location::select([
'locations.id',
@ -33,6 +33,7 @@ class LocationsController extends Controller
'locations.zip',
'locations.country',
'locations.parent_id',
'locations.manager_id',
'locations.created_at',
'locations.updated_at',
'locations.currency'

View file

@ -63,7 +63,8 @@ class LocationsController extends Controller
return view('locations/edit')
->with('location_options', $location_options)
->with('item', new Location);
->with('item', new Location)
->with('manager_list', Helper::managerList());
}
@ -88,6 +89,7 @@ class LocationsController extends Controller
$location->state = Input::get('state');
$location->country = Input::get('country');
$location->zip = Input::get('zip');
$location->manager_id = Input::get('manager_id');
$location->user_id = Auth::id();
if ($location->save()) {
@ -154,7 +156,10 @@ class LocationsController extends Controller
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return view('locations/edit', compact('item'))->with('location_options', $location_options);
return view('locations/edit', compact('item'))
->with('location_options', $location_options)
->with('manager_list', Helper::managerList());
}
@ -185,6 +190,7 @@ class LocationsController extends Controller
$location->country = Input::get('country');
$location->zip = Input::get('zip');
$location->ldap_ou = Input::get('ldap_ou');
$location->manager_id = Input::get('manager_id');
// Was the location updated?
if ($location->save()) {
@ -232,8 +238,6 @@ class LocationsController extends Controller
* the content for the locations detail page.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::getDataViewUsers() method that returns JSON for location users
* @see LocationsController::getDataViewAssets() method that returns JSON for location assets
* @param int $locationId
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
@ -252,78 +256,4 @@ class LocationsController extends Controller
return redirect()->route('locations.index')->with('error', $error);
}
/**
* Returns a JSON response that contains the users association with the
* selected location, to be used by the location detail view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::getView() method that creates the display view
* @param $locationID
* @return array
* @internal param int $locationId
* @since [v1.8]
*/
public function getDataViewUsers($locationID)
{
$location = Location::find($locationID);
$users = User::where('location_id', '=', $location->id);
if (Input::has('search')) {
$users = $users->TextSearch(e(Input::get('search')));
}
$users = $users->get();
$rows = array();
foreach ($users as $user) {
$rows[] = array(
'name' => (string)link_to_route('users.show', e($user->present()->fullName()), ['user'=>$user->id])
);
}
$data = array('total' => $users->count(), 'rows' => $rows);
return $data;
}
/**
* Returns a JSON response that contains the assets association with the
* selected location, to be used by the location detail view.
*
* @todo This is broken for accessories and consumables.
* @todo This is a very naive implementation. Should clean this up with query scopes.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::getView() method that creates the display view
* @param int $locationID
* @since [v1.8]
* @return array
*/
public function getDataViewAssets($locationID)
{
$location = Location::find($locationID)->load('assignedassets.model');
$assets = Asset::AssetsByLocation($location);
if (Input::has('search')) {
$assets = $assets->TextSearch(e(Input::get('search')));
}
$assets = $assets->get();
$rows = array();
foreach ($assets as $asset) {
$rows[] = [
'name' => (string)link_to_route('hardware.show', e($asset->present()->name()), ['hardware' => $asset->id]),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
'model' => e($asset->model->name),
];
}
$data = array('total' => $assets->count(), 'rows' => $rows);
return $data;
}
}

View file

@ -376,7 +376,6 @@ class UsersController extends Controller
}
if ($user->licenses()->count() > 0) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->licenses()->count() . ' licenses associated with them.');
}
@ -386,6 +385,11 @@ class UsersController extends Controller
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories()->count() . ' accessories associated with them.');
}
if ($user->managedLocations()->count() > 0) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.');
}
// Delete the user
$user->delete();

View file

@ -9,7 +9,7 @@ use App\Helpers\Helper;
class LocationsTransformer
{
public function transformLocations (Collection $locations, $total)
public function transformLocations(Collection $locations, $total)
{
$array = array();
foreach ($locations as $location) {
@ -18,7 +18,7 @@ class LocationsTransformer
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformLocation (Location $location = null)
public function transformLocation(Location $location = null)
{
if ($location) {
@ -45,6 +45,9 @@ class LocationsTransformer
'id' => (int) $location->parent->id,
'name'=> e($location->parent->name)
] : null,
'manager' => ($location->manager) ? (new UsersTransformer)->transformUser($location->manager) : null,
'children' => $children_arr,
];

View file

@ -276,13 +276,17 @@ class Asset extends Depreciable
if (!empty($this->assignedType())) {
if ($this->assignedType() == self::ASSET) {
return $this->assignedTo->assetloc(); // Recurse until we have a final location
} elseif ($this->assignedType() == self::LOCATION) {
}
if ($this->assignedType() == self::LOCATION) {
return $this->assignedTo();
} elseif (!$this->assignedTo) {
return $this->defaultLoc();
} elseif ($this->assignedType() == self::USER) {
return $this->assignedTo->userLoc();
}
if ($this->assignedType() == self::USER) {
return $this->assignedTo->userLoc();
}
}
return $this->defaultLoc();
}

View file

@ -24,6 +24,7 @@ class Location extends SnipeModel
'address' => 'max:80|nullable',
'address2' => 'max:80|nullable',
'zip' => 'min:3|max:10|nullable',
// 'manager_id' => 'exists:users'
);
/**
@ -66,6 +67,11 @@ class Location extends SnipeModel
return $this->belongsTo('\App\Models\Location', 'parent_id','id');
}
public function manager()
{
return $this->belongsTo('\App\Models\User', 'manager_id');
}
public function childLocations()
{
return $this->hasMany('\App\Models\Location', 'parent_id');

View file

@ -205,6 +205,14 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
return $this->belongsTo('\App\Models\User', 'manager_id')->withTrashed();
}
/**
* Get any locations the user manages.
**/
public function managedLocations()
{
return $this->hasMany('\App\Models\Location', 'manager_id')->withTrashed();
}
/**
* Get user groups
*/

View file

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddManagerToLocationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('locations', function (Blueprint $table) {
//
$table->integer('manager_id')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('locations', function (Blueprint $table) {
//
$table->dropColumn('manager_id');
});
}
}

View file

@ -19,6 +19,7 @@ return array(
'location' => 'Location',
'lock_passwords' => 'Login details cannot be changed on this installation.',
'manager' => 'Manager',
'managed_locations' => 'Managed Locations',
'name' => 'Name',
'notes' => 'Notes',
'password_confirm' => 'Confirm Password',

View file

@ -21,6 +21,17 @@
</div>
</div>
<!-- Manager-->
<div class="form-group {{ $errors->has('manager_id') ? ' has-error' : '' }}">
<label for="manager_id" class="col-md-3 control-label">
{{ trans('admin/users/table.manager') }}
</label>
<div class="col-md-9{{ (\App\Helpers\Helper::checkIfRequired($item, 'manager_id')) ? ' required' : '' }}">
{!! Form::select('manager_id', $manager_list , Input::old('manager_id', $item->manager_id), array('class'=>'select2 parent', 'style'=>'width:350px')) !!}
{!! $errors->first('manager_id', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Currency -->
<div class="form-group {{ $errors->has('currency') ? ' has-error' : '' }}">
<label for="currency" class="col-md-3 control-label">

View file

@ -37,13 +37,15 @@
<th data-searchable="true" data-sortable="true" data-field="city">{{ trans('admin/locations/table.city') }}
</th>
<th data-searchable="true" data-sortable="true" data-field="state">
{{ trans('admin/locations/table.state') }}
{{ trans('admin/locations/table.state') }}
</th>
<th data-searchable="true" data-sortable="true" data-field="zip">
{{ trans('admin/locations/table.zip') }}
</th>
<th data-searchable="true" data-sortable="true" data-field="zip">
{{ trans('admin/locations/table.zip') }}
</th>
<th data-searchable="true" data-sortable="true" data-field="country">
{{ trans('admin/locations/table.country') }}</th>
{{ trans('admin/locations/table.country') }}
</th>
<th data-sortable="true" data-formatter="usersLinkObjFormatter" data-field="manager" data-searchable="true">{{ trans('admin/users/table.manager') }}</th>
<th data-switchable="false" data-formatter="locationsActionsFormatter" data-searchable="false" data-sortable="false" data-field="actions">{{ trans('table.actions') }}</th>
</tr>
</thead>

View file

@ -3,8 +3,11 @@
{{-- Page title --}}
@section('title')
{{ trans('general.location') }}:
{{ $location->name }}
{{ trans('general.location') }}
@if ($location->manager)
<div class="h6"> {!! trans('admin/users/table.manager') . ': ' . $location->manager->present()->nameUrl() !!}</div>
@endif
@parent
@stop
@ -26,7 +29,7 @@
name="location_users"
id="table-users"
class="table table-striped snipe-table"
data-url="{{route('api.users.index', ['location_id' => $location->id]) }}"
data-url="{{route('api.locations.viewusers', $location->id)}}"
data-cookie="true"
data-click-to-select="true"
data-cookie-id-table="location_usersDetailTable">

View file

@ -73,6 +73,16 @@
</a>
</li>
@if ($user->managedLocations()->count() >= 0 )
<li>
<a href="#managed_tab" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="fa fa-clock-o"></i></span>
<span class="hidden-xs hidden-sm">{{ trans('admin/users/table.managed_locations') }}</span>
</a>
</li>
@endif
@can('update', $user)
<li class="dropdown pull-right">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
@ -451,6 +461,27 @@
</div>
</div><!-- /.tab-pane -->
<div class="tab-pane" id="managed_tab">
<div class="table-responsive">
<table class="display table table-striped">
<thead>
<tr>
<th class="col-md-8">{{ trans('general.name') }}</th>
<th class="col-md-4">{{ trans('general.date') }}</th>
</tr>
</thead>
<tbody>
@foreach ($user->managedLocations as $location)
<tr>
<td>{!! $location->present()->nameUrl() !!}</a></td>
<td>{{ $location->created_at }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div><!-- /consumables-tab -->
</div><!-- /.tab-content -->
</div><!-- nav-tabs-custom -->
</div>

View file

@ -330,6 +330,20 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () {
Route::group(['prefix' => 'locations'], function () {
Route::get('{location}/users',
[
'as'=>'api.locations.viewusers',
'uses'=>'LocationsController@getDataViewUsers'
]
);
Route::get('{location}/assets',
[
'as'=>'api.locations.viewassets',
'uses'=>'LocationsController@getDataViewAssets'
]
);
// Do we actually still need this, now that we have an API?
Route::get('{location}/check',
[

File diff suppressed because one or more lines are too long