BOD-14 Cleanup and re-org of some components for messaging.

This commit is contained in:
Patrick Fic
2020-03-27 16:33:31 -07:00
parent f80f96f3df
commit c0be80b42e
11 changed files with 123 additions and 155 deletions

View File

@@ -2,15 +2,8 @@ import { ShrinkOutlined } from "@ant-design/icons";
import { Avatar, Badge, Col, List, Row } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
openConversation,
toggleChatVisible
} from "../../redux/messaging/messaging.actions";
import { openConversation, toggleChatVisible } from "../../redux/messaging/messaging.actions";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
});
const mapDispatchToProps = dispatch => ({
toggleChatVisible: () => dispatch(toggleChatVisible()),
openConversation: number => dispatch(openConversation(number))
@@ -59,7 +52,4 @@ export function ChatConversationListComponent({
</div>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChatConversationListComponent);
export default connect(null, mapDispatchToProps)(ChatConversationListComponent);

View File

@@ -21,8 +21,8 @@ function ChatConversationClosedComponent({
closeConversation
}) {
return (
<div className='chat-overlay-closed'>
<div onClick={() => toggleConversationVisible(conversation.phone_num)}>
<div>
<div onClick={() => toggleConversationVisible(conversation.id)}>
<PhoneFormatter>{conversation.phone_num}</PhoneFormatter>
</div>
<Button

View File

@@ -1,18 +1,9 @@
import { useSubscription } from "@apollo/react-hooks";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { MESSAGES_SUBSCRIPTION } from "../../graphql/messages.queries";
import ChatConversationComponent from "./chat-conversation.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
});
const mapDispatchToProps = dispatch => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function ChatConversationContainer({ conversation }) {
export default function ChatConversationContainer({ conversation }) {
const { loading, error, data } = useSubscription(MESSAGES_SUBSCRIPTION, {
variables: { conversationId: conversation.id }
});
@@ -26,7 +17,3 @@ export function ChatConversationContainer({ conversation }) {
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChatConversationContainer);

View File

@@ -1,8 +1,8 @@
import React, { useEffect, useRef } from "react";
import React from "react";
import AlertComponent from "../alert/alert.component";
import ChatSendMessage from "../chat-send-message/chat-send-message.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import { CheckOutlined, CheckCircleOutlined } from "@ant-design/icons";
import ChatMessageListComponent from "../chat-messages-list/chat-message-list.component";
export default function ChatConversationOpenComponent({
conversation,
@@ -10,49 +10,13 @@ export default function ChatConversationOpenComponent({
subState
}) {
const [loading, error] = subState;
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
console.log("use");
!!messagesEndRef.current &&
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
};
useEffect(scrollToBottom, [messages]);
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type='error' />;
const StatusRender = status => {
switch (status) {
case "sent":
return <CheckOutlined style={{ margin: "2px", float: "right" }} />;
case "delivered":
return (
<CheckCircleOutlined style={{ margin: "2px", float: "right" }} />
);
default:
return null;
}
};
return (
<div className='chat-overlay-open'>
<div className='messages'>
<ul>
{messages.map(item => (
<li
key={item.id}
className={`${item.isoutbound ? "replies" : "sent"}`}>
<p>
{item.text}
{StatusRender(item.status)}
</p>
</li>
))}
<li ref={messagesEndRef} />
</ul>
</div>
<ChatMessageListComponent messages={messages} />
<ChatSendMessage conversation={conversation} />
</div>
);

View File

@@ -0,0 +1,30 @@
import { Affix } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectConversations } from "../../redux/messaging/messaging.selectors";
import ChatConversationContainer from "../chat-conversation/chat-conversation.container";
import ChatMessagesButton from "../chat-messages-button/chat-messages-button.component";
const mapStateToProps = createStructuredSelector({
activeConversations: selectConversations
});
export function ChatOverlayContainer({ activeConversations }) {
return (
<Affix offsetBottom={0}>
<ChatMessagesButton />
{activeConversations
? activeConversations.map(conversation => (
<ChatConversationContainer
conversation={conversation}
key={conversation.id}
/>
))
: null}
</Affix>
);
}
export default connect(mapStateToProps, null)(ChatOverlayContainer);

View File

@@ -0,0 +1,37 @@
import { MessageFilled } from "@ant-design/icons";
import { Card } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import ChatConversationListContainer from "../chat-conversation-list/chat-conversation-list.container";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectChatVisible } from "../../redux/messaging/messaging.selectors";
import { toggleChatVisible } from "../../redux/messaging/messaging.actions";
const mapStateToProps = createStructuredSelector({
chatVisible: selectChatVisible
});
const mapDispatchToProps = dispatch => ({
toggleChatVisible: () => dispatch(toggleChatVisible())
});
export function ChatWindowComponent({ chatVisible, toggleChatVisible }) {
const { t } = useTranslation();
return (
<Card size='small'>
{chatVisible ? (
<ChatConversationListContainer />
) : (
<div onClick={() => toggleChatVisible()}>
<MessageFilled />
<strong>{t("messaging.labels.messaging")}</strong>
</div>
)}
</Card>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChatWindowComponent);

View File

@@ -0,0 +1,44 @@
import { CheckCircleOutlined, CheckOutlined } from "@ant-design/icons";
import React, { useEffect, useRef } from "react";
export default function ChatMessageListComponent({ messages }) {
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
console.log("use");
!!messagesEndRef.current &&
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
};
useEffect(scrollToBottom, [messages]);
const StatusRender = status => {
switch (status) {
case "sent":
return <CheckOutlined style={{ margin: "2px", float: "right" }} />;
case "delivered":
return (
<CheckCircleOutlined style={{ margin: "2px", float: "right" }} />
);
default:
return null;
}
};
return (
<div className='messages'>
<ul>
{messages.map(item => (
<li
key={item.id}
className={`${item.isoutbound ? "replies" : "sent"}`}>
<p>
{item.text}
{StatusRender(item.status)}
</p>
</li>
))}
<li ref={messagesEndRef} />
</ul>
</div>
);
}

View File

@@ -1,30 +0,0 @@
import { MessageFilled } from "@ant-design/icons";
import { Card } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import ChatConversationListContainer from "../chat-conversation-list/chat-conversation-list.container";
export default function ChatWindowComponent({
chatVisible,
toggleChatVisible
}) {
const { t } = useTranslation();
return (
<Card
className="chat-overlay"
size='small'>
{chatVisible ? (
<ChatConversationListContainer />
) : (
<div className="chat-overlay-closed" onClick={() => toggleChatVisible()}>
<MessageFilled />
<strong style={{ paddingLeft: "10px" }}>
{t("messaging.labels.messaging")}
</strong>
</div>
)}
</Card>
);
}

View File

@@ -1,54 +0,0 @@
import { Affix, Badge } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { toggleChatVisible } from "../../redux/messaging/messaging.actions";
import {
selectChatVisible,
selectConversations
} from "../../redux/messaging/messaging.selectors";
import ChatConversationContainer from "../chat-conversation/chat-conversation.container";
import ChatOverlayComponent from "./chat-overlay.component";
const mapStateToProps = createStructuredSelector({
chatVisible: selectChatVisible,
activeConversations: selectConversations
});
const mapDispatchToProps = dispatch => ({
toggleChatVisible: () => dispatch(toggleChatVisible())
});
export function ChatOverlayContainer({
chatVisible,
toggleChatVisible,
activeConversations
}) {
return (
<Affix offsetBottom={0}>
<div className={`chat-overlay-wrapper`}>
<div className={`chat-overlay-scroller`}>
<Badge count={10}>
<ChatOverlayComponent
chatVisible={chatVisible}
toggleChatVisible={toggleChatVisible}
/>
</Badge>
{activeConversations
? activeConversations.map(conversation => (
<ChatConversationContainer
conversation={conversation}
key={conversation.id}
/>
))
: null}
</div>
</div>
</Affix>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChatOverlayContainer);

View File

@@ -20,8 +20,8 @@ const ProfilePage = lazy(() => import("../profile/profile.container.page"));
const JobsAvailablePage = lazy(() =>
import("../jobs-available/jobs-available.page.container")
);
const ChatWindowContainer = lazy(() =>
import("../../components/chat-overlay/chat-overlay.container")
const ChatDockContainer = lazy(() =>
import("../../components/chat-dock/chat-dock.container")
);
const ScheduleContainer = lazy(() =>
import("../schedule/schedule.page.container")
@@ -135,7 +135,7 @@ export default function Manage({ match }) {
<Footer>
<FooterComponent />
</Footer>
<ChatWindowContainer />
<ChatDockContainer />
<BackTop />
</Layout>
);

View File

@@ -94,7 +94,7 @@ const messagingReducer = (state = INITIAL_STATE, action) => {
return {
...state,
conversations: state.conversations.map(c =>
c.phone_num === action.payload ? { ...c, open: !c.open } : c
c.id === action.payload ? { ...c, open: !c.open } : c
)
};