Skip to content

Commit

Permalink
Ability to delete threads and messages (#2)
Browse files Browse the repository at this point in the history
* Delete Threads + Individual Messages

* Update ViewThread UI, minor bug fix
  • Loading branch information
ethancheez committed Nov 13, 2023
1 parent fafb52c commit 20827f3
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 21 deletions.
2 changes: 1 addition & 1 deletion app/imports/ui/components/DicussionPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
57 changes: 44 additions & 13 deletions app/imports/ui/components/Message.jsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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;
Expand All @@ -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 ? (
<Container className="mb-3" style={{ borderWidth: 0.5, borderColor: '#dee2e6', borderStyle: 'solid', borderRadius: 5, margin: 10, padding: 10, width: '95%', minWidth: '400px' }}>
{(message.user === Meteor.user().username || Roles.userIsInRole(Meteor.user(), ['admin'])) ? (
<XCircleFill xs="true" color="red" className="mouse-hover-click" style={{ float: 'right', marginTop: '-18px', marginRight: '-18px' }} onClick={deleteMessage} />
) : ''}
<Row style={{ width: '100%', marginBottom: 5 }} className="d-flex align-items-center">
<Col xs={2} className="d-flex justify-content-center align-items-center">
<Image roundedCircle src="/images/pfp.jpg" width="40vh" />
Expand Down
53 changes: 46 additions & 7 deletions app/imports/ui/pages/ViewThread.jsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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.
Expand All @@ -42,16 +51,14 @@ 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(),
likes: 0,
dislikes: 0,
});

console.log(messageArr);

Discussions.collection.update(
{ _id: discID },
{ $set: { messages: messageArr } },
Expand All @@ -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;
Expand Down Expand Up @@ -121,7 +134,13 @@ const ViewThread = () => {
<p style={{ color: 'grey' }}>Created by: {thread?.owner}</p>
</Col>
<Col>
<div style={{ float: 'right', padding: '0px' }} id="segmented-buttons-wrapper">
<p style={{ textAlign: 'right' }}>{thread.messages[0].time.toLocaleDateString('en-us', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric' })}</p>
{(thread.owner === Meteor.user().username || Roles.userIsInRole(Meteor.user(), ['admin'])) ? (
<div className="mb-2" style={{ float: 'right' }}>
<Button variant="danger" onClick={() => setShowDeleteModal(true)}>Delete Thread</Button>
</div>
) : ''}
<div style={{ float: 'right', padding: '0px', marginRight: '2em' }} id="segmented-buttons-wrapper">
<div id="segmented-like-button">
{(Users.collection.findOne(Meteor.user()._id).likes.indexOf(_id) >= 0) ? (
<span>
Expand Down Expand Up @@ -154,6 +173,10 @@ const ViewThread = () => {
</Col>
</Row>

<Row className="my-4">
<p style={{ wordWrap: 'break-word', lineHeight: 'normal' }}>{thread.messages[0].message}</p>
</Row>

<div id="discussion-input-box" style={inputStyle}>
<div className="d-flex flex-row justify-content-between align-items-center w-100">
<div>
Expand Down Expand Up @@ -181,13 +204,29 @@ const ViewThread = () => {
<div style={{ overflowY: 'auto' }} ref={containerRef}>
{(ready && thread && thread.messages.length !== 0) ? (
<div>
{thread.messages.map((item, index) => (
{thread.messages.slice(1).map((item, index) => (
<Message key={index} message={item} id={_id} />
))}
</div>
) : <p className="text-center">No messages in this discussion</p>}
</div>

<Modal show={showDeleteModal} onHide={() => setShowDeleteModal(false)} style={{ marginTop: '20vh' }}>
<Modal.Body className="py-5" style={{ textAlign: 'center' }}>
<ExclamationTriangle color="red" style={{ fontSize: '5vw' }} />
<h2>Are you sure?</h2>
<p><b>You are about to delete this thread.</b></p>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={() => setShowDeleteModal(false)}>
Cancel
</Button>
<Button variant="danger" onClick={deleteThread}>
Delete
</Button>
</Modal.Footer>
</Modal>

</Container>
) : <LoadingSpinner />;

Expand Down

0 comments on commit 20827f3

Please sign in to comment.