From 20827f36a06d5a54afea1074a7a4d770482dd09e Mon Sep 17 00:00:00 2001 From: Ethan Chee <61472206+ethancheez@users.noreply.github.com> Date: Mon, 13 Nov 2023 04:29:28 -0800 Subject: [PATCH] Ability to delete threads and messages (#2) * Delete Threads + Individual Messages * Update ViewThread UI, minor bug fix --- app/imports/ui/components/DicussionPanel.jsx | 2 +- app/imports/ui/components/Message.jsx | 57 +++++++++++++++----- app/imports/ui/pages/ViewThread.jsx | 53 +++++++++++++++--- 3 files changed, 91 insertions(+), 21 deletions(-) diff --git a/app/imports/ui/components/DicussionPanel.jsx b/app/imports/ui/components/DicussionPanel.jsx index e84b0f6..85a2f91 100644 --- a/app/imports/ui/components/DicussionPanel.jsx +++ b/app/imports/ui/components/DicussionPanel.jsx @@ -40,7 +40,7 @@ const DiscussionPanel = ({ id, type }) => { const messageArr = discussion.messages; const discID = discussion._id; messageArr.push({ - id: messageArr.length, + id: (messageArr.length > 0) ? messageArr[messageArr.length - 1].id + 1 : 0, user: owner, message: state.message, time: new Date(), diff --git a/app/imports/ui/components/Message.jsx b/app/imports/ui/components/Message.jsx index 579c999..edf0fc4 100644 --- a/app/imports/ui/components/Message.jsx +++ b/app/imports/ui/components/Message.jsx @@ -1,9 +1,10 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; +import { Roles } from 'meteor/alanning:roles'; import { Col, Container, Image, Row } from 'react-bootstrap'; import { useTracker } from 'meteor/react-meteor-data'; import { Meteor } from 'meteor/meteor'; -import { HandThumbsDown, HandThumbsDownFill, HandThumbsUp, HandThumbsUpFill } from 'react-bootstrap-icons'; +import { HandThumbsDown, HandThumbsDownFill, HandThumbsUp, HandThumbsUpFill, XCircleFill } from 'react-bootstrap-icons'; import { Users } from '../../api/user/User'; import { Discussions } from '../../api/discussion/Discussion'; @@ -26,10 +27,21 @@ const Message = ({ message, id }) => { // eslint-disable-next-line no-unused-vars const [state, setState] = useState({ - likes: discussion.messages[message.id].likes, - dislikes: discussion.messages[message.id].dislikes, + likes: message.likes, + dislikes: message.dislikes, }); + const getMessageIndex = () => { + let index = 0; + // eslint-disable-next-line no-restricted-syntax + for (index in discussion.messages) { + if (discussion.messages[index].id === message.id) { + break; + } + } + return index; + }; + const handleLikeDislike = (likeDislike) => { const me = Users.collection.findOne({ _id: Meteor.user()._id }); const likes = me.likes; @@ -40,43 +52,62 @@ const Message = ({ message, id }) => { if (likeDislike === 'like') { if (likeIndex >= 0) { likes.splice(likeIndex, 1); - discussion.messages[message.id].likes--; + discussion.messages[getMessageIndex()].likes--; } else if (dislikeIndex >= 0) { dislikes.splice(dislikeIndex, 1); likes.push(messageId); - discussion.messages[message.id].dislikes--; - discussion.messages[message.id].likes++; + discussion.messages[getMessageIndex()].dislikes--; + discussion.messages[getMessageIndex()].likes++; } else { likes.push(messageId); - discussion.messages[message.id].likes++; + discussion.messages[getMessageIndex()].likes++; } Users.collection.update(me._id, { $set: { dislikes, likes } }); } else { if (dislikeIndex >= 0) { dislikes.splice(dislikeIndex, 1); - discussion.messages[message.id].dislikes--; + discussion.messages[getMessageIndex()].dislikes--; } else if (likeIndex >= 0) { likes.splice(likeIndex, 1); dislikes.push(messageId); - discussion.messages[message.id].likes--; - discussion.messages[message.id].dislikes++; + discussion.messages[getMessageIndex()].likes--; + discussion.messages[getMessageIndex()].dislikes++; } else { dislikes.push(messageId); - discussion.messages[message.id].dislikes++; + discussion.messages[getMessageIndex()].dislikes++; } Users.collection.update(me._id, { $set: { dislikes, likes } }); } - state.likes = discussion.messages[message.id].likes; - state.dislikes = discussion.messages[message.id].dislikes; + if (discussion.messages[getMessageIndex()].likes < 0) { + discussion.messages[getMessageIndex()].likes = 0; + } + if (discussion.messages[getMessageIndex()].dislikes < 0) { + discussion.messages[getMessageIndex()].dislikes = 0; + } + + state.likes = discussion.messages[getMessageIndex()].likes; + state.dislikes = discussion.messages[getMessageIndex()].dislikes; Discussions.collection.update( { _id: id }, { $set: { messages: discussion.messages } }, ); }; + const deleteMessage = () => { + const messages = discussion.messages; + messages.splice(getMessageIndex(), 1); + + Discussions.collection.update(discussion._id, { $set: { messages } }, () => { + window.location.reload(); + }); + }; + return ready && discussion ? ( + {(message.user === Meteor.user().username || Roles.userIsInRole(Meteor.user(), ['admin'])) ? ( + + ) : ''} diff --git a/app/imports/ui/pages/ViewThread.jsx b/app/imports/ui/pages/ViewThread.jsx index b2efc09..324151e 100644 --- a/app/imports/ui/pages/ViewThread.jsx +++ b/app/imports/ui/pages/ViewThread.jsx @@ -1,10 +1,17 @@ import React, { useState, useRef } from 'react'; -import { Button, Container, Image, InputGroup, Row, Col } from 'react-bootstrap'; +import { Roles } from 'meteor/alanning:roles'; +import { Button, Container, Image, InputGroup, Row, Col, Modal } from 'react-bootstrap'; import swal from 'sweetalert'; import { useTracker } from 'meteor/react-meteor-data'; import { Meteor } from 'meteor/meteor'; import Form from 'react-bootstrap/Form'; -import { HandThumbsDown, HandThumbsDownFill, HandThumbsUp, HandThumbsUpFill } from 'react-bootstrap-icons'; +import { + ExclamationTriangle, + HandThumbsDown, + HandThumbsDownFill, + HandThumbsUp, + HandThumbsUpFill, +} from 'react-bootstrap-icons'; import { useParams } from 'react-router'; import { Users } from '../../api/user/User'; import { Discussions } from '../../api/discussion/Discussion'; @@ -17,6 +24,8 @@ const ViewThread = () => { const [state, setState] = useState({ message: '', }); + const [showDeleteModal, setShowDeleteModal] = useState(false); + const containerRef = useRef(null); const { ready, thread } = useTracker(() => { // Get access to Discussions documents. @@ -42,7 +51,7 @@ const ViewThread = () => { const messageArr = thread.messages; const discID = thread._id; messageArr.push({ - id: messageArr.length, + id: (messageArr.length > 0) ? messageArr[messageArr.length - 1].id + 1 : 0, user: owner, message: state.message, time: new Date(), @@ -50,8 +59,6 @@ const ViewThread = () => { dislikes: 0, }); - console.log(messageArr); - Discussions.collection.update( { _id: discID }, { $set: { messages: messageArr } }, @@ -73,6 +80,12 @@ const ViewThread = () => { } }; + const deleteThread = () => { + Discussions.collection.remove({ _id: _id }); + setShowDeleteModal(false); + window.location.replace('/Discussions'); + }; + const handleLikeDislike = (likeDislike) => { const me = Users.collection.findOne(Meteor.user()._id); const likes = me.likes; @@ -121,7 +134,13 @@ const ViewThread = () => {

Created by: {thread?.owner}

-
+

{thread.messages[0].time.toLocaleDateString('en-us', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric' })}

+ {(thread.owner === Meteor.user().username || Roles.userIsInRole(Meteor.user(), ['admin'])) ? ( +
+ +
+ ) : ''} +
{(Users.collection.findOne(Meteor.user()._id).likes.indexOf(_id) >= 0) ? ( @@ -154,6 +173,10 @@ const ViewThread = () => { + +

{thread.messages[0].message}

+
+
@@ -181,13 +204,29 @@ const ViewThread = () => {
{(ready && thread && thread.messages.length !== 0) ? (
- {thread.messages.map((item, index) => ( + {thread.messages.slice(1).map((item, index) => ( ))}
) :

No messages in this discussion

}
+ setShowDeleteModal(false)} style={{ marginTop: '20vh' }}> + + +

Are you sure?

+

You are about to delete this thread.

+
+ + + + +
+ ) : ;