Compare commits
8 Commits
add-status
...
custom_fie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
251080d5b8 | ||
|
|
3a3f26ba8b | ||
|
|
58656fbaec | ||
|
|
873d260f55 | ||
|
|
48fd6f3f26 | ||
|
|
05a68afab9 | ||
|
|
21ff0e748c | ||
|
|
d2b7828569 |
77
app/Helpers/CustomFieldHelper.php
Normal file
77
app/Helpers/CustomFieldHelper.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/*********************
|
||||
* These two helper methods are more designed for being re-used with the new HasCustomFields Trait
|
||||
*
|
||||
* The 'transform' method is designed for BlahTransformer things that need to return custom field values.
|
||||
*
|
||||
* The 'present' method is designed for when you're trying to generate fieldlists for use in Bootstrap tables
|
||||
* - typically the 'dataTableLayout' method
|
||||
*
|
||||
*********************/
|
||||
class CustomFieldHelper {
|
||||
|
||||
static function transform($fieldset, $item) {
|
||||
if ($fieldset && ($fieldset->fields->count() > 0)) {
|
||||
$fields_array = [];
|
||||
|
||||
foreach ($fieldset->fields as $field) {
|
||||
if ($field->isFieldDecryptable($item->{$field->db_column})) {
|
||||
$decrypted = Helper::gracefulDecrypt($field, $item->{$field->db_column});
|
||||
$value = (Gate::allows('assets.view.encrypted_custom_fields')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
|
||||
if ($field->format == 'DATE'){
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')){
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
} else {
|
||||
$value = strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
}
|
||||
}
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => e($field->db_column),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
'element' => $field->element,
|
||||
];
|
||||
|
||||
} else {
|
||||
$value = $item->{$field->db_column};
|
||||
|
||||
if (($field->format == 'DATE') && (!is_null($value)) && ($value!='')){
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
}
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => e($field->db_column),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
'element' => $field->element,
|
||||
];
|
||||
}
|
||||
|
||||
return $fields_array;
|
||||
}
|
||||
} else {
|
||||
return new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||
}
|
||||
}
|
||||
|
||||
static function present($field) {
|
||||
return [
|
||||
'field' => 'custom_fields.'.$field->db_column,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => $field->name,
|
||||
'formatter'=> 'customFieldsFormatter',
|
||||
'escape' => true,
|
||||
'class' => ($field->field_encrypted == '1') ? 'css-padlock' : '',
|
||||
'visible' => ($field->show_in_listview == '1') ? true : false,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -651,6 +651,17 @@ class Helper
|
||||
return $customfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the different types of custom fields there are
|
||||
* TODO - how to make this more general? Or more useful? or more dynamic?
|
||||
* idea - key of classname, *value* of trans? (thus having to make this a method, which is fine)
|
||||
*/
|
||||
static $itemtypes_having_custom_fields = [
|
||||
0 => \App\Models\Asset::class,
|
||||
1 => \App\Models\User::class,
|
||||
// 2 => \App\Models\Accessory::class
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the list of custom field formats in an array to make a dropdown menu
|
||||
*
|
||||
|
||||
@@ -67,7 +67,7 @@ class AssetModelsController extends Controller
|
||||
'models.deleted_at',
|
||||
'models.updated_at',
|
||||
])
|
||||
->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues')
|
||||
->with('category', 'depreciation', 'manufacturer')
|
||||
->withCount('assets as assets_count');
|
||||
|
||||
if ($request->input('status')=='deleted') {
|
||||
|
||||
@@ -120,7 +120,7 @@ class AssetsController extends Controller
|
||||
$filter = json_decode($request->input('filter'), true);
|
||||
}
|
||||
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
$all_custom_fields = CustomField::where('type', Asset::class); //used as a 'cache' of custom fields throughout this page load
|
||||
foreach ($all_custom_fields as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
@@ -586,48 +586,8 @@ class AssetsController extends Controller
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
// Update custom fields in the database.
|
||||
$model = AssetModel::find($request->input('model_id'));
|
||||
$asset->customFill($request, Auth::user(), true);
|
||||
|
||||
// Check that it's an object and not a collection
|
||||
// (Sometimes people send arrays here and they shouldn't
|
||||
if (($model) && ($model instanceof AssetModel) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
|
||||
// Set the field value based on what was sent in the request
|
||||
$field_val = $request->input($field->db_column, null);
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if ($field_val == null) {
|
||||
Log::debug('Field value for '.$field->db_column.' is null');
|
||||
$field_val = $field->defaultValue($request->get('model_id'));
|
||||
Log::debug('Use the default fieldset value of '.$field->defaultValue($request->get('model_id')));
|
||||
}
|
||||
|
||||
// if the field is set to encrypted, make sure we encrypt the value
|
||||
if ($field->field_encrypted == '1') {
|
||||
Log::debug('This model field is encrypted in this fieldset.');
|
||||
|
||||
if (Gate::allows('admin')) {
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if (($field_val == null) && ($request->has('model_id') != '')) {
|
||||
$field_val = Crypt::encrypt($field->defaultValue($request->get('model_id')));
|
||||
} else {
|
||||
$field_val = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($field->element == 'checkbox') {
|
||||
if(is_array($field_val)) {
|
||||
$field_val = implode(',', $field_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
|
||||
if ($asset->save()) {
|
||||
if ($request->get('assigned_user')) {
|
||||
@@ -688,33 +648,8 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = AssetModel::find($asset->model_id);
|
||||
|
||||
// Update custom fields
|
||||
$problems_updating_encrypted_custom_fields = false;
|
||||
if (($model) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
$field_val = $request->input($field->db_column, null);
|
||||
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->element == 'checkbox') {
|
||||
if(is_array($field_val)) {
|
||||
$field_val = implode(',', $field_val);
|
||||
}
|
||||
}
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
$field_val = Crypt::encrypt($field_val);
|
||||
} else {
|
||||
$problems_updating_encrypted_custom_fields = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$problems_updating_encrypted_custom_fields = !$asset->customFill($request, Auth::user());
|
||||
|
||||
if ($asset->save()) {
|
||||
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
|
||||
@@ -35,7 +35,7 @@ class CustomFieldsetsController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', CustomField::class);
|
||||
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
|
||||
$fieldsets = CustomFieldset::withCount('fields as fields_count')->get();
|
||||
|
||||
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
|
||||
}
|
||||
@@ -125,7 +125,7 @@ class CustomFieldsetsController extends Controller
|
||||
$this->authorize('delete', CustomField::class);
|
||||
$fieldset = CustomFieldset::findOrFail($id);
|
||||
|
||||
$modelsCount = $fieldset->models->count();
|
||||
$modelsCount = $fieldset->customizables()->count();
|
||||
$fieldsCount = $fieldset->fields->count();
|
||||
|
||||
if (($modelsCount > 0) || ($fieldsCount > 0)) {
|
||||
|
||||
@@ -14,6 +14,7 @@ use App\Http\Transformers\UsersTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
@@ -37,7 +38,7 @@ class UsersController extends Controller
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$users = User::select([
|
||||
$allowed_columns = [
|
||||
'users.activated',
|
||||
'users.created_by',
|
||||
'users.address',
|
||||
@@ -75,7 +76,12 @@ class UsersController extends Controller
|
||||
'users.autoassign_licenses',
|
||||
'users.website',
|
||||
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy')
|
||||
];
|
||||
|
||||
foreach (CustomField::where('type', User::class)->get() as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
$users = User::select($allowed_columns)->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
|
||||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
|
||||
|
||||
|
||||
@@ -396,7 +402,9 @@ class UsersController extends Controller
|
||||
}
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
|
||||
$user->customFill($request,Auth::user());
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
@@ -496,7 +504,9 @@ class UsersController extends Controller
|
||||
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
|
||||
$user->customFill($request,Auth::user());
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
// Check if the request has groups passed and has a value, AND that the user us a superuser
|
||||
|
||||
@@ -9,6 +9,7 @@ use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\User;
|
||||
use App\Models\DefaultValuesForCustomFields;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\View;
|
||||
@@ -163,7 +164,7 @@ class AssetModelsController extends Controller
|
||||
$model->notes = $request->input('notes');
|
||||
$model->requestable = $request->input('requestable', '0');
|
||||
|
||||
$this->removeCustomFieldsDefaultValues($model);
|
||||
DefaultValuesForCustomFields::forPivot($model, Asset::class)->delete();
|
||||
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
|
||||
@@ -480,7 +481,7 @@ class AssetModelsController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default values to a model (as long as they are truthy)
|
||||
* Adds default values to a model (as long as they are truthy) (does this mean I cannot set a default value of 0?)
|
||||
*
|
||||
* @param AssetModel $model
|
||||
* @param array $defaultValues
|
||||
@@ -515,22 +516,12 @@ class AssetModelsController extends Controller
|
||||
}
|
||||
|
||||
foreach ($defaultValues as $customFieldId => $defaultValue) {
|
||||
if(is_array($defaultValue)){
|
||||
$model->defaultValues()->attach($customFieldId, ['default_value' => implode(', ', $defaultValue)]);
|
||||
}elseif ($defaultValue) {
|
||||
$model->defaultValues()->attach($customFieldId, ['default_value' => $defaultValue]);
|
||||
if (is_array($defaultValue)) {
|
||||
$defaultValue = implode(', ', $defaultValue);
|
||||
}
|
||||
DefaultValuesForCustomFields::updateOrCreate(['custom_field_id' => $customFieldId, 'item_pivot_id' => $model->id], ['default_value' => $defaultValue]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all default values
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeCustomFieldsDefaultValues(AssetModel $model)
|
||||
{
|
||||
$model->defaultValues()->detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,29 +160,7 @@ class AssetsController extends Controller
|
||||
$asset = $request->handleImages($asset);
|
||||
}
|
||||
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handled through the AssetRequest form request
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$asset->customFill($request, Auth::user()); // Update custom fields in the database.
|
||||
|
||||
// Validate the asset before saving
|
||||
if ($asset->isValid() && $asset->save()) {
|
||||
|
||||
@@ -6,9 +6,11 @@ use App\Helpers\Helper;
|
||||
use App\Http\Requests\CustomFieldRequest;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Custom Asset Fields for
|
||||
* the Snipe-IT Asset Management application.
|
||||
@@ -20,6 +22,7 @@ use Illuminate\Http\Request;
|
||||
*/
|
||||
class CustomFieldsController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view with a listing of custom fields.
|
||||
*
|
||||
@@ -28,12 +31,16 @@ class CustomFieldsController extends Controller
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', CustomField::class);
|
||||
if ($request->input('tab') == 1) {
|
||||
// Users section, make sure to auto-create the first fieldset if so
|
||||
CustomFieldset::firstOrCreate(['type' => Helper::$itemtypes_having_custom_fields[1]], ['name' => 'default']);
|
||||
}
|
||||
|
||||
$fieldsets = CustomFieldset::with('fields', 'models')->get();
|
||||
$fields = CustomField::with('fieldset')->get();
|
||||
$fieldsets = CustomFieldset::with('fields')->where("type", Helper::$itemtypes_having_custom_fields[$request->get('tab', 0)])->get(); //cannot eager-load 'customizable' because it's not a relation
|
||||
$fields = CustomField::with('fieldset')->where("type", Helper::$itemtypes_having_custom_fields[$request->get('tab', 0)])->get();
|
||||
|
||||
return view('custom_fields.index')->with('custom_fieldsets', $fieldsets)->with('custom_fields', $fields);
|
||||
}
|
||||
@@ -66,7 +73,7 @@ class CustomFieldsController extends Controller
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
$fieldsets = CustomFieldset::get();
|
||||
$fieldsets = CustomFieldset::where('type', Helper::$itemtypes_having_custom_fields[$request->get('tab')])->get();
|
||||
|
||||
return view('custom_fields.fields.edit', [
|
||||
'predefinedFormats' => Helper::predefined_formats(),
|
||||
@@ -110,8 +117,10 @@ class CustomFieldsController extends Controller
|
||||
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
|
||||
"show_in_listview" => $request->get("show_in_listview", 0),
|
||||
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
|
||||
"user_id" => Auth::id()
|
||||
"user_id" => Auth::id(),
|
||||
]);
|
||||
// not mass-assignable; must be manual
|
||||
$field->type = Helper::$itemtypes_having_custom_fields[$request->get('tab')];
|
||||
|
||||
|
||||
if ($request->filled('custom_format')) {
|
||||
@@ -124,14 +133,17 @@ class CustomFieldsController extends Controller
|
||||
|
||||
// Sync fields with fieldsets
|
||||
$fieldset_array = $request->input('associate_fieldsets');
|
||||
if ($request->has('associate_fieldsets') && (is_array($fieldset_array))) {
|
||||
if ($request->get('tab') == 1) {
|
||||
$fieldset_array = [CustomFieldset::firstOrCreate(['type' => User::class], ['name' => 'default'])->id => true];
|
||||
}
|
||||
if (($request->has('associate_fieldsets') || $request->get('tab') == 1) && (is_array($fieldset_array))) {
|
||||
$field->fieldset()->sync(array_keys($fieldset_array));
|
||||
} else {
|
||||
$field->fieldset()->sync([]);
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/message.field.create.success'));
|
||||
return redirect()->route('fields.index', ['tab' => $request->get('tab', 0)])->with('success', trans('admin/custom_fields/message.field.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('selected_fieldsets', $request->input('associate_fieldsets'))->withInput()
|
||||
@@ -184,12 +196,16 @@ class CustomFieldsController extends Controller
|
||||
if ($field = CustomField::find($field_id)) {
|
||||
$this->authorize('delete', $field);
|
||||
|
||||
if ($field->type == User::class) {
|
||||
$field->fieldset()->detach(); // remove from 'default' group (and others, if they exist in the future!)
|
||||
}
|
||||
if (($field->fieldset) && ($field->fieldset->count() > 0)) {
|
||||
return redirect()->back()->withErrors(['message' => 'Field is in-use']);
|
||||
}
|
||||
$type = $field->type;
|
||||
$field->delete();
|
||||
return redirect()->route("fields.index")
|
||||
->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
return redirect()->route('fields.index', ['tab' => array_search($type, Helper::$itemtypes_having_custom_fields)])
|
||||
->with('success', trans('admin/custom_fields/message.field.delete.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withErrors(['message' => 'Field does not exist']);
|
||||
@@ -290,7 +306,7 @@ class CustomFieldsController extends Controller
|
||||
$field->fieldset()->sync([]);
|
||||
}
|
||||
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/message.field.update.success'));
|
||||
return redirect()->route('fields.index', ['tab' => $request->get('tab', 0)])->with('success', trans('admin/custom_fields/message.field.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.update.error'));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
@@ -38,7 +39,7 @@ class CustomFieldsetsController extends Controller
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show($id)
|
||||
public function show( $id)
|
||||
{
|
||||
$cfset = CustomFieldset::with('fields')
|
||||
->where('id', '=', $id)->orderBy('id', 'ASC')->first();
|
||||
@@ -46,7 +47,7 @@ class CustomFieldsetsController extends Controller
|
||||
$this->authorize('view', $cfset);
|
||||
|
||||
if ($cfset) {
|
||||
$custom_fields_list = ['' => 'Add New Field to Fieldset'] + CustomField::pluck('name', 'id')->toArray();
|
||||
$custom_fields_list = ['' => 'Add New Field to Fieldset'] + CustomField::where('type', $cfset->type)->pluck('name', 'id')->toArray();
|
||||
|
||||
$maxid = 0;
|
||||
foreach ($cfset->fields as $field) {
|
||||
@@ -96,6 +97,8 @@ class CustomFieldsetsController extends Controller
|
||||
$fieldset = new CustomFieldset([
|
||||
'name' => $request->get('name'),
|
||||
'user_id' => Auth::user()->id,
|
||||
'type' => Helper::$itemtypes_having_custom_fields[$request->get('tab')]
|
||||
// 'sub' =>
|
||||
]);
|
||||
|
||||
$validator = Validator::make($request->all(), $fieldset->rules);
|
||||
|
||||
@@ -130,6 +130,9 @@ class UsersController extends Controller
|
||||
// we have to invoke the
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
\Log::info("About to call customFill, in the 'store' controller!!!");
|
||||
$user->customFill($request, Auth::user());
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
@@ -321,7 +324,31 @@ class UsersController extends Controller
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
if (!Auth::user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
$permissions_array['superuser'] = $orig_superuser;
|
||||
}
|
||||
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
// Handle uploaded avatar
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
\Log::debug("calling custom fill from the UPDATE method!");
|
||||
$user->customFill($request, Auth::user());
|
||||
//\Log::debug(print_r($user, true));
|
||||
|
||||
// Was the user updated?
|
||||
if ($user->save()) {
|
||||
// Redirect to the user page
|
||||
return redirect()->route('users.index')
|
||||
->with('success', trans('admin/users/message.success.update'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\DefaultValuesForCustomFields;
|
||||
use Livewire\Component;
|
||||
|
||||
use App\Models\CustomFieldset;
|
||||
@@ -30,7 +32,7 @@ class CustomFieldSetDefaultValuesForModel extends Component
|
||||
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
|
||||
}
|
||||
|
||||
$this->add_default_values = ($this->model->defaultValues->count() > 0);
|
||||
$this->add_default_values = (DefaultValuesForCustomFields::forPivot($this->model, Asset::class)->count() > 0);
|
||||
}
|
||||
|
||||
public function updatedFieldsetId()
|
||||
|
||||
@@ -109,7 +109,7 @@ class Importer extends Component
|
||||
if ($type == "asset") {
|
||||
// add Custom Fields after a horizontal line
|
||||
$results['-'] = "———" . trans('admin/custom_fields/general.custom_fields') . "———’";
|
||||
foreach (CustomField::orderBy('name')->get() as $field) {
|
||||
foreach (CustomField::where('type', \App\Models\Asset::class)->orderBy('name')->get() as $field) { // TODO - generalize?
|
||||
$results[$field->db_column_name()] = $field->name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,12 +34,14 @@ class CustomFieldRequest extends FormRequest
|
||||
case 'POST':
|
||||
{
|
||||
$rules['name'] = 'required|unique:custom_fields';
|
||||
$rules['tab'] = 'required';
|
||||
break;
|
||||
}
|
||||
|
||||
// Save all fields
|
||||
case 'PUT':
|
||||
$rules['name'] = 'required';
|
||||
$rules['tab'] = 'required';
|
||||
break;
|
||||
|
||||
// Save only what's passed
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\CustomFieldHelper;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
@@ -99,49 +100,7 @@ class AssetsTransformer
|
||||
];
|
||||
|
||||
|
||||
if (($asset->model) && ($asset->model->fieldset) && ($asset->model->fieldset->fields->count() > 0)) {
|
||||
$fields_array = [];
|
||||
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
if ($field->isFieldDecryptable($asset->{$field->db_column})) {
|
||||
$decrypted = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||
$value = (Gate::allows('assets.view.encrypted_custom_fields')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
|
||||
if ($field->format == 'DATE'){
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')){
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
} else {
|
||||
$value = strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
}
|
||||
}
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => e($field->db_column),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
'element' => $field->element,
|
||||
];
|
||||
|
||||
} else {
|
||||
$value = $asset->{$field->db_column};
|
||||
|
||||
if (($field->format == 'DATE') && (!is_null($value)) && ($value!='')){
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
}
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => e($field->db_column),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
'element' => $field->element,
|
||||
];
|
||||
}
|
||||
|
||||
$array['custom_fields'] = $fields_array;
|
||||
}
|
||||
} else {
|
||||
$array['custom_fields'] = new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||
}
|
||||
$array['custom_fields'] = CustomFieldHelper::transform($asset->model->fieldset,$asset);
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'checkout' => ($asset->deleted_at=='' && Gate::allows('checkout', Asset::class)) ? true : false,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\CustomFieldset;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
@@ -21,8 +23,13 @@ class CustomFieldsetsTransformer
|
||||
public function transformCustomFieldset(CustomFieldset $fieldset)
|
||||
{
|
||||
$fields = $fieldset->fields;
|
||||
$models = $fieldset->models;
|
||||
$models = [];
|
||||
$modelsArray = [];
|
||||
if ($fieldset->type == Asset::class) {
|
||||
\Log::debug("Item pivot id is: ".$fieldset->item_pivot_id);
|
||||
$models = AssetModel::where('fieldset_id', $fieldset->id)->get();
|
||||
\Log::debug("And the models object count is: ".$models->count());
|
||||
}
|
||||
|
||||
foreach ($models as $model) {
|
||||
$modelsArray[] = [
|
||||
@@ -30,15 +37,21 @@ class CustomFieldsetsTransformer
|
||||
'name' => e($model->name),
|
||||
];
|
||||
}
|
||||
\Log::debug("Models array is: ".print_r($modelsArray,true));
|
||||
|
||||
$array = [
|
||||
'id' => (int) $fieldset->id,
|
||||
'name' => e($fieldset->name),
|
||||
'fields' => (new CustomFieldsTransformer)->transformCustomFields($fields, $fieldset->fields_count),
|
||||
'models' => (new DatatablesTransformer)->transformDatatables($modelsArray, $fieldset->models_count),
|
||||
'customizables' => (new DatatablesTransformer)->transformDatatables($fieldset->customizables(),count($fieldset->customizables())),
|
||||
'created_at' => Helper::getFormattedDateObject($fieldset->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($fieldset->updated_at, 'datetime'),
|
||||
'type' => $fieldset->type,
|
||||
];
|
||||
if ($fieldset->type == Asset::class) {
|
||||
// TODO - removeme - legacy column just for Assets?
|
||||
$array['models'] = (new DatatablesTransformer)->transformDatatables($modelsArray, count($modelsArray));
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\CustomFieldHelper;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
@@ -80,6 +83,8 @@ class UsersTransformer
|
||||
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
|
||||
];
|
||||
|
||||
$array['custom_fields'] = CustomFieldHelper::transform(CustomFieldset::where('type',User::class)->first(), $user);
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => (Gate::allows('update', User::class) && ($user->deleted_at == '')),
|
||||
'delete' => $user->isDeletable(),
|
||||
|
||||
@@ -28,9 +28,10 @@ class AssetImporter extends ItemImporter
|
||||
// ItemImporter handles the general fetching.
|
||||
parent::handle($row);
|
||||
|
||||
// FIXME : YUP!!!!! This shit needs to go (?) Yeah?
|
||||
if ($this->customFields) {
|
||||
foreach ($this->customFields as $customField) {
|
||||
$customFieldValue = $this->array_smart_custom_field_fetch($row, $customField);
|
||||
$customFieldValue = $this->array_smart_custom_field_fetch($row, $customField); // TODO/FIXME - this might require a new 'mode' on customFill()?
|
||||
|
||||
if ($customFieldValue) {
|
||||
if ($customField->field_encrypted == 1) {
|
||||
@@ -40,7 +41,7 @@ class AssetImporter extends ItemImporter
|
||||
$this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue;
|
||||
$this->log('Custom Field '.$customField->name.': '.$customFieldValue);
|
||||
}
|
||||
} else {
|
||||
} else { // FIXME - think this through? Do we want to blank this? Is that how other stuff works?
|
||||
// Clear out previous data.
|
||||
$this->item['custom_fields'][$customField->db_column_name()] = null;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ abstract class Importer
|
||||
* @author Daniel Meltzer
|
||||
* @since 5.0
|
||||
*/
|
||||
protected function populateCustomFields($headerRow)
|
||||
protected function populateCustomFields($headerRow) // FIXME - what in the actual fuck is this.
|
||||
{
|
||||
// Stolen From https://adamwathan.me/2016/07/14/customizing-keys-when-mapping-collections/
|
||||
// This 'inverts' the fields such that we have a collection of fields indexed by name.
|
||||
|
||||
@@ -8,6 +8,8 @@ use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Customizable;
|
||||
use App\Models\Traits\HasCustomFields;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use AssetPresenter;
|
||||
@@ -17,6 +19,7 @@ use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
@@ -37,8 +40,21 @@ class Asset extends Depreciable
|
||||
public const ASSET = 'asset';
|
||||
public const USER = 'user';
|
||||
|
||||
use Acceptable;
|
||||
use Acceptable, HasCustomFields;
|
||||
|
||||
public function getFieldsetKey(): object|int|null
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
public static function getFieldsetUsers(int $fieldset_id): array
|
||||
{
|
||||
$models = [];
|
||||
foreach (AssetModel::where("fieldset_id", $fieldset_id)->get() as $model) {
|
||||
$models[route('models.show', $model->id)] = $model->name . (($model->model_number) ? ' (' . $model->model_number . ')' : '');
|
||||
}
|
||||
return $models;
|
||||
}
|
||||
/**
|
||||
* Run after the checkout acceptance was declined by the user
|
||||
*
|
||||
@@ -201,40 +217,6 @@ class Asset extends Depreciable
|
||||
$this->attributes['expected_checkin'] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles the custom field validation for assets
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public function save(array $params = [])
|
||||
{
|
||||
if ($this->model_id != '') {
|
||||
$model = AssetModel::find($this->model_id);
|
||||
|
||||
if (($model) && ($model->fieldset)) {
|
||||
|
||||
foreach ($model->fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
||||
$this->rules += $model->fieldset->validation_rules();
|
||||
|
||||
if ($this->model->fieldset){
|
||||
foreach ($this->model->fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::save($params);
|
||||
}
|
||||
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->present()->name();
|
||||
|
||||
@@ -142,6 +142,7 @@ class AssetModel extends SnipeModel
|
||||
*/
|
||||
public function fieldset()
|
||||
{
|
||||
// this is actually OK - we don't *need* to do this, but it's okay to make references from Model to fieldset
|
||||
return $this->belongsTo(\App\Models\CustomFieldset::class, 'fieldset_id');
|
||||
}
|
||||
|
||||
@@ -150,18 +151,6 @@ class AssetModel extends SnipeModel
|
||||
return $this->fieldset()->first()->fields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the model -> custom field default values relationship
|
||||
*
|
||||
* @author hannah tinkler
|
||||
* @since [v4.3]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function defaultValues()
|
||||
{
|
||||
return $this->belongsToMany(\App\Models\CustomField::class, 'models_custom_fields')->withPivot('default_value');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full url for the image
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ class CustomField extends Model
|
||||
UniqueUndeletedTrait;
|
||||
|
||||
/**
|
||||
* Custom field predfined formats
|
||||
* Custom field predefined formats
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@@ -82,30 +82,19 @@ class CustomField extends Model
|
||||
'show_in_requestable_list',
|
||||
];
|
||||
|
||||
/**
|
||||
* This is confusing, since it's actually the custom fields table that
|
||||
* we're usually modifying, but since we alter the assets table, we have to
|
||||
* say that here, otherwise the new fields get added onto the custom fields
|
||||
* table instead of the assets table.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public static $table_name = 'assets';
|
||||
|
||||
/**
|
||||
* Convert the custom field's name property to a db-safe string.
|
||||
*
|
||||
* We could probably have used str_slug() here but not sure what it would
|
||||
* do with previously existing values. - @snipe
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.4]
|
||||
* @return string
|
||||
* @since [v3.4]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public static function name_to_db_name($name)
|
||||
{
|
||||
return '_snipeit_'.preg_replace('/[^a-zA-Z0-9]/', '_', strtolower($name));
|
||||
return '_snipeit_' . preg_replace('/[^a-zA-Z0-9]/', '_', strtolower($name));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,23 +105,22 @@ class CustomField extends Model
|
||||
* if they have changed, so we handle that here so that we don't have to remember
|
||||
* to do it in the controllers.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.4]
|
||||
* @return bool
|
||||
* @since [v3.4]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
self::created(function ($custom_field) {
|
||||
|
||||
// Column already exists on the assets table - nothing to do here.
|
||||
// This *shouldn't* happen in the wild.
|
||||
if (Schema::hasColumn(self::$table_name, $custom_field->db_column)) {
|
||||
if (Schema::hasColumn($custom_field->getTableName(), $custom_field->db_column)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the column name in the assets table
|
||||
Schema::table(self::$table_name, function ($table) use ($custom_field) {
|
||||
Schema::table($custom_field->getTableName(), function ($table) use ($custom_field) {
|
||||
$table->text($custom_field->convertUnicodeDbSlug())->nullable();
|
||||
});
|
||||
|
||||
@@ -145,7 +133,7 @@ class CustomField extends Model
|
||||
|
||||
// Column already exists on the assets table - nothing to do here.
|
||||
if ($custom_field->isDirty('name')) {
|
||||
if (Schema::hasColumn(self::$table_name, $custom_field->convertUnicodeDbSlug())) {
|
||||
if (Schema::hasColumn($custom_field->getTableName(), $custom_field->convertUnicodeDbSlug())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -155,7 +143,7 @@ class CustomField extends Model
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
// Rename the field if the name has changed
|
||||
Schema::table(self::$table_name, function ($table) use ($custom_field) {
|
||||
Schema::table($custom_field->getTableName(), function ($table) use ($custom_field) {
|
||||
$table->renameColumn($custom_field->convertUnicodeDbSlug($custom_field->getOriginal('name')), $custom_field->convertUnicodeDbSlug());
|
||||
});
|
||||
|
||||
@@ -171,12 +159,19 @@ class CustomField extends Model
|
||||
|
||||
// Drop the assets column if we've deleted it from custom fields
|
||||
self::deleting(function ($custom_field) {
|
||||
return Schema::table(self::$table_name, function ($table) use ($custom_field) {
|
||||
return Schema::table($custom_field->getTableName(), function ($table) use ($custom_field) {
|
||||
$table->dropColumn($custom_field->db_column);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function getTableName()
|
||||
{
|
||||
$type = $this->type;
|
||||
$instance = new $type();
|
||||
return $instance->getTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the customfield -> fieldset relationship
|
||||
*
|
||||
@@ -207,31 +202,23 @@ class CustomField extends Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the customfield -> default values relationship
|
||||
*
|
||||
* @author Hannah Tinkler
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function defaultValues()
|
||||
{
|
||||
return $this->belongsToMany(\App\Models\AssetModel::class, 'models_custom_fields')->withPivot('default_value');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value for a given model using the defaultValues
|
||||
* Returns the default value for a given 'item' using the defaultValues
|
||||
* relationship
|
||||
*
|
||||
* @param int $modelId
|
||||
* @return string
|
||||
*/
|
||||
public function defaultValue($modelId)
|
||||
public function defaultValue($pivot_id)
|
||||
{
|
||||
return $this->defaultValues->filter(function ($item) use ($modelId) {
|
||||
return $item->pivot->asset_model_id == $modelId;
|
||||
})->map(function ($item) {
|
||||
return $item->pivot->default_value;
|
||||
})->first();
|
||||
/*
|
||||
below, you might think you need to add:
|
||||
|
||||
where('type', $this->type),
|
||||
|
||||
but the type can be inferred from by the custom_field itself (which also has a type)
|
||||
can't use forPivot() here because we don't have an object yet. (TODO?)
|
||||
*/
|
||||
DefaultValuesForCustomFields::where('item_pivot_id', $pivot_id)->where('custom_field_id', $this->id)->first()?->default_value; //TODO - php8-only operator!
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@ class CustomFieldset extends Model
|
||||
*/
|
||||
public $rules = [
|
||||
'name' => 'required|unique:custom_fieldsets',
|
||||
''
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -50,11 +51,13 @@ class CustomFieldset extends Model
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function models()
|
||||
public function customizables() // TODO - I don't like this name, but I can't think of anything better
|
||||
{
|
||||
return $this->hasMany(\App\Models\AssetModel::class, 'fieldset_id');
|
||||
$customizable_class_name = $this->type; //TODO - copypasta from Customizable trait?
|
||||
\Log::debug("Customizable Class name is: ".$customizable_class_name);
|
||||
return $customizable_class_name::getFieldsetUsers($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,6 +82,7 @@ class CustomFieldset extends Model
|
||||
*/
|
||||
public function validation_rules()
|
||||
{
|
||||
\Log::debug("CALLING validation_rules FOR customfiledsets!");
|
||||
$rules = [];
|
||||
foreach ($this->fields as $field) {
|
||||
$rule = [];
|
||||
@@ -92,7 +96,12 @@ class CustomFieldset extends Model
|
||||
$rule[] = 'unique_undeleted';
|
||||
}
|
||||
|
||||
array_push($rule, $field->attributes['format']);
|
||||
\Log::debug("Field Format for".$field->name." is: ".$field->format);
|
||||
if($field->format == 'DATE') { //we do a weird mutator thing, it's confusing - but, yes, it's all-caps
|
||||
$rule[] = 'date_format:Y-m-d';
|
||||
} else {
|
||||
array_push($rule, $field->attributes['format']);
|
||||
}
|
||||
$rules[$field->db_column_name()] = $rule;
|
||||
|
||||
// add not_array to rules for all fields but checkboxes
|
||||
|
||||
34
app/Models/DefaultValuesForCustomFields.php
Normal file
34
app/Models/DefaultValuesForCustomFields.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class DefaultValuesForCustomFields extends Model
|
||||
{
|
||||
use HasFactory, ValidatingTrait;
|
||||
|
||||
protected $rules = [
|
||||
'type' => 'required'
|
||||
];
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
public function field() {
|
||||
return $this->belongsTo('custom_fields');
|
||||
}
|
||||
|
||||
// There is, effectively, another 'relation' here, but it's weirdly polymorphic
|
||||
// and impossible to represent in Laravel.
|
||||
// we have a 'type', and we have an 'item_pivot_id' -
|
||||
// For example, in Assets the 'type' would be App\Models\Asset, and the 'item_pivot_id' would be a model_id
|
||||
// I can't come up with any way to represent this in Laravel/Eloquent
|
||||
|
||||
// TODO: might be getting overly-fancy here; maybe just want to do an ID? Instead of an Eloquent Model?
|
||||
public function scopeForPivot(Builder $query, Model $item, string $class) {
|
||||
return $query->where('item_pivot_id', $item->id)->where('type', $class);
|
||||
}
|
||||
}
|
||||
150
app/Models/Traits/HasCustomFields.php
Normal file
150
app/Models/Traits/HasCustomFields.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Traits;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use App\Models\DefaultValuesForCustomFields;
|
||||
|
||||
/*********************************
|
||||
* Trait HasCustomFields
|
||||
* @package App\Models\Traits
|
||||
*
|
||||
* How to use: declare a PHP function getFieldset that will return your fieldset (not the ID, the actual set)
|
||||
*
|
||||
*/
|
||||
|
||||
trait HasCustomFields
|
||||
{
|
||||
protected static function bootHasCustomFields()
|
||||
{
|
||||
// https://tech.chrishardie.com/2022/define-fire-listen-custom-laravel-model-events-trait/
|
||||
|
||||
static::registerModelEvent('validating', function ($model, $event) {
|
||||
// \Log::error("Uh, something happened? Something good, maybe?");
|
||||
// \Log::error("model: $model, event: $event");
|
||||
// \Log::error("WHATS MY NAME? " . HasCustomFields::class);
|
||||
// dump(class_uses_recursive($model));
|
||||
if (in_array(HasCustomFields::class, class_uses_recursive($model))) {
|
||||
\Log::error("!!!!!!!!!!!!! YOU ARE USING THE TRAIT!");
|
||||
self::augmentValidationRulesForCustomFields($model);
|
||||
} else {
|
||||
\Log::error("You aren't useing the trait so go away");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/***************
|
||||
* @return CustomFieldset|null
|
||||
*
|
||||
* This function by default will use the "getFieldsetKey()" method to
|
||||
* return the customFieldset (or null) for this particular item. If
|
||||
* necessary, you can override this method if your getFieldsetKey()
|
||||
* cannot respond to `->fieldset` or `->id`.
|
||||
*/
|
||||
public function getFieldset(): ?CustomFieldset {
|
||||
$pivot = $this->getFieldsetKey();
|
||||
if(is_int($pivot)) { //why does this look just like the other thing? (below, look for is_int()
|
||||
return CustomFieldset::find($pivot);
|
||||
}
|
||||
return $pivot?->fieldset; //this is bonkers, why is this even firing?!
|
||||
}
|
||||
|
||||
/**********************
|
||||
* @return Object|int|null
|
||||
* (if this is in PHP 8.0, can we just put that as the signature?)
|
||||
*
|
||||
* This is the main method you have to override. It should either return an
|
||||
* Object who you can call `->fieldset` on and get a fieldset object, and also
|
||||
* be able to call `->id` on to get a unique key to be able to show custom fields.
|
||||
* For example, for Assets, the element that is returned is the 'model' for the Asset.
|
||||
* For something like Users, which will probably have only one universal set of custom fields,
|
||||
* it should just return the Fieldset ID for it. Or, if there are no custom fields, it should
|
||||
* return null
|
||||
*/
|
||||
abstract public function getFieldsetKey(): Object|int|null; // php v8 minimum, GOOD. TODO
|
||||
|
||||
/***********************
|
||||
* @param int $fieldset_id
|
||||
* @return Collection
|
||||
*
|
||||
* This is the main method you need to override to return a list of things that are *using* this fieldset
|
||||
* The format is an array with keys: a URL, and values. So, for assets, it might return
|
||||
* {
|
||||
* "models/14" => "MacBook Pro 13 (model no: 12345)"
|
||||
* }
|
||||
*/
|
||||
abstract public static function getFieldsetUsers(int $fieldset_id): array;
|
||||
|
||||
public static function augmentValidationRulesForCustomFields($model) {
|
||||
\Log::debug("Augmenting validation rules for custom fields!!!!!!");
|
||||
$fieldset = $model->getFieldset();
|
||||
if ($fieldset) {
|
||||
foreach ($fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){ // TODO - this 'feels' like entanglement of concerns?
|
||||
$model->{$field->db_column} = filter_var($model->{$model->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$model->rules) {
|
||||
$model->rules = [];
|
||||
}
|
||||
$model->rules += $model->getFieldset()->validation_rules();
|
||||
\Log::debug("FINAL RULES ARE: ".print_r($model->rules,true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function getDefaultValue(CustomField $field)
|
||||
{
|
||||
$pivot = $this->getFieldsetKey(); // TODO - feels copypasta-ish?
|
||||
$key_id = null;
|
||||
|
||||
if( is_int($pivot) ) { // TODO: *WHY* does this code repeat?!
|
||||
$key_id = $pivot; // now we're done
|
||||
} elseif( is_object($pivot) ) {
|
||||
$key_id = $pivot?->id;
|
||||
}
|
||||
if(is_null($key_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO - begninng to think my custom scope really should be just an integer :/
|
||||
return DefaultValuesForCustomFields::where('type',self::class)
|
||||
->where('custom_field_id',$field->id)
|
||||
->where('item_pivot_id',$key_id)->first()?->default_value;
|
||||
}
|
||||
|
||||
public function customFill(Request $request, User $user, bool $shouldSetDefaults = false) {
|
||||
$success = true;
|
||||
if ($this->getFieldset()) {
|
||||
foreach ($this->getFieldset()->fields as $field) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$field_value = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$field_value = $request->input($field->db_column);
|
||||
}
|
||||
|
||||
if ($shouldSetDefaults && (is_null($field_value) || $field_value === '')) {
|
||||
$field_value = $this->getDefaultValue($field);
|
||||
}
|
||||
if ($field->field_encrypted == '1') {
|
||||
if ($user->can('admin')) {
|
||||
$this->{$field->db_column} = Crypt::encrypt($field_value);
|
||||
} else {
|
||||
$success = false;
|
||||
continue; //may not be necessary? I'm not sure. I like the other way of doing this TODO
|
||||
}
|
||||
} else {
|
||||
$this->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\HasCustomFields;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -32,6 +33,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
use Notifiable;
|
||||
use Presentable;
|
||||
use Searchable;
|
||||
use HasCustomFields;
|
||||
|
||||
protected $hidden = ['password', 'remember_token', 'permissions', 'reset_password_code', 'persist_code'];
|
||||
protected $table = 'users';
|
||||
@@ -137,6 +139,20 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'manager' => ['first_name', 'last_name', 'username'],
|
||||
];
|
||||
|
||||
public function getFieldsetKey(): object|int|null
|
||||
{
|
||||
// TODO/FIXME - that's hardcoded text, but what language should you use?! I don't know.
|
||||
// also TODO - is this going to beat on the DB too hard?
|
||||
return CustomFieldset::where('type', User::class)->first()?->id;
|
||||
}
|
||||
|
||||
public static function getFieldsetUsers(int $fieldset_id): array
|
||||
{
|
||||
return [
|
||||
'no_idea_what_id_to_put' => 'No idea what string to put?' // FIXME obvs.
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internally check the user permission for the given section
|
||||
*
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use App\Helpers\CustomFieldHelper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use Carbon\CarbonImmutable;
|
||||
use App\Models\CustomFieldset;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
@@ -299,25 +302,21 @@ class AssetPresenter extends Presenter
|
||||
// models. We only pass the fieldsets that pertain to each asset (via their model) so that we
|
||||
// don't junk up the REST API with tons of custom fields that don't apply
|
||||
|
||||
$fields = CustomField::whereHas('fieldset', function ($query) {
|
||||
$query->whereHas('models');
|
||||
})->get();
|
||||
//only get fieldsets that have fields
|
||||
$fieldsets = CustomFieldset::where("type", Asset::class)->whereHas('fields')->get();
|
||||
$ids = [];
|
||||
foreach($fieldsets as $fieldset) {
|
||||
if (count($fieldset->customizables()) > 0) { //only get fieldsets that are 'in use'
|
||||
$ids[] = $fieldset->id;
|
||||
}
|
||||
}
|
||||
|
||||
$fields = CustomField::whereIn('id',$ids)->get(); // FIXME: d'oh! this is wrong. We just got fieldsets, above. Now we're getting fields?
|
||||
// Note: We do not need to e() escape the field names here, as they are already escaped when
|
||||
// they are presented in the blade view. If we escape them here, custom fields with quotes in their
|
||||
// name can break the listings page. - snipe
|
||||
foreach ($fields as $field) {
|
||||
$layout[] = [
|
||||
'field' => 'custom_fields.'.$field->db_column,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => $field->name,
|
||||
'formatter'=> 'customFieldsFormatter',
|
||||
'escape' => true,
|
||||
'class' => ($field->field_encrypted == '1') ? 'css-padlock' : '',
|
||||
'visible' => ($field->show_in_listview == '1') ? true : false,
|
||||
];
|
||||
$layout[] = CustomFieldHelper::present($field);
|
||||
}
|
||||
|
||||
$layout[] = [
|
||||
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use App\Helpers\CustomFieldHelper;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -386,6 +392,30 @@ class UserPresenter extends Presenter
|
||||
],
|
||||
];
|
||||
|
||||
// TODO - FIXME - this is all copy-pasta'ed from the AssetPresenter! <start>
|
||||
//only get fieldsets that have fields
|
||||
$fieldsets = CustomFieldset::where("type", User::class)->whereHas('fields')->get();
|
||||
$ids = [];
|
||||
foreach($fieldsets as $fieldset) {
|
||||
if (count($fieldset->customizables()) > 0) { //only get fieldsets that are 'in use'
|
||||
\Log::debug("Found a fieldset! It's: ".$fieldset->id);
|
||||
$ids[] = $fieldset->id;
|
||||
} else {
|
||||
\Log::debug("Didn't find fieldset: ".$fieldset->id);
|
||||
}
|
||||
}
|
||||
|
||||
$fields = CustomField::whereHas('fieldset', function (Builder $query) use($ids) {
|
||||
$query->whereIn('custom_fieldsets.id', $ids);
|
||||
})->get();
|
||||
// Note: We do not need to e() escape the field names here, as they are already escaped when
|
||||
// they are presented in the blade view. If we escape them here, custom fields with quotes in their
|
||||
// name can break the listings page. - snipe
|
||||
foreach ($fields as $field) {
|
||||
\Log::debug("iterating through fields!");
|
||||
$layout[] = CustomFieldHelper::present($field);
|
||||
}
|
||||
|
||||
return json_encode($layout);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ class AuthServiceProvider extends ServiceProvider
|
||||
]);
|
||||
|
||||
$this->registerPolicies();
|
||||
//Passport::routes(); //this is no longer required in newer passport versions
|
||||
Passport::tokensExpireIn(Carbon::now()->addYears(config('passport.expiration_years')));
|
||||
Passport::refreshTokensExpireIn(Carbon::now()->addYears(config('passport.expiration_years')));
|
||||
Passport::personalAccessTokensExpireIn(Carbon::now()->addYears(config('passport.expiration_years')));
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DO NOT EDIT THIS FILE DIRECTLY.
|
||||
@@ -57,6 +59,9 @@ return [
|
||||
*
|
||||
* @link https://symfony.com/doc/current/deployment/proxies.html
|
||||
*/
|
||||
// 'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL, //this is mostly handled already
|
||||
|
||||
'headers' => Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB,
|
||||
];
|
||||
|
||||
@@ -387,4 +387,15 @@ class AssetFactory extends Factory
|
||||
$asset->setValidating(true);
|
||||
});
|
||||
}
|
||||
|
||||
public function withComplicatedCustomFields()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'model_id' => function () {
|
||||
return AssetModel::where('name', 'complicated')->first() ?? AssetModel::factory()->complicated();
|
||||
}
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,4 +448,13 @@ class AssetModelFactory extends Factory
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function complicated()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'Complicated fieldset'
|
||||
];
|
||||
})->for(CustomFieldSet::factory()->complicated(), 'fieldset');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ class CustomFieldFactory extends Factory
|
||||
'element' => 'text',
|
||||
'auto_add_to_fieldsets' => '0',
|
||||
'show_in_requestable_list' => '0',
|
||||
'type' => 'App\\Models\\Asset'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ class CustomFieldFactory extends Factory
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'MAC Address',
|
||||
'name' => 'MAC Address EXPLICIT',
|
||||
'format' => 'regex:/^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/',
|
||||
];
|
||||
});
|
||||
@@ -93,6 +94,15 @@ class CustomFieldFactory extends Factory
|
||||
});
|
||||
}
|
||||
|
||||
public function plainText()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'plain_text',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function testCheckbox()
|
||||
{
|
||||
return $this->state(function () {
|
||||
@@ -117,4 +127,13 @@ class CustomFieldFactory extends Factory
|
||||
});
|
||||
}
|
||||
|
||||
public function date()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'date',
|
||||
'format' => 'date'
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class CustomFieldsetFactory extends Factory
|
||||
@@ -58,13 +58,13 @@ class CustomFieldsetFactory extends Factory
|
||||
{
|
||||
return $this->afterCreating(function (CustomFieldset $fieldset) use ($fields) {
|
||||
if (empty($fields)) {
|
||||
$mac_address = CustomField::factory()->macAddress()->create();
|
||||
$ram = CustomField::factory()->ram()->create();
|
||||
$cpu = CustomField::factory()->cpu()->create();
|
||||
$mac_address = CustomField::factory()->macAddress()->create();
|
||||
$ram = CustomField::factory()->ram()->create();
|
||||
$cpu = CustomField::factory()->cpu()->create();
|
||||
|
||||
$fieldset->fields()->attach($mac_address, ['order' => '1', 'required' => false]);
|
||||
$fieldset->fields()->attach($ram, ['order' => '2', 'required' => false]);
|
||||
$fieldset->fields()->attach($cpu, ['order' => '3', 'required' => false]);
|
||||
$fieldset->fields()->attach($mac_address, ['order' => '1', 'required' => false]);
|
||||
$fieldset->fields()->attach($ram, ['order' => '2', 'required' => false]);
|
||||
$fieldset->fields()->attach($cpu, ['order' => '3', 'required' => false]);
|
||||
} else {
|
||||
foreach ($fields as $field) {
|
||||
$fieldset->fields()->attach($field, ['order' => '1', 'required' => false]);
|
||||
@@ -72,4 +72,16 @@ class CustomFieldsetFactory extends Factory
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function complicated()
|
||||
{
|
||||
//$mac = CustomField::factory()->macAddress()->create();
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'complicated'
|
||||
];
|
||||
})->hasAttached(CustomField::factory()->macAddress(), ['required' => false, 'order' => 0], 'fields')
|
||||
->hasAttached(CustomField::factory()->plainText(), ['required' => true, 'order' => 1], 'fields')
|
||||
->hasAttached(CustomField::factory()->date(), ['required' => false, 'order' => 2], 'fields');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ function updateLegacyColumnName($customfield)
|
||||
$name_to_db_name = CustomField::name_to_db_name($customfield->name);
|
||||
//\Log::debug('Trying to rename '.$name_to_db_name." to ".$customfield->convertUnicodeDbSlug()."...\n");
|
||||
|
||||
if (Schema::hasColumn(CustomField::$table_name, $name_to_db_name)) {
|
||||
return Schema::table(CustomField::$table_name,
|
||||
if (Schema::hasColumn('assets', $name_to_db_name)) {
|
||||
return Schema::table('assets',
|
||||
function ($table) use ($name_to_db_name, $customfield) {
|
||||
$table->renameColumn($name_to_db_name, $customfield->convertUnicodeDbSlug());
|
||||
}
|
||||
@@ -81,8 +81,8 @@ class FixUtf8CustomFieldColumnNames extends Migration
|
||||
// "_snipeit_imei_1" becomes "_snipeit_imei"
|
||||
$legacyColumnName = (string) Str::of($currentColumnName)->replaceMatches('/_(\d)+$/', '');
|
||||
|
||||
if (Schema::hasColumn(CustomField::$table_name, $currentColumnName)) {
|
||||
Schema::table(CustomField::$table_name, function (Blueprint $table) use ($currentColumnName, $legacyColumnName) {
|
||||
if (Schema::hasColumn('assets', $currentColumnName)) {
|
||||
Schema::table('assets', function (Blueprint $table) use ($currentColumnName, $legacyColumnName) {
|
||||
$table->renameColumn(
|
||||
$currentColumnName,
|
||||
$legacyColumnName
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Asset;
|
||||
|
||||
class AddTypeToCustomFields extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('custom_fields', function (Blueprint $table) {
|
||||
//
|
||||
$table->text('type')->default('App\\Models\\Asset'); // TODO this default is needed for a not-nullable column, I guess? I don't like this because it will silently 'fix' errors we should properly 'fix'
|
||||
});
|
||||
CustomField::query()->update(['type' => Asset::class]); // TODO - is this still necessary with that 'default'?
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('custom_fields', function (Blueprint $table) {
|
||||
//
|
||||
$table->dropColumn('type');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\Asset;
|
||||
|
||||
class AddTypeToCustomFieldsets extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('custom_fieldsets', function (Blueprint $table) {
|
||||
//
|
||||
$table->text('type')->default('App\\Models\\Asset');
|
||||
});
|
||||
CustomFieldset::query()->update(['type' => Asset::class]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('custom_fieldsets', function (Blueprint $table) {
|
||||
//
|
||||
$table->dropColumn('type');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class GeneralizeDefaultValuesForCustomFields extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::rename('models_custom_fields', 'default_values_for_custom_fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::rename('default_values_for_custom_fields', 'models_custom_fields');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\DefaultValuesForCustomFields;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTypeColumnToDefaultValuesForCustomFields extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('default_values_for_custom_fields', function (Blueprint $table) {
|
||||
$table->renameColumn('asset_model_id','item_pivot_id'); //this one works. okay. that's someting.
|
||||
});
|
||||
Schema::table('default_values_for_custom_fields', function (Blueprint $table) {
|
||||
$table->string('type')->nullable();
|
||||
});
|
||||
DefaultValuesForCustomFields::query()->update(['type' => Asset::class]);
|
||||
Schema::table('default_values_for_custom_fields', function (Blueprint $table) {
|
||||
//$table->renameColumn('asset_model_id','item_pivot_id'); //this one works. okay. that's someting.
|
||||
$table->string('type')->nullable(false)->change();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('default_values_for_custom_fields', function (Blueprint $table) {
|
||||
$table->dropColumn('type');
|
||||
$table->renameColumn('item_pivot_id','asset_model_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
@endif
|
||||
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="tab" value="{{ Request::query('tab') }}" />
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box box-default">
|
||||
@@ -151,12 +153,16 @@
|
||||
|
||||
|
||||
<!-- Auto-Add to Future Fieldsets -->
|
||||
<div class="form-group {{ $errors->has('auto_add_to_fieldsets') ? ' has-error' : '' }}"
|
||||
id="auto_add_to_fieldsets">
|
||||
@if (Request::query('tab') != 1)
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="auto_add_to_fieldsets" aria-label="auto_add_to_fieldsets" value="1"{{ (old('auto_add_to_fieldsets') || $field->auto_add_to_fieldsets) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.auto_add_to_fieldsets') }}
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Show in list view -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
@@ -208,7 +214,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
@if ($fieldsets->count() > 0)
|
||||
@if ($fieldsets->count() > 0 && Request::query('tab') != 1)
|
||||
<!-- begin fieldset columns -->
|
||||
<div class="col-md-4">
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
@section('inputFields')
|
||||
@include ('partials.forms.edit.name', ['translated_name' => trans('general.name')])
|
||||
<input type="hidden" name="tab" value="{{ Request::query('tab') }}" />
|
||||
@stop
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,29 @@
|
||||
@section('content')
|
||||
|
||||
@can('view', \App\Models\CustomFieldset::class)
|
||||
<div class="row">
|
||||
<div calss="col-md-12">
|
||||
<div class="box box-default">
|
||||
<div class="box-body">
|
||||
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs">
|
||||
{{-- TODO - generalize this so it's less 'hardcoded' --}}
|
||||
<li {!! !Request::query('tab') ? 'class="active"': '' !!}><a
|
||||
href="{{ route("fields.index",["tab" => 0]) }}">Asset Custom Fields</a></li>
|
||||
<li {!! Request::query('tab') == 1 ? 'class="active"': '' !!}><a
|
||||
href="{{ route("fields.index",["tab" => 1]) }}">Users</a></li>
|
||||
<li {!! Request::query('tab') == 2 ? 'class="active"': '' !!}><a
|
||||
href="{{ route("fields.index",["tab" => 2]) }}">Accessories</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Do not show fieldsets for Users' customf ields --}}
|
||||
@if(Request::query('tab') != 1)
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box box-default">
|
||||
@@ -21,7 +44,9 @@
|
||||
<h2 class="box-title">{{ trans('admin/custom_fields/general.fieldsets') }}</h2>
|
||||
<div class="box-tools pull-right">
|
||||
@can('create', \App\Models\CustomFieldset::class)
|
||||
<a href="{{ route('fieldsets.create') }}" class="btn btn-sm btn-primary" data-tooltip="true" title="{{ trans('admin/custom_fields/general.create_fieldset_title') }}">{{ trans('admin/custom_fields/general.create_fieldset') }}</a>
|
||||
<a href="{{ route('fieldsets.create',['tab' => Request::query('tab',0)]) }}" class="btn btn-sm btn-primary"
|
||||
data-tooltip="true"
|
||||
title="{{ trans('admin/custom_fields/general.create_fieldset_title') }}">{{ trans('admin/custom_fields/general.create_fieldset') }}</a>
|
||||
@endcan
|
||||
</div>
|
||||
</div><!-- /.box-header -->
|
||||
@@ -47,7 +72,7 @@
|
||||
<tr>
|
||||
<th>{{ trans('general.name') }}</th>
|
||||
<th>{{ trans('admin/custom_fields/general.qty_fields') }}</th>
|
||||
<th>{{ trans('admin/custom_fields/general.used_by_models') }}</th>
|
||||
<th>{{ trans('admin/custom_fields/general.used_by_models') }}{{-- FIXME --}}</th>
|
||||
<th>{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -63,9 +88,9 @@
|
||||
{{ $fieldset->fields->count() }}
|
||||
</td>
|
||||
<td>
|
||||
@foreach($fieldset->models as $model)
|
||||
<a href="{{ route('models.show', $model->id) }}" class="label label-default">{{ $model->name }}{{ ($model->model_number) ? ' ('.$model->model_number.')' : '' }}</a>
|
||||
|
||||
@foreach($fieldset->customizables() as $url => $name)
|
||||
<a href="{{ $url }}" class="label label-default">{{ $name }}</a>
|
||||
{{-- get_class($customizable) }}: {{ $customizable->name<br /> --}}
|
||||
@endforeach
|
||||
</td>
|
||||
<td>
|
||||
@@ -88,10 +113,13 @@
|
||||
|
||||
@can('delete', $fieldset)
|
||||
{{ Form::open(['route' => array('fieldsets.destroy', $fieldset->id), 'method' => 'delete','style' => 'display:inline-block']) }}
|
||||
@if($fieldset->models->count() > 0)
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" data-tooltip="true" title="{{ trans('general.cannot_be_deleted') }}" disabled><i class="fas fa-trash"></i></button>
|
||||
@if(count($fieldset->customizables()) > 0 /* TODO - hate 'customizables' */)
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" data-tooltip="true"
|
||||
title="{{ trans('general.cannot_be_deleted') }}" disabled><i class="fas fa-trash"></i>
|
||||
</button>
|
||||
@else
|
||||
<button type="submit" class="btn btn-danger btn-sm" data-tooltip="true" title="{{ trans('general.delete') }}"><i class="fas fa-trash"></i></button>
|
||||
<button type="submit" class="btn btn-danger btn-sm" data-tooltip="true"
|
||||
title="{{ trans('general.delete') }}"><i class="fas fa-trash"></i></button>
|
||||
@endif
|
||||
{{ Form::close() }}
|
||||
@endcan
|
||||
@@ -109,6 +137,7 @@
|
||||
|
||||
|
||||
</div> <!-- .row-->
|
||||
@endif
|
||||
@endcan
|
||||
@can('view', \App\Models\CustomField::class)
|
||||
<div class="row">
|
||||
@@ -118,7 +147,9 @@
|
||||
<h2 class="box-title">{{ trans('admin/custom_fields/general.custom_fields') }}</h2>
|
||||
<div class="box-tools pull-right">
|
||||
@can('create', \App\Models\CustomField::class)
|
||||
<a href="{{ route('fields.create') }}" class="btn btn-sm btn-primary" data-tooltip="true" title="{{ trans('admin/custom_fields/general.create_field_title') }}">{{ trans('admin/custom_fields/general.create_field') }}</a>
|
||||
<a href="{{ route('fields.create', ['tab' => Request::query('tab',0)]) }}" class="btn btn-sm btn-primary"
|
||||
data-tooltip="true"
|
||||
title="{{ trans('admin/custom_fields/general.create_field_title') }}">{{ trans('admin/custom_fields/general.create_field') }}</a>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
@@ -195,7 +226,8 @@
|
||||
<nobr>
|
||||
{{ Form::open(array('route' => array('fields.destroy', $field->id), 'method' => 'delete', 'style' => 'display:inline-block')) }}
|
||||
@can('update', $field)
|
||||
<a href="{{ route('fields.edit', $field->id) }}" class="btn btn-warning btn-sm" data-tooltip="true" title="{{ trans('general.update') }}">
|
||||
<a href="{{ route('fields.edit', $field->id) }}?tab={{ array_search($field->type, Helper::$itemtypes_having_custom_fields) }}"
|
||||
class="btn btn-warning btn-sm" data-tooltip="true" title="{{ trans('general.update') }}">
|
||||
<i class="fas fa-pencil-alt" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('button.edit') }}</span>
|
||||
</a>
|
||||
@@ -203,7 +235,7 @@
|
||||
|
||||
@can('delete', $field)
|
||||
|
||||
@if($field->fieldset->count()>0)
|
||||
@if($field->fieldset->count()>0 && Request::query('tab') != 1 )
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" data-tooltip="true" title="{{ trans('general.cannot_be_deleted') }}" disabled>
|
||||
<i class="fas fa-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('button.delete') }}</span></button>
|
||||
|
||||
@@ -75,20 +75,17 @@
|
||||
|
||||
<div id='custom_fields_content'>
|
||||
<!-- Custom Fields -->
|
||||
@if ($item->model && $item->model->fieldset)
|
||||
<?php $model = $item->model; ?>
|
||||
@endif
|
||||
@if (Request::old('model_id'))
|
||||
@php
|
||||
$model = \App\Models\AssetModel::find(old('model_id'));
|
||||
$item->model = \App\Models\AssetModel::find(old('model_id'));
|
||||
@endphp
|
||||
@elseif (isset($selected_model))
|
||||
@php
|
||||
$model = $selected_model;
|
||||
$item->model_id = $selected_model;
|
||||
@endphp
|
||||
@endif
|
||||
@if (isset($model) && $model)
|
||||
@include("models/custom_fields_form",["model" => $model])
|
||||
@if ($item->getFieldset())
|
||||
@include("models/custom_fields_form",["item" => $item])
|
||||
@endif
|
||||
</div>
|
||||
|
||||
|
||||
@@ -418,63 +418,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (($asset->model) && ($asset->model->fieldset))
|
||||
@foreach($asset->model->fieldset->fields as $field)
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<strong>
|
||||
{{ $field->name }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-6{{ (($field->format=='URL') && ($asset->{$field->db_column_name()}!='')) ? ' ellipsis': '' }}">
|
||||
@if (($field->field_encrypted=='1') && ($asset->{$field->db_column_name()}!=''))
|
||||
<i class="fas fa-lock" data-tooltip="true" data-placement="top" title="{{ trans('admin/custom_fields/general.value_encrypted') }}" onclick="showHideEncValue(this)" id="text-{{ $field->id }}"></i>
|
||||
@endif
|
||||
|
||||
@if ($field->isFieldDecryptable($asset->{$field->db_column_name()} ))
|
||||
@can('assets.view.encrypted_custom_fields')
|
||||
@php
|
||||
$fieldSize=strlen(Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}))
|
||||
@endphp
|
||||
@if ($fieldSize>0)
|
||||
<span id="text-{{ $field->id }}-to-hide">{{ str_repeat('*', $fieldSize) }}</span>
|
||||
<span class="js-copy-{{ $field->id }}" id="text-{{ $field->id }}-to-show" style="font-size: 0px;">
|
||||
@if (($field->format=='URL') && ($asset->{$field->db_column_name()}!=''))
|
||||
<a href="{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}" target="_new">{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}</a>
|
||||
@elseif (($field->format=='DATE') && ($asset->{$field->db_column_name()}!=''))
|
||||
{{ \App\Helpers\Helper::gracefulDecrypt($field, \App\Helpers\Helper::getFormattedDateObject($asset->{$field->db_column_name()}, 'date', false)) }}
|
||||
@else
|
||||
{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}
|
||||
@endif
|
||||
</span>
|
||||
<i class="fa-regular fa-clipboard js-copy-link" data-clipboard-target=".js-copy-{{ $field->id }}" aria-hidden="true" data-tooltip="true" data-placement="top" title="{{ trans('general.copy_to_clipboard') }}">
|
||||
<span class="sr-only">{{ trans('general.copy_to_clipboard') }}</span>
|
||||
</i>
|
||||
@endif
|
||||
@else
|
||||
{{ strtoupper(trans('admin/custom_fields/general.encrypted')) }}
|
||||
@endcan
|
||||
|
||||
@else
|
||||
@if (($field->format=='BOOLEAN') && ($asset->{$field->db_column_name()}!=''))
|
||||
{!! ($asset->{$field->db_column_name()} == 1) ? "<span class='fas fa-check-circle' style='color:green' />" : "<span class='fas fa-times-circle' style='color:red' />" !!}
|
||||
@elseif (($field->format=='URL') && ($asset->{$field->db_column_name()}!=''))
|
||||
<a href="{{ $asset->{$field->db_column_name()} }}" target="_new">{{ $asset->{$field->db_column_name()} }}</a>
|
||||
@elseif (($field->format=='DATE') && ($asset->{$field->db_column_name()}!=''))
|
||||
{{ \App\Helpers\Helper::getFormattedDateObject($asset->{$field->db_column_name()}, 'date', false) }}
|
||||
@else
|
||||
{!! nl2br(e($asset->{$field->db_column_name()})) !!}
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
@if ($asset->{$field->db_column_name()}=='')
|
||||
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
@include('partials.custom-fields-view', ['item' => $asset,'width' => 2])
|
||||
|
||||
|
||||
@if ($asset->purchase_date)
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
@if (($model) && ($model->fieldset))
|
||||
@foreach($model->fieldset->fields AS $field)
|
||||
{{--
|
||||
|
||||
Okay, now how am I going to work *this* out. I think it's less bad than I think.
|
||||
|
||||
I think we can pass the $asset or the $user to this partial.
|
||||
|
||||
This partial can be aware of the HasCustomFields trait, and call getFieldset() to get the appropriate fieldset; that's good.
|
||||
|
||||
But we also need the 'discriminator' so that we can use defaultValuesForCustomFields, right?
|
||||
|
||||
Well, that should be easy enough, right? Just call getFieldsetKey(), right? Or maybe we don't even have to do that -
|
||||
|
||||
We can call $item->getDefaultValue($field), right?
|
||||
|
||||
So the old way - already on this page - is:
|
||||
|
||||
$item->defaultValue($field))
|
||||
|
||||
And we just do a simple 'replace' to make it be:
|
||||
|
||||
$item->defaultValue($field)
|
||||
--}}
|
||||
|
||||
@if ($item->getFieldset())
|
||||
@foreach($item->getFieldset()->fields AS $field)
|
||||
<div class="form-group{{ $errors->has($field->db_column_name()) ? ' has-error' : '' }}">
|
||||
<label for="{{ $field->db_column_name() }}" class="col-md-3 control-label">{{ $field->name }} </label>
|
||||
<div class="col-md-7 col-sm-12{{ ($field->pivot->required=='1') ? ' required' : '' }}">
|
||||
@@ -12,14 +35,14 @@
|
||||
Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }}
|
||||
|
||||
@elseif ($field->element=='textarea')
|
||||
<textarea class="col-md-6 form-control" id="{{ $field->db_column_name() }}" name="{{ $field->db_column_name() }}">{{ Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))) }}</textarea>
|
||||
<textarea class="col-md-6 form-control" id="{{ $field->db_column_name() }}" name="{{ $field->db_column_name() }}">{{ Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $item->defaultValue($field))) }}</textarea>
|
||||
|
||||
@elseif ($field->element=='checkbox')
|
||||
<!-- Checkboxes -->
|
||||
@foreach ($field->formatFieldValuesAsArray() as $key => $value)
|
||||
<div>
|
||||
<label class="form-control">
|
||||
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
|
||||
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $item->defaultValue($field)))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
</div>
|
||||
@@ -30,7 +53,7 @@
|
||||
|
||||
<div>
|
||||
<label class="form-control">
|
||||
<input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}>
|
||||
<input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $item->defaultValue($field))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
</div>
|
||||
@@ -46,7 +69,7 @@
|
||||
|
||||
<div class="input-group col-md-5" style="padding-left: 0px;">
|
||||
<div class="input-group date" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-autoclose="true" data-date-clear-btn="true">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="{{ $field->db_column_name() }}" id="{{ $field->db_column_name() }}" readonly value="{{ old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))) }}" style="background-color:inherit">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="{{ $field->db_column_name() }}" id="{{ $field->db_column_name() }}" readonly value="{{ old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $item->defaultValue($field))) }}" style="background-color:inherit">
|
||||
<span class="input-group-addon"><i class="fas fa-calendar" aria-hidden="true"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,7 +77,7 @@
|
||||
|
||||
@else
|
||||
@if (($field->field_encrypted=='0') || (Gate::allows('assets.view.encrypted_custom_fields')))
|
||||
<input type="text" value="{{ Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))) }}" id="{{ $field->db_column_name() }}" class="form-control" name="{{ $field->db_column_name() }}" placeholder="Enter {{ strtolower($field->format) }} text">
|
||||
<input type="text" value="{{ Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $item->defaultValue($field))) }}" id="{{ $field->db_column_name() }}" class="form-control" name="{{ $field->db_column_name() }}" placeholder="Enter {{ strtolower($field->format) }} text">
|
||||
@else
|
||||
<input type="text" value="{{ strtoupper(trans('admin/custom_fields/general.encrypted')) }}" class="form-control disabled" disabled>
|
||||
@endif
|
||||
|
||||
47
resources/views/partials/custom-fields-view.blade.php
Normal file
47
resources/views/partials/custom-fields-view.blade.php
Normal file
@@ -0,0 +1,47 @@
|
||||
{{-- FIXME - this doesn't work for Assets (crap!) --}}
|
||||
@if ($item->getFieldset())
|
||||
@foreach($item->getFieldset()->fields as $field)
|
||||
<div class="row">
|
||||
<div class="col-md-{{ $width }}">
|
||||
<strong>
|
||||
{{ $field->name }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-{{ 12 - $width }}{{ (($field->format=='URL') && ($item->{$field->db_column_name()}!='')) ? ' ellipsis': '' }}">
|
||||
@if ($field->field_encrypted=='1')
|
||||
<i class="fas fa-lock" data-tooltip="true" data-placement="top" title="{{ trans('admin/custom_fields/general.value_encrypted') }}"></i>
|
||||
@endif
|
||||
|
||||
@if ($field->isFieldDecryptable($item->{$field->db_column_name()} ))
|
||||
@can('assets.view.encrypted_custom_fields')
|
||||
@if (($field->format=='URL') && ($item->{$field->db_column_name()}!=''))
|
||||
<a href="{{ Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) }}" target="_new">{{ Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) }}</a>
|
||||
@elseif (($field->format=='DATE') && ($item->{$field->db_column_name()}!=''))
|
||||
{{ \App\Helpers\Helper::gracefulDecrypt($field, \App\Helpers\Helper::getFormattedDateObject($item->{$field->db_column_name()}, 'date', false)) }}
|
||||
@else
|
||||
{{ Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) }}
|
||||
@endif
|
||||
@else
|
||||
{{ strtoupper(trans('admin/custom_fields/general.encrypted')) }}
|
||||
@endcan
|
||||
|
||||
@else
|
||||
@if (($field->format=='BOOLEAN') && ($item->{$field->db_column_name()}!=''))
|
||||
{!! ($item->{$field->db_column_name()} == 1) ? "<span class='fas fa-check-circle' style='color:green' />" : "<span class='fas fa-times-circle' style='color:red' />" !!}
|
||||
@elseif (($field->format=='URL') && ($item->{$field->db_column_name()}!=''))
|
||||
<a href="{{ $item->{$field->db_column_name()} }}" target="_new">{{ $item->{$field->db_column_name()} }}</a>
|
||||
@elseif (($field->format=='DATE') && ($item->{$field->db_column_name()}!=''))
|
||||
{{ \App\Helpers\Helper::getFormattedDateObject($item->{$field->db_column_name()}, 'date', false) }}
|
||||
@else
|
||||
{!! nl2br(e($item->{$field->db_column_name()})) !!}
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
@if ($item->{$field->db_column_name()}=='')
|
||||
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
@@ -279,6 +279,15 @@
|
||||
|
||||
@include ('partials.forms.edit.image-upload', ['fieldname' => 'avatar', 'image_path' => app('users_upload_path')])
|
||||
|
||||
{{-- FIXME - copypasta from hardware/edit.blade.php <start> --}}
|
||||
<div id='custom_fields_content'>
|
||||
<!-- Custom Fields -->
|
||||
@if ($user->getFieldset())
|
||||
@include("models/custom_fields_form",["item" => $user])
|
||||
@endif
|
||||
</div>
|
||||
{{-- FIXME - copypasts from hardware/edit.blade.php <end> --}}
|
||||
|
||||
|
||||
<!-- begin optional disclosure arrow stuff -->
|
||||
<div class="form-group">
|
||||
|
||||
@@ -677,7 +677,60 @@
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
@endif
|
||||
</div> <!--/end striped container-->
|
||||
{{-- FIXME - copypasta from hardware/view.blade.php! <start> --}}
|
||||
@if (($user->getFieldsetKey()) && (App\Models\CustomFieldset::find($user->getFieldsetKey())))
|
||||
@foreach(App\Models\CustomFieldset::find($user->getFieldsetKey())->fields as $field)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<strong>
|
||||
{{ $field->name }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-9{{ (($field->format=='URL') && ($user->{$field->db_column_name()}!='')) ? ' ellipsis': '' }}">
|
||||
@if ($field->field_encrypted=='1')
|
||||
<i class="fas fa-lock" data-tooltip="true" data-placement="top"
|
||||
title="{{ trans('admin/custom_fields/general.value_encrypted') }}"></i>
|
||||
@endif
|
||||
|
||||
@if ($field->isFieldDecryptable($user->{$field->db_column_name()} ))
|
||||
@can('assets.view.encrypted_custom_fields')
|
||||
@if (($field->format=='URL') && ($user->{$field->db_column_name()}!=''))
|
||||
<a href="{{ Helper::gracefulDecrypt($field, $user->{$field->db_column_name()}) }}"
|
||||
target="_new">{{ Helper::gracefulDecrypt($field, $user->{$field->db_column_name()}) }}</a>
|
||||
@elseif (($field->format=='DATE') && ($user->{$field->db_column_name()}!=''))
|
||||
{{ \App\Helpers\Helper::gracefulDecrypt($field, \App\Helpers\Helper::getFormattedDateObject($user->{$field->db_column_name()}, 'date', false)) }}
|
||||
@else
|
||||
{{ Helper::gracefulDecrypt($field, $user->{$field->db_column_name()}) }}
|
||||
@endif
|
||||
@else
|
||||
{{ strtoupper(trans('admin/custom_fields/general.encrypted')) }}
|
||||
@endcan
|
||||
|
||||
@else
|
||||
@if (($field->format=='BOOLEAN') && ($user->{$field->db_column_name()}!=''))
|
||||
{!! ($user->{$field->db_column_name()} == 1) ? "<span class='fas fa-check-circle' style='color:green' />" : "<span class='fas fa-times-circle' style='color:red' />" !!}
|
||||
@elseif (($field->format=='URL') && ($user->{$field->db_column_name()}!=''))
|
||||
<a href="{{ $user->{$field->db_column_name()} }}"
|
||||
target="_new">{{ $user->{$field->db_column_name()} }}</a>
|
||||
@elseif (($field->format=='DATE') && ($user->{$field->db_column_name()}!=''))
|
||||
{{ \App\Helpers\Helper::getFormattedDateObject($user->{$field->db_column_name()}, 'date', false) }}
|
||||
@else
|
||||
{!! nl2br(e($user->{$field->db_column_name()})) !!}
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
@if ($user->{$field->db_column_name()}=='')
|
||||
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
{{-- FIXME <end> copypasta from hardware/view.blade.php --}}
|
||||
@include('partials.custom-fields-view',['item' => $user,'width' => 3])
|
||||
|
||||
</div> <!--/end striped container-->
|
||||
</div> <!-- end col-md-9 -->
|
||||
</div> <!--/.row-->
|
||||
</div><!-- /.tab-pane -->
|
||||
|
||||
@@ -18,12 +18,13 @@ class UpdateAssetTest extends TestCase
|
||||
$asset = Asset::factory()->hasEncryptedCustomField($field)->create();
|
||||
$superuser = User::factory()->superuser()->create();
|
||||
|
||||
$this->actingAsForApi($superuser)
|
||||
$results = $this->actingAsForApi($superuser)
|
||||
->patchJson(route('api.assets.update', $asset->id), [
|
||||
$field->db_column_name() => 'This is encrypted field'
|
||||
])
|
||||
->assertStatusMessageIs('success')
|
||||
->assertOk();
|
||||
\Log::error(print_r($results, true));
|
||||
|
||||
$asset->refresh();
|
||||
$this->assertEquals('This is encrypted field', Crypt::decrypt($asset->{$field->db_column_name()}));
|
||||
|
||||
83
tests/Unit/HasCustomFieldsTraitTest.php
Normal file
83
tests/Unit/HasCustomFieldsTraitTest.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\Traits\HasCustomFields;
|
||||
use Illuminate\Support\Collection;
|
||||
use Tests\Support\InitializesSettings;
|
||||
use Tests\TestCase;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
|
||||
|
||||
class HasCustomFieldsTraitTest extends TestCase
|
||||
{
|
||||
use InitializesSettings;
|
||||
|
||||
//seems bonkers, but Assets needs it? (for currency calculation?)
|
||||
|
||||
public function testAssetSchema()
|
||||
{
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->create();
|
||||
|
||||
$this->assertEquals($asset->model->fieldset->fields->count(), 3,'Custom Fieldset should have exactly 3 custom fields');
|
||||
$this->assertTrue(Schema::hasColumn('assets','_snipeit_mac_address_explicit_2'),'Assets table should have MAC address column');
|
||||
$this->assertTrue(Schema::hasColumn('assets','_snipeit_plain_text_3'),'Assets table should have MAC address column');
|
||||
$this->assertTrue(Schema::hasColumn('assets','_snipeit_date_4'),'Assets table should have MAC address column');
|
||||
}
|
||||
public function testRequired()
|
||||
{
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->create();
|
||||
$this->assertFalse($asset->save(),'save() should fail due to required text field');
|
||||
}
|
||||
|
||||
public function testFormat()
|
||||
{
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->make();
|
||||
$asset->_snipeit_plain_text_3 = 'something';
|
||||
$asset->_snipeit_mac_address_explicit_2 = 'fartsssssss';
|
||||
$this->assertFalse($asset->save(), 'should fail due to bad MAC address');
|
||||
}
|
||||
|
||||
public function testDate()
|
||||
{
|
||||
// \Log::error("uh, what the heck is going on here?!");
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->make();
|
||||
$asset->_snipeit_plain_text_3 = 'some text';
|
||||
$asset->_snipeit_date_4 = '1/2/2023';
|
||||
// $asset->save();
|
||||
// dd($asset);
|
||||
$this->assertFalse($asset->save(),'Should fail due to incorrectly formatted date.');
|
||||
}
|
||||
|
||||
public function testSaveMinimal()
|
||||
{
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->make();
|
||||
$asset->_snipeit_plain_text_3 = "some text";
|
||||
$this->assertTrue($asset->save(),"Asset should've saved okay, the one required field was filled out");
|
||||
}
|
||||
|
||||
public function testSaveMaximal()
|
||||
{
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->make();
|
||||
$asset->_snipeit_plain_text_3 = "some text";
|
||||
$asset->_snipeit_date_4 = "2023-01-02";
|
||||
$asset->_snipeit_mac_address_explicit_2 = "ff:ff:ff:ff:ff:ff";
|
||||
$this->assertTrue($asset->save(),"Asset should've saved okay, the one required field was filled out, and so were the others");
|
||||
}
|
||||
|
||||
public function testJsonPost()
|
||||
{
|
||||
//FIXME - this is in the wrong place and it might just be genuinley wrong?
|
||||
$this->markTestIncomplete();
|
||||
$asset = Asset::factory()->withComplicatedCustomFields()->make();
|
||||
$response = $this->postJson('/api/v1/hardware', [
|
||||
|
||||
]);
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user