-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15714 from akemidx/saving_custom_report_template
Saved Custom Report Templates
- Loading branch information
Showing
28 changed files
with
1,593 additions
and
212 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
namespace App\Http\Controllers; | ||
|
||
use App\Models\CustomField; | ||
use App\Models\ReportTemplate; | ||
use Illuminate\Http\RedirectResponse; | ||
use Illuminate\Http\Request; | ||
use Illuminate\Support\Arr; | ||
|
||
class ReportTemplatesController extends Controller | ||
{ | ||
public function store(Request $request): RedirectResponse | ||
{ | ||
$this->authorize('reports.view'); | ||
|
||
// Ignore "options" rules since data does not come in under that key... | ||
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options')); | ||
|
||
$report = $request->user()->reportTemplates()->create([ | ||
'name' => $validated['name'], | ||
'options' => $request->except(['_token', 'name']), | ||
]); | ||
|
||
session()->flash('success', trans('admin/reports/message.create.success')); | ||
|
||
return redirect()->route('report-templates.show', $report->id); | ||
} | ||
|
||
public function show(ReportTemplate $reportTemplate) | ||
{ | ||
$this->authorize('reports.view'); | ||
|
||
$customfields = CustomField::get(); | ||
$report_templates = ReportTemplate::orderBy('name')->get(); | ||
|
||
return view('reports/custom', [ | ||
'customfields' => $customfields, | ||
'report_templates' => $report_templates, | ||
'template' => $reportTemplate, | ||
]); | ||
} | ||
|
||
public function edit(ReportTemplate $reportTemplate) | ||
{ | ||
$this->authorize('reports.view'); | ||
|
||
return view('reports/custom', [ | ||
'customfields' => CustomField::get(), | ||
'template' => $reportTemplate, | ||
]); | ||
} | ||
|
||
public function update(Request $request, ReportTemplate $reportTemplate): RedirectResponse | ||
{ | ||
$this->authorize('reports.view'); | ||
|
||
// Ignore "options" rules since data does not come in under that key... | ||
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options')); | ||
|
||
$reportTemplate->update([ | ||
'name' => $validated['name'], | ||
'options' => $request->except(['_token', 'name']), | ||
]); | ||
|
||
session()->flash('success', trans('admin/reports/message.update.success')); | ||
|
||
return redirect()->route('report-templates.show', $reportTemplate->id); | ||
} | ||
|
||
public function destroy(ReportTemplate $reportTemplate): RedirectResponse | ||
{ | ||
$this->authorize('reports.view'); | ||
|
||
$reportTemplate->delete(); | ||
|
||
return redirect()->route('reports/custom') | ||
->with('success', trans('admin/reports/message.delete.success')); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
<?php | ||
|
||
namespace App\Models; | ||
|
||
use Illuminate\Database\Eloquent\Builder; | ||
use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
use Illuminate\Database\Eloquent\Model; | ||
use Illuminate\Database\Eloquent\Relations\BelongsTo; | ||
use Illuminate\Database\Eloquent\SoftDeletes; | ||
use Watson\Validating\ValidatingTrait; | ||
|
||
class ReportTemplate extends Model | ||
{ | ||
use HasFactory; | ||
use SoftDeletes; | ||
use ValidatingTrait; | ||
|
||
protected $casts = [ | ||
'options' => 'array', | ||
]; | ||
|
||
protected $fillable = [ | ||
'created_by', | ||
'name', | ||
'options', | ||
]; | ||
|
||
protected $rules = [ | ||
'name' => [ | ||
'required', | ||
'string', | ||
], | ||
'options' => [ | ||
'required', | ||
'array', | ||
], | ||
]; | ||
|
||
protected static function booted() | ||
{ | ||
// Scope to current user | ||
static::addGlobalScope('current_user', function (Builder $builder) { | ||
if (auth()->check()) { | ||
$builder->where('created_by', auth()->id()); | ||
} | ||
}); | ||
|
||
static::created(function (ReportTemplate $reportTemplate) { | ||
$logAction = new Actionlog([ | ||
'item_type' => ReportTemplate::class, | ||
'item_id' => $reportTemplate->id, | ||
'created_by' => auth()->id(), | ||
]); | ||
|
||
$logAction->logaction('create'); | ||
}); | ||
|
||
static::updated(function (ReportTemplate $reportTemplate) { | ||
$changed = []; | ||
|
||
foreach ($reportTemplate->getDirty() as $key => $value) { | ||
$changed[$key] = [ | ||
'old' => $reportTemplate->getOriginal($key), | ||
'new' => $reportTemplate->getAttribute($key), | ||
]; | ||
} | ||
|
||
$logAction = new Actionlog(); | ||
$logAction->item_type = ReportTemplate::class; | ||
$logAction->item_id = $reportTemplate->id; | ||
$logAction->created_by = auth()->id(); | ||
$logAction->log_meta = json_encode($changed); | ||
$logAction->logaction('update'); | ||
}); | ||
|
||
static::deleted(function (ReportTemplate $reportTemplate) { | ||
$logAction = new Actionlog([ | ||
'item_type' => ReportTemplate::class, | ||
'item_id' => $reportTemplate->id, | ||
'created_by' => auth()->id(), | ||
]); | ||
|
||
$logAction->logaction('delete'); | ||
}); | ||
} | ||
|
||
/** | ||
* Establishes the report template -> creator relationship. | ||
* | ||
*/ | ||
public function creator(): BelongsTo | ||
{ | ||
return $this->belongsTo(User::class, 'created_by'); | ||
} | ||
|
||
/** | ||
* Get the value of a checkbox field for the given field name. | ||
* | ||
* @param string $fieldName | ||
* @param string $fallbackValue The value to return if the report template is not saved yet. | ||
* | ||
*/ | ||
public function checkmarkValue(string $fieldName, string $fallbackValue = '1'): string | ||
{ | ||
// Assuming we're using the null object pattern, and an empty model | ||
// was passed to the view when showing the default report page, | ||
// return the fallback value so that checkboxes are checked by default. | ||
if (is_null($this->id)) { | ||
return $fallbackValue; | ||
} | ||
|
||
// If the model does exist then return the value of the field | ||
// or return 0 so the checkbox is unchecked. | ||
// Falling back to 0 here is because checkboxes are not sent | ||
// in the request when unchecked so they are not | ||
// actually saved in the model's options. | ||
return $this->options[$fieldName] ?? '0'; | ||
} | ||
|
||
/** | ||
* Get the value of a radio field for the given field name. | ||
* | ||
* @param string $fieldName | ||
* @param string $value The value to check against. | ||
* @param bool $isDefault Whether the radio input being checked is the default. | ||
* | ||
*/ | ||
public function radioValue(string $fieldName, string $value, bool $isDefault = false): bool | ||
{ | ||
$fieldExists = array_has($this->options, $fieldName); | ||
|
||
// If the field doesn't exist but the radio input | ||
// being checked is the default then return true. | ||
if (!$fieldExists && $isDefault) { | ||
return true; | ||
} | ||
|
||
// If the field exists and matches what we're checking then return true. | ||
if ($fieldExists && $this->options[$fieldName] === $value) { | ||
return true; | ||
} | ||
|
||
// Otherwise return false. | ||
return false; | ||
} | ||
|
||
/** | ||
* Get the value of a select field for the given field name. | ||
* | ||
* @param string $fieldName | ||
* @param string|null $model The Eloquent model to check against. | ||
* | ||
* @return mixed|null | ||
* | ||
*/ | ||
public function selectValue(string $fieldName, string $model = null) | ||
{ | ||
// If the field does not exist then return null. | ||
if (!isset($this->options[$fieldName])) { | ||
return null; | ||
} | ||
|
||
$value = $this->options[$fieldName]; | ||
|
||
// If the value was stored as an array, most likely | ||
// due to a previously being a multi-select, | ||
// then return the first value. | ||
if (is_array($value)) { | ||
$value = $value[0]; | ||
} | ||
|
||
// If a model is provided then we should ensure we only return | ||
// the value if the model still exists. | ||
// Note: It is possible $value is an id that no longer exists and this will return null. | ||
if ($model) { | ||
$foundModel = $model::find($value); | ||
|
||
return $foundModel ? $foundModel->id : null; | ||
} | ||
|
||
return $value; | ||
} | ||
|
||
/** | ||
* Get the values of a multi-select field for the given field name. | ||
* | ||
* @param string $fieldName | ||
* @param string|null $model The Eloquent model to check against. | ||
* | ||
* @return iterable | ||
* | ||
*/ | ||
public function selectValues(string $fieldName, string $model = null): iterable | ||
{ | ||
// If the field does not exist then return an empty array. | ||
if (!isset($this->options[$fieldName])) { | ||
return []; | ||
} | ||
|
||
// If a model is provided then we should ensure we only return | ||
// the ids of models that exist and are not deleted. | ||
if ($model) { | ||
return $model::findMany($this->options[$fieldName])->pluck('id'); | ||
} | ||
|
||
// Wrap the value in an array if needed. This is to ensure | ||
// values previously stored as a single value, | ||
// most likely from a single select, are returned as an array. | ||
if (!is_array($this->options[$fieldName])) { | ||
return [$this->options[$fieldName]]; | ||
} | ||
|
||
return $this->options[$fieldName]; | ||
} | ||
|
||
/** | ||
* Get the value of a text field for the given field name. | ||
* | ||
* @param string $fieldName | ||
* @param string|null $fallbackValue | ||
* | ||
* @return string | ||
*/ | ||
public function textValue(string $fieldName, string|null $fallbackValue = ''): string | ||
{ | ||
// Assuming we're using the null object pattern, | ||
// return the default value if the object is not saved yet. | ||
if (is_null($this->id)) { | ||
return (string) $fallbackValue; | ||
} | ||
|
||
// Return the field's value if it exists | ||
// and return the default value if not. | ||
return $this->options[$fieldName] ?? ''; | ||
} | ||
|
||
public function getDisplayNameAttribute() | ||
{ | ||
return $this->name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.