Skip to content
Extraits de code Groupes Projets
Valider 228bf3ff rédigé par Brieuc Dubois's avatar Brieuc Dubois
Parcourir les fichiers

Implement #105

parent 7b2c0ef4
Aucune branche associée trouvée
Aucune étiquette associée trouvée
2 requêtes de fusion!14Merge dev into main,!12Merge dev into main
......@@ -247,6 +247,21 @@ def create_message_feedback(
return db_message_feedback
def get_message_feedback(db: Session, feedback_id: int):
return (
db.query(models.MessageFeedback)
.filter(models.MessageFeedback.id == feedback_id)
.first()
)
def delete_message_feedback(db: Session, feedback_id: int):
db.query(models.MessageFeedback).filter(
models.MessageFeedback.id == feedback_id
).delete()
db.commit()
def create_study(db: Session, study: schemas.StudyCreate):
db_study = models.Study(**study.dict())
db.add(db_study)
......
......@@ -740,9 +740,8 @@ async def send_websoket_message(session_id: int, message: schemas.Message, actio
await user_websocket.send_text(content)
async def send_websoket_feedback(session_id: int, feedback: dict):
content = json.dumps({"type": "message", "action": "feedback", "data": feedback})
async def send_websoket_feedback(session_id: int, action: str, feedback: dict):
content = json.dumps({"type": "message", "action": action, "data": feedback})
for _, user_websockets in websocket_users[session_id].items():
for user_websocket in user_websockets:
......@@ -825,12 +824,60 @@ def feedback_message(
background_tasks.add_task(
send_websoket_feedback,
session_id,
"feedback",
schemas.MessageFeedback.model_validate(feedback).to_dict(),
)
return feedback.id
@sessionsRouter.delete(
"/{session_id}/messages/{message_id}/feedback/{feedback_id}",
status_code=status.HTTP_204_NO_CONTENT,
)
async def delete_feedback(
session_id: int,
message_id: int,
feedback_id: int,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
current_user: schemas.User = Depends(get_jwt_user),
):
db_session = crud.get_session(db, session_id)
if db_session is None:
raise HTTPException(status_code=404, detail="Session not found")
if (
not check_user_level(current_user, models.UserType.ADMIN)
and current_user not in db_session.users
):
raise HTTPException(
status_code=401,
detail="You do not have permission to delete feedbacks in this session",
)
db_message = crud.get_message(db, message_id)
if db_message is None:
raise HTTPException(status_code=404, detail="Message not found")
db_feedback = crud.get_message_feedback(db, feedback_id)
if db_feedback is None:
raise HTTPException(status_code=404, detail="Feedback not found")
crud.delete_message_feedback(db, feedback_id)
background_tasks.add_task(
send_websoket_feedback,
session_id,
"deleteFeedback",
{
"message_id": message_id,
"feedback_id": feedback_id,
},
)
async def send_websoket_typing(session_id: int, user_id: int):
content = json.dumps(
{"type": "message", "action": "typing", "data": {"user": user_id}}
......
......@@ -46,6 +46,7 @@
},
"type": "module",
"dependencies": {
"@sveltekit-i18n/base": "^1.3.7",
"@sveltekit-i18n/parser-icu": "^1.0.8",
"dayjs": "^1.11.13",
"emoji-picker-element": "^1.23.0",
......
Ce diff est replié.
......@@ -19,7 +19,8 @@
"sendError": "Erreur lors de l'envoi du message",
"disabled": "Cette session est accessible uniquement en lecture",
"edited": "modifié",
"history": "Historique"
"history": "Historique",
"deleteFeedback": "Êtes-vous sûr de vouloir supprimer ce feedback ? Cette action est irréversible."
},
"home": {
"email": "E-mail",
......
......@@ -95,6 +95,21 @@ export async function createMessageFeedbackAPI(
return response.data;
}
export async function deleteMessageFeedbackAPI(
id: number,
message_id: number,
feedback_id: number
) {
const response = await axiosInstance.delete(
`/sessions/${id}/messages/${message_id}/feedback/${feedback_id}`
);
if (response.status !== 204) {
toastAlert('Failed to delete feedback');
return false;
}
return true;
}
export async function patchLanguageAPI(id: number, language: string) {
const response = await axiosInstance.patch(`/sessions/${id}`, { language });
......
......@@ -11,6 +11,7 @@
import type Feedback from '$lib/types/feedback';
import linkifyHtml from 'linkify-html';
import { sanitize } from '$lib/utils/sanitize';
import CloseIcon from '../icons/closeIcon.svelte';
export let message: Message;
......@@ -157,6 +158,13 @@
$: parts = getParts(message.content, $fbs);
const isSender = message.user.id == $user?.id;
async function deleteFeedback(feedback: Feedback | null) {
if (!feedback) return;
if (!confirm($t('chatbox.deleteFeedback'))) return;
await message.deleteFeedback(feedback);
}
</script>
<div
......@@ -199,22 +207,32 @@
{#each parts as part}
{#if isEdit || !part.feedback}
{@html linkifyHtml(sanitize(part.text), { className: 'underline', target: '_blank' })}
{:else if part.feedback.content}
<span class="tooltip tooltip-accent" data-tip={part.feedback.content}
{:else}
<!-- prettier-ignore -->
<span class=""
><!--
--><span class="underline decoration-wavy decoration-blue-500 hover:cursor-help"
--><span
class="underline group/feedback relative decoration-wavy hover:cursor-help"
class:decoration-blue-500={part.feedback.content}
class:decoration-red-500={!part.feedback.content}
><div
class="absolute group-hover/feedback:flex hidden bg-secondary h-6 items-center rounded left-1/2 transform -translate-x-1/2 -top-6 px-2 z-10"
><!--
-->{part.feedback.content}<button
aria-label="close"
class:ml-1={part.feedback.content}
class="hover:border-inherit border border-transparent rounded"
on:click={() => deleteFeedback(part.feedback)}
>
<CloseIcon />
</button>
</div
><!--
-->{part.text}<!--
--></span
><!--
--></span
>
{:else}
<span class="underline decoration-wavy decoration-red-500 decoration-1"
><!--
-->{part.text}<!--
--></span
>
{/if}
{/each}
</div>
......
import { deleteMessageFeedbackAPI } from '$lib/api/sessions';
import { parseToLocalDate } from '$lib/utils/date';
import { toastAlert } from '$lib/utils/toasts';
import Message from './message';
......@@ -16,7 +17,7 @@ export default class Feedback {
start: number,
end: number,
content: string | null,
date: Date
date: Date = new Date()
) {
this._id = id;
this._message = message;
......@@ -81,6 +82,10 @@ export default class Feedback {
return feedback;
}
async delete(): Promise<boolean> {
return await deleteMessageFeedbackAPI(this._message.session.id, this._message.id, this._id);
}
static parseAll(json: any, message: Message): Feedback[] {
if (json === null || json == undefined) {
toastAlert('Failed to parse feedbacks: json is null');
......
......@@ -119,6 +119,18 @@ export default class Message {
});
}
async deleteFeedback(feedback: Feedback): Promise<boolean> {
const response = await feedback.delete();
if (!response) return false;
this._feedbacks.update((f) => f.filter((fb) => fb.id != feedback.id));
return true;
}
deleteLocalFeedback(feedback_id: number): void {
this._feedbacks.update((f) => f.filter((fb) => fb.id != feedback_id));
}
static parse(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json: any,
......
......@@ -317,6 +317,14 @@ export default class Session {
return;
}
}
} else if (data['action'] == 'deleteFeedback') {
const message = get(this._messages).find(
(m) => m instanceof Message && m.id === data['data']['message_id']
);
if (message && message instanceof Message) {
message.deleteLocalFeedback(data['data']['feedback_id']);
return;
}
}
} else if (data['type'] === 'presence') {
const user_id = data['data']['user'];
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter