mirror of
https://github.com/snipe/snipe-it.git
synced 2025-02-02 08:21:09 -08:00
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:
commit
08f3e78d26
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
];
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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',
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue