delete comment / reply working
This commit is contained in:
parent
58c08690f8
commit
ac48b4166a
5 changed files with 131 additions and 59 deletions
|
|
@ -13,14 +13,6 @@ Template: document
|
||||||
Comments:
|
Comments:
|
||||||
|
|
||||||
-
|
-
|
||||||
page:
|
|
||||||
uri: projects/miss-dior-blooming-bouquet
|
|
||||||
title: Miss Dior Blooming Bouquet
|
|
||||||
file:
|
|
||||||
uuid: file://s0lNtRA0Z7ybTCWG
|
|
||||||
pageIndex: 1
|
|
||||||
replies:
|
|
||||||
-
|
|
||||||
page:
|
page:
|
||||||
uri: projects/miss-dior-blooming-bouquet
|
uri: projects/miss-dior-blooming-bouquet
|
||||||
title: Miss Dior Blooming Bouquet
|
title: Miss Dior Blooming Bouquet
|
||||||
|
|
@ -28,44 +20,14 @@ Comments:
|
||||||
uuid: file://s0lNtRA0Z7ybTCWG
|
uuid: file://s0lNtRA0Z7ybTCWG
|
||||||
pageIndex: 1
|
pageIndex: 1
|
||||||
replies: [ ]
|
replies: [ ]
|
||||||
text: Test de réponse
|
text: Un certain commentaire
|
||||||
author:
|
author:
|
||||||
name: Adrien Payet
|
name: Adrien Payet
|
||||||
email: adrien.payet@outlook.com
|
email: adrien.payet@outlook.com
|
||||||
uuid: user://WWjXgPWk
|
uuid: user://WWjXgPWk
|
||||||
role: admin
|
role: admin
|
||||||
date: 2024-10-30T12:26:44+01:00
|
date: 2024-10-30T16:26:22+01:00
|
||||||
id: m2vskcko
|
id: m2w14iph
|
||||||
type: comment
|
|
||||||
isRead: false
|
|
||||||
parentId: m2vsk6jn
|
|
||||||
-
|
|
||||||
page:
|
|
||||||
uri: projects/miss-dior-blooming-bouquet
|
|
||||||
title: Miss Dior Blooming Bouquet
|
|
||||||
file:
|
|
||||||
uuid: file://s0lNtRA0Z7ybTCWG
|
|
||||||
pageIndex: 1
|
|
||||||
replies: [ ]
|
|
||||||
text: deuxième réponse
|
|
||||||
author:
|
|
||||||
name: Adrien Payet
|
|
||||||
email: adrien.payet@outlook.com
|
|
||||||
uuid: user://WWjXgPWk
|
|
||||||
role: admin
|
|
||||||
date: 2024-10-30T12:27:42+01:00
|
|
||||||
id: m2vslkxg
|
|
||||||
type: comment
|
|
||||||
isRead: false
|
|
||||||
parentId: m2vsk6jn
|
|
||||||
text: Un premier commentaire
|
|
||||||
author:
|
|
||||||
name: Adrien Payet
|
|
||||||
email: adrien.payet@outlook.com
|
|
||||||
uuid: user://WWjXgPWk
|
|
||||||
role: admin
|
|
||||||
date: 2024-10-30T12:26:37+01:00
|
|
||||||
id: m2vsk6jn
|
|
||||||
type: comment
|
type: comment
|
||||||
isRead: false
|
isRead: false
|
||||||
position:
|
position:
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,50 @@ return [
|
||||||
$json = file_get_contents('php://input');
|
$json = file_get_contents('php://input');
|
||||||
$data = json_decode($json);
|
$data = json_decode($json);
|
||||||
|
|
||||||
$page = page($data->pageUri);
|
$page = page($data->page->uri);
|
||||||
$file = $page->file($data->fileName);
|
$file = $page->file($data->file->uuid);
|
||||||
$user = kirby()->user($data->userUuid);
|
$isReply = $data->parentId ?? false;
|
||||||
|
|
||||||
|
|
||||||
$comments = $file->comments()->isEmpty() == true ? [] : Yaml::decode($file->comments()->value());
|
$comments = $file->comments()->isEmpty() == true ? [] : Yaml::decode($file->comments()->value());
|
||||||
|
|
||||||
unset($comments[$data->id] );
|
foreach ($comments as $key => &$comment) {
|
||||||
|
if ($isReply) {
|
||||||
|
if ($comment['id'] === $data->parentId) {
|
||||||
|
foreach ($comment['replies'] as $replyKey => $reply) {
|
||||||
|
if ($reply['id'] === $data->id) {
|
||||||
|
unset($comment['replies'][$replyKey]);
|
||||||
|
$comment['replies'] = array_values($comment['replies']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($comment['id'] === $data->id) {
|
||||||
|
unset($comments[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$comments = array_values($comments); // Réindexe les commentaires
|
||||||
|
|
||||||
|
foreach (kirby()->users() as $user) {
|
||||||
|
try {
|
||||||
|
$notifications = $user->notifications()->isNotEmpty()
|
||||||
|
? Yaml::decode($user->notifications()->value())
|
||||||
|
: [];
|
||||||
|
|
||||||
|
foreach ($notifications as $key => $notification) {
|
||||||
|
if ($notification['id'] === $data->id) {
|
||||||
|
unset($notifications[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update([
|
||||||
|
'notifications' => $notifications
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
throw new Exception("Error updating notifications: " . $th->getMessage() . ' line ' . $th->getLine(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$newFile = $file->update([
|
$newFile = $file->update([
|
||||||
'comments' => $comments
|
'comments' => $comments
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,36 @@
|
||||||
•
|
•
|
||||||
</template>
|
</template>
|
||||||
<span class="comment__page">Page {{ comment.file.pageIndex }}</span>
|
<span class="comment__page">Page {{ comment.file.pageIndex }}</span>
|
||||||
<time class="comment__date" :datetime="dayjs(comment.date).format('YYYY-MM-DD')">{{
|
<time
|
||||||
formatDate(comment.date)
|
class="comment__date"
|
||||||
}}</time>
|
:datetime="dayjs(comment.date).format('YYYY-MM-DD')"
|
||||||
|
>{{ formatDate(comment.date) }}</time
|
||||||
|
>
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
<p class="comment__body">
|
<p class="comment__body">
|
||||||
{{ comment.text }}
|
{{ comment.text }}
|
||||||
</p>
|
</p>
|
||||||
<footer v-if="comment.replies?.length > 0" class="comment__replies">
|
<footer class="comment__replies">
|
||||||
<p>{{ comment.replies.length }} réponse{{ comment.replies.length > 1 ? 's' : '' }}</p>
|
<p v-if="comment.replies?.length > 0">
|
||||||
<!-- TODO: n'afficher que s'il s'agit du commentaire de l'utilisateur actuellement connecté -->
|
{{ comment.replies.length }} réponse{{
|
||||||
<div class="comment__ctas | mt-8">
|
comment.replies.length > 1 ? "s" : ""
|
||||||
<button class="btn btn--transparent btn--icon btn--sm" data-icon="edit"><span class="sr-only">Éditer</span></button>
|
}}
|
||||||
<button class="btn btn--transparent btn--icon btn--sm" data-icon="delete"><span class="sr-only">Supprimer</span></button>
|
</p>
|
||||||
|
<div
|
||||||
|
v-if="comment.author.uuid === user.uuid"
|
||||||
|
class="comment__ctas | mt-8"
|
||||||
|
>
|
||||||
|
<button class="btn btn--transparent btn--icon btn--sm" data-icon="edit">
|
||||||
|
<span class="sr-only">Éditer</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn--transparent btn--icon btn--sm"
|
||||||
|
data-icon="delete"
|
||||||
|
@click="deleteComment($event, comment)"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Supprimer</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
|
|
@ -30,6 +46,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import "dayjs/locale/fr";
|
import "dayjs/locale/fr";
|
||||||
|
import { useUserStore } from "../../stores/user";
|
||||||
|
import { useApiStore } from "../../stores/api";
|
||||||
|
|
||||||
dayjs.locale("fr");
|
dayjs.locale("fr");
|
||||||
|
|
||||||
|
|
@ -38,6 +56,11 @@ const { comment, commentIndex } = defineProps({
|
||||||
commentIndex: Number,
|
commentIndex: Number,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(["update:file", "close:comment"]);
|
||||||
|
|
||||||
|
const { user } = useUserStore();
|
||||||
|
const api = useApiStore();
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
function setStatus(comment) {
|
function setStatus(comment) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -80,6 +103,15 @@ async function readNotification(notificationId) {
|
||||||
|
|
||||||
user.notifications = newNotifications;
|
user.notifications = newNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteComment(event, comment) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const newFile = await api.deleteComment(comment);
|
||||||
|
emits("update:file", newFile);
|
||||||
|
if (comment.parentId) {
|
||||||
|
emits("close:comment");
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
:commentIndex="comments.length - commentIndex"
|
:commentIndex="comments.length - commentIndex"
|
||||||
:key="comment.id"
|
:key="comment.id"
|
||||||
@click="openedComment = comment"
|
@click="openedComment = comment"
|
||||||
|
@update:file="changeFile"
|
||||||
|
@close:comment="closeComment"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
|
@ -23,13 +25,20 @@
|
||||||
>
|
>
|
||||||
<span>Retour à la liste</span>
|
<span>Retour à la liste</span>
|
||||||
</button>
|
</button>
|
||||||
<Comment :comment="openedComment" data-opened="true" />
|
<Comment
|
||||||
|
:comment="openedComment"
|
||||||
|
data-opened="true"
|
||||||
|
@update:file="changeFile"
|
||||||
|
@close:comment="closeComment"
|
||||||
|
/>
|
||||||
<div v-if="sortedReplies.length > 0" class="replies | flow">
|
<div v-if="sortedReplies.length > 0" class="replies | flow">
|
||||||
<Comment
|
<Comment
|
||||||
v-for="(reply, commentIndex) in sortedReplies"
|
v-for="(reply, commentIndex) in sortedReplies"
|
||||||
:comment="reply"
|
:comment="reply"
|
||||||
:commentIndex="sortedReplies.length - commentIndex"
|
:commentIndex="sortedReplies.length - commentIndex"
|
||||||
:key="reply.id"
|
:key="reply.id"
|
||||||
|
@update:file="changeFile"
|
||||||
|
@close:comment="closeComment"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -154,6 +163,15 @@ async function addComment(newComment) {
|
||||||
isAddOpen.value = false;
|
isAddOpen.value = false;
|
||||||
emits("update:file", newFile);
|
emits("update:file", newFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeFile(newFile) {
|
||||||
|
console.log(newFile);
|
||||||
|
emits("update:file", newFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeComment() {
|
||||||
|
openedComment.value = null;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,29 @@ export const useApiStore = defineStore("api", () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteComment(comment) {
|
||||||
|
const headers = {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(comment),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("/delete-comment.json", headers);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
const newFile = await response.json();
|
||||||
|
return newFile;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
"Une erreur s'est produite lors de la suppression du commentaire :",
|
||||||
|
comment,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function replyComment(comment) {
|
async function replyComment(comment) {
|
||||||
const headers = {
|
const headers = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -198,6 +221,7 @@ export const useApiStore = defineStore("api", () => {
|
||||||
fetchData,
|
fetchData,
|
||||||
fetchRoute,
|
fetchRoute,
|
||||||
addComment,
|
addComment,
|
||||||
|
deleteComment,
|
||||||
replyComment,
|
replyComment,
|
||||||
readNotification,
|
readNotification,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue