merge and add opened comment view
This commit is contained in:
parent
c3860d4a38
commit
4e4216f8d3
6 changed files with 164 additions and 134 deletions
|
|
@ -12,11 +12,11 @@ Template: document
|
||||||
|
|
||||||
Comments:
|
Comments:
|
||||||
|
|
||||||
m2u905al:
|
m2ucagze:
|
||||||
pageUri: >
|
pageUri: >
|
||||||
projects/miss-dior-blooming-bouquet/client-brief
|
projects/miss-dior-blooming-bouquet/client-brief
|
||||||
fileUuid: file://s0lNtRA0Z7ybTCWG
|
fileUuid: file://s0lNtRA0Z7ybTCWG
|
||||||
filePageTarget: 1
|
filePageIndex: 1
|
||||||
position:
|
position:
|
||||||
x: null
|
x: null
|
||||||
y: null
|
y: null
|
||||||
|
|
@ -27,22 +27,22 @@ m2u905al:
|
||||||
email: adrien.payet@outlook.com
|
email: adrien.payet@outlook.com
|
||||||
uuid: user://WWjXgPWk
|
uuid: user://WWjXgPWk
|
||||||
role: admin
|
role: admin
|
||||||
date: 2024-10-29T10:31:23+01:00
|
date: 2024-10-29T12:03:24+01:00
|
||||||
id: m2u905al
|
id: m2ucagze
|
||||||
m2u955a7:
|
m2ucgaoe:
|
||||||
pageUri: >
|
pageUri: >
|
||||||
projects/miss-dior-blooming-bouquet/client-brief
|
projects/miss-dior-blooming-bouquet/client-brief
|
||||||
fileUuid: file://s0lNtRA0Z7ybTCWG
|
fileUuid: file://s0lNtRA0Z7ybTCWG
|
||||||
filePageTarget: 1
|
filePageIndex: 1
|
||||||
position:
|
position:
|
||||||
x: null
|
x: null
|
||||||
y: null
|
y: null
|
||||||
replies: [ ]
|
replies: [ ]
|
||||||
text: come2
|
text: Deuxième commentaire
|
||||||
user:
|
user:
|
||||||
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-29T10:35:16+01:00
|
date: 2024-10-29T12:07:55+01:00
|
||||||
id: m2u955a7
|
id: m2ucgaoe
|
||||||
|
|
@ -17,7 +17,7 @@ return [
|
||||||
$newComment = [
|
$newComment = [
|
||||||
'pageUri' => $data->pageUri,
|
'pageUri' => $data->pageUri,
|
||||||
'fileUuid' => (string) $file->uuid(),
|
'fileUuid' => (string) $file->uuid(),
|
||||||
'filePageTarget' => $data->targetPage,
|
'filePageIndex' => $data->filePageIndex,
|
||||||
'position' => [
|
'position' => [
|
||||||
'x' => null,
|
'x' => null,
|
||||||
'y' => null
|
'y' => null
|
||||||
|
|
@ -40,7 +40,7 @@ return [
|
||||||
'comments' => $comments
|
'comments' => $comments
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user->sendNotification('comments', $newComment);
|
// $user->sendNotification('comments', $newComment);
|
||||||
|
|
||||||
return getFileData($newFile);
|
return getFileData($newFile);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
public/site/plugins/notifications/user-methods/read.php
Normal file
16
public/site/plugins/notifications/user-methods/read.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return function ($group, $notificationId) {
|
||||||
|
$notifications = Yaml::decode($this->notifications()->value());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$notifications[$group][$notificationId]['isRead'] = true;
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
//throw $th;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->update([
|
||||||
|
"notifications" => $notifications
|
||||||
|
]);
|
||||||
|
return $notifications;
|
||||||
|
};
|
||||||
26
public/site/plugins/notifications/user-methods/send.php
Normal file
26
public/site/plugins/notifications/user-methods/send.php
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return function ($group, $data) {
|
||||||
|
foreach (kirby()->users()->not($this) as $otherUser) {
|
||||||
|
try {
|
||||||
|
$notifications = $otherUser->notifications()->isNotEmpty()
|
||||||
|
? Yaml::decode($otherUser->notifications()->value())
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (!isset($notifications[$group])) {
|
||||||
|
$notifications[$group] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$data['isRead'] = false;
|
||||||
|
|
||||||
|
$notifications[$group][$data['id']] = $data;
|
||||||
|
|
||||||
|
$otherUser->update([
|
||||||
|
'notifications' => $notifications
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
throw new Exception("Error updating notifications: " . $th->getMessage() . ' line ' . $th->getLine(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
78
src/components/comments/Comment.vue
Normal file
78
src/components/comments/Comment.vue
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
<template>
|
||||||
|
<article class="comment | flow" :data-status="setStatus(comment)">
|
||||||
|
<header>
|
||||||
|
<p>
|
||||||
|
<strong>{{ comment.user.name ?? comment.user.email }}</strong>
|
||||||
|
<template v-if="commentIndex">
|
||||||
|
<span class="comment__id">#{{ commentIndex }}</span>
|
||||||
|
•
|
||||||
|
</template>
|
||||||
|
<span class="comment__page">Page {{ comment.filePageIndex }}</span>
|
||||||
|
<time :datetime="dayjs(comment.date).format('YYYY-MM-DD')">{{
|
||||||
|
formatDate(comment.date)
|
||||||
|
}}</time>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="comment__body">
|
||||||
|
{{ comment.text }}
|
||||||
|
</p>
|
||||||
|
<footer v-if="comment.replies?.length > 0" class="comment__replies">
|
||||||
|
<span>{{ comment.replies.length }} réponse</span>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import "dayjs/locale/fr";
|
||||||
|
|
||||||
|
dayjs.locale("fr");
|
||||||
|
|
||||||
|
const { comment, commentIndex } = defineProps({
|
||||||
|
comment: Object,
|
||||||
|
commentIndex: Number,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
function setStatus(comment) {
|
||||||
|
try {
|
||||||
|
if (!user?.notifications?.comments[comment.id].isRead) {
|
||||||
|
return "unread";
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(date) {
|
||||||
|
const todayNumber = parseInt(dayjs().format("YYMMD"));
|
||||||
|
const dateNumber = parseInt(dayjs(date).format("YYMMD"));
|
||||||
|
|
||||||
|
if (dateNumber === todayNumber) {
|
||||||
|
return "Aujourd'hui";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dateNumber === todayNumber - 1) {
|
||||||
|
return "hier";
|
||||||
|
}
|
||||||
|
|
||||||
|
return dayjs(date).format("D MMM YY");
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAddField() {
|
||||||
|
isAddOpen.value = false;
|
||||||
|
newCommentText.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readNotification(notificationId) {
|
||||||
|
const newNotifications = await api.readNotification(
|
||||||
|
user.uuid,
|
||||||
|
"comments",
|
||||||
|
notificationId
|
||||||
|
);
|
||||||
|
|
||||||
|
user.notifications = newNotifications;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -2,87 +2,38 @@
|
||||||
<aside id="comments-container" aria-labelledby="comments-label">
|
<aside id="comments-container" aria-labelledby="comments-label">
|
||||||
<h2 id="comments-label" class="sr-only">Commentaires</h2>
|
<h2 id="comments-label" class="sr-only">Commentaires</h2>
|
||||||
<div class="comments | flow">
|
<div class="comments | flow">
|
||||||
|
<template v-if="comments">
|
||||||
<template v-if="!openedComment">
|
<template v-if="!openedComment">
|
||||||
<!-- TODO: faire un composant comment -->
|
<Comment
|
||||||
<article
|
|
||||||
v-for="(comment, commentIndex) in Object.values(comments).reverse()"
|
v-for="(comment, commentIndex) in Object.values(comments).reverse()"
|
||||||
:key="commentIndex"
|
:comment="comment"
|
||||||
class="comment | flow"
|
:commentIndex="commentIndex + 1"
|
||||||
:data-status="setStatus(comment)"
|
:key="comment.id"
|
||||||
@click="open(comment)"
|
@click="openedComment = comment"
|
||||||
>
|
/>
|
||||||
<header>
|
|
||||||
<p>
|
|
||||||
<strong>{{ comment.user.name ?? comment.user.email }}</strong>
|
|
||||||
<span class="comment__id">#{{ commentIndex + 1 }}</span> •
|
|
||||||
<span class="comment__page">Page {{ pageIndex }}</span>
|
|
||||||
<time :datetime="dayjs(comment.date).format('YYYY-MM-DD')">{{
|
|
||||||
formatDate(comment.date)
|
|
||||||
}}</time>
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
<p class="comment__body">
|
|
||||||
{{ comment.text }}
|
|
||||||
</p>
|
|
||||||
<!-- TODO: à dynamiser (affichage ou non si replies + nombre de replies)-->
|
|
||||||
<footer class="comment__replies">
|
|
||||||
<span>1 réponse</span>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<!-- TODO: mettre la bonne cible pour to: -->
|
<button
|
||||||
<router-link
|
|
||||||
:to="'/' + page.parent"
|
|
||||||
class="btn | justify-start w-full | bg-white-10 text-white | px-8"
|
class="btn | justify-start w-full | bg-white-10 text-white | px-8"
|
||||||
data-icon="chevron-single-left"
|
data-icon="chevron-single-left"
|
||||||
|
@click="openedComment = null"
|
||||||
>
|
>
|
||||||
<span>Retour à la liste</span>
|
<span>Retour à la liste</span>
|
||||||
</router-link>
|
</button>
|
||||||
<!-- TODO: utiliser le composant comment ici -->
|
<Comment :comment="openedComment" />
|
||||||
<article
|
<div v-if="openedComment?.replies?.length > 0" class="replies">
|
||||||
class="comment"
|
<Comment
|
||||||
data-opened="true"
|
v-for="(reply, commentIndex) in Object.values(
|
||||||
>
|
openedComment.replies
|
||||||
<header>
|
).reverse()"
|
||||||
<p>
|
:comment="reply"
|
||||||
<strong>{{ openedComment.user.name ?? openedComment.user.email }}</strong>
|
:commentIndex="commentIndex + 1"
|
||||||
<span class="comment__id">#{{ commentIndex + 1 }}</span> •
|
:key="reply.id"
|
||||||
<span class="comment__page">Page {{ pageIndex }}</span>
|
/>
|
||||||
<time :datetime="dayjs(openedComment.date).format('YYYY-MM-DD')">{{
|
|
||||||
formatDate(openedComment.date)
|
|
||||||
}}</time>
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
<p class="comment__body">
|
|
||||||
{{ openedComment.text }}
|
|
||||||
</p>
|
|
||||||
<footer class="comment__replies">
|
|
||||||
<span>1 réponse</span>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
<div class="replies">
|
|
||||||
<!-- TODO: utiliser le composant comment ici -->
|
|
||||||
<article
|
|
||||||
v-for="comment in openedComment.replies"
|
|
||||||
class="comment reply"
|
|
||||||
>
|
|
||||||
<header>
|
|
||||||
<p>
|
|
||||||
<strong>{{ comment.user.name ?? comment.user.email }}</strong>
|
|
||||||
<span class="comment__id">#{{ commentIndex + 1 }}</span> •
|
|
||||||
<span class="comment__page">Page {{ pageIndex }}</span>
|
|
||||||
<time :datetime="dayjs(comment.date).format('YYYY-MM-DD')">{{
|
|
||||||
formatDate(comment.date)
|
|
||||||
}}</time>
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
<p class="comment__body">
|
|
||||||
{{ comment.text }}
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else> état aucun commentaire </template>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="!openedComment && !isAddOpen"
|
v-if="!openedComment && !isAddOpen"
|
||||||
|
|
@ -93,7 +44,7 @@
|
||||||
Ajouter un commentaire
|
Ajouter un commentaire
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="openedComment && !isReplyOpen"
|
v-else
|
||||||
id="reply-comment"
|
id="reply-comment"
|
||||||
class="btn btn--white-20 | justify-start w-full | text-white-50"
|
class="btn btn--white-20 | justify-start w-full | text-white-50"
|
||||||
@click="isReplyOpen = true"
|
@click="isReplyOpen = true"
|
||||||
|
|
@ -135,6 +86,7 @@ import { ref } from "vue";
|
||||||
import { useUserStore } from "../../stores/user";
|
import { useUserStore } from "../../stores/user";
|
||||||
import { usePageStore } from "../../stores/page";
|
import { usePageStore } from "../../stores/page";
|
||||||
import { useApiStore } from "../../stores/api";
|
import { useApiStore } from "../../stores/api";
|
||||||
|
import Comment from "./Comment.vue";
|
||||||
|
|
||||||
dayjs.locale("fr");
|
dayjs.locale("fr");
|
||||||
|
|
||||||
|
|
@ -160,7 +112,7 @@ async function addComment(event) {
|
||||||
const date = dayjs().format();
|
const date = dayjs().format();
|
||||||
const comment = {
|
const comment = {
|
||||||
pageUri: page.uri + "/client-brief",
|
pageUri: page.uri + "/client-brief",
|
||||||
targetPage: currentPageIndex,
|
filePageIndex: currentPageIndex,
|
||||||
fileName: file.name,
|
fileName: file.name,
|
||||||
userUuid: user.uuid,
|
userUuid: user.uuid,
|
||||||
text: newCommentText.value,
|
text: newCommentText.value,
|
||||||
|
|
@ -172,46 +124,4 @@ async function addComment(event) {
|
||||||
isAddOpen.value = false;
|
isAddOpen.value = false;
|
||||||
emits("update:file", newFile);
|
emits("update:file", newFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(date) {
|
|
||||||
const todayNumber = parseInt(dayjs().format("YYMMD"));
|
|
||||||
const dateNumber = parseInt(dayjs(date).format("YYMMD"));
|
|
||||||
|
|
||||||
if (dateNumber === todayNumber) {
|
|
||||||
return "Aujourd'hui";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dateNumber === todayNumber - 1) {
|
|
||||||
return "hier";
|
|
||||||
}
|
|
||||||
|
|
||||||
return dayjs(date).format("D MMM YY");
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeAddField() {
|
|
||||||
isAddOpen.value = false;
|
|
||||||
newCommentText.value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function setStatus(comment) {
|
|
||||||
try {
|
|
||||||
if (!user?.notifications?.comments[comment.id].isRead) {
|
|
||||||
return "unread";
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readNotification(notificationId) {
|
|
||||||
const newNotifications = await api.readNotification(
|
|
||||||
user.uuid,
|
|
||||||
"comments",
|
|
||||||
notificationId
|
|
||||||
);
|
|
||||||
|
|
||||||
user.notifications = newNotifications;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue