new content notification working for client brief

This commit is contained in:
isUnknown 2024-11-22 09:20:38 +01:00
parent 8ae00d7657
commit c1d2c73118
9 changed files with 277 additions and 70 deletions

View file

@ -28,10 +28,94 @@ Comments:
url: file://s0lNtRA0Z7ybTCWG url: file://s0lNtRA0Z7ybTCWG
position: position:
pageIndex: 1 pageIndex: 1
x: '27.05459466102' x: "27.05459466102"
y: '35.135135135135' y: "35.135135135135"
replies:
-
location:
page:
uri: >
projects/miss-dior-blooming-bouquet/client-brief
title: Brief client
href: >
/projects/miss-dior-blooming-bouquet?dialog=client-brief
project:
title: Miss Dior Blooming Bouquet
uri: projects/miss-dior-blooming-bouquet
file:
uuid: file://s0lNtRA0Z7ybTCWG
url: file://s0lNtRA0Z7ybTCWG
position:
pageIndex: 1
replies: [ ] replies: [ ]
text: test text: test
author:
name: Utilisateur Dior
email: utilisateur@dior.com
uuid: user://HfuumN8s
role: client
date: 2024-11-22T08:08:39+01:00
id: m3seh19r
type: comment
isRead: false
parentId: m3sdsq23
-
location:
page:
uri: >
projects/miss-dior-blooming-bouquet/client-brief
title: Brief client
href: >
/projects/miss-dior-blooming-bouquet?dialog=client-brief
project:
title: Miss Dior Blooming Bouquet
uri: projects/miss-dior-blooming-bouquet
file:
uuid: file://s0lNtRA0Z7ybTCWG
url: file://s0lNtRA0Z7ybTCWG
position:
pageIndex: 1
replies: [ ]
text: Deuxième réponse
author:
name: Utilisateur Dior
email: utilisateur@dior.com
uuid: user://HfuumN8s
role: client
date: 2024-11-22T08:10:12+01:00
id: m3sej19k
type: comment
isRead: false
parentId: m3sdsq23
-
location:
page:
uri: >
projects/miss-dior-blooming-bouquet/client-brief
title: Brief client
href: >
/projects/miss-dior-blooming-bouquet?dialog=client-brief
project:
title: Miss Dior Blooming Bouquet
uri: projects/miss-dior-blooming-bouquet
file:
uuid: file://s0lNtRA0Z7ybTCWG
url: file://s0lNtRA0Z7ybTCWG
position:
pageIndex: 1
replies: [ ]
text: Encore
author:
name: Utilisateur Dior
email: utilisateur@dior.com
uuid: user://HfuumN8s
role: client
date: 2024-11-22T08:12:39+01:00
id: m3sem6sz
type: comment
isRead: false
parentId: m3sdsq23
text: test
author: author:
name: Adrien Payet name: Adrien Payet
email: adrien.payet@outlook.com email: adrien.payet@outlook.com
@ -41,3 +125,90 @@ Comments:
id: m3sdsq23 id: m3sdsq23
type: comment type: comment
isRead: false isRead: false
-
location:
page:
uri: >
projects/miss-dior-blooming-bouquet/client-brief
title: Brief client
href: >
/projects/miss-dior-blooming-bouquet?dialog=client-brief
project:
title: Miss Dior Blooming Bouquet
uri: projects/miss-dior-blooming-bouquet
file:
uuid: file://s0lNtRA0Z7ybTCWG
url: file://s0lNtRA0Z7ybTCWG
position:
pageIndex: 1
x: "65.847110638459"
y: "53.474903474903"
replies: [ ]
text: test
author:
name: Adrien Payet
email: adrien.payet@outlook.com
uuid: user://WWjXgPWk
role: admin
date: 2024-11-22T08:50:41+01:00
id: m3sfz36o
type: comment
isRead: false
-
location:
page:
uri: >
projects/miss-dior-blooming-bouquet/client-brief
title: Brief client
href: >
/projects/miss-dior-blooming-bouquet?dialog=client-brief
project:
title: Miss Dior Blooming Bouquet
uri: projects/miss-dior-blooming-bouquet
file:
uuid: file://s0lNtRA0Z7ybTCWG
url: file://s0lNtRA0Z7ybTCWG
position:
pageIndex: 1
x: "32.518325137231"
y: "62.548262548263"
replies: [ ]
text: test
author:
name: Adrien Payet
email: adrien.payet@outlook.com
uuid: user://WWjXgPWk
role: admin
date: 2024-11-22T09:18:05+01:00
id: m3sgybwq
type: comment
isRead: false
-
location:
page:
uri: >
projects/miss-dior-blooming-bouquet/client-brief
title: Brief client
href: >
/projects/miss-dior-blooming-bouquet?dialog=client-brief
project:
title: Miss Dior Blooming Bouquet
uri: projects/miss-dior-blooming-bouquet
file:
uuid: file://s0lNtRA0Z7ybTCWG
url: file://s0lNtRA0Z7ybTCWG
position:
pageIndex: 1
x: '73.769521704789'
y: '83.204633204633'
replies: [ ]
text: 'Adrien Payet : test'
author:
name: Adrien Payet
email: adrien.payet@outlook.com
uuid: user://WWjXgPWk
role: admin
date: 2024-11-22T09:20:04+01:00
id: m3sh0vfu
type: comment
isRead: false

View file

@ -1,30 +1,47 @@
<?php <?php
return [ return [
'pattern' => '(:all)validate-brief.json', 'pattern' => 'validate-brief.json',
'method' => 'POST', 'method' => 'POST',
'action' => function () { 'action' => function () {
$json = file_get_contents('php://input'); $json = file_get_contents('php://input');
$data = json_decode($json); $data = json_decode($json);
$page = page($data->pageUri); $brief = page($data->briefUri);
$project = $brief->parent();
$href = $data->dialogUri ? $data->dialogUri : $brief->url();
try { try {
$newPage = $page->update([ $newPage = $brief->update([
'isValidated' => 'true' 'isValidated' => 'true'
]); ]);
echo json_encode([
"success" => "'" . $newPage->title()->value() . "' brief validated."
]);
kirby()->user()->sendNotification($newPage->parent(), [ $notification = [
'location' => [
'href' => (string) $href,
'project' => [
'title' => (string) $project->title(),
'uri' => (string) $project->url()
]
],
'date' => $newPage->modified('YYYY-MM-DD'), 'date' => $newPage->modified('YYYY-MM-DD'),
'author' => kirby()->user()->name()->isNotEmpty() ? kirby()->user()->name() : kirby()->user()->email(), 'author' => [
'url' => $newPage->url(), 'name' => (string) kirby()->user()->name(),
'email' => (string) kirby()->user()->email(),
'uuid' => (string) kirby()->user()->uuid(),
'role' => (string) kirby()->user()->role(),
],
'type' => 'content' 'type' => 'content'
]); ];
kirby()->user()->sendNotification($project, $notification);
return [
"success" => "'" . $project->title()->value() . "' brief validated."
];
} catch (\Throwable $th) { } catch (\Throwable $th) {
return [ return [
"error" => "Can't validate '" . $page->title()->value() . "' brief.", "error" => "Can't validate '" . $brief->title()->value() . "' brief.",
'details' => $th->getMessage() 'details' => $th->getMessage()
]; ];
} }

View file

@ -35,7 +35,7 @@ class ProjectPage extends Page {
'slug' => $child->slug(), 'slug' => $child->slug(),
'index' => intval($child->stepIndex()->value()), 'index' => intval($child->stepIndex()->value()),
'modified' => $child->modified('Y-MM-dd'), 'modified' => $child->modified('Y-MM-dd'),
'isValidated' => $child->isValidated()->value() ?? false, 'isValidated' => (bool) $child->isValidated()->value() ?? false,
'uri' => $uri, 'uri' => $uri,
'files' => $files, 'files' => $files,
]; ];

View file

@ -33,7 +33,7 @@ return [
'y' => $data->position->y 'y' => $data->position->y
], ],
'replies' => [], 'replies' => [],
'text' => $data->text, 'text' => $user->name()->isNotEmpty() ? $user->name()->value() . ' : ' . $data->text : $user->email()->value() . ' : ' . $data->text,
'author' => $user, 'author' => $user,
'date' => (string) $data->date, 'date' => (string) $data->date,
'id' => $data->id, 'id' => $data->id,

View file

@ -9,7 +9,14 @@ 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); $parsedUrl = parse_url($data->path);
$query = $parsedUrl['query'] ?? null;
parse_str($query, $queryParams);
$stepSlug = $queryParams['dialog'] ?? null;
$targetPageUri = $stepSlug ? $parsedUrl['path'] . '/' . $stepSlug : $parsedUrl['path'];
$page = page($targetPageUri);
$file = $page->file($data->fileName); $file = $page->file($data->fileName);
$user = kirby()->user($data->userUuid); $user = kirby()->user($data->userUuid);
@ -17,6 +24,7 @@ return [
$comments = $file->comments()->isEmpty() == true ? [] : Yaml::decode($file->comments()->value()); $comments = $file->comments()->isEmpty() == true ? [] : Yaml::decode($file->comments()->value());
$data = [ $data = [
'href' => $data->path,
'page' => $page, 'page' => $page,
'parentId' => $data->parentId, 'parentId' => $data->parentId,
'file' => $file, 'file' => $file,

View file

@ -13,12 +13,13 @@
* @throws Exception If an error occurs while updating a user's notifications. * @throws Exception If an error occurs while updating a user's notifications.
*/ */
return function ($project, $notificationData) { return function ($project, $notificationData) {
$recipients = $project->managers()->without($this); $recipients = $project->managers()->without($this);
if (!$recipients) return; if ($recipients->isEmpty()) return;
$notificationData['isRead'] = false;
$notificationData['isRead'];
foreach ($recipients as $otherUser) { foreach ($recipients as $otherUser) {
try { try {
$notifications = $otherUser->notifications()->isNotEmpty() $notifications = $otherUser->notifications()->isNotEmpty()
@ -31,6 +32,7 @@ return function ($project, $notificationData) {
'notifications' => $notifications 'notifications' => $notifications
]); ]);
} catch (\Throwable $th) { } catch (\Throwable $th) {
error_log("Notification error for user " . $otherUser->email() . ": " . $th->getMessage());
throw new Exception("Error updating notifications: " . $th->getMessage() . ' line ' . $th->getLine(), 1); throw new Exception("Error updating notifications: " . $th->getMessage() . ' line ' . $th->getLine(), 1);
} }
} }

View file

@ -183,12 +183,13 @@ function handleSubmit(event = null) {
userUuid: user.uuid, userUuid: user.uuid,
text: draftComment.value.text, text: draftComment.value.text,
date, date,
position: position: {
{ pageIndex: openedComment.value
pageIndex: draftComment.value.position.pageIndex, ? openedComment.value.position.pageIndex
x: draftComment.value.position?.x, : draftComment.value.position.pageIndex,
y: draftComment.value.position?.y, x: openedComment.value ? false : draftComment.value.position.x,
} ?? false, y: openedComment.value ? false : draftComment.value.position.y,
},
id: uniqid(), id: uniqid(),
}; };
if (openedComment.value) { if (openedComment.value) {
@ -201,9 +202,7 @@ function handleSubmit(event = null) {
async function replyComment(newComment) { async function replyComment(newComment) {
newComment.parentId = openedComment.value.id; newComment.parentId = openedComment.value.id;
const newFile = await api.replyComment(newComment); const newFile = await api.replyComment(newComment);
draftComment.value.text = ""; resetDraftComment();
draftComment.value.position = null;
draftComment.value.padeIndex = null;
isAddOpen.value = false; isAddOpen.value = false;
dialog.updateFile(newFile); dialog.updateFile(newFile);
openedComment.value = newFile.comments.find( openedComment.value = newFile.comments.find(
@ -213,12 +212,15 @@ async function replyComment(newComment) {
async function addComment(newComment) { async function addComment(newComment) {
const newFile = await api.addComment(newComment); const newFile = await api.addComment(newComment);
resetDraftComment();
isAddOpen.value = false;
dialog.updateFile(newFile);
}
function resetDraftComment() {
draftComment.value.text = ""; draftComment.value.text = "";
draftComment.value.position = null; draftComment.value.position = null;
draftComment.value.padeIndex = null; draftComment.value.padeIndex = null;
isAddOpen.value = false;
dialog.updateFile(newFile);
} }
function closeComment() { function closeComment() {
@ -267,9 +269,7 @@ function handleCommentPositionClick(event) {
} }
function openComment(comment) { function openComment(comment) {
if (comment.replies.length) {
openedComment.value = comment; openedComment.value = comment;
}
} }
</script> </script>

View file

@ -12,7 +12,8 @@
<template #header> <template #header>
<button <button
v-if=" v-if="
dialog.content.id === 'clientBrief' && !dialog.content?.isValidated dialog.content.id === 'clientBrief' &&
dialog.content.isValidated !== true
" "
class="btn" class="btn"
@click="validate()" @click="validate()"
@ -191,8 +192,15 @@ function showDraftMarker(draftComment) {
} }
async function validate() { async function validate() {
const response = await api.validateBrief(route.path + "/client-brief"); const response = await api.validateBrief(
route.path + "/client-brief",
route.fullPath
);
if (response.success) {
dialog.content.isValidated = true; dialog.content.isValidated = true;
} else {
console.alert(response);
}
} }
</script> </script>

View file

@ -212,11 +212,12 @@ export const useApiStore = defineStore("api", () => {
} }
} }
async function validateBrief(briefUri) { async function validateBrief(briefUri, dialogUri = null) {
const headers = { const headers = {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
pageUri: briefUri, briefUri: briefUri,
dialogUri,
}), }),
}; };
try { try {
@ -231,7 +232,7 @@ export const useApiStore = defineStore("api", () => {
return data; return data;
} }
} catch (error) { } catch (error) {
throw error; console.log(error);
} }
} }