Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor chat component #10494

Closed
wants to merge 24 commits into from

Conversation

narender2031
Copy link
Contributor

What type of PR is this? (check all applicable)

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

  • Refactor chat component.

Related Tickets & Documents

QA Instructions, Screenshots, Recordings

Please replace this line with instructions on how to test your changes, as well
as any relevant images for UI changes.

Added tests?

  • yes
  • no, because they aren't needed
  • no, because I need help

Added to documentation?

  • docs.forem.com
  • readme
  • no documentation needed

[optional] Are there any post deployment tasks we need to perform?

[optional] What gif best describes this PR or how it makes you feel?

alt_text

@pr-triage pr-triage bot added the PR: draft bot applied label for PR's that are a work in progress label Sep 30, 2020
@reobin
Copy link
Contributor

reobin commented Sep 30, 2020

Hey @narender2031 !

Saw "refactor chat component", and it caught my attention. I just fixed a bug with the chat component causing it to not clear the input after being sent. It's over at #10487.

I think it would be compatible with your work if you want to take it into consideration while refactoring, especially the stuff I did with the Compose and Chat components, which cleans up the chat textarea's input state management.

I also added tests for the textarea being cleared after the message being sent, which can help you make sure nothing went wrong with the merge.

import { h } from 'preact';
import PropTypes from 'prop-types';

const OpenInroMessage = ({ activeChannel }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a typo, it should be Intro, not Inro.

import { h } from 'preact';
import PropTypes from 'prop-types';

const DireactIntroMessages = ({ activeChannel }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a typo: Direct, not Direact.

@nickytonline nickytonline changed the title [WIP]: Refactor chat component Refactor chat component Oct 14, 2020
Copy link
Contributor

@nickytonline nickytonline left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@narender2031 the draft is starting to look good. I have some feedback and request changes. I'll continue reviewing in the morning.

triggerDeleteMessage,
}) => {
if (!messages[activeChannelId]) {
return '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (best practice): There is no need to return an empty string. If a component ends up returning nothing via conditional rendering, return null.


Message.propTypes = {
activeChannelId: PropTypes.number,
messages: PropTypes.arrayOf(PropTypes.object),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): Use PropTypes.shape to describe the shape of a message prop. If the message proptype exist elsewhere, consider importing a shred prop type. For an example of this, see https://github.com/forem/forem/blob/master/app/javascript/common-prop-types/article-prop-types.js.

For more information on PropTypes.shape, see the PropTypes documentation.

return (
<div className="chatmessage" style={{ color: 'grey' }}>
<div className="chatmessage__body">
You have joined {activeChannel.channel_name}! All interactions{' '}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (non-blocking): Consider using a template string instead.

Suggested change
You have joined {activeChannel.channel_name}! All interactions{' '}
{`You have joined ${activeChannel.channel_name}! All interactions `}

.then(successCb)
.catch(failureCb);
}
// export function getAllMessages(channelId, messageOffset, successCb, failureCb) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): Remove dead commented out code.

@@ -56,20 +57,30 @@ export function editMessage(editedMessage, successCb, failureCb) {
.catch(failureCb);
}

export function sendOpen(activeChannelId, successCb, failureCb) {
fetch(`/chat_channels/${activeChannelId}/open`, {
// export function sendOpen(activeChannelId, successCb, failureCb) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): remove dead commented out code.

.then((response) => response.json())
.then(successCb)
.catch(failureCb);
body: JSON.stringify({}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The request utility function converts the body automatically to JSON. See https://github.com/forem/forem/blob/master/app/javascript/utilities/http/request.js#L35

Suggested change
body: JSON.stringify({}),
body: {},

});

return response.json()
// fetch('/chat_channels?state=unopened_ids', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): remove dead commented out code.

// }

export async function getContent(url) {
const response = await request(url, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'GET' is the default and credentials: 'same-origin' are included automatically when using the request utility function. See lines https://github.com/forem/forem/blob/master/app/javascript/utilities/http/request.js#L27 and https://github.com/forem/forem/blob/master/app/javascript/utilities/http/request.js#L47

})

return response.json();
// fetch(`/chat_channels/${channelId}?message_offset=${messageOffset}`, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): remove dead commented out code.


export async function getAllMessages(channelId, messageOffset) {
const response = await request(`/chat_channels/${channelId}?message_offset=${messageOffset}`, {
method: 'GET',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'GET' is the default and credentials: 'same-origin' are included automatically when using the request utility function. See lines https://github.com/forem/forem/blob/master/app/javascript/utilities/http/request.js#L27 and https://github.com/forem/forem/blob/master/app/javascript/utilities/http/request.js#L47

Copy link
Contributor

@nickytonline nickytonline left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (non-blocking): All components and variables defined with an arrow function are unnecessary since there is no use of this. Prefer using a traditional function. This is something I need to update in our frontend documentation and potentially incorporate a lint rule.

For more information about this see the official arrow function documentation on MDN as well as this post, When (and why) you should use ES6 arrow functions — and when you shouldn’t.

@@ -0,0 +1,307 @@
export function connectReducer(state, action) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation (blocking): For any functions, constants etc. that are exported in an ES module, provide documentation using JSDoc comments. For an example, see https://github.com/forem/forem/blob/master/app/javascript/utilities/http/request.js#L1.

@@ -0,0 +1,22 @@
import { h, createContext } from 'preact';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@narender2031, @citizen428, since we're going to go with useReducer and context, I'll merge my PR, #9799, first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

@nickytonline
Copy link
Contributor

@narender2031, @citizen428, once this PR is out of draft mode, I will give it another review.

@narender2031 narender2031 marked this pull request as ready for review October 23, 2020 07:17
@pr-triage pr-triage bot added PR: unreviewed bot applied label for PR's with no review and removed PR: draft bot applied label for PR's that are a work in progress labels Oct 23, 2020
Copy link
Contributor

@nickytonline nickytonline left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments and request changes.

import { h } from 'preact';
import PropTypes from 'prop-types';

const ActiveChannel = ({ _activeChannel }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): This component appears to do only render an empty <div />. Is this component still a work in progress? It also does not appear to be used anywhere in the codebase.

? Object.values(channelUsers[activeChannelId])
.filter((user) => user.username.match(filterRegx))
.map((user) => (
<div
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): Use a semantic HTML button instead of a div with a role attribute of "button". Since we are in Prreact land, use our design system Button component.

alt={user.name}
style={!user.profile_image ? { display: 'none' } : ' '}
/>
<span
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): Avoid inline styles. Use our CSS utility classes or a custom CSS class if necessary.

<div className="crayons-modal__box__body">
<h3>Are you sure, you want to delete this message?</h3>
<div className="delete-actions__container">
<div
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): Use a semantic HTML button instead of a div with a role attribute of "button". Since we are in PRreact land, use the Button component.

@@ -1,7 +1,7 @@
import { h } from 'preact';
import PropTypes from 'prop-types';

const ModFaqSection = ({ email, currentMembershipRole }) => {
const ModFaqSection = ({ currentMembershipRole }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (non-blocking): This can just be membershipRole


const ConnectStateProvider = ({ children, initialState, reducer }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change isn't necessary. It's fine that it uses the function keyword instead of an arrow function. Arrow functions work well when you need scope, i.e. "this".

@@ -0,0 +1,320 @@
import * as Type from './components/ChatTypes';
export function connectReducer(state, action) {
const { type, payload = {} } = action;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (blocking): There is no need to give payload a default value of {}. This will actually mask potential errors when a payload isn't being sent that may be required by an action.

export function connectReducer(state, action) {
const { type, payload = {} } = action;

switch (type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (non-blocking): consider combining reducers instead of a super long switch case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do these changes incoming PRs with more refactoring.

@pr-triage pr-triage bot added PR: reviewed-changes-requested bot applied label for PR's where reviewer requests changes and removed PR: unreviewed bot applied label for PR's with no review labels Nov 3, 2020
Copy link
Contributor

@nickytonline nickytonline left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned the ones about converting <div />s to actual buttons via our <Button /> component, but I noticed there are a lot of <div />s being used instead of potentially better matched semantic HTML elements.

Co-authored-by: Nick Taylor <nick@iamdeveloper.com>
@@ -0,0 +1,23 @@
require "rails_helper"

RSpec.describe "Admin creates new page", type: :system do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused, is this spec really related to the changes in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes updated due to conflict. I think this file is deleted in the master branch. I will check and update this.

@@ -1,6 +1,31 @@
import { h } from 'preact';
import PropTypes from 'prop-types';

/**
* This component is used to render the list of all Achtive chat channel Members
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling (nitpick)

Suggested change
* This component is used to render the list of all Achtive chat channel Members
* This component is used to render the list of all Active chat channel Members

@@ -3,7 +3,36 @@ import PropTypes from 'prop-types';
import ActionMessage from '../actionMessage';
import Message from '../message';
import DirectChatInfoMessage from './IntroductionMessages/DireactIntroMessages';
import OpenChatInfoMessagge from './IntroductionMessages/OpenItnroMessage';
import IntroductionMessage from './IntroductionMessages/OpenItnroMessage';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling (nitpick): OpenItnroMessage should be OpenIntroMessage

Suggested change
import IntroductionMessage from './IntroductionMessages/OpenItnroMessage';
import IntroductionMessage from './IntroductionMessages/OpenIntroMessage';

Copy link
Contributor

@citizen428 citizen428 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all the feedback has been addressed now, thanks @narender2031! 🚀

@pr-triage pr-triage bot added PR: partially-approved bot applied label for PR's where a single reviewer approves changes and removed PR: unreviewed bot applied label for PR's with no review labels Nov 9, 2020
@narender2031
Copy link
Contributor Author

I think all the feedback has been addressed now, thanks @narender2031! 🚀

@citizen428 & @nickytonline I need a small help Can you please test these changes locally. Just for a safe case.

@citizen428
Copy link
Contributor

@narender2031 Could you please fill in the "QA Instructions" section of the PR to point out what to look for specifically? This also helps other potential reviewers who weren't following along.

@narender2031
Copy link
Contributor Author

@narender2031 Could you please fill in the "QA Instructions" section of the PR to point out what to look for specifically? This also helps other potential reviewers who weren't following along.

@citizen428 & @nickytonline

QA Instructions:-

  • All Messages in the chat channel should load.
  • You can delete, update, the message from the chat channel.
  • you can send the messages.
  • you can open the chat channel settings and perform the actions.
  • you can switch the chat channels.
  • you can open the mention POP up (*NOTE- Mention is not working in this PR. Another PR with the FIX is already done)
  • you can search the chat channels.
  • you can open the request center

@citizen428
Copy link
Contributor

Quick question: since this is a refactoring PR, are you planning on also addressing some of the CodeClimate issues or will you do that separately?

@narender2031
Copy link
Contributor Author

Quick question: since this is a refactoring PR, are you planning on also addressing some of the CodeClimate issues or will you do that separately?

we will do separately because some of the files have a large number of the line so we will refactor those also one by one.

@citizen428
Copy link
Contributor

Feedback:

  1. On first starting the app after checking out this branch I get the following when opening the site in the browser:

    Failed to compile.

    ./app/javascript/chat/channels.jsx
    Module not found: Error: [CaseSensitivePathsPlugin] /Users/xxx/src/work/forem/app/javascript/chat/components/ChannelButton.jsx does not match the corresponding path on disk channelButton.jsx.

    Renaming the file fixed this:

    $ git mv app/javascript/chat/components/{c,C}hannelButton.jsx
    
  2. The placeholder text says "Write message to undefined"
    Screen Shot 2020-11-10 at 13 13 24

  3. It seems messages don't show up for me until I refresh. That's true for both new messages and edited ones as well as when deleting messages:
    2020-11-10 13 16 25

@narender2031
Copy link
Contributor Author

narender2031 commented Nov 10, 2020

Feedback:
3. It seems messages don't show up for me until I refresh. That's true for both new messages and edited ones as well as when deleting messages:

@citizen428 You need to integrate the PUSHER locally for this. Can you please check with the other branch? is that happening with all. Because in my case locally in other branches messages don't show up on send or updates. It requires refresh.
And for rest I will take a look.

@citizen428
Copy link
Contributor

Yes @narender2031, correct re 3, I just realized this after changing branches and noticing the same behavior. Sorry for the false alarm on this one.

@narender2031
Copy link
Contributor Author

Yes @narender2031, correct re 3, I just realized this after changing branches and noticing the same behavior. Sorry for the false alarm on this one.

np @citizen428

@pr-triage pr-triage bot added PR: unreviewed bot applied label for PR's with no review and removed PR: partially-approved bot applied label for PR's where a single reviewer approves changes labels Nov 12, 2020
@narender2031
Copy link
Contributor Author

Feedback:

  1. On first starting the app after checking out this branch I get the following when opening the site in the browser:
  1. The placeholder text says "Write message to undefined"

@citizen428 issues are fixed.

@nickytonline
Copy link
Contributor

@narender2031 and @sarthology, can we pause work on this PR until #11332 and #9741 are finished? There are change requests in both of those PRs. cc: @citizen428

@nickytonline
Copy link
Contributor

As discussed, going to put this on hold and reassess the refactor. Closing this for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR: unreviewed bot applied label for PR's with no review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants