Skip to content

Commit

Permalink
WIP Postmeta
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniputra committed May 12, 2024
1 parent fb06efe commit 20055f7
Show file tree
Hide file tree
Showing 13 changed files with 255 additions and 64 deletions.
15 changes: 15 additions & 0 deletions database/migrations/2024_04_10_000005_create_ngeblog_tables.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ public function up(): void

$table->unique(['post_id', 'tag_id']);
});

Schema::create('ngeblog_postmetas', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained('ngeblog_posts')->cascadeOnDelete();
$table->string('field_type');
$table->tinyInteger('order')->default(0);
$table->string('key');
$table->string('label')->nullable();
$table->longText('value');
$table->timestamps();

$table->index('key');
$table->index('order');
});
}

/**
Expand All @@ -65,5 +79,6 @@ public function down(): void
Schema::dropIfExists('ngeblog_posts');
Schema::dropIfExists('ngeblog_tags');
Schema::dropIfExists('ngeblog_post_tag');
Schema::dropIfExists('ngeblog_postmetas');
}
};

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/ngeblog-admin-assets/Form.css
Original file line number Diff line number Diff line change
@@ -1 +1 @@
.is-active[data-v-70502711]{--tw-bg-opacity: 1;background-color:var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity)));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}
.is-active[data-v-1e473e72]{--tw-bg-opacity: 1;background-color:var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity)));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}
2 changes: 1 addition & 1 deletion dist/ngeblog-admin-assets/ngeblog.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/ngeblog-admin-assets/ngeblog.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions resources/js/components/ContentEditor.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<div class="flex flex-col border pb-8">
<div class="flex flex-col rounded border pb-8">
<div
v-if="editorElement"
class="sticky top-0 z-10 mb-8 flex flex-wrap gap-1 border-b bg-white p-2"
class="sticky top-0 z-10 mb-8 flex flex-wrap gap-1 rounded-t border-b bg-white p-2"
>
<button
type="button"
Expand Down Expand Up @@ -240,7 +240,7 @@ onMounted(() => {
extensions: [StarterKit],
editorProps: {
attributes: {
class: "prose prose-sm sm:prose-base lg:prose-lg mx-auto focus:outline-none dark:prose-invert",
class: "prose prose-sm sm:prose-base lg:prose-lg mx-auto focus:outline-none dark:prose-invert px-2",
},
},
content: props.modelValue || defaultContent,
Expand Down
111 changes: 111 additions & 0 deletions resources/js/components/FormMetas.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<script setup>
import { reactive } from "vue";
import FormControl from "./FormControl.vue";
const props = defineProps({
modelValue: Array,
});
const emits = defineEmits(["update:modelValue"]);
const metaItem = reactive({
field_type: "text",
key: "",
label: "",
value: "",
});
</script>

<template>
<details class="collapse rounded border" open>
<summary class="collapse-title p-0">
<div
class="flex items-center justify-between bg-gray-100 px-4 py-2 text-lg font-medium hover:bg-gray-200"
>
<p>
<span class="underline underline-offset-2">Meta Data</span>
<span class="ml-2 text-sm italic">(optional)</span>
</p>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-6 w-6 flex-none"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M6 9l6 6l6 -6" />
</svg>
</div>
</summary>

<div class="collapse-content p-0">
<div class="flex flex-col divide-y">
<div
v-for="i in [1, 2, 3]"
class="relative grid grid-cols-3 justify-center gap-2 p-4 pt-8"
>
<div
class="absolute left-1 top-1 inline-flex h-8 w-8 items-center justify-center self-start rounded-full border bg-gray-200 p-2"
>
{{ i }}
</div>

<FormControl label="Field Type:" required class="">
<select
v-model="metaItem.field_type"
class="select select-bordered select-sm"
>
<option value="text">Text</option>
<option value="textarea">Textarea</option>
</select>
</FormControl>

<FormControl label="Key:" required class="">
<input
type="text"
v-model="metaItem.key"
placeholder="e.g: co_author"
class="input input-sm input-bordered"
/>
</FormControl>

<FormControl label="Label:" :required="false" class="">
<input
type="text"
placeholder="e.g: Co Author"
class="input input-sm input-bordered"
/>
</FormControl>

<FormControl label="Value:" required class="col-span-full">
<input
type="text"
placeholder="e.g: Sobirin Rodriguez"
class="input input-sm input-bordered"
/>
</FormControl>

<div class="absolute right-1 top-1 flex">
<button
type="button"
class="btn btn-outline btn-error btn-sm"
>
Delete
</button>
</div>
</div>
</div>
</div>

<!-- <ModalConfirmation
:show="postRemoving.show"
@close="postRemoving.close()"
@confirm="postRemoving.triggerConfirm()"
v-bind="postRemoving.props"
/> -->
</details>
</template>
27 changes: 16 additions & 11 deletions resources/js/pages/posts/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { apiBasePath, slugify } from "@/utils";
import { useForm } from "laravel-precognition-vue";
import { useLoadData } from "@/composables/loadData";
import ContentEditor from "@/components/ContentEditor.vue";
import FormMetas from "@/components/FormMetas.vue";
const route = useRoute();
const router = useRouter();
Expand All @@ -30,6 +31,7 @@ const postForm = useForm("post", apiBasePath("posts"), {
is_visible: true,
excerpt: "",
content: "",
metas: [],
tags: [],
});
Expand All @@ -49,6 +51,7 @@ const populateForm = () => {
excerpt: data.excerpt,
content: data.content,
tags: tagsIds,
metas: data.metas,
});
});
};
Expand Down Expand Up @@ -134,17 +137,15 @@ const submit = () => {
:required="true"
:error-message="postForm.errors['title']"
>
<div class="flex flex-col gap-2">
<input
type="text"
v-model="postForm.title"
placeholder="e.g: Awesome Technology"
class="input input-bordered"
:class="{
'input-error': postForm.errors['title'],
}"
/>
</div>
<input
type="text"
v-model="postForm.title"
placeholder="e.g: Awesome Technology"
class="input input-bordered"
:class="{
'input-error': postForm.errors['title'],
}"
/>
</FormControl>

<div class="form-control">
Expand Down Expand Up @@ -221,6 +222,10 @@ const submit = () => {
</p>
</div>

<div class="py-8">
<FormMetas v-model="postForm.metas" />
</div>

<div
v-if="Object.keys(postForm.errors).length"
class="self-center"
Expand Down
3 changes: 2 additions & 1 deletion src/Http/Controllers/Api/PostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function index()
'deleted_at'
])
->with('tags')
->withCount('metas')
->latest()
->paginate(10)
->withQueryString();
Expand All @@ -49,7 +50,7 @@ public function index()

public function show(Post $post)
{
$post->load('tags');
$post->load('metas', 'tags');
return PostResource::make($post)->resolve();
}

Expand Down
14 changes: 10 additions & 4 deletions src/Http/Resources/PostResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@ public function toArray(Request $request): array
'content_type' => $this->whenHas('content_type'),
'excerpt' => $this->whenHas('excerpt'),
'content' => $this->whenHas('content'),
'parsed_content' => $this->when(
$this->content_type && $this->content,
fn () => $this->parsed_content
),

// * upcoming later
// 'parsed_content' => $this->when(
// $this->content_type && $this->content,
// fn () => $this->parsed_content
// ),

'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'deleted_at' => $this->deleted_at,

'metas_count' => $this->whenCounted('metas'),

'author' => $this->whenLoaded('author'),
'metas' => $this->whenLoaded('metas'),
'tags' => TagResource::collection($this->whenLoaded('tags')),
];
}
Expand Down
52 changes: 29 additions & 23 deletions src/Models/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

class Post extends Model
Expand All @@ -31,6 +32,11 @@ public function author(): BelongsTo
return $this->belongsTo('App\\Models\\User', 'author_id');
}

public function metas(): HasMany
{
return $this->hasMany(Postmeta::class, 'post_id');
}

public function tags(): BelongsToMany
{
return $this->belongsToMany(Tag::class, 'ngeblog_post_tag')
Expand Down Expand Up @@ -85,28 +91,28 @@ public function toggleVisibility()
return $this->save();
}

protected function parsedContent(): Attribute
{
return Attribute::get(function () {
if (! $this->exists) {
return null;
}

return match ($this->content_type) {
null => null,
self::CONTENT_TYPE_MARKDOWN => $this->parseMarkdown(),
self::CONTENT_TYPE_RICHTEXT => $this->parseRichtext(),
};
});
}

protected function parseMarkdown()
{
return Str::markdown($this->content);
}
// protected function parsedContent(): Attribute
// {
// return Attribute::get(function () {
// if (! $this->exists) {
// return null;
// }

// return match ($this->content_type) {
// null => null,
// self::CONTENT_TYPE_MARKDOWN => $this->parseMarkdown(),
// self::CONTENT_TYPE_RICHTEXT => $this->parseRichtext(),
// };
// });
// }

// protected function parseMarkdown()
// {
// return Str::markdown($this->content);
// }

protected function parseRichtext()
{
return $this->content;
}
// protected function parseRichtext()
// {
// return $this->content;
// }
}
34 changes: 34 additions & 0 deletions src/Models/Postmeta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace AntoniPutra\Ngeblog\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Postmeta extends Model
{
use HasFactory;

const FIELD_TYPE_TEXT = 'text';
const FIELD_TYPE_TEXTAREA = 'textarea';

protected $table = 'ngeblog_postmetas';

protected $guarded = [];

public function post(): BelongsTo
{
return $this->belongsTo(Post::class);
}

// * Dynamically casting the attributes.
// protected function getCastType($key)
// {
// if ($key == 'value' && !empty($this->type)) {
// return $this->type;
// } else {
// return parent::getCastType($key);
// }
// }
}
Loading

0 comments on commit 20055f7

Please sign in to comment.