From 8e3dfa264e1e2238344cd20de75f8cf39b277735 Mon Sep 17 00:00:00 2001 From: William Li <52115161+Trollermaner@users.noreply.github.com> Date: Mon, 1 Jan 2024 13:31:23 -0500 Subject: [PATCH 1/8] fixed email recipients into ENV --- backend/emails/emails.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/backend/emails/emails.js b/backend/emails/emails.js index 43fd076..5139297 100644 --- a/backend/emails/emails.js +++ b/backend/emails/emails.js @@ -15,13 +15,7 @@ const currencyFormatter = new Intl.NumberFormat('en-CA', { }) const getEmailToSection = async (reporter_id, recipients) => { - const emailToSet = new Set( - process.env.EMAIL_RECIPIENTS?.split(',') || [ - 'jw4he@watonomous.ca', - 'v2zheng@watonomous.ca', - 'william.li@watonomous.ca', - ] - ) + const emailToSet = new Set(process.env.EMAIL_RECIPIENTS?.split(',')) if (recipients.includes(EMAIL_RECIPIENTS.admin)) { // TODO: use ADMIN_IDENTIFIERS (rename to ADMIN_EMAILS) after migrating to new onboarding data From a9b24e2cb669dc9f13d7e57479c7f91477bc6d76 Mon Sep 17 00:00:00 2001 From: William Li <52115161+Trollermaner@users.noreply.github.com> Date: Mon, 1 Jan 2024 13:33:51 -0500 Subject: [PATCH 2/8] added default emails --- backend/emails/emails.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/emails/emails.js b/backend/emails/emails.js index 5139297..43fd076 100644 --- a/backend/emails/emails.js +++ b/backend/emails/emails.js @@ -15,7 +15,13 @@ const currencyFormatter = new Intl.NumberFormat('en-CA', { }) const getEmailToSection = async (reporter_id, recipients) => { - const emailToSet = new Set(process.env.EMAIL_RECIPIENTS?.split(',')) + const emailToSet = new Set( + process.env.EMAIL_RECIPIENTS?.split(',') || [ + 'jw4he@watonomous.ca', + 'v2zheng@watonomous.ca', + 'william.li@watonomous.ca', + ] + ) if (recipients.includes(EMAIL_RECIPIENTS.admin)) { // TODO: use ADMIN_IDENTIFIERS (rename to ADMIN_EMAILS) after migrating to new onboarding data From 440583e855280e369125f4d826e34f9942958526 Mon Sep 17 00:00:00 2001 From: William Li <52115161+Trollermaner@users.noreply.github.com> Date: Fri, 26 Jan 2024 00:52:14 -0500 Subject: [PATCH 3/8] added comments (beta) --- backend/models/comment.model.js | 10 +- backend/server.js | 2 + frontend/package-lock.json | 77 +++++++++++ frontend/package.json | 3 + frontend/src/components/CommentInput.js | 104 +++++++++++++++ frontend/src/components/CommentSection.js | 142 ++++++--------------- frontend/src/components/CommentView.js | 126 ++++++++++++++++++ frontend/src/components/SlateComponents.js | 4 +- frontend/src/pages/Dashboard.js | 8 +- 9 files changed, 363 insertions(+), 113 deletions(-) create mode 100644 frontend/src/components/CommentInput.js create mode 100644 frontend/src/components/CommentView.js diff --git a/backend/models/comment.model.js b/backend/models/comment.model.js index 5ee409f..e7628fa 100644 --- a/backend/models/comment.model.js +++ b/backend/models/comment.model.js @@ -1,11 +1,15 @@ const mongoose = require('mongoose') const { Schema } = mongoose +const Mixed = Schema.Types.Mixed + +//sort by new -> old for parent comments, old -> new for replies const CommentSchema = new Schema( { - // reference_code would be parent ticket here - reference_code: { type: String, index: true }, - commment: { type: String }, + // reference_code would be parent ticket/parent comment here + reference_code: { type: String, index: true, required: true }, + comment: { type: [Mixed], required: true }, + author_id: {type: String, required: true}, }, { timestamps: true, diff --git a/backend/server.js b/backend/server.js index fe56817..67c4b78 100644 --- a/backend/server.js +++ b/backend/server.js @@ -31,6 +31,7 @@ const UWFinancePurchaseRouter = require('./routes/uwfinancepurchases.routes') const usersRouter = require('./routes/users.routes') const groupRouter = require('./routes/googlegroup.routes') const filesRouter = require('./routes/files.routes') +const commentRouter = require('./routes/comments.routes') app.use(express.json()) app.use('/fundingitems', fundingItemsRouter) @@ -40,6 +41,7 @@ app.use('/uwfinancepurchases', UWFinancePurchaseRouter) app.use('/users', usersRouter) app.use('/googlegroups', groupRouter) app.use('/files', filesRouter) +app.use('/comments', commentRouter) app.listen(port, async () => { console.log(`Server is running on port: ${port}`) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index cc845df..03d23f6 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,6 +13,9 @@ "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", "@mui/icons-material": "^5.14.12", "@mui/material": "^5.14.12", "@testing-library/jest-dom": "^5.16.5", @@ -3740,6 +3743,51 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.7.3", "license": "Apache-2.0", @@ -23484,6 +23532,35 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" }, + "@fortawesome/fontawesome-common-types": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.5.1" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.5.1" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "requires": { + "prop-types": "^15.8.1" + } + }, "@grpc/grpc-js": { "version": "1.7.3", "requires": { diff --git a/frontend/package.json b/frontend/package.json index c436e02..f749412 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,9 @@ "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", "@mui/icons-material": "^5.14.12", "@mui/material": "^5.14.12", "@testing-library/jest-dom": "^5.16.5", diff --git a/frontend/src/components/CommentInput.js b/frontend/src/components/CommentInput.js new file mode 100644 index 0000000..3c6fa5a --- /dev/null +++ b/frontend/src/components/CommentInput.js @@ -0,0 +1,104 @@ +import {useCallback, useMemo, useState} from 'react' +import isHotkey from 'is-hotkey' +import { Editable, withReact, Slate } from 'slate-react' +import { createEditor } from 'slate' +import { withHistory } from 'slate-history' +import { useAuth } from '../contexts/AuthContext' +import { axiosPreset } from '../axiosConfig' +import { Box, Button } from '@chakra-ui/react' + +import { + BlockButton, + Element, + Leaf, + MarkButton, + Toolbar, + toggleMark, +} from './SlateComponents' + +const HOTKEYS = { + 'mod+b': 'bold', + 'mod+i': 'italic', + 'mod+u': 'underline', +} + +const CommentInput = ({code, getComments, reply, onClose, type}) => { + const renderElement = useCallback((props) => , []) + const renderLeaf = useCallback((props) => , []) + const editor = useMemo(() => withHistory(withReact(createEditor())), []) + const auth = useAuth() + const [val, setVal] = useState(editor.children) + const handleSubmit = (ref) => { + const payload = { + author_id: auth.currentUser.uid, + comment: editor.children, + reference_code: ref, + } + axiosPreset.post( + '/comments', + payload, + ) + .then(() => getComments(ref)) + } + + return ( + {setVal([...editor.children])}}> + { + for (const hotkey in HOTKEYS) { + if (isHotkey(hotkey, event)) { + event.preventDefault() + const mark = HOTKEYS[hotkey] + toggleMark(editor, mark) + } + } + }} + /> + + + + + + + + + + {reply && } + + + + + ) +} + +// example taken from https://github.com/ianstormtaylor/slate/blob/main/site/components.tsx +// remove once dynamically fetched from backend +const initialValue = [ + { + type: 'paragraph', + children: [{ text: '' }], + }, +] + +export default CommentInput + +//make a function that removes white lines in the start +//parses data to make it look nice \ No newline at end of file diff --git a/frontend/src/components/CommentSection.js b/frontend/src/components/CommentSection.js index 4ad4600..c35be06 100644 --- a/frontend/src/components/CommentSection.js +++ b/frontend/src/components/CommentSection.js @@ -1,114 +1,50 @@ // modified version of https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx -import React, { useCallback, useMemo } from 'react' -import isHotkey from 'is-hotkey' -import { Editable, withReact, Slate } from 'slate-react' -import { createEditor } from 'slate' -import { withHistory } from 'slate-history' - -import { - BlockButton, - Element, - Leaf, - MarkButton, - Toolbar, - toggleMark, -} from './SlateComponents' +import React, { useState, useEffect } from 'react' import { Box, Heading } from '@chakra-ui/react' +import { axiosPreset } from '../axiosConfig' +import CommentInput from './CommentInput' +import CommentView from './CommentView' -const HOTKEYS = { - 'mod+b': 'bold', - 'mod+i': 'italic', - 'mod+u': 'underline', - 'mod+`': 'code', -} +const CommentSection = ({ticket, allUsers}) => { + const [comments, setComments] = useState([]) + const [refreshKey, setRefreshKey] = useState(0); + + const forceRefresh = () => { + setRefreshKey(oldKey => oldKey + 1); + }; + + const getComments = async (ref) => { + axiosPreset.get('/comments/' + ref) + .then((data) => {setComments([...data.data]); forceRefresh()}) + } + + useEffect(() => { + getComments(ticket) + }, [ticket]) -const CommentSection = () => { - const renderElement = useCallback((props) => , []) - const renderLeaf = useCallback((props) => , []) - const editor = useMemo(() => withHistory(withReact(createEditor())), []) return ( - - Comment Section - - - - - - - - - - - - - - - - - { - for (const hotkey in HOTKEYS) { - if (isHotkey(hotkey, event)) { - event.preventDefault() - const mark = HOTKEYS[hotkey] - toggleMark(editor, mark) - } - } - }} - /> - + + Comments +
+ + {comments.map((content, index) => { + return( + + ) + })} +
) } -// example taken from https://github.com/ianstormtaylor/slate/blob/main/site/components.tsx -// remove once dynamically fetched from backend -const initialValue = [ - { - type: 'paragraph', - children: [ - { text: 'This is editable ' }, - { text: 'rich', bold: true }, - { text: ' text, ' }, - { text: 'much', italic: true }, - { text: ' better than a ' }, - { text: '