diff --git a/app/Http/Controllers/Api/CustomFieldsetsController.php b/app/Http/Controllers/Api/CustomFieldsetsController.php index 915518e945..3855e826a0 100644 --- a/app/Http/Controllers/Api/CustomFieldsetsController.php +++ b/app/Http/Controllers/Api/CustomFieldsetsController.php @@ -156,8 +156,26 @@ class CustomFieldsetsController extends Controller { $this->authorize('view', CustomFieldset::class); $set = CustomFieldset::findOrFail($id); - $fields = $set->fields->get(); + $fields = $set->fields; return (new CustomFieldsTransformer)->transformCustomFields($fields, $fields->count()); } + /** + * Return JSON containing a list of fields belonging to a fieldset with the + * default values for a given model + * + * @param $modelId + * @param $fieldsetId + * @return string JSON + */ + public function fieldsWithDefaultValues($fieldsetId, $modelId) + { + $this->authorize('view', CustomFieldset::class); + + $set = CustomFieldset::findOrFail($fieldsetId); + + $fields = $set->fields; + + return (new CustomFieldsTransformer)->transformCustomFieldsWithDefaultValues($fields, $modelId, $fields->count()); + } } diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 389f1edd94..28ea51aa3f 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -110,6 +110,10 @@ class AssetModelsController extends Controller // Was it created? if ($model->save()) { + if ($this->shouldAddDefaultValues($request->input())) { + $this->assignCustomFieldsDefaultValues($model, $request->input('default_values')); + } + // Redirect to the new model page return redirect()->route("models.index")->with('success', trans('admin/models/message.create.success')); } @@ -206,10 +210,16 @@ class AssetModelsController extends Controller $model->notes = $request->input('notes'); $model->requestable = $request->input('requestable', '0'); + $this->removeCustomFieldsDefaultValues($model); + if ($request->input('custom_fieldset')=='') { $model->fieldset_id = null; } else { $model->fieldset_id = $request->input('custom_fieldset'); + + if ($this->shouldAddDefaultValues($request->input())) { + $this->assignCustomFieldsDefaultValues($model, $request->input('default_values')); + } } $old_image = $model->image; @@ -531,4 +541,43 @@ class AssetModelsController extends Controller } + /** + * Returns true if a fieldset is set, 'add default values' is ticked and if + * any default values were entered into the form. + * + * @param array $input + * @return boolean + */ + private function shouldAddDefaultValues(array $input) + { + return !empty($input['add_default_values']) + && !empty($input['default_values']) + && !empty($input['custom_fieldset']); + } + + /** + * Adds default values to a model (as long as they are truthy) + * + * @param AssetModel $model + * @param array $defaultValues + * @return void + */ + private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues) + { + foreach ($defaultValues as $customFieldId => $defaultValue) { + if ($defaultValue) { + $model->defaultValues()->attach($customFieldId, ['default_value' => $defaultValue]); + } + } + } + + /** + * Removes all default values + * + * @return void + */ + private function removeCustomFieldsDefaultValues(AssetModel $model) + { + $model->defaultValues()->detach(); + } } diff --git a/app/Http/Transformers/CustomFieldsTransformer.php b/app/Http/Transformers/CustomFieldsTransformer.php index 5c6e5d4fc2..1f8f02e278 100644 --- a/app/Http/Transformers/CustomFieldsTransformer.php +++ b/app/Http/Transformers/CustomFieldsTransformer.php @@ -18,15 +18,34 @@ class CustomFieldsTransformer return (new DatatablesTransformer)->transformDatatables($array, $total); } + /** + * Builds up an array of formatted custom fields + * @param Collection $fields + * @param int $modelId + * @param int $total + * @return array + */ + public function transformCustomFieldsWithDefaultValues (Collection $fields, $modelId, $total) + { + $array = []; + + foreach ($fields as $field) { + $array[] = self::transformCustomFieldWithDefaultValue($field, $modelId); + } + + return (new DatatablesTransformer)->transformDatatables($array, $total); + } + public function transformCustomField (CustomField $field) { - $array = [ 'id' => $field->id, 'name' => e($field->name), 'db_column_name' => e($field->db_column_name()), 'format' => e($field->format), 'field_values' => ($field->field_values) ? e($field->field_values) : null, + 'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null, + 'type' => e($field->element), 'required' => $field->pivot ? $field->pivot->required : false, 'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'), @@ -34,5 +53,22 @@ class CustomFieldsTransformer return $array; } - + /** + * Returns the core data for a field, including the default value it has + * when attributed to a certain model + * + * @param CustomField $field + * @param int $modelId + * @return array + */ + public function transformCustomFieldWithDefaultValue (CustomField $field, $modelId) + { + return [ + 'id' => $field->id, + 'name' => e($field->name), + 'type' => e($field->element), + 'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null, + 'default_value' => $field->defaultValue($modelId), + ]; + } } diff --git a/app/Models/AssetModel.php b/app/Models/AssetModel.php index 48c86686c9..79a91c284b 100755 --- a/app/Models/AssetModel.php +++ b/app/Models/AssetModel.php @@ -98,6 +98,11 @@ class AssetModel extends SnipeModel return $this->belongsTo('\App\Models\CustomFieldset', 'fieldset_id'); } + public function defaultValues() + { + return $this->belongsToMany('\App\Models\CustomField', 'models_custom_fields')->withPivot('default_value'); + } + public function getImageUrl() { if ($this->image) { diff --git a/app/Models/CustomField.php b/app/Models/CustomField.php index c744705f1c..c59483dcc6 100644 --- a/app/Models/CustomField.php +++ b/app/Models/CustomField.php @@ -146,6 +146,26 @@ class CustomField extends Model return $this->belongsTo('\App\Models\User'); } + public function defaultValues() + { + return $this->belongsToMany('\App\Models\AssetModel', 'models_custom_fields')->withPivot('default_value'); + } + + /** + * Returns the default value for a given model using the defaultValues + * relationship + * + * @param int $modelId + * @return string + */ + public function defaultValue($modelId) + { + return $this->defaultValues->filter(function ($item) use ($modelId) { + return $item->pivot->asset_model_id == $modelId; + })->map(function ($item) { + return $item->pivot->default_value; + })->first(); + } public function check_format($value) { diff --git a/database/migrations/2018_04_16_133902_create_custom_field_default_values_table.php b/database/migrations/2018_04_16_133902_create_custom_field_default_values_table.php new file mode 100644 index 0000000000..b8f9191a26 --- /dev/null +++ b/database/migrations/2018_04_16_133902_create_custom_field_default_values_table.php @@ -0,0 +1,33 @@ +increments('id'); + $table->integer('asset_model_id'); + $table->integer('custom_field_id'); + $table->text('default_value')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('models_custom_fields'); + } +} diff --git a/public/css/AdminLTE.css b/public/css/AdminLTE.css index dd3eb5e016..9089be3ccf 100755 Binary files a/public/css/AdminLTE.css and b/public/css/AdminLTE.css differ diff --git a/public/css/build/all.css b/public/css/build/all.css index 42a3afede7..d2cff3f6c2 100644 Binary files a/public/css/build/all.css and b/public/css/build/all.css differ diff --git a/public/css/dist/all.css b/public/css/dist/all.css index 42a3afede7..d2cff3f6c2 100644 Binary files a/public/css/dist/all.css and b/public/css/dist/all.css differ diff --git a/public/js/build/all.js b/public/js/build/all.js index c1a69a16e4..421ff3a55b 100644 Binary files a/public/js/build/all.js and b/public/js/build/all.js differ diff --git a/public/js/build/vue.js b/public/js/build/vue.js index 459f1d9c35..37ab5d77a6 100644 Binary files a/public/js/build/vue.js and b/public/js/build/vue.js differ diff --git a/public/js/build/vue.js.map b/public/js/build/vue.js.map index ca1f9ce263..06b14b39c6 100644 Binary files a/public/js/build/vue.js.map and b/public/js/build/vue.js.map differ diff --git a/public/js/dist/all.js b/public/js/dist/all.js index c1a69a16e4..421ff3a55b 100644 Binary files a/public/js/dist/all.js and b/public/js/dist/all.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 4cd81236d0..cf517d2f6f 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,14 +1,14 @@ { - "/js/build/vue.js": "/js/build/vue.js?id=cd8def41b04c6707fc9e", - "/css/AdminLTE.css": "/css/AdminLTE.css?id=b8be19a285eaf44eec37", + "/js/build/vue.js": "/js/build/vue.js?id=88921ad9bb64a0915ebb", + "/css/AdminLTE.css": "/css/AdminLTE.css?id=5e72463a66acbcc740d5", "/css/app.css": "/css/app.css?id=407edb63cc6b6dc62405", "/css/overrides.css": "/css/overrides.css?id=c289c71c08df753ebc45", - "/js/build/vue.js.map": "/js/build/vue.js.map?id=ae61f2fa91bc184b92a9", + "/js/build/vue.js.map": "/js/build/vue.js.map?id=0b7679d18eb22094e3b7", "/css/AdminLTE.css.map": "/css/AdminLTE.css.map?id=99f5a5a03c4155cf69f6", "/css/app.css.map": "/css/app.css.map?id=bdbe05e6ecd70ccfac72", "/css/overrides.css.map": "/css/overrides.css.map?id=898c91d4a425b01b589b", - "/css/dist/all.css": "/css/dist/all.css?id=5fdad90c2d445e4a1a2c", - "/js/dist/all.js": "/js/dist/all.js?id=dc00b6ea982000d41b0e", - "/css/build/all.css": "/css/build/all.css?id=5fdad90c2d445e4a1a2c", - "/js/build/all.js": "/js/build/all.js?id=dc00b6ea982000d41b0e" + "/css/dist/all.css": "/css/dist/all.css?id=e3ae07b03a1d53657a1e", + "/js/dist/all.js": "/js/dist/all.js?id=3f7017ebedf1da0319ef", + "/css/build/all.css": "/css/build/all.css?id=e3ae07b03a1d53657a1e", + "/js/build/all.js": "/js/build/all.js?id=3f7017ebedf1da0319ef" } \ No newline at end of file diff --git a/resources/assets/js/components/forms/asset-models/fieldset-default-values.vue b/resources/assets/js/components/forms/asset-models/fieldset-default-values.vue new file mode 100644 index 0000000000..71d7ee01ed --- /dev/null +++ b/resources/assets/js/components/forms/asset-models/fieldset-default-values.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/resources/assets/js/vue.js b/resources/assets/js/vue.js index 39d2cb4ad8..cc851bb8cc 100644 --- a/resources/assets/js/vue.js +++ b/resources/assets/js/vue.js @@ -32,6 +32,11 @@ Vue.component( require('./components/importer/importer.vue') ); +Vue.component( + 'fieldset-default-values', + require('./components/forms/asset-models/fieldset-default-values.vue') +); + // Commented out currently to avoid trying to load vue everywhere. // const app = new Vue({ // el: '#app' diff --git a/resources/assets/less/AdminLTE.less b/resources/assets/less/AdminLTE.less index d5c277cd8b..711b6d141a 100755 --- a/resources/assets/less/AdminLTE.less +++ b/resources/assets/less/AdminLTE.less @@ -39,6 +39,10 @@ @import "labels.less"; @import "modal.less"; +//HELPERS +//----------- +@import "spacing.less"; + //PAGES //------ @import "login_and_register.less"; diff --git a/resources/assets/less/spacing.less b/resources/assets/less/spacing.less new file mode 100644 index 0000000000..d668983934 --- /dev/null +++ b/resources/assets/less/spacing.less @@ -0,0 +1,56 @@ +/* + * Helpers: Spacing + * Universal minor spacing classes to help space things out without + * use-dedicated classes + * ----------------- + */ + +@props: margin m, padding p; +@spacers: xs 5px 10px, + sm 10px 20px, + md 20px 30px; + +.loop-props(@prop-index) when (@prop-index > 0){ + @prop: extract(@props, @prop-index); + @prop-name: extract(@prop, 1); + @abbrev: extract(@prop, 2); + + .loop-sizes(@prop-name; @abbrev; length(@spacers)); + + .loop-props(@prop-index - 1); +} + +.loop-props(length(@props)) !important; + +.loop-sizes(@prop-name; @abbrev; @size-index) when (@size-index > 0){ + @spacer: extract(@spacers, @size-index); + @size: extract(@spacer, 1); + @x: extract(@spacer, 2); + @y: extract(@spacer, 3); + + .@{abbrev}-a-@{size} { + @{prop-name}: @y @x; + } + .@{abbrev}-t-@{size} { + @{prop-name}-top: @y; + } + .@{abbrev}-r-@{size} { + @{prop-name}-right: @x; + } + .@{abbrev}-b-@{size} { + @{prop-name}-bottom: @y; + } + .@{abbrev}-l-@{size} { + @{prop-name}-left: @x; + } + .@{abbrev}-x-@{size} { + @{prop-name}-right: @x; + @{prop-name}-left: @x; + } + .@{abbrev}-y-@{size} { + @{prop-name}-top: @y; + @{prop-name}-bottom: @y; + } + + .loop-sizes(@prop-name; @abbrev; @size-index - 1); +} diff --git a/resources/lang/en/admin/models/general.php b/resources/lang/en/admin/models/general.php index 7fc92ca6ae..3281cfe0fc 100644 --- a/resources/lang/en/admin/models/general.php +++ b/resources/lang/en/admin/models/general.php @@ -14,5 +14,5 @@ return array( 'view_models' => 'View Models', 'fieldset' => 'Fieldset', 'no_custom_field' => 'No custom fields', - + 'add_default_values' => 'Add default values', ); diff --git a/resources/views/models/custom_fields_form.blade.php b/resources/views/models/custom_fields_form.blade.php index 9301a76ee6..3ec43cad7e 100644 --- a/resources/views/models/custom_fields_form.blade.php +++ b/resources/views/models/custom_fields_form.blade.php @@ -8,7 +8,7 @@ @if ($field->element=='listbox') {{ Form::select($field->db_column_name(), $field->formatFieldValuesAsArray(), - Input::old($field->db_column_name(),(isset($item) ? $item->{$field->db_column_name()} : "")), ['class'=>'format select2 form-control']) }} + Input::old($field->db_column_name(),(isset($item) ? $item->{$field->db_column_name()} : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }} @elseif ($field->element=='checkbox') @@ -39,7 +39,7 @@ @else @if (($field->field_encrypted=='0') || (Gate::allows('admin'))) - + @else @endif diff --git a/resources/views/models/edit.blade.php b/resources/views/models/edit.blade.php index 117531c572..4861b5d7a1 100755 --- a/resources/views/models/edit.blade.php +++ b/resources/views/models/edit.blade.php @@ -33,12 +33,25 @@ -
- -
- {{ Form::select('custom_fieldset', \App\Helpers\Helper::customFieldsetList(),Input::old('custom_fieldset', $item->fieldset_id), array('class'=>'select2', 'style'=>'width:350px')) }} - {!! $errors->first('custom_fieldset', '
:message
') !!} +
+
+ +
+ {{ Form::select('custom_fieldset', \App\Helpers\Helper::customFieldsetList(),Input::old('custom_fieldset', $item->fieldset_id), array('class'=>'select2 js-fieldset-field', 'style'=>'width:350px')) }} + {!! $errors->first('custom_fieldset', '
:message
') !!} + +
+ + +
@include ('partials.forms.edit.notes') @@ -59,3 +72,11 @@ @include ('partials.forms.edit.image-upload') @stop + +@section('moar_scripts') + +@endsection diff --git a/routes/api.php b/routes/api.php index 30bafae0e1..97c032caa6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -259,6 +259,12 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { 'uses' => 'CustomFieldsetsController@fields' ] ); + Route::get('/{fieldset}/fields/{model}', + [ + 'as' => 'api.fieldsets.fields-with-default-value', + 'uses' => 'CustomFieldsetsController@fieldsWithDefaultValues' + ] + ); }); Route::resource('fieldsets', 'CustomFieldsetsController',