Added sorting to msgs sub and added some styling for messaging items. BOD-309 BOD-310
This commit is contained in:
@@ -10,11 +10,13 @@ import "./chat-affix.styles.scss";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import { selectChatVisible } from "../../redux/messaging/messaging.selectors";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
chatVisible: selectChatVisible,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function ChatAffixContainer({ bodyshop }) {
|
export function ChatAffixContainer({ bodyshop, chatVisible }) {
|
||||||
const { loading, error, data } = useSubscription(
|
const { loading, error, data } = useSubscription(
|
||||||
CONVERSATION_LIST_SUBSCRIPTION,
|
CONVERSATION_LIST_SUBSCRIPTION,
|
||||||
{
|
{
|
||||||
@@ -26,7 +28,7 @@ export function ChatAffixContainer({ bodyshop }) {
|
|||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Affix className="chat-affix">
|
<Affix className={`chat-affix ${chatVisible ? "chat-affix-open" : ""}`}>
|
||||||
<div>
|
<div>
|
||||||
{bodyshop && bodyshop.messagingservicesid ? (
|
{bodyshop && bodyshop.messagingservicesid ? (
|
||||||
<ChatAffixComponent
|
<ChatAffixComponent
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 2vh;
|
bottom: 2vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-affix-open {
|
||||||
|
-webkit-box-shadow: 0px 0px 10px 0px rgba(69, 69, 69, 1);
|
||||||
|
-moz-box-shadow: 0px 0px 10px 0px rgba(69, 69, 69, 1);
|
||||||
|
box-shadow: 0px 0px 10px 0px rgba(69, 69, 69, 1);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Badge, List } from "antd";
|
import { Badge, List, Tag } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setSelectedConversation } from "../../redux/messaging/messaging.actions";
|
import { setSelectedConversation } from "../../redux/messaging/messaging.actions";
|
||||||
@@ -22,43 +21,46 @@ export function ChatConversationListComponent({
|
|||||||
selectedConversation,
|
selectedConversation,
|
||||||
setSelectedConversation,
|
setSelectedConversation,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List
|
<div className="chat-list-container">
|
||||||
bordered
|
<List
|
||||||
size="small"
|
bordered
|
||||||
dataSource={conversationList}
|
size="small"
|
||||||
renderItem={(item) => (
|
dataSource={conversationList}
|
||||||
<List.Item
|
renderItem={(item) => (
|
||||||
onClick={() => setSelectedConversation(item.id)}
|
<List.Item
|
||||||
className={`chat-list-item ${
|
onClick={() => setSelectedConversation(item.id)}
|
||||||
item.id === selectedConversation
|
className={`chat-list-item ${
|
||||||
? "chat-list-selected-conversation"
|
item.id === selectedConversation
|
||||||
: null
|
? "chat-list-selected-conversation"
|
||||||
}`}
|
: null
|
||||||
>
|
}`}
|
||||||
<List.Item.Meta
|
>
|
||||||
title={<PhoneFormatter>{item.phone_num}</PhoneFormatter>}
|
{item.job_conversations.length > 0 ? (
|
||||||
description={
|
<div className="chat-name">
|
||||||
item.job_conversations.length > 0 ? (
|
{item.job_conversations.map((j, idx) => (
|
||||||
<div>
|
<span key={idx}>
|
||||||
{item.job_conversations.map(
|
{`${j.job.ownr_fn || ""} ${j.job.ownr_ln || ""} ${
|
||||||
(j) =>
|
j.job.ownr_co_nm || ""
|
||||||
`${j.job.ownr_fn || ""} ${j.job.ownr_ln || ""} ${
|
} `}
|
||||||
j.job.ownr_co_nm || ""
|
</span>
|
||||||
}`
|
))}
|
||||||
)}
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||||
t("messaging.labels.nojobs")
|
)}
|
||||||
)
|
{item.job_conversations.length > 0
|
||||||
}
|
? item.job_conversations.map((j, idx) => (
|
||||||
/>
|
<Tag key={idx} className="ro-number-tag">
|
||||||
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
{j.job.ro_number}
|
||||||
</List.Item>
|
</Tag>
|
||||||
)}
|
))
|
||||||
/>
|
: null}
|
||||||
|
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|||||||
@@ -1,10 +1,24 @@
|
|||||||
.chat-list-selected-conversation {
|
.chat-list-selected-conversation {
|
||||||
background-color: rgba(128, 128, 128, 0.2);
|
background-color: rgba(128, 128, 128, 0.2);
|
||||||
}
|
}
|
||||||
|
.chat-list-container {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-list-item {
|
.chat-list-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #ff7a00;
|
color: #ff7a00;
|
||||||
}
|
}
|
||||||
|
.chat-name {
|
||||||
|
flex: 1;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.ro-number-tag {
|
||||||
|
align-self: baseline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,14 @@ export default function ChatConversationTitleTags({ jobConversations }) {
|
|||||||
<Tag
|
<Tag
|
||||||
key={item.job.id}
|
key={item.job.id}
|
||||||
closable
|
closable
|
||||||
color='blue'
|
color="blue"
|
||||||
style={{ cursor: "pointer" }}
|
style={{ cursor: "pointer" }}
|
||||||
onClose={() => handleRemoveTag(item.job.id)}>
|
onClose={() => handleRemoveTag(item.job.id)}
|
||||||
|
>
|
||||||
<Link to={`/manage/jobs/${item.job.id}`}>
|
<Link to={`/manage/jobs/${item.job.id}`}>
|
||||||
{item.job.ro_number || "?"}
|
{`${item.job.ro_number || "?"} | ${item.job.ownr_fn || ""} ${
|
||||||
|
item.job.ownr_ln || ""
|
||||||
|
} ${item.job.ownr_co_nm || ""}`}
|
||||||
</Link>
|
</Link>
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,32 +1,23 @@
|
|||||||
import { Space } from "antd";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||||
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
||||||
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
||||||
import ChatPresetsComponent from "../chat-presets/chat-presets.component";
|
|
||||||
|
|
||||||
export default function ChatConversationTitle({ conversation }) {
|
export default function ChatConversationTitle({ conversation }) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Space>
|
<div className="imex-flex-row">
|
||||||
<strong>{conversation && conversation.phone_num}</strong>
|
|
||||||
<span>
|
|
||||||
{conversation &&
|
|
||||||
conversation.job_conversations.map(
|
|
||||||
(j) =>
|
|
||||||
`${j.job.ownr_fn || ""} ${j.job.ownr_ln || ""} ${
|
|
||||||
j.job.ownr_co_nm || ""
|
|
||||||
} | `
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</Space>
|
|
||||||
<div className="imex-flex-row imex-flex-row__margin">
|
|
||||||
<ChatConversationTitleTags
|
<ChatConversationTitleTags
|
||||||
jobConversations={
|
jobConversations={
|
||||||
(conversation && conversation.job_conversations) || []
|
(conversation && conversation.job_conversations) || []
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ChatTagRoContainer conversation={conversation || []} />
|
<ChatTagRoContainer conversation={conversation || []} />
|
||||||
<ChatPresetsComponent />
|
</div>
|
||||||
|
<div className="imex-flex-row">
|
||||||
|
<PhoneNumberFormatter>
|
||||||
|
{conversation && conversation.phone_num}
|
||||||
|
</PhoneNumberFormatter>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
// bottom: 0rem;
|
// bottom: 0rem;
|
||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
border: #000000;
|
border: #000000;
|
||||||
margin-left: 0.2rem;
|
position: absolute;
|
||||||
margin-right: 0rem;
|
margin: 0 0.1rem;
|
||||||
// z-index: 5;
|
bottom: 0.1rem;
|
||||||
|
right: 0.3rem;
|
||||||
|
|
||||||
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat {
|
.chat {
|
||||||
@@ -84,6 +87,7 @@
|
|||||||
background: linear-gradient(to bottom, #00d0ea 0%, #0085d1 100%);
|
background: linear-gradient(to bottom, #00d0ea 0%, #0085d1 100%);
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
padding-bottom: 0.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mine .message.last:before {
|
.mine .message.last:before {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export function ChatPopupComponent({
|
|||||||
style={{ position: "absolute", right: ".5rem", top: ".5rem" }}
|
style={{ position: "absolute", right: ".5rem", top: ".5rem" }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Row className="chat-popup-content">
|
<Row gutter={[8, 8]} className="chat-popup-content">
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<ChatConversationListComponent conversationList={conversationList} />
|
<ChatConversationListComponent conversationList={conversationList} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -6,8 +6,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chat-popup-content {
|
.chat-popup-content {
|
||||||
//height: 50vh;
|
min-height: 0px; /* IMPORTANT: you need this for non-chrome browsers */
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
//height: 100%;
|
||||||
|
.ant-col {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 992px) {
|
@media only screen and (min-width: 992px) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { DownOutlined } from "@ant-design/icons";
|
import { PlusCircleOutlined } from "@ant-design/icons";
|
||||||
import { Dropdown, Menu } from "antd";
|
import { Dropdown, Menu } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setMessage } from "../../redux/messaging/messaging.actions";
|
import { setMessage } from "../../redux/messaging/messaging.actions";
|
||||||
@@ -16,9 +15,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
setMessage: (message) => dispatch(setMessage(message)),
|
setMessage: (message) => dispatch(setMessage(message)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function ChatPresetsComponent({ bodyshop, setMessage }) {
|
export function ChatPresetsComponent({ bodyshop, setMessage, className }) {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<Menu>
|
<Menu>
|
||||||
{bodyshop.md_messaging_presets.map((i, idx) => (
|
{bodyshop.md_messaging_presets.map((i, idx) => (
|
||||||
@@ -30,15 +27,9 @@ export function ChatPresetsComponent({ bodyshop, setMessage }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={className}>
|
||||||
<Dropdown trigger={["click"]} overlay={menu}>
|
<Dropdown trigger={["click"]} overlay={menu}>
|
||||||
<a
|
<PlusCircleOutlined />
|
||||||
className="ant-dropdown-link"
|
|
||||||
href="# "
|
|
||||||
onClick={(e) => e.preventDefault()}
|
|
||||||
>
|
|
||||||
{t("messaging.labels.presets")} <DownOutlined />
|
|
||||||
</a>
|
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
selectMessage,
|
selectMessage,
|
||||||
} from "../../redux/messaging/messaging.selectors";
|
} from "../../redux/messaging/messaging.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import ChatPresetsComponent from "../chat-presets/chat-presets.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -53,6 +54,8 @@ function ChatSendMessageComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="imex-flex-row">
|
<div className="imex-flex-row">
|
||||||
|
<ChatPresetsComponent className="imex-flex-row__margin" />
|
||||||
|
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
className="imex-flex-row__margin imex-flex-row__grow"
|
className="imex-flex-row__margin imex-flex-row__grow"
|
||||||
allowClear
|
allowClear
|
||||||
@@ -68,6 +71,7 @@ function ChatSendMessageComponent({
|
|||||||
if (!!!event.shiftKey) handleEnter();
|
if (!!!event.shiftKey) handleEnter();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SendOutlined className="imex-flex-row__margin" onClick={handleEnter} />
|
<SendOutlined className="imex-flex-row__margin" onClick={handleEnter} />
|
||||||
<Spin
|
<Spin
|
||||||
style={{ display: `${isSending ? "" : "none"}` }}
|
style={{ display: `${isSending ? "" : "none"}` }}
|
||||||
|
|||||||
@@ -1,51 +1,46 @@
|
|||||||
|
import { CloseCircleOutlined, LoadingOutlined } from "@ant-design/icons";
|
||||||
|
import { Select, Empty } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { AutoComplete } from "antd";
|
|
||||||
import { LoadingOutlined, CloseCircleOutlined } from "@ant-design/icons";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function ChatTagRoComponent({
|
export default function ChatTagRoComponent({
|
||||||
searchQueryState,
|
|
||||||
roOptions,
|
roOptions,
|
||||||
loading,
|
loading,
|
||||||
executeSearch,
|
handleSearch,
|
||||||
handleInsertTag,
|
handleInsertTag,
|
||||||
setVisible,
|
setVisible,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const setSearchQuery = searchQueryState[1];
|
|
||||||
const handleSearchQuery = (value) => {
|
|
||||||
setSearchQuery(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleKeyDown = (event) => {
|
|
||||||
if (event.key === "Enter") {
|
|
||||||
executeSearch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<div>
|
||||||
<AutoComplete
|
<Select
|
||||||
style={{ width: 100 }}
|
showSearch
|
||||||
onSearch={handleSearchQuery}
|
autoFocus
|
||||||
onSelect={handleInsertTag}
|
style={{
|
||||||
|
width: 300,
|
||||||
|
}}
|
||||||
placeholder={t("general.labels.search")}
|
placeholder={t("general.labels.search")}
|
||||||
onKeyDown={handleKeyDown}
|
filterOption={false}
|
||||||
|
onSearch={handleSearch}
|
||||||
|
onSelect={handleInsertTag}
|
||||||
|
notFoundContent={loading ? <LoadingOutlined /> : <Empty />}
|
||||||
>
|
>
|
||||||
{roOptions.map((item, idx) => (
|
{roOptions.map((item, idx) => (
|
||||||
<AutoComplete.Option key={item.id || idx}>
|
<Select.Option key={item.id || idx}>
|
||||||
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
||||||
item.ownr_ln || ""
|
item.ownr_ln || ""
|
||||||
} ${item.ownr_co_nm || ""}`}
|
} ${item.ownr_co_nm || ""}`}
|
||||||
</AutoComplete.Option>
|
</Select.Option>
|
||||||
))}
|
))}
|
||||||
</AutoComplete>
|
</Select>
|
||||||
|
{loading ? <LoadingOutlined /> : null}
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<LoadingOutlined />
|
<LoadingOutlined />
|
||||||
) : (
|
) : (
|
||||||
<CloseCircleOutlined onClick={() => setVisible(false)} />
|
<CloseCircleOutlined onClick={() => setVisible(false)} />
|
||||||
)}
|
)}
|
||||||
</span>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,29 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
import ChatTagRo from "./chat-tag-ro.component";
|
|
||||||
import { useLazyQuery, useMutation } from "@apollo/react-hooks";
|
|
||||||
import { SEARCH_FOR_JOBS } from "../../graphql/jobs.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";
|
import { PlusOutlined } from "@ant-design/icons";
|
||||||
|
import { useLazyQuery, useMutation } from "@apollo/react-hooks";
|
||||||
|
import { Tag } from "antd";
|
||||||
|
import _ from "lodash";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
||||||
|
import { SEARCH_FOR_JOBS } from "../../graphql/jobs.queries";
|
||||||
|
import ChatTagRo from "./chat-tag-ro.component";
|
||||||
|
|
||||||
export default function ChatTagRoContainer({ conversation }) {
|
export default function ChatTagRoContainer({ conversation }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const searchQueryState = useState("");
|
|
||||||
const searchText = searchQueryState[0];
|
|
||||||
|
|
||||||
const [loadRo, { called, loading, data, refetch }] = useLazyQuery(
|
const [loadRo, { loading, data }] = useLazyQuery(SEARCH_FOR_JOBS);
|
||||||
SEARCH_FOR_JOBS,
|
|
||||||
{
|
|
||||||
variables: { search: `%${searchText}%` },
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const executeSearch = () => {
|
const executeSearch = (v) => {
|
||||||
logImEXEvent("messaging_search_job_tag", { searchTerm: searchText });
|
logImEXEvent("messaging_search_job_tag", { searchTerm: v });
|
||||||
if (called) refetch();
|
loadRo(v);
|
||||||
else {
|
};
|
||||||
loadRo();
|
|
||||||
}
|
const debouncedExecuteSearch = _.debounce(executeSearch, 800);
|
||||||
|
|
||||||
|
const handleSearch = (value) => {
|
||||||
|
debouncedExecuteSearch({ variables: { search: value } });
|
||||||
};
|
};
|
||||||
|
|
||||||
const [insertTag] = useMutation(INSERT_CONVERSATION_TAG, {
|
const [insertTag] = useMutation(INSERT_CONVERSATION_TAG, {
|
||||||
@@ -45,7 +42,7 @@ export default function ChatTagRoContainer({ conversation }) {
|
|||||||
conversation.job_conversations.map((i) => i.jobid);
|
conversation.job_conversations.map((i) => i.jobid);
|
||||||
|
|
||||||
const roOptions = data
|
const roOptions = data
|
||||||
? data.jobs.filter((job) => !existingJobTags.includes(job.id))
|
? data.search_jobs.filter((job) => !existingJobTags.includes(job.id))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -53,9 +50,8 @@ export default function ChatTagRoContainer({ conversation }) {
|
|||||||
{visible ? (
|
{visible ? (
|
||||||
<ChatTagRo
|
<ChatTagRo
|
||||||
loading={loading}
|
loading={loading}
|
||||||
searchQueryState={searchQueryState}
|
|
||||||
roOptions={roOptions}
|
roOptions={roOptions}
|
||||||
executeSearch={executeSearch}
|
handleSearch={handleSearch}
|
||||||
handleInsertTag={handleInsertTag}
|
handleInsertTag={handleInsertTag}
|
||||||
setVisible={setVisible}
|
setVisible={setVisible}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
|
import { LoadingOutlined } from "@ant-design/icons";
|
||||||
import { useLazyQuery } from "@apollo/react-hooks";
|
import { useLazyQuery } from "@apollo/react-hooks";
|
||||||
import { Select } from "antd";
|
import { Empty, Select } from "antd";
|
||||||
|
import _ from "lodash";
|
||||||
import React, { forwardRef, useEffect, useState } from "react";
|
import React, { forwardRef, useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
SEARCH_JOBS_FOR_AUTOCOMPLETE,
|
|
||||||
SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE,
|
SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE,
|
||||||
|
SEARCH_JOBS_FOR_AUTOCOMPLETE,
|
||||||
} from "../../graphql/jobs.queries";
|
} from "../../graphql/jobs.queries";
|
||||||
import { LoadingOutlined } from "@ant-design/icons";
|
|
||||||
import _ from "lodash";
|
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
@@ -33,7 +33,6 @@ const JobSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (value === option) {
|
if (value === option) {
|
||||||
console.log("Job ID Provided, searching...");
|
|
||||||
callIdSearch({ variables: { id: value } });
|
callIdSearch({ variables: { id: value } });
|
||||||
}
|
}
|
||||||
}, [value, option, callIdSearch]);
|
}, [value, option, callIdSearch]);
|
||||||
@@ -71,7 +70,7 @@ const JobSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
|
|||||||
onSearch={handleSearch}
|
onSearch={handleSearch}
|
||||||
// onChange={setOption}
|
// onChange={setOption}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
notFoundContent={loading ? <LoadingOutlined /> : null}
|
notFoundContent={loading ? <LoadingOutlined /> : <Empty />}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
>
|
>
|
||||||
{theOptions
|
{theOptions
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import gql from "graphql-tag";
|
|||||||
|
|
||||||
export const CONVERSATION_LIST_SUBSCRIPTION = gql`
|
export const CONVERSATION_LIST_SUBSCRIPTION = gql`
|
||||||
subscription CONVERSATION_LIST_SUBSCRIPTION {
|
subscription CONVERSATION_LIST_SUBSCRIPTION {
|
||||||
conversations {
|
conversations(order_by: { updated_at: desc }, limit: 100) {
|
||||||
phone_num
|
phone_num
|
||||||
id
|
id
|
||||||
job_conversations {
|
job_conversations {
|
||||||
|
|||||||
@@ -711,7 +711,7 @@ export const SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE = gql`
|
|||||||
|
|
||||||
export const SEARCH_FOR_JOBS = gql`
|
export const SEARCH_FOR_JOBS = gql`
|
||||||
query SEARCH_FOR_JOBS($search: String!) {
|
query SEARCH_FOR_JOBS($search: String!) {
|
||||||
jobs(where: { ro_number: { _ilike: $search } }) {
|
search_jobs(args: { search: $search }) {
|
||||||
id
|
id
|
||||||
ro_number
|
ro_number
|
||||||
ownr_fn
|
ownr_fn
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
- args:
|
||||||
|
cascade: true
|
||||||
|
read_only: false
|
||||||
|
sql: "CREATE OR REPLACE FUNCTION update_conversation_on_message()\nRETURNS TRIGGER
|
||||||
|
AS $$\nBEGIN\n UPDATE conversations SET last_updated = now() WHERE id = NEW.\"conversationid\";\n
|
||||||
|
\ RETURN NEW; \nEND;\n$$ language 'plpgsql';\n\nDROP TRIGGER IF EXISTS trigger_update_conversation_on_message
|
||||||
|
ON messages;\nCREATE TRIGGER trigger_update_conversation_on_message AFTER INSERT
|
||||||
|
ON messages FOR EACH ROW EXECUTE PROCEDURE update_conversation_on_message();"
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
- args:
|
||||||
|
cascade: true
|
||||||
|
read_only: false
|
||||||
|
sql: "CREATE OR REPLACE FUNCTION update_conversation_on_message()\nRETURNS TRIGGER
|
||||||
|
AS $$\nBEGIN\n UPDATE conversations SET updated_at = now() WHERE id = NEW.\"conversationid\";\n
|
||||||
|
\ RETURN NEW; \nEND;\n$$ language 'plpgsql';\n\nDROP TRIGGER IF EXISTS trigger_update_conversation_on_message
|
||||||
|
ON messages;\nCREATE TRIGGER trigger_update_conversation_on_message AFTER INSERT
|
||||||
|
ON messages FOR EACH ROW EXECUTE PROCEDURE update_conversation_on_message();"
|
||||||
|
type: run_sql
|
||||||
Reference in New Issue
Block a user