comments / notifications : improve abstraction
This commit is contained in:
parent
f467012241
commit
32c026acfe
11 changed files with 92 additions and 65 deletions
|
|
@ -13,11 +13,23 @@ Template: document
|
||||||
Comments:
|
Comments:
|
||||||
|
|
||||||
-
|
-
|
||||||
page:
|
location:
|
||||||
uri: projects/miss-dior-blooming-bouquet
|
page:
|
||||||
title: Miss Dior Blooming Bouquet
|
uri: >
|
||||||
file:
|
projects/miss-dior-blooming-bouquet/client-brief
|
||||||
uuid: file://s0lNtRA0Z7ybTCWG
|
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: '20.46332046332'
|
||||||
replies: [ ]
|
replies: [ ]
|
||||||
text: test
|
text: test
|
||||||
author:
|
author:
|
||||||
|
|
@ -25,10 +37,7 @@ Comments:
|
||||||
email: adrien.payet@outlook.com
|
email: adrien.payet@outlook.com
|
||||||
uuid: user://WWjXgPWk
|
uuid: user://WWjXgPWk
|
||||||
role: admin
|
role: admin
|
||||||
position:
|
date: 2024-11-18T11:59:06+01:00
|
||||||
pageIndex: 1
|
id: m3mwxzuo
|
||||||
x: '25.96184356358'
|
type: comment
|
||||||
y: '22.393822393822'
|
isRead: false
|
||||||
date: 2024-11-17T12:13:39+01:00
|
|
||||||
id: m3li0uhb
|
|
||||||
type: comment
|
|
||||||
|
|
@ -28,6 +28,7 @@ class ProjectPage extends Page {
|
||||||
return [
|
return [
|
||||||
'label' => $child->title()->value(),
|
'label' => $child->title()->value(),
|
||||||
'id' => $child->stepName()->value(),
|
'id' => $child->stepName()->value(),
|
||||||
|
'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'),
|
||||||
'uri' => $uri,
|
'uri' => $uri,
|
||||||
|
|
@ -44,13 +45,13 @@ class ProjectPage extends Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($child->pdf()->isNotEmpty()) {
|
if ($child->pdf()->isNotEmpty()) {
|
||||||
$uri = $child->parent()->uri() . '?dialog=' . $child->stepName()->value();
|
$uri = $child->parent()->uri() . '?dialog=' . $child->slug();
|
||||||
$files[] = getFileData($child->pdf()->toFile());
|
$files[] = getFileData($child->pdf()->toFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleVirtualSampleStep($child, &$files, &$uri) {
|
private function handleVirtualSampleStep($child, &$files, &$uri) {
|
||||||
$uri = $child->parent()->uri() . '?dialog=' . $child->stepName()->value();
|
$uri = $child->parent()->uri() . '?dialog=' . $child->slug();
|
||||||
foreach ($child->views()->toFiles() as $file) {
|
foreach ($child->views()->toFiles() as $file) {
|
||||||
$files[] = getFileData($file);
|
$files[] = getFileData($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,
|
||||||
'file' => $file,
|
'file' => $file,
|
||||||
'position' => [
|
'position' => [
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ return [
|
||||||
$json = file_get_contents('php://input');
|
$json = file_get_contents('php://input');
|
||||||
$data = json_decode($json);
|
$data = json_decode($json);
|
||||||
|
|
||||||
$page = page($data->page->uri);
|
$page = page($data->location->page->uri);
|
||||||
$file = $page->file($data->file->uuid);
|
$project = page($data->location->project->uri);
|
||||||
|
$file = $page->file($data->location->file->uuid);
|
||||||
$isReply = $data->parentId ?? false;
|
$isReply = $data->parentId ?? false;
|
||||||
|
|
||||||
$comments = $file->comments()->isEmpty() == true ? [] : Yaml::decode($file->comments()->value());
|
$comments = $file->comments()->isEmpty() == true ? [] : Yaml::decode($file->comments()->value());
|
||||||
|
|
@ -38,7 +39,7 @@ return [
|
||||||
|
|
||||||
echo json_encode(getFileData($newFile));
|
echo json_encode(getFileData($newFile));
|
||||||
|
|
||||||
kirby()->user()->deleteNotification($page->managers()->toUsers(), $data->id);
|
kirby()->user()->deleteNotification($project->managers()->toUsers(), $data->id);
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
namespace adrienpayet\comments;
|
namespace adrienpayet\comments;
|
||||||
|
|
||||||
class BaseComment {
|
class BaseComment {
|
||||||
protected $page;
|
protected $href;
|
||||||
protected $file;
|
protected $location;
|
||||||
protected $position;
|
protected $position;
|
||||||
protected $replies;
|
protected $replies;
|
||||||
protected $text;
|
protected $text;
|
||||||
|
|
@ -16,6 +16,7 @@ class BaseComment {
|
||||||
|
|
||||||
public function __construct($data) {
|
public function __construct($data) {
|
||||||
$page = $data['page'];
|
$page = $data['page'];
|
||||||
|
$project = $page->template() == 'project' ? $page : $page->parent();
|
||||||
$file = $data['file'];
|
$file = $data['file'];
|
||||||
$position = $data['position'];
|
$position = $data['position'];
|
||||||
$replies = $data['replies'] ?? [];
|
$replies = $data['replies'] ?? [];
|
||||||
|
|
@ -25,13 +26,22 @@ class BaseComment {
|
||||||
$id = $data['id'];
|
$id = $data['id'];
|
||||||
$type = $data['type'] ?? 'comment';
|
$type = $data['type'] ?? 'comment';
|
||||||
|
|
||||||
$this->page = [
|
$this->location = [
|
||||||
'uri' => (string) $page->parent()->uri(),
|
'page' => [
|
||||||
'title' => (string) $page->parent()->title(),
|
'uri' => (string) $page->uri(),
|
||||||
];
|
'title' => (string) $page->title(),
|
||||||
$this->file = [
|
],
|
||||||
|
'href' => (string) $data['href'],
|
||||||
|
'project' => [
|
||||||
|
'title' => (string) $project->title(),
|
||||||
|
'uri' => (string) $project->uri(),
|
||||||
|
],
|
||||||
|
'file' => $file ? [
|
||||||
'uuid' => (string) $file->uuid(),
|
'uuid' => (string) $file->uuid(),
|
||||||
|
'url' => (string) $file->uuid()
|
||||||
|
] : false,
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->replies = $replies ?? [];
|
$this->replies = $replies ?? [];
|
||||||
$this->text = $text;
|
$this->text = $text;
|
||||||
$this->author = [
|
$this->author = [
|
||||||
|
|
@ -47,12 +57,12 @@ class BaseComment {
|
||||||
$this->position = $position;
|
$this->position = $position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function page() {
|
public function location() {
|
||||||
return $this->page;
|
return $this->location;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function file() {
|
public function file() {
|
||||||
return $this->file;
|
return $this->location['file'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function replies() {
|
public function replies() {
|
||||||
|
|
@ -99,12 +109,11 @@ class BaseComment {
|
||||||
|
|
||||||
public function toArray() {
|
public function toArray() {
|
||||||
return [
|
return [
|
||||||
'page' => $this->page,
|
'location' => $this->location,
|
||||||
'file' => $this->file,
|
'position' => $this->position,
|
||||||
'replies' => $this->replies,
|
'replies' => $this->replies,
|
||||||
'text' => $this->text,
|
'text' => $this->text,
|
||||||
'author' => $this->author,
|
'author' => $this->author,
|
||||||
'position' => $this->position,
|
|
||||||
'date' => $this->date,
|
'date' => $this->date,
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'type' => $this->type,
|
'type' => $this->type,
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,23 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return function($notificationId) {
|
return function($projectManagers, $notificationId) {
|
||||||
$user = kirby()->user();
|
foreach ($projectManagers as $projectManager) {
|
||||||
try {
|
try {
|
||||||
$notifications = $user->notifications()->isNotEmpty()
|
$notifications = $projectManager->notifications()->isNotEmpty()
|
||||||
? Yaml::decode($user->notifications()->value())
|
? Yaml::decode($projectManager->notifications()->value())
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
foreach ($notifications as $key => $notification) {
|
foreach ($notifications as $key => $notification) {
|
||||||
if ($notification['id'] === $notificationId) {
|
if ($notification['id'] === $notificationId) {
|
||||||
unset($notifications[$key]);
|
unset($notifications[$key]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$projectManager->update([
|
||||||
|
'notifications' => Yaml::encode(array_values($notifications))
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
throw new Exception("Error updating notifications: " . $th->getMessage() . ' line ' . $th->getLine(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->update([
|
|
||||||
'notifications' => Yaml::encode(array_values($notifications))
|
|
||||||
]);
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
throw new Exception("Error updating notifications: " . $th->getMessage() . ' line ' . $th->getLine(), 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
<span class="comment__id">#{{ commentIndex }}</span>
|
<span class="comment__id">#{{ commentIndex }}</span>
|
||||||
•
|
•
|
||||||
</template>
|
</template>
|
||||||
<span class="comment__page">Page {{ comment.file.pageIndex }}</span>
|
<span class="comment__page">Page {{ comment.position.pageIndex }}</span>
|
||||||
<time
|
<time
|
||||||
class="comment__date"
|
class="comment__date"
|
||||||
:datetime="dayjs(comment.date).format('YYYY-MM-DD')"
|
:datetime="dayjs(comment.date).format('YYYY-MM-DD')"
|
||||||
|
|
@ -55,7 +55,6 @@ import { useUserStore } from "../../stores/user";
|
||||||
import { useApiStore } from "../../stores/api";
|
import { useApiStore } from "../../stores/api";
|
||||||
import { useDialogStore } from "../../stores/dialog";
|
import { useDialogStore } from "../../stores/dialog";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
|
|
||||||
dayjs.locale("fr");
|
dayjs.locale("fr");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ import { useApiStore } from "../../stores/api";
|
||||||
import { useDialogStore } from "../../stores/dialog";
|
import { useDialogStore } from "../../stores/dialog";
|
||||||
import Comment from "./Comment.vue";
|
import Comment from "./Comment.vue";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
dayjs.locale("fr");
|
dayjs.locale("fr");
|
||||||
|
|
||||||
|
|
@ -129,6 +130,7 @@ const newCommentPageIndex = ref(null);
|
||||||
const newCommentPosition = ref(null);
|
const newCommentPosition = ref(null);
|
||||||
const newCommentText = ref("");
|
const newCommentText = ref("");
|
||||||
const isAddOpen = ref(false);
|
const isAddOpen = ref(false);
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const sortedComments = computed(() => comments.value.reverse());
|
const sortedComments = computed(() => comments.value.reverse());
|
||||||
const sortedReplies = ref(null);
|
const sortedReplies = ref(null);
|
||||||
|
|
@ -162,8 +164,8 @@ function handleSubmit(event = null) {
|
||||||
}
|
}
|
||||||
const date = dayjs().format();
|
const date = dayjs().format();
|
||||||
const newComment = {
|
const newComment = {
|
||||||
pageUri: page.uri + "/client-brief",
|
path: route.fullPath,
|
||||||
fileName: openedFile.value.name,
|
fileName: openedFile ? openedFile.value.name : false,
|
||||||
userUuid: user.uuid,
|
userUuid: user.uuid,
|
||||||
text: newCommentText.value,
|
text: newCommentText.value,
|
||||||
date,
|
date,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<PdfViewer v-if="dialog.content.id === 'clientBrief'" />
|
<PdfViewer v-if="dialog.content.slug === 'client-brief'" />
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import PdfViewer from "./client-brief/PdfViewer.vue";
|
import PdfViewer from "./client-brief/PdfViewer.vue";
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,7 @@
|
||||||
<DialogWrapper v-if="dialog.content" />
|
<DialogWrapper v-if="dialog.content" />
|
||||||
|
|
||||||
<div class="kanban">
|
<div class="kanban">
|
||||||
<ProjectStep
|
<ProjectStep v-for="step in page.steps" :key="step" :step="step">
|
||||||
v-for="step in page.steps"
|
|
||||||
:key="step"
|
|
||||||
:step="step"
|
|
||||||
@update:dialog="updateDialog"
|
|
||||||
>
|
|
||||||
</ProjectStep>
|
</ProjectStep>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
@ -37,10 +32,10 @@ if (route.query.dialog) {
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query.dialog,
|
() => route.query.dialog,
|
||||||
(targetStepId) => {
|
(targetStepSlug) => {
|
||||||
if (targetStepId) {
|
if (targetStepSlug) {
|
||||||
const targetStep = page.value.steps.find(
|
const targetStep = page.value.steps.find(
|
||||||
(step) => step.id === targetStepId
|
(step) => step.slug === targetStepSlug
|
||||||
);
|
);
|
||||||
dialog.content = targetStep;
|
dialog.content = targetStep;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -49,8 +44,10 @@ watch(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function openDialog(stepId) {
|
function openDialog(targetStepSlug) {
|
||||||
const targetStep = page.value.steps.find((step) => step.id === stepId);
|
const targetStep = page.value.steps.find(
|
||||||
|
(step) => step.slug === targetStepSlug
|
||||||
|
);
|
||||||
dialog.content = targetStep;
|
dialog.content = targetStep;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
v-if="currentTab === 'all' || !notification.isRead"
|
v-if="currentTab === 'all' || !notification.isRead"
|
||||||
:to="notification.page.uri + '?notificationId=' + notification.id"
|
:to="notification.location.href"
|
||||||
>
|
>
|
||||||
<article
|
<article
|
||||||
class="notification | bg-white rounded-lg | p-16 | flow"
|
class="notification | bg-white rounded-lg | p-16 | flow"
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
}}</strong
|
}}</strong
|
||||||
>
|
>
|
||||||
<span class="notification__client | text-grey-700">{{
|
<span class="notification__client | text-grey-700">{{
|
||||||
notification.page.title
|
notification.location.project.title
|
||||||
}}</span>
|
}}</span>
|
||||||
<time
|
<time
|
||||||
datetime=""
|
datetime=""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue