add / show comments working
This commit is contained in:
parent
a9992b0ff5
commit
6bffbc1707
10 changed files with 163 additions and 40 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -16,6 +16,7 @@
|
||||||
"primevue": "^4.0.6",
|
"primevue": "^4.0.6",
|
||||||
"slugify": "^1.6.6",
|
"slugify": "^1.6.6",
|
||||||
"three": "^0.168.0",
|
"three": "^0.168.0",
|
||||||
|
"uniqid": "^5.4.0",
|
||||||
"vue": "^3.5.6",
|
"vue": "^3.5.6",
|
||||||
"vue-router": "^4.4.5"
|
"vue-router": "^4.4.5"
|
||||||
},
|
},
|
||||||
|
|
@ -1827,6 +1828,11 @@
|
||||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/uniqid": {
|
||||||
|
"version": "5.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz",
|
||||||
|
"integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A=="
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
"primevue": "^4.0.6",
|
"primevue": "^4.0.6",
|
||||||
"slugify": "^1.6.6",
|
"slugify": "^1.6.6",
|
||||||
"three": "^0.168.0",
|
"three": "^0.168.0",
|
||||||
|
"uniqid": "^5.4.0",
|
||||||
"vue": "^3.5.6",
|
"vue": "^3.5.6",
|
||||||
"vue-router": "^4.4.5"
|
"vue-router": "^4.4.5"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,31 @@ Uuid: s0lNtRA0Z7ybTCWG
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
Template: document
|
Template: document
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Comments:
|
||||||
|
|
||||||
|
1:
|
||||||
|
m2lmqu2u:
|
||||||
|
text: test
|
||||||
|
username: Adrien Payet
|
||||||
|
date: 2024-10-23T10:46:08+02:00
|
||||||
|
m2lo4obv:
|
||||||
|
text: nouveau commentaire
|
||||||
|
username: Adrien Payet
|
||||||
|
date: 2024-10-23T11:24:53+02:00
|
||||||
|
m2lo6ckw:
|
||||||
|
text: Encore un autre commentaire
|
||||||
|
username: Adrien Payet
|
||||||
|
date: 2024-10-23T11:26:11+02:00
|
||||||
|
2:
|
||||||
|
m2loaj2f:
|
||||||
|
text: Autre commentaire
|
||||||
|
username: Adrien Payet
|
||||||
|
date: 2024-10-23T11:29:26+02:00
|
||||||
|
m2loam7s:
|
||||||
|
text: Autre commentaire
|
||||||
|
username: Adrien Payet
|
||||||
|
date: 2024-10-23T11:29:30+02:00
|
||||||
|
|
@ -26,6 +26,7 @@ return [
|
||||||
require(__DIR__ . '/routes/save-file.php'),
|
require(__DIR__ . '/routes/save-file.php'),
|
||||||
require(__DIR__ . '/routes/remove-file.php'),
|
require(__DIR__ . '/routes/remove-file.php'),
|
||||||
require(__DIR__ . '/routes/upload-pdf.php'),
|
require(__DIR__ . '/routes/upload-pdf.php'),
|
||||||
|
require(__DIR__ . '/routes/add-comment.php'),
|
||||||
],
|
],
|
||||||
'hooks' => [
|
'hooks' => [
|
||||||
'page.create:after' => require_once(__DIR__ . '/hooks/create-steps.php'),
|
'page.create:after' => require_once(__DIR__ . '/hooks/create-steps.php'),
|
||||||
|
|
|
||||||
32
public/site/config/routes/add-comment.php
Normal file
32
public/site/config/routes/add-comment.php
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'pattern' => '(:all)add-comment.json',
|
||||||
|
'method' => 'POST',
|
||||||
|
'action' => function () {
|
||||||
|
$json = file_get_contents('php://input');
|
||||||
|
$data = json_decode($json);
|
||||||
|
|
||||||
|
// return json_encode($data->pageUri);
|
||||||
|
|
||||||
|
$page = page($data->pageUri);
|
||||||
|
$file = $page->file($data->fileName);
|
||||||
|
$user = kirby()->user($data->userUuid);
|
||||||
|
|
||||||
|
|
||||||
|
$comments = $file->comments()->isEmpty() == true ? [] : Data::decode($file->comments()->toArray()['comments'], 'yaml');
|
||||||
|
|
||||||
|
$comments[$data->targetPage][$data->id] = [
|
||||||
|
'text' => $data->text,
|
||||||
|
'username' => (string) $user->name(),
|
||||||
|
'date' => (string) $data->date,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
$newFile = $file->update([
|
||||||
|
'comments' => $comments
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $comments;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
@ -5,7 +5,7 @@ function getFileData($file) {
|
||||||
'url' => $file->url(),
|
'url' => $file->url(),
|
||||||
'uuid' => (string) $file->uuid(),
|
'uuid' => (string) $file->uuid(),
|
||||||
'name' => $file->filename(),
|
'name' => $file->filename(),
|
||||||
'type' => (string) $file->type()
|
'type' => (string) $file->type(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($file->description()->exists()) {
|
if ($file->description()->exists()) {
|
||||||
|
|
@ -13,5 +13,9 @@ function getFileData($file) {
|
||||||
$data['tags'] = $file->tags()->split();
|
$data['tags'] = $file->tags()->split();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if($file->comments()->exists()) {
|
||||||
|
$data['comments'] = Data::decode($file->comments()->value(), 'yaml');
|
||||||
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
@ -2,20 +2,31 @@
|
||||||
<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">
|
||||||
<article class="comment | flow" data-status="unread">
|
<div
|
||||||
<header>
|
v-for="(page, pageIndex) in localComments"
|
||||||
<p>
|
class="comments__page-group"
|
||||||
<strong>François</strong>
|
>
|
||||||
<span class="comment__id">#1</span> •
|
<article
|
||||||
<span class="comment__page">Page 12</span>
|
v-for="(comment, commentIndex) in Object.values(page)"
|
||||||
<time datetime="2024-10-22">Hier</time>
|
:key="pageIndex + commentIndex"
|
||||||
|
class="comment | flow"
|
||||||
|
data-status="unread"
|
||||||
|
>
|
||||||
|
<header>
|
||||||
|
<p>
|
||||||
|
<strong>{{ comment.username }}</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>
|
</p>
|
||||||
</header>
|
</article>
|
||||||
<p class="comment__body">
|
</div>
|
||||||
Lectus adipiscing nulla quis odio in aliquam. Adipiscing libero in
|
|
||||||
consequat porta mauris hendrerit malesuada viverra turpis.
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
id="add-comment"
|
id="add-comment"
|
||||||
|
|
@ -50,28 +61,66 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import "dayjs/locale/fr";
|
||||||
|
import uniqid from "uniqid";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useUserStore } from "../../stores/user";
|
import { useUserStore } from "../../stores/user";
|
||||||
import dayjs from "dayjs";
|
import { usePageStore } from "../../stores/page";
|
||||||
|
|
||||||
const { currentPage } = defineProps({
|
dayjs.locale("fr");
|
||||||
currentPage: Number,
|
|
||||||
|
const { currentPageIndex, file, comments } = defineProps({
|
||||||
|
currentPageIndex: Number,
|
||||||
|
file: Object,
|
||||||
|
comments: Object,
|
||||||
});
|
});
|
||||||
const { user } = useUserStore();
|
const { user } = useUserStore();
|
||||||
|
const { page } = usePageStore();
|
||||||
|
|
||||||
const newCommentText = ref("");
|
const newCommentText = ref("");
|
||||||
|
|
||||||
const isAddOpen = ref(false);
|
const isAddOpen = ref(false);
|
||||||
|
const localComments = ref(comments);
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
function addComment(event) {
|
function addComment(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
const date = dayjs().format();
|
||||||
const comment = {
|
const comment = {
|
||||||
|
pageUri: page.uri + "/client-brief",
|
||||||
|
targetPage: currentPageIndex,
|
||||||
|
fileName: file.name,
|
||||||
userUuid: user.uuid,
|
userUuid: user.uuid,
|
||||||
text: newCommentText.value,
|
text: newCommentText.value,
|
||||||
page: currentPage,
|
date,
|
||||||
date: dayjs().format(),
|
id: uniqid(),
|
||||||
};
|
};
|
||||||
console.log(comment);
|
|
||||||
|
const headers = {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(comment),
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch("/add-comment.json", headers)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((json) => (localComments.value = json))
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Erreur lors de la sauvegarde :", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
}}</time>
|
}}</time>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
<template v-if="step.files[0]?.type === 'image'">
|
<template v-if="step.files[0]?.type === 'image'">
|
||||||
<figure
|
<figure
|
||||||
class="card__images"
|
class="card__images"
|
||||||
|
|
@ -31,6 +32,8 @@
|
||||||
/>
|
/>
|
||||||
</figure>
|
</figure>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- PDF -->
|
||||||
<template v-if="step.files[0]?.type === 'document'">
|
<template v-if="step.files[0]?.type === 'document'">
|
||||||
<div
|
<div
|
||||||
@click="showPdf"
|
@click="showPdf"
|
||||||
|
|
@ -53,7 +56,7 @@ const { step } = defineProps({
|
||||||
step: Object,
|
step: Object,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["update:pdf"]);
|
const emit = defineEmits(["update:file"]);
|
||||||
|
|
||||||
dayjs.locale("fr");
|
dayjs.locale("fr");
|
||||||
|
|
||||||
|
|
@ -79,7 +82,7 @@ function setStatus() {
|
||||||
|
|
||||||
function showPdf(event) {
|
function showPdf(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
emit("update:pdf", step.files[0].url);
|
emit("update:file", step.files[0]);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
<VPdfViewer
|
<VPdfViewer
|
||||||
:darkMode="true"
|
:darkMode="true"
|
||||||
:initialThumbnailsVisible="true"
|
:initialThumbnailsVisible="true"
|
||||||
:src="src"
|
:src="file.url"
|
||||||
local="fr_FR"
|
local="fr_FR"
|
||||||
@loaded="onPdfLoaded"
|
@loaded="onPdfLoaded"
|
||||||
/>
|
/>
|
||||||
|
|
@ -29,7 +29,12 @@
|
||||||
>
|
>
|
||||||
<span class="sr-only">Afficher les commentaires</span>
|
<span class="sr-only">Afficher les commentaires</span>
|
||||||
</button>
|
</button>
|
||||||
<Comments v-if="isCommentsOpen" :current-page="currentPage" />
|
<Comments
|
||||||
|
v-if="isCommentsOpen"
|
||||||
|
:current-page-index="currentPageIndex"
|
||||||
|
:file="file"
|
||||||
|
:comments="file.comments"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -40,8 +45,8 @@ import Comments from "../../comments/Comments.vue";
|
||||||
import { VPdfViewer, useLicense } from "@vue-pdf-viewer/viewer";
|
import { VPdfViewer, useLicense } from "@vue-pdf-viewer/viewer";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
|
|
||||||
const { src } = defineProps({
|
const { file } = defineProps({
|
||||||
src: String,
|
file: Object,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits("close");
|
const emit = defineEmits("close");
|
||||||
|
|
@ -55,7 +60,7 @@ watch(isOpen, (newValue) => {
|
||||||
emit("close");
|
emit("close");
|
||||||
});
|
});
|
||||||
const isCommentsOpen = ref(false);
|
const isCommentsOpen = ref(false);
|
||||||
const currentPage = ref(1);
|
const currentPageIndex = ref(1);
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
const onPdfLoaded = () => {
|
const onPdfLoaded = () => {
|
||||||
|
|
@ -65,7 +70,7 @@ const onPdfLoaded = () => {
|
||||||
(entries) => {
|
(entries) => {
|
||||||
entries.forEach((entry, index) => {
|
entries.forEach((entry, index) => {
|
||||||
if (entry.intersectionRatio > 0.5) {
|
if (entry.intersectionRatio > 0.5) {
|
||||||
currentPage.value = parseInt(
|
currentPageIndex.value = parseInt(
|
||||||
entry.target.getAttribute("aria-label").split(" ")[1]
|
entry.target.getAttribute("aria-label").split(" ")[1]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
<Header :title="page.content.title" />
|
<Header :title="page.content.title" />
|
||||||
<!-- Kanban: Status Brief Enrichi -->
|
<!-- Kanban: Status Brief Enrichi -->
|
||||||
|
|
||||||
<PdfViewer v-if="pdf" :src="pdf" @close="pdf = null" />
|
<PdfViewer v-if="file" :file="file" @close="file = null" />
|
||||||
|
|
||||||
<div class="kanban">
|
<div class="kanban">
|
||||||
<ProjectStep
|
<ProjectStep
|
||||||
v-for="step in page.steps"
|
v-for="step in page.steps"
|
||||||
:key="step"
|
:key="step"
|
||||||
:step="step"
|
:step="step"
|
||||||
@update:pdf="changePdf"
|
@update:file="changeFile"
|
||||||
>
|
>
|
||||||
</ProjectStep>
|
</ProjectStep>
|
||||||
<!-- <section
|
<!-- <section
|
||||||
|
|
@ -168,7 +168,7 @@ import { ref } from "vue";
|
||||||
const { page } = storeToRefs(usePageStore());
|
const { page } = storeToRefs(usePageStore());
|
||||||
const user = useUserStore().user;
|
const user = useUserStore().user;
|
||||||
|
|
||||||
const pdf = ref(null);
|
const file = ref(null);
|
||||||
|
|
||||||
function setStepStatus(stepName) {
|
function setStepStatus(stepName) {
|
||||||
const stepIndex = steps.indexOf(stepName);
|
const stepIndex = steps.indexOf(stepName);
|
||||||
|
|
@ -178,13 +178,8 @@ function setStepStatus(stepName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePdf(src) {
|
function changeFile(newFile) {
|
||||||
pdf.value = src;
|
file.value = newFile;
|
||||||
}
|
|
||||||
|
|
||||||
function hidePdf() {
|
|
||||||
console.log("test");
|
|
||||||
pdf.value = null;
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue