BOD-14 Added virtualization for messages with known bug. Added messages geting marked as read.
This commit is contained in:
@@ -10168,6 +10168,32 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>messaging</name>
|
<name>messaging</name>
|
||||||
<children>
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>actions</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>link</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>labels</name>
|
<name>labels</name>
|
||||||
<children>
|
<children>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
"react-scripts": "3.4.1",
|
"react-scripts": "3.4.1",
|
||||||
"react-trello": "^2.2.5",
|
"react-trello": "^2.2.5",
|
||||||
|
"react-virtualized": "^9.21.2",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"redux-saga": "^1.1.3",
|
"redux-saga": "^1.1.3",
|
||||||
|
|||||||
@@ -1,15 +1,37 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Tag } from "antd";
|
import { Tag } from "antd";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { useMutation } from "@apollo/react-hooks";
|
||||||
|
import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
||||||
|
|
||||||
export default function ChatConversationTitleTags({ jobConversations }) {
|
export default function ChatConversationTitleTags({ jobConversations }) {
|
||||||
|
const [removeJobConversation] = useMutation(REMOVE_CONVERSATION_TAG);
|
||||||
|
|
||||||
|
const handleRemoveTag = (jobId) => {
|
||||||
|
const convId = jobConversations[0].conversationid;
|
||||||
|
if (!!convId) {
|
||||||
|
removeJobConversation({
|
||||||
|
variables: {
|
||||||
|
conversationId: convId,
|
||||||
|
jobId: jobId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{jobConversations.map((item) => (
|
{jobConversations.map((item) => (
|
||||||
<Link to={`/manage/jobs/${item.job.id}`}>
|
<Tag
|
||||||
<Tag color='blue' style={{ cursor: "pointer" }}>
|
key={item.job.id}
|
||||||
|
closable
|
||||||
|
color='blue'
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
onClose={() => handleRemoveTag(item.job.id)}>
|
||||||
|
<Link to={`/manage/jobs/${item.job.id}`}>
|
||||||
{item.job.ro_number || "?"}
|
{item.job.ro_number || "?"}
|
||||||
</Tag>
|
</Link>
|
||||||
</Link>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx"
|
|||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import ChatConversationTitle from "../chat-conversation-title/chat-conversation-title.component";
|
import ChatConversationTitle from "../chat-conversation-title/chat-conversation-title.component";
|
||||||
|
|
||||||
export default function ChatConversationComponent({ subState, conversation }) {
|
export default function ChatConversationComponent({
|
||||||
|
subState,
|
||||||
|
conversation,
|
||||||
|
handleMarkConversationAsRead,
|
||||||
|
}) {
|
||||||
const [loading, error] = subState;
|
const [loading, error] = subState;
|
||||||
|
|
||||||
if (loading) return <LoadingSkeleton />;
|
if (loading) return <LoadingSkeleton />;
|
||||||
@@ -20,12 +24,13 @@ export default function ChatConversationComponent({ subState, conversation }) {
|
|||||||
conversation.messages_aggregate.aggregate.count) ||
|
conversation.messages_aggregate.aggregate.count) ||
|
||||||
0;
|
0;
|
||||||
|
|
||||||
const messages =
|
const messages = (conversation && conversation.messages) || [];
|
||||||
(conversation && conversation.messages) ||
|
|
||||||
[];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='chat-conversation'>
|
<div
|
||||||
|
className='chat-conversation'
|
||||||
|
onMouseDown={handleMarkConversationAsRead}
|
||||||
|
onKeyDown={handleMarkConversationAsRead}>
|
||||||
<Badge count={unreadCount}>
|
<Badge count={unreadCount}>
|
||||||
<Card size='small'>
|
<Card size='small'>
|
||||||
<ChatConversationTitle conversation={conversation} />
|
<ChatConversationTitle conversation={conversation} />
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useSubscription } from "@apollo/react-hooks";
|
import { useMutation, useSubscription } from "@apollo/react-hooks";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { CONVERSATION_SUBSCRIPTION_BY_PK } from "../../graphql/conversations.queries";
|
|
||||||
import ChatConversationComponent from "./chat-conversation.component";
|
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { CONVERSATION_SUBSCRIPTION_BY_PK } from "../../graphql/conversations.queries";
|
||||||
|
import { MARK_MESSAGES_AS_READ_BY_CONVERSATION } from "../../graphql/messages.queries";
|
||||||
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
|
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
|
||||||
|
import ChatConversationComponent from "./chat-conversation.component";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
selectedConversation: selectSelectedConversation,
|
selectedConversation: selectSelectedConversation,
|
||||||
});
|
});
|
||||||
@@ -13,10 +13,6 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
export default connect(mapStateToProps, null)(ChatConversationContainer);
|
export default connect(mapStateToProps, null)(ChatConversationContainer);
|
||||||
|
|
||||||
export function ChatConversationContainer({ selectedConversation }) {
|
export function ChatConversationContainer({ selectedConversation }) {
|
||||||
console.log(
|
|
||||||
"ChatConversationContainer -> selectedConversation",
|
|
||||||
selectedConversation
|
|
||||||
);
|
|
||||||
const { loading, error, data } = useSubscription(
|
const { loading, error, data } = useSubscription(
|
||||||
CONVERSATION_SUBSCRIPTION_BY_PK,
|
CONVERSATION_SUBSCRIPTION_BY_PK,
|
||||||
{
|
{
|
||||||
@@ -24,12 +20,33 @@ export function ChatConversationContainer({ selectedConversation }) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [markConversationRead] = useMutation(
|
||||||
|
MARK_MESSAGES_AS_READ_BY_CONVERSATION,
|
||||||
|
{
|
||||||
|
variables: { conversationId: selectedConversation },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const unreadCount =
|
||||||
|
(data &&
|
||||||
|
data.conversations_by_pk &&
|
||||||
|
data.conversations_by_pk &&
|
||||||
|
data.conversations_by_pk.messages_aggregate &&
|
||||||
|
data.conversations_by_pk.messages_aggregate.aggregate &&
|
||||||
|
data.conversations_by_pk.messages_aggregate.aggregate.count) ||
|
||||||
|
0;
|
||||||
|
|
||||||
|
const handleMarkConversationAsRead = () => {
|
||||||
|
if (unreadCount > 0 && !!selectedConversation) {
|
||||||
|
markConversationRead();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatConversationComponent
|
<ChatConversationComponent
|
||||||
subState={[loading, error]}
|
subState={[loading, error]}
|
||||||
conversation={data ? data.conversations_by_pk : {}}
|
conversation={data ? data.conversations_by_pk : {}}
|
||||||
|
handleMarkConversationAsRead={handleMarkConversationAsRead}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,68 @@
|
|||||||
import { CheckCircleOutlined, CheckOutlined } from "@ant-design/icons";
|
import { CheckCircleOutlined, CheckOutlined } from "@ant-design/icons";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import "./chat-message-list.styles.scss";
|
import "./chat-message-list.styles.scss";
|
||||||
|
import { List, CellMeasurer, CellMeasurerCache } from "react-virtualized";
|
||||||
|
|
||||||
export default function ChatMessageListComponent({ messages }) {
|
export default function ChatMessageListComponent({ messages }) {
|
||||||
const messagesEndRef = useRef(null);
|
const virtualizedListRef = useRef(null);
|
||||||
|
|
||||||
|
const _cache = new CellMeasurerCache({
|
||||||
|
fixedWidth: true,
|
||||||
|
minHeight: 20,
|
||||||
|
});
|
||||||
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
!!messagesEndRef.current &&
|
console.log("SCrolling to", messages.length);
|
||||||
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
|
!!virtualizedListRef.current &&
|
||||||
|
virtualizedListRef.current.scrollToRow(messages.length - 1);
|
||||||
|
|
||||||
|
//TODO Outstanding isue on virtualization: https://github.com/bvaughn/react-virtualized/issues/1179
|
||||||
|
//Scrolling does not work on this version of React.
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(scrollToBottom, [messages]);
|
useEffect(scrollToBottom, [messages]);
|
||||||
const StatusRender = (status) => {
|
|
||||||
switch (status) {
|
const _rowRenderer = ({ index, key, parent, style }) => {
|
||||||
case "sent":
|
return (
|
||||||
return <CheckOutlined style={{ margin: "2px", float: "right" }} />;
|
<CellMeasurer cache={_cache} key={key} rowIndex={index} parent={parent}>
|
||||||
case "delivered":
|
{({ measure, registerChild }) => (
|
||||||
return (
|
<li
|
||||||
<CheckCircleOutlined style={{ margin: "2px", float: "right" }} />
|
ref={registerChild}
|
||||||
);
|
style={style}
|
||||||
default:
|
className={`${messages[index].isoutbound ? "replies" : "sent"}`}>
|
||||||
return null;
|
<p onLoad={measure}>
|
||||||
}
|
{messages[index].text}
|
||||||
|
{StatusRender(messages[index].status)}
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</CellMeasurer>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='messages'>
|
<div className='messages'>
|
||||||
<ul>
|
<ul>
|
||||||
{messages.map((item) => (
|
<List
|
||||||
<li
|
ref={virtualizedListRef}
|
||||||
key={item.id}
|
width={300}
|
||||||
className={`${item.isoutbound ? "replies" : "sent"}`}>
|
height={300}
|
||||||
<p>
|
rowHeight={_cache.rowHeight}
|
||||||
{item.text}
|
rowRenderer={_rowRenderer}
|
||||||
{StatusRender(item.status)}
|
rowCount={messages.length}
|
||||||
</p>
|
/>
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
<li ref={messagesEndRef} />
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
.messages {
|
// .messages {
|
||||||
height: 350px;
|
// height: 300px;
|
||||||
min-height: calc(100% - 10px);
|
// min-height: calc(100% - 10px);
|
||||||
max-height: calc(100% - 93px);
|
// max-height: calc(100% - 93px);
|
||||||
overflow-y: scroll;
|
// overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
// overflow-x: hidden;
|
||||||
}
|
// }
|
||||||
@media screen and (max-width: 735px) {
|
// @media screen and (max-width: 735px) {
|
||||||
.messages {
|
// .messages {
|
||||||
max-height: calc(100% - 105px);
|
// max-height: calc(100% - 105px);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
.messages::-webkit-scrollbar {
|
// .messages::-webkit-scrollbar {
|
||||||
width: 8px;
|
// width: 8px;
|
||||||
background: transparent;
|
// background: transparent;
|
||||||
}
|
// }
|
||||||
.messages::-webkit-scrollbar-thumb {
|
// .messages::-webkit-scrollbar-thumb {
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
// background-color: rgba(0, 0, 0, 0.3);
|
||||||
}
|
// }
|
||||||
.messages ul li {
|
.messages ul li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
clear: both;
|
clear: both;
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { AutoComplete } from "antd";
|
import { AutoComplete } from "antd";
|
||||||
import { LoadingOutlined } from "@ant-design/icons";
|
import { LoadingOutlined, CloseCircleOutlined } from "@ant-design/icons";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function ChatTagRoComponent({
|
export default function ChatTagRoComponent({
|
||||||
searchQueryState,
|
searchQueryState,
|
||||||
roOptions,
|
roOptions,
|
||||||
loading,
|
loading,
|
||||||
executeSearch,
|
executeSearch,
|
||||||
handleInsertTag,
|
handleInsertTag,
|
||||||
|
setVisible,
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const setSearchQuery = searchQueryState[1];
|
const setSearchQuery = searchQueryState[1];
|
||||||
const handleSearchQuery = (value) => {
|
const handleSearchQuery = (value) => {
|
||||||
setSearchQuery(value);
|
setSearchQuery(value);
|
||||||
@@ -20,19 +25,26 @@ export default function ChatTagRoComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoComplete
|
<span>
|
||||||
suffixIcon={loading ? <LoadingOutlined /> : null}
|
<AutoComplete
|
||||||
style={{ width: 200 }}
|
style={{ width: 100 }}
|
||||||
onSearch={handleSearchQuery}
|
onSearch={handleSearchQuery}
|
||||||
onSelect={handleInsertTag}
|
onSelect={handleInsertTag}
|
||||||
onKeyDown={handleKeyDown}>
|
placeholder={t("general.labels.search")}
|
||||||
{roOptions.map((item, idx) => (
|
onKeyDown={handleKeyDown}>
|
||||||
<AutoComplete.Option key={item.id || idx}>
|
{roOptions.map((item, idx) => (
|
||||||
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
<AutoComplete.Option key={item.id || idx}>
|
||||||
item.ownr_ln || ""
|
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
||||||
}`}
|
item.ownr_ln || ""
|
||||||
</AutoComplete.Option>
|
}`}
|
||||||
))}
|
</AutoComplete.Option>
|
||||||
</AutoComplete>
|
))}
|
||||||
|
</AutoComplete>
|
||||||
|
{loading ? (
|
||||||
|
<LoadingOutlined />
|
||||||
|
) : (
|
||||||
|
<CloseCircleOutlined onClick={() => setVisible(false)} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,14 @@ import ChatTagRo from "./chat-tag-ro.component";
|
|||||||
import { useLazyQuery, useMutation } from "@apollo/react-hooks";
|
import { useLazyQuery, useMutation } from "@apollo/react-hooks";
|
||||||
import { SEARCH_FOR_JOBS } from "../../graphql/jobs.queries";
|
import { SEARCH_FOR_JOBS } from "../../graphql/jobs.queries";
|
||||||
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
||||||
|
import { Tag } from "antd";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { PlusOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
export default function ChatTagRoContainer({ conversation }) {
|
export default function ChatTagRoContainer({ conversation }) {
|
||||||
console.log("ChatTagRoContainer -> conversation", conversation);
|
console.log("ChatTagRoContainer -> conversation", conversation);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
const searchQueryState = useState("");
|
const searchQueryState = useState("");
|
||||||
const searchText = searchQueryState[0];
|
const searchText = searchQueryState[0];
|
||||||
|
|
||||||
@@ -28,19 +33,33 @@ export default function ChatTagRoContainer({ conversation }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleInsertTag = (value, option) => {
|
const handleInsertTag = (value, option) => {
|
||||||
console.log("value, option", value, option);
|
|
||||||
insertTag({ variables: { jobId: option.key } });
|
insertTag({ variables: { jobId: option.key } });
|
||||||
|
setVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const existingJobTags = conversation.job_conversations.map((i) => i.jobid);
|
||||||
|
|
||||||
|
const roOptions = data
|
||||||
|
? data.jobs.filter((job) => !existingJobTags.includes(job.id))
|
||||||
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ChatTagRo
|
{visible ? (
|
||||||
loading={loading}
|
<ChatTagRo
|
||||||
searchQueryState={searchQueryState}
|
loading={loading}
|
||||||
roOptions={data ? data.jobs : []}
|
searchQueryState={searchQueryState}
|
||||||
executeSearch={executeSearch}
|
roOptions={roOptions}
|
||||||
handleInsertTag={handleInsertTag}
|
executeSearch={executeSearch}
|
||||||
/>
|
handleInsertTag={handleInsertTag}
|
||||||
|
setVisible={setVisible}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Tag onClick={() => setVisible(true)}>
|
||||||
|
<PlusOutlined />
|
||||||
|
{t("messaging.actions.link")}
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const CONVERSATION_LIST_SUBSCRIPTION = gql`
|
|||||||
export const CONVERSATION_SUBSCRIPTION_BY_PK = gql`
|
export const CONVERSATION_SUBSCRIPTION_BY_PK = gql`
|
||||||
subscription CONVERSATION_SUBSCRIPTION_BY_PK($conversationId: uuid!) {
|
subscription CONVERSATION_SUBSCRIPTION_BY_PK($conversationId: uuid!) {
|
||||||
conversations_by_pk(id: $conversationId) {
|
conversations_by_pk(id: $conversationId) {
|
||||||
messages {
|
messages(order_by: { created_at: asc_nulls_first }) {
|
||||||
id
|
id
|
||||||
status
|
status
|
||||||
text
|
text
|
||||||
|
|||||||
@@ -12,3 +12,18 @@ export const INSERT_CONVERSATION_TAG = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const REMOVE_CONVERSATION_TAG = gql`
|
||||||
|
mutation REMOVE_CONVERSATION_TAG($conversationId: uuid!, $jobId: uuid!) {
|
||||||
|
delete_job_conversations(
|
||||||
|
where: {
|
||||||
|
_and: {
|
||||||
|
jobid: { _eq: $jobId }
|
||||||
|
conversationid: { _eq: $conversationId }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
14
client/src/graphql/messages.queries.js
Normal file
14
client/src/graphql/messages.queries.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { gql } from "apollo-boost";
|
||||||
|
|
||||||
|
export const MARK_MESSAGES_AS_READ_BY_CONVERSATION = gql`
|
||||||
|
mutation MARK_MESSAGES_AS_READ_BY_CONVERSATION($conversationId: uuid) {
|
||||||
|
update_messages(
|
||||||
|
where: { conversationid: { _eq: $conversationId } }
|
||||||
|
_set: { read: true }
|
||||||
|
) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -10,8 +10,8 @@ import applicationReducer from "./application/application.reducer";
|
|||||||
const persistConfig = {
|
const persistConfig = {
|
||||||
key: "root",
|
key: "root",
|
||||||
storage,
|
storage,
|
||||||
//whitelist: ["user"]
|
whitelist: ["messaging"],
|
||||||
blacklist: ["user", "email", "messaging", "modals"]
|
blacklist: ["user", "email", "modals"],
|
||||||
};
|
};
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
@@ -19,7 +19,7 @@ const rootReducer = combineReducers({
|
|||||||
messaging: messagingReducer,
|
messaging: messagingReducer,
|
||||||
email: emailReducer,
|
email: emailReducer,
|
||||||
modals: modalsReducer,
|
modals: modalsReducer,
|
||||||
application: applicationReducer
|
application: applicationReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default persistReducer(persistConfig, rootReducer);
|
export default persistReducer(persistConfig, rootReducer);
|
||||||
|
|||||||
@@ -641,6 +641,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"messaging": {
|
"messaging": {
|
||||||
|
"actions": {
|
||||||
|
"link": "Link to Job"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"messaging": "Messaging",
|
"messaging": "Messaging",
|
||||||
"typeamessage": "Send a message..."
|
"typeamessage": "Send a message..."
|
||||||
|
|||||||
@@ -641,6 +641,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"messaging": {
|
"messaging": {
|
||||||
|
"actions": {
|
||||||
|
"link": ""
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"messaging": "Mensajería",
|
"messaging": "Mensajería",
|
||||||
"typeamessage": "Enviar un mensaje..."
|
"typeamessage": "Enviar un mensaje..."
|
||||||
|
|||||||
@@ -641,6 +641,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"messaging": {
|
"messaging": {
|
||||||
|
"actions": {
|
||||||
|
"link": ""
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"messaging": "Messagerie",
|
"messaging": "Messagerie",
|
||||||
"typeamessage": "Envoyer un message..."
|
"typeamessage": "Envoyer un message..."
|
||||||
|
|||||||
@@ -1294,6 +1294,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.8.7":
|
||||||
|
version "7.9.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f"
|
||||||
|
integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
|
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
|
||||||
version "7.8.6"
|
version "7.8.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
|
||||||
@@ -3978,7 +3985,7 @@ clone-deep@^4.0.1:
|
|||||||
kind-of "^6.0.2"
|
kind-of "^6.0.2"
|
||||||
shallow-clone "^3.0.0"
|
shallow-clone "^3.0.0"
|
||||||
|
|
||||||
clsx@^1.0.4:
|
clsx@^1.0.1, clsx@^1.0.4:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702"
|
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702"
|
||||||
integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==
|
integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==
|
||||||
@@ -4964,6 +4971,14 @@ dom-helpers@^3.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
|
|
||||||
|
dom-helpers@^5.0.0:
|
||||||
|
version "5.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.4.tgz#4609680ab5c79a45f2531441f1949b79d6587f4b"
|
||||||
|
integrity sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.8.7"
|
||||||
|
csstype "^2.6.7"
|
||||||
|
|
||||||
dom-helpers@^5.1.0:
|
dom-helpers@^5.1.0:
|
||||||
version "5.1.3"
|
version "5.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821"
|
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821"
|
||||||
@@ -8205,7 +8220,7 @@ long@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||||
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
@@ -11281,6 +11296,18 @@ react-trello@^2.2.5:
|
|||||||
trello-smooth-dnd "1.0.0"
|
trello-smooth-dnd "1.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
|
react-virtualized@^9.21.2:
|
||||||
|
version "9.21.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e"
|
||||||
|
integrity sha512-oX7I7KYiUM7lVXQzmhtF4Xg/4UA5duSA+/ZcAvdWlTLFCoFYq1SbauJT5gZK9cZS/wdYR6TPGpX/dqzvTqQeBA==
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
clsx "^1.0.1"
|
||||||
|
dom-helpers "^5.0.0"
|
||||||
|
loose-envify "^1.3.0"
|
||||||
|
prop-types "^15.6.0"
|
||||||
|
react-lifecycles-compat "^3.0.4"
|
||||||
|
|
||||||
"react@>= 16.3", react@^16.13.1:
|
"react@>= 16.3", react@^16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
||||||
|
|||||||
Reference in New Issue
Block a user