mirror of https://github.com/kcal-app/kcal.git
Refactor Quill handling as a separate database column
This commit is contained in:
parent
99300d1b2d
commit
053c8305a1
|
|
@ -154,6 +154,7 @@ class RecipeController extends Controller
|
||||||
$input = $request->validate([
|
$input = $request->validate([
|
||||||
'name' => ['required', 'string'],
|
'name' => ['required', 'string'],
|
||||||
'description' => ['nullable', 'string'],
|
'description' => ['nullable', 'string'],
|
||||||
|
'description_delta' => ['nullable', 'string'],
|
||||||
'servings' => ['required', 'numeric'],
|
'servings' => ['required', 'numeric'],
|
||||||
'time_prep' => ['nullable', 'numeric'],
|
'time_prep' => ['nullable', 'numeric'],
|
||||||
'time_active' => ['nullable', 'numeric'],
|
'time_active' => ['nullable', 'numeric'],
|
||||||
|
|
@ -186,6 +187,7 @@ class RecipeController extends Controller
|
||||||
$recipe->fill([
|
$recipe->fill([
|
||||||
'name' => Str::lower($input['name']),
|
'name' => Str::lower($input['name']),
|
||||||
'description' => $input['description'],
|
'description' => $input['description'],
|
||||||
|
'description_delta' => $input['description_delta'],
|
||||||
'servings' => (int) $input['servings'],
|
'servings' => (int) $input['servings'],
|
||||||
'weight' => $input['weight'],
|
'weight' => $input['weight'],
|
||||||
'time_prep' => (int) $input['time_prep'],
|
'time_prep' => (int) $input['time_prep'],
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class RecipeSchema extends SchemaProvider
|
||||||
return [
|
return [
|
||||||
'slug' => $resource->slug,
|
'slug' => $resource->slug,
|
||||||
'name' => $resource->name,
|
'name' => $resource->name,
|
||||||
'description' => $resource->description_html,
|
'description' => $resource->description,
|
||||||
'time_prep' => $resource->time_prep,
|
'time_prep' => $resource->time_prep,
|
||||||
'time_active' => $resource->time_active,
|
'time_active' => $resource->time_active,
|
||||||
'time_total' => $resource->time_total,
|
'time_total' => $resource->time_total,
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ use Spatie\Tags\HasTags;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Recipe whereTimeActive($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Recipe whereTimeActive($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Recipe whereTimePrep($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Recipe whereTimePrep($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Recipe withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
* @method static \Illuminate\Database\Eloquent\Builder|Recipe withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
||||||
* @property-read string $description_html
|
* @property string|null $description_delta
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|Recipe whereDescriptionDelta($value)
|
||||||
*/
|
*/
|
||||||
final class Recipe extends Model
|
final class Recipe extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -81,6 +82,7 @@ final class Recipe extends Model
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'description',
|
'description',
|
||||||
|
'description_delta',
|
||||||
'time_prep',
|
'time_prep',
|
||||||
'time_active',
|
'time_active',
|
||||||
'source',
|
'source',
|
||||||
|
|
@ -114,7 +116,6 @@ final class Recipe extends Model
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected $appends = [
|
protected $appends = [
|
||||||
'description_html',
|
|
||||||
'serving_weight',
|
'serving_weight',
|
||||||
'time_total',
|
'time_total',
|
||||||
];
|
];
|
||||||
|
|
@ -127,30 +128,13 @@ final class Recipe extends Model
|
||||||
return [
|
return [
|
||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'tags' => $this->tags->pluck('name')->toArray(),
|
'tags' => $this->tags->pluck('name')->toArray(),
|
||||||
'description' => $this->description_html,
|
'description' => $this->description,
|
||||||
'source' => $this->source,
|
'source' => $this->source,
|
||||||
'created_at' => $this->created_at,
|
'created_at' => $this->created_at,
|
||||||
'updated_at' => $this->updated_at,
|
'updated_at' => $this->updated_at,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get description as an HTML string.
|
|
||||||
*/
|
|
||||||
public function getDescriptionHtmlAttribute(): ?string {
|
|
||||||
$description = $this->description;
|
|
||||||
if (!empty($description)) {
|
|
||||||
try {
|
|
||||||
$quill = new Render($this->description);
|
|
||||||
$description = $quill->render();
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// TODO: Log this or something.
|
|
||||||
$description = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get total recipe time.
|
* Get total recipe time.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class CreateRecipesTable extends Migration
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->string('slug')->unique();
|
$table->string('slug')->unique();
|
||||||
$table->longText('description')->nullable();
|
$table->longText('description')->nullable();
|
||||||
|
$table->longText('description_delta')->nullable();
|
||||||
$table->integer('time_prep')->nullable();
|
$table->integer('time_prep')->nullable();
|
||||||
$table->integer('time_active')->nullable();
|
$table->integer('time_active')->nullable();
|
||||||
$table->string('source')->nullable();
|
$table->string('source')->nullable();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Recipe;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddDescriptionDeltaToRecipes extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('recipes', function (Blueprint $table) {
|
||||||
|
$table->longText('description_delta')->nullable()->after('description');
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (Recipe::all() as $recipe) {
|
||||||
|
if (empty($recipe->description)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format as a basic Quill Delta.
|
||||||
|
// See: https://quilljs.com/docs/delta/
|
||||||
|
$delta = ['ops' => [['insert' => "{$recipe->description}\n"]]];
|
||||||
|
$recipe->description_delta = json_encode($delta);
|
||||||
|
$recipe->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('recipes', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('description_delta');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -76,6 +76,10 @@
|
||||||
:value="old('description', $recipe->description)" />
|
:value="old('description', $recipe->description)" />
|
||||||
|
|
||||||
<div class="quill-editor"></div>
|
<div class="quill-editor"></div>
|
||||||
|
|
||||||
|
<x-inputs.input name="description_delta"
|
||||||
|
type="hidden"
|
||||||
|
:value="old('description_delta', $recipe->description_delta)" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Source -->
|
<!-- Source -->
|
||||||
|
|
@ -152,7 +156,7 @@
|
||||||
theme: 'snow'
|
theme: 'snow'
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
description.setContents(JSON.parse(document.querySelector('input[name="description"]').value));
|
description.setContents(JSON.parse(document.querySelector('input[name="description_delta"]').value));
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
new Draggable.Sortable(document.querySelector('.ingredients'), {
|
new Draggable.Sortable(document.querySelector('.ingredients'), {
|
||||||
|
|
@ -195,8 +199,11 @@
|
||||||
// Remove any hidden templates before form submit.
|
// Remove any hidden templates before form submit.
|
||||||
document.querySelectorAll(':scope .entry-template').forEach(e => e.remove());
|
document.querySelectorAll(':scope .entry-template').forEach(e => e.remove());
|
||||||
|
|
||||||
// Add description value to hidden field.
|
// Add description values to hidden fields.
|
||||||
document.querySelector('input[name="description"]').value = JSON.stringify(description.getContents());
|
document.querySelector('input[name="description_delta"]').value = JSON.stringify(description.getContents());
|
||||||
|
document.querySelector('input[name="description"]').value = description.root.innerHTML
|
||||||
|
// Remove extraneous spaces from rendered result.
|
||||||
|
.replaceAll('<p><br></p>', '');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,9 @@
|
||||||
</x-slot>
|
</x-slot>
|
||||||
<div class="flex flex-col-reverse justify-between pb-4 sm:flex-row">
|
<div class="flex flex-col-reverse justify-between pb-4 sm:flex-row">
|
||||||
<div x-data="{showNutrientsSummary: false}">
|
<div x-data="{showNutrientsSummary: false}">
|
||||||
@if($recipe->description_html)
|
@if($recipe->description)
|
||||||
<section class="mb-2 prose prose-lg md:prose-xl">
|
<section class="mb-2 prose prose-lg md:prose-xl">
|
||||||
{!! $recipe->description_html !!}
|
{!! $recipe->description !!}
|
||||||
</section>
|
|
||||||
@endif
|
|
||||||
@if(!$recipe->tags->isEmpty())
|
|
||||||
<section class="mb-2 text-gray-700 text-sm">
|
|
||||||
<h1 class="font-extrabold inline">Tags:</h1>
|
|
||||||
{{ implode(', ', $recipe->tags->pluck('name')->all()) }}
|
|
||||||
</section>
|
</section>
|
||||||
@endif
|
@endif
|
||||||
@if($recipe->time_total > 0)
|
@if($recipe->time_total > 0)
|
||||||
|
|
@ -138,4 +132,10 @@
|
||||||
@endif
|
@endif
|
||||||
</footer>
|
</footer>
|
||||||
@endif
|
@endif
|
||||||
|
@if(!$recipe->tags->isEmpty())
|
||||||
|
<section class="mb-2 text-gray-500 text-sm">
|
||||||
|
<h1 class="font-extrabold inline">Tags:</h1>
|
||||||
|
{{ implode(', ', $recipe->tags->pluck('name')->all()) }}
|
||||||
|
</section>
|
||||||
|
@endif
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue