This commit is contained in:
parent
cd04c232a6
commit
32b01f4c98
3 changed files with 87 additions and 18 deletions
|
|
@ -3,7 +3,10 @@
|
||||||
:id="`comment-${comment.id}`"
|
:id="`comment-${comment.id}`"
|
||||||
class="comment | flow"
|
class="comment | flow"
|
||||||
:data-status="getStatus"
|
:data-status="getStatus"
|
||||||
@click="read()"
|
@click="handleClick()"
|
||||||
|
@mouseenter="hightlightCorrespondingMarker()"
|
||||||
|
@mouseleave="unhightlightCorrespondingMarker()"
|
||||||
|
ref="comment-node"
|
||||||
>
|
>
|
||||||
<header>
|
<header>
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -80,7 +83,7 @@ import "dayjs/locale/fr";
|
||||||
import { useUserStore } from "../../stores/user";
|
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, ref } from "vue";
|
import { computed, onMounted, ref, useTemplateRef } from "vue";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
dayjs.locale("fr");
|
dayjs.locale("fr");
|
||||||
|
|
@ -95,9 +98,11 @@ const emits = defineEmits(["update:file", "close:comment"]);
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const api = useApiStore();
|
const api = useApiStore();
|
||||||
const dialog = useDialogStore();
|
const dialog = useDialogStore();
|
||||||
const { activeTracks } = storeToRefs(useDialogStore());
|
const { activeTracks, openedComment } = storeToRefs(useDialogStore());
|
||||||
const draftText = ref(comment.text);
|
const draftText = ref(comment.text);
|
||||||
const editField = ref(null);
|
const editField = ref(null);
|
||||||
|
const commentNode = useTemplateRef("comment-node");
|
||||||
|
let correspondingMarker = null;
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
const getStatus = computed(() => {
|
const getStatus = computed(() => {
|
||||||
|
|
@ -130,6 +135,11 @@ function closeAddField() {
|
||||||
newCommentText.value = "";
|
newCommentText.value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
read();
|
||||||
|
scrollTo();
|
||||||
|
}
|
||||||
|
|
||||||
async function read() {
|
async function read() {
|
||||||
if (getStatus.value !== "unread") return;
|
if (getStatus.value !== "unread") return;
|
||||||
try {
|
try {
|
||||||
|
|
@ -141,13 +151,21 @@ async function read() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scrollTo() {
|
||||||
|
const correspondingMarker = document.querySelector(
|
||||||
|
`.comment-marker[href="#comment-${comment.id}"]`
|
||||||
|
);
|
||||||
|
if (!correspondingMarker) return;
|
||||||
|
correspondingMarker.scrollIntoView();
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteComment(event) {
|
async function deleteComment(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const newFile = await api.deleteComment(comment);
|
const newFile = await api.deleteComment(comment);
|
||||||
|
|
||||||
// If there is an active track,
|
// If there is an active track, we are not in PDF mode with a single file.
|
||||||
// it's not the opened file that should be updated
|
// Thus, it's not the opened file that should be updated
|
||||||
// but the corresponding file in the active track
|
// but the corresponding file in the active track.
|
||||||
if (activeTracks.value?.length > 0) {
|
if (activeTracks.value?.length > 0) {
|
||||||
activeTracks.value[0].files = activeTracks.value[0].files.map((file) => {
|
activeTracks.value[0].files = activeTracks.value[0].files.map((file) => {
|
||||||
if (file.uuid !== newFile.uuid) return file;
|
if (file.uuid !== newFile.uuid) return file;
|
||||||
|
|
@ -181,6 +199,32 @@ function editComment(event) {
|
||||||
editField.value.focus();
|
editField.value.focus();
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hightlightCorrespondingMarker() {
|
||||||
|
if (comment.type === "comment-reply") return;
|
||||||
|
|
||||||
|
const correspondingMarker = document.querySelector(
|
||||||
|
`.comment-marker[href="#comment-${comment.id}"]`
|
||||||
|
);
|
||||||
|
if (!correspondingMarker) return;
|
||||||
|
|
||||||
|
commentNode.value.classList.add("highlight");
|
||||||
|
correspondingMarker.classList.add("active");
|
||||||
|
correspondingMarker.classList.add("big");
|
||||||
|
}
|
||||||
|
function unhightlightCorrespondingMarker() {
|
||||||
|
if (comment.type === "comment-reply") return;
|
||||||
|
|
||||||
|
const correspondingMarker = document.querySelector(
|
||||||
|
`.comment-marker[href="#comment-${comment.id}"]`
|
||||||
|
);
|
||||||
|
if (!correspondingMarker) return;
|
||||||
|
if (openedComment.value) return;
|
||||||
|
|
||||||
|
commentNode.value.classList.remove("highlight");
|
||||||
|
correspondingMarker.classList.remove("active");
|
||||||
|
correspondingMarker.classList.remove("big");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -121,13 +121,10 @@ dayjs.locale("fr");
|
||||||
const { user } = useUserStore();
|
const { user } = useUserStore();
|
||||||
const { page } = usePageStore();
|
const { page } = usePageStore();
|
||||||
const dialog = useDialogStore();
|
const dialog = useDialogStore();
|
||||||
const { comments, openedFile, draftComment, activeTracks } = storeToRefs(
|
const { comments, openedFile, openedComment, draftComment, activeTracks } =
|
||||||
useDialogStore()
|
storeToRefs(useDialogStore());
|
||||||
);
|
|
||||||
const api = useApiStore();
|
const api = useApiStore();
|
||||||
|
|
||||||
const openedComment = ref(null);
|
|
||||||
|
|
||||||
const isAddOpen = ref(false);
|
const isAddOpen = ref(false);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const waitingForCommentPosition = ref(false);
|
const waitingForCommentPosition = ref(false);
|
||||||
|
|
@ -139,6 +136,10 @@ const sortedReplies = ref(null);
|
||||||
|
|
||||||
watch(openedComment, (newVal) => {
|
watch(openedComment, (newVal) => {
|
||||||
sortedReplies.value = newVal ? newVal.replies.slice().reverse() : null;
|
sortedReplies.value = newVal ? newVal.replies.slice().reverse() : null;
|
||||||
|
|
||||||
|
if (!newVal) {
|
||||||
|
unhighlightAllComments();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(isAddOpen, (newVal) => {
|
watch(isAddOpen, (newVal) => {
|
||||||
|
|
@ -165,6 +166,13 @@ window.addEventListener("keydown", (event) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
function unhighlightAllComments() {
|
||||||
|
document.querySelectorAll(".comment-marker.big").forEach((commentNode) => {
|
||||||
|
commentNode.classList.remove("big");
|
||||||
|
commentNode.classList.remove("active");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handleSubmit(event = null) {
|
function handleSubmit(event = null) {
|
||||||
if (event) {
|
if (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -427,6 +435,7 @@ function openComment(comment) {
|
||||||
width: var(--marker-size);
|
width: var(--marker-size);
|
||||||
height: var(--marker-size);
|
height: var(--marker-size);
|
||||||
background: var(--icon-comment-default) no-repeat center / contain;
|
background: var(--icon-comment-default) no-repeat center / contain;
|
||||||
|
scroll-margin-block-start: 4rem;
|
||||||
cursor: pointer !important;
|
cursor: pointer !important;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
@ -435,7 +444,8 @@ function openComment(comment) {
|
||||||
margin-left: calc(var(--marker-size) * -0.025);
|
margin-left: calc(var(--marker-size) * -0.025);
|
||||||
margin-top: calc(var(--marker-size) / -1.025);
|
margin-top: calc(var(--marker-size) / -1.025);
|
||||||
}
|
}
|
||||||
.comment-marker:hover {
|
.comment-marker:hover,
|
||||||
|
.comment-marker.big {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
.comment-marker.active,
|
.comment-marker.active,
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export const useDialogStore = defineStore("dialog", () => {
|
||||||
const isCommentsOpen = ref(
|
const isCommentsOpen = ref(
|
||||||
route.query.hasOwnProperty("comments") ? true : false
|
route.query.hasOwnProperty("comments") ? true : false
|
||||||
);
|
);
|
||||||
|
const openedComment = ref(null);
|
||||||
|
|
||||||
const draftComment = ref({});
|
const draftComment = ref({});
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -84,10 +85,17 @@ export const useDialogStore = defineStore("dialog", () => {
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
function setCommentMarkers() {
|
function setCommentMarkers() {
|
||||||
if (!comments.value) return;
|
if (!comments.value) return;
|
||||||
comments.value.forEach((comment) => {
|
comments.value.forEach((comment) => {
|
||||||
|
const correspondingMarker = document.querySelector(
|
||||||
|
`.comment-marker[href="#comment-${comment.id}"]`
|
||||||
|
);
|
||||||
if (comment.location.file.uuid !== openedFile.value.uuid) return;
|
if (comment.location.file.uuid !== openedFile.value.uuid) return;
|
||||||
|
if (comment.type === "comment-reply") return;
|
||||||
|
if (correspondingMarker) return;
|
||||||
|
|
||||||
const bubble = document.createElement("a");
|
const bubble = document.createElement("a");
|
||||||
|
|
||||||
bubble.classList.add("comment-marker");
|
bubble.classList.add("comment-marker");
|
||||||
|
|
@ -109,17 +117,23 @@ export const useDialogStore = defineStore("dialog", () => {
|
||||||
)
|
)
|
||||||
: document.querySelector(".track");
|
: document.querySelector(".track");
|
||||||
|
|
||||||
container.appendChild(bubble);
|
try {
|
||||||
|
container.appendChild(bubble);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
bubble.addEventListener("mouseenter", () => highlight(comment));
|
bubble.addEventListener("mouseenter", () => highlight(comment));
|
||||||
bubble.addEventListener("mouseleave", () => unhighlight(comment));
|
bubble.addEventListener("mouseleave", () => unhighlight(comment));
|
||||||
}, 100);
|
}, 100);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`Impossible de monter la bulle du commentaire ${comment.id}. La page n°${comment.position.pageIndex} n'existe pas dans le DOM.`
|
||||||
|
);
|
||||||
|
}
|
||||||
}, timeOut);
|
}, timeOut);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeCommentMarkers() {
|
function removeCommentMarkers() {
|
||||||
|
console.log("remove comment markers");
|
||||||
document.querySelectorAll(".comment-marker").forEach((bubble) => {
|
document.querySelectorAll(".comment-marker").forEach((bubble) => {
|
||||||
bubble.parentNode.removeChild(bubble);
|
bubble.parentNode.removeChild(bubble);
|
||||||
});
|
});
|
||||||
|
|
@ -143,5 +157,6 @@ export const useDialogStore = defineStore("dialog", () => {
|
||||||
isCommentsOpen,
|
isCommentsOpen,
|
||||||
isCommentPanelEnabled,
|
isCommentPanelEnabled,
|
||||||
updateFile,
|
updateFile,
|
||||||
|
openedComment,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue