diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index e74d64730..64e87d01b 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -1253,6 +1253,27 @@ + + lastnumberworkingdays + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + logo_img_path false @@ -1274,6 +1295,69 @@ + + md_referral_sources + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + messaginglabel + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + messagingtext + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + responsibilitycenter false @@ -5494,6 +5578,27 @@ actions + + add + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + cancel false @@ -14796,6 +14901,27 @@ + + presets + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + typeamessage false diff --git a/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx b/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx index 75c305320..cd2b89ebe 100644 --- a/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx +++ b/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx @@ -2,6 +2,7 @@ import { Space } from "antd"; import React from "react"; import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component"; import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container"; +import ChatPresetsComponent from "../chat-presets/chat-presets.component"; export default function ChatConversationTitle({ conversation }) { return ( @@ -17,13 +18,14 @@ export default function ChatConversationTitle({ conversation }) { )} - + + ); diff --git a/client/src/components/chat-presets/chat-presets.component.jsx b/client/src/components/chat-presets/chat-presets.component.jsx new file mode 100644 index 000000000..752a1eee2 --- /dev/null +++ b/client/src/components/chat-presets/chat-presets.component.jsx @@ -0,0 +1,50 @@ +import React from "react"; + +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { setMessage } from "../../redux/messaging/messaging.actions"; +import { Dropdown, Button, Menu } from "antd"; +import { useTranslation } from "react-i18next"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import { DownOutlined } from "@ant-design/icons"; + +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser + bodyshop: selectBodyshop, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) + setMessage: (message) => dispatch(setMessage(message)), +}); + +export function ChatPresetsComponent({ bodyshop, setMessage }) { + const { t } = useTranslation(); + + const menu = ( + + {bodyshop.md_messaging_presets.map((i, idx) => ( + setMessage(i.text)} key={idx}> + {i.label} + + ))} + + ); + + return ( + + + e.preventDefault()} + > + {t("messaging.labels.presets")} + + + + ); +} +export default connect( + mapStateToProps, + mapDispatchToProps +)(ChatPresetsComponent); diff --git a/client/src/components/chat-send-message/chat-send-message.component.jsx b/client/src/components/chat-send-message/chat-send-message.component.jsx index b74593051..f7c3a9ebd 100644 --- a/client/src/components/chat-send-message/chat-send-message.component.jsx +++ b/client/src/components/chat-send-message/chat-send-message.component.jsx @@ -1,21 +1,29 @@ import { LoadingOutlined } from "@ant-design/icons"; import { Input, Spin } from "antd"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; -import { sendMessage } from "../../redux/messaging/messaging.actions"; -import { selectIsSending } from "../../redux/messaging/messaging.selectors"; +import { + sendMessage, + setMessage, +} from "../../redux/messaging/messaging.actions"; +import { + selectIsSending, + selectMessage, +} from "../../redux/messaging/messaging.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, isSending: selectIsSending, + message: selectMessage, }); const mapDispatchToProps = (dispatch) => ({ sendMessage: (message) => dispatch(sendMessage(message)), + setMessage: (message) => dispatch(setMessage(message)), }); function ChatSendMessageComponent({ @@ -23,13 +31,11 @@ function ChatSendMessageComponent({ bodyshop, sendMessage, isSending, + message, + setMessage, }) { - const [message, setMessage] = useState(""); const inputArea = useRef(null); useEffect(() => { - if (isSending === false) { - setMessage(""); - } inputArea.current.focus(); }, [isSending, setMessage]); diff --git a/client/src/components/shop-info/shop-info.component.jsx b/client/src/components/shop-info/shop-info.component.jsx index 45f8f51cc..8154bd709 100644 --- a/client/src/components/shop-info/shop-info.component.jsx +++ b/client/src/components/shop-info/shop-info.component.jsx @@ -8,6 +8,7 @@ import { Radio, Select, } from "antd"; +import { DeleteFilled } from "@ant-design/icons"; import { useTranslation } from "react-i18next"; import ShopInfoROStatusComponent from "./shop-info.rostatus.component"; import ShopInfoOrderStatusComponent from "./shop-info.orderstatus.component"; @@ -188,6 +189,68 @@ export default function ShopInfoComponent({ form }) { }} + + {(fields, { add, remove }) => { + return ( + + {fields.map((field, index) => ( + + + + + + + + + { + remove(field.name); + }} + /> + + + ))} + + { + add(); + }} + style={{ width: "100%" }} + > + {t("general.actions.add")} + + + + ); + }} + + { + const handleFinish = (values) => { console.log("values", values); logImEXEvent("shop_update"); updateBodyshop({ - variables: { id: data.bodyshops[0].id, shop: values } + variables: { id: data.bodyshops[0].id, shop: values }, }) - .then(r => { + .then((r) => { notification["success"]({ message: t("bodyshop.successes.save") }); - refetch().then(_ => form.resetFields()); + refetch().then((_) => form.resetFields()); }) - .catch(error => { - notification["error"]( - { message: t("bodyshop.errors.saving") }, - { message: error } - ); + .catch((error) => { + notification["error"]({ + message: t("bodyshop.errors.saving", { message: error }), + }); }); }; diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index 11252e7a6..f0c743d81 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -45,6 +45,7 @@ export const QUERY_BODYSHOP = gql` ssbuckets scoreboard_target md_referral_sources + md_messaging_presets employees { id first_name @@ -98,6 +99,7 @@ export const UPDATE_SHOP = gql` ssbuckets scoreboard_target md_referral_sources + md_messaging_presets employees { id first_name diff --git a/client/src/redux/messaging/messaging.actions.js b/client/src/redux/messaging/messaging.actions.js index 77bb569c7..f53b5c468 100644 --- a/client/src/redux/messaging/messaging.actions.js +++ b/client/src/redux/messaging/messaging.actions.js @@ -27,4 +27,9 @@ export const setSelectedConversation = (conversationId) => ({ export const openChatByPhone = (phoneNumber) => ({ type: MessagingActionTypes.OPEN_CHAT_BY_PHONE, payload: phoneNumber, +}); + +export const setMessage = (message) => ({ + type: MessagingActionTypes.SET_MESSAGE, + payload: message, }); \ No newline at end of file diff --git a/client/src/redux/messaging/messaging.reducer.js b/client/src/redux/messaging/messaging.reducer.js index 471a4d4fc..e43bad872 100644 --- a/client/src/redux/messaging/messaging.reducer.js +++ b/client/src/redux/messaging/messaging.reducer.js @@ -5,10 +5,13 @@ const INITIAL_STATE = { selectedConversationId: null, isSending: false, error: null, + message: null, }; const messagingReducer = (state = INITIAL_STATE, action) => { switch (action.type) { + case MessagingActionTypes.SET_MESSAGE: + return { ...state, message: action.payload }; case MessagingActionTypes.TOGGLE_CHAT_VISIBLE: return { ...state, @@ -29,6 +32,7 @@ const messagingReducer = (state = INITIAL_STATE, action) => { case MessagingActionTypes.SEND_MESSAGE_SUCCESS: return { ...state, + message: "", isSending: false, }; case MessagingActionTypes.SEND_MESSAGE_FAILURE: diff --git a/client/src/redux/messaging/messaging.selectors.js b/client/src/redux/messaging/messaging.selectors.js index 90d326e90..c46c20d74 100644 --- a/client/src/redux/messaging/messaging.selectors.js +++ b/client/src/redux/messaging/messaging.selectors.js @@ -21,3 +21,8 @@ export const selectSelectedConversation = createSelector( [selectMessaging], (messaging) => messaging.selectedConversationId ); + +export const selectMessage = createSelector( + [selectMessaging], + (messaging) => messaging.message +); diff --git a/client/src/redux/messaging/messaging.types.js b/client/src/redux/messaging/messaging.types.js index a620ef027..084ed08c7 100644 --- a/client/src/redux/messaging/messaging.types.js +++ b/client/src/redux/messaging/messaging.types.js @@ -5,5 +5,6 @@ const MessagingActionTypes = { SEND_MESSAGE_FAILURE: "SEND_MESSAGE_FAILURE", SET_SELECTED_CONVERSATION: "SET_SELECTED_CONVERSATION", OPEN_CHAT_BY_PHONE: "OPEN_CHAT_BY_PHONE", + SET_MESSAGE: "SET_MESSAGE", }; export default MessagingActionTypes; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index c4f9545ed..9573d3e03 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -94,7 +94,11 @@ "invoice_federal_tax_rate": "Invoices - Federal Tax Rate %", "invoice_local_tax_rate": "Invoices - State Tax Rate %", "invoice_state_tax_rate": "Invoices - State Tax Rate %", + "lastnumberworkingdays": "Scoreboard - Last Number of Working Days", "logo_img_path": "Shop Logo", + "md_referral_sources": "Referral Sources", + "messaginglabel": "Messaging Preset Label", + "messagingtext": "Messaging Preset Text", "responsibilitycenter": "Responsibility Center", "responsibilitycenter_accountdesc": "Account Description", "responsibilitycenter_accountitem": "Item", @@ -377,6 +381,7 @@ }, "general": { "actions": { + "add": "Add", "cancel": "Cancel", "close": "Close", "create": "Create", @@ -901,6 +906,7 @@ "labels": { "messaging": "Messaging", "nojobs": "Not associated to any job.", + "presets": "Presets", "typeamessage": "Send a message..." } }, diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 44a2d68a1..ca8d3da57 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -94,7 +94,11 @@ "invoice_federal_tax_rate": "", "invoice_local_tax_rate": "", "invoice_state_tax_rate": "", + "lastnumberworkingdays": "", "logo_img_path": "", + "md_referral_sources": "", + "messaginglabel": "", + "messagingtext": "", "responsibilitycenter": "", "responsibilitycenter_accountdesc": "", "responsibilitycenter_accountitem": "", @@ -377,6 +381,7 @@ }, "general": { "actions": { + "add": "", "cancel": "", "close": "", "create": "", @@ -901,6 +906,7 @@ "labels": { "messaging": "MensajerÃa", "nojobs": "", + "presets": "", "typeamessage": "Enviar un mensaje..." } }, diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 725eb7fe3..7e6434f7d 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -94,7 +94,11 @@ "invoice_federal_tax_rate": "", "invoice_local_tax_rate": "", "invoice_state_tax_rate": "", + "lastnumberworkingdays": "", "logo_img_path": "", + "md_referral_sources": "", + "messaginglabel": "", + "messagingtext": "", "responsibilitycenter": "", "responsibilitycenter_accountdesc": "", "responsibilitycenter_accountitem": "", @@ -377,6 +381,7 @@ }, "general": { "actions": { + "add": "", "cancel": "", "close": "", "create": "", @@ -901,6 +906,7 @@ "labels": { "messaging": "Messagerie", "nojobs": "", + "presets": "", "typeamessage": "Envoyer un message..." } }, diff --git a/hasura/migrations/1595368680511_alter_table_public_bodyshops_add_column_md_messaging_presets/down.yaml b/hasura/migrations/1595368680511_alter_table_public_bodyshops_add_column_md_messaging_presets/down.yaml new file mode 100644 index 000000000..7181e71eb --- /dev/null +++ b/hasura/migrations/1595368680511_alter_table_public_bodyshops_add_column_md_messaging_presets/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "md_messaging_presets"; + type: run_sql diff --git a/hasura/migrations/1595368680511_alter_table_public_bodyshops_add_column_md_messaging_presets/up.yaml b/hasura/migrations/1595368680511_alter_table_public_bodyshops_add_column_md_messaging_presets/up.yaml new file mode 100644 index 000000000..4effad2dc --- /dev/null +++ b/hasura/migrations/1595368680511_alter_table_public_bodyshops_add_column_md_messaging_presets/up.yaml @@ -0,0 +1,6 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "md_messaging_presets" jsonb + NULL DEFAULT jsonb_build_array(); + type: run_sql diff --git a/hasura/migrations/1595368689122_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1595368689122_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..a356f7c0d --- /dev/null +++ b/hasura/migrations/1595368689122_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,56 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - accountingconfig + - address1 + - address2 + - appt_length + - city + - country + - created_at + - email + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - invoice_tax_rates + - logo_img_path + - md_order_statuses + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - messagingservicesid + - production_config + - region_config + - scoreboard_target + - shopname + - shoprates + - ssbuckets + - state + - state_tax_id + - stripe_acct_id + - template_header + - textid + - updated_at + - zip_post + computed_fields: [] + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1595368689122_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1595368689122_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..b0494d6ee --- /dev/null +++ b/hasura/migrations/1595368689122_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,57 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - accountingconfig + - address1 + - address2 + - appt_length + - city + - country + - created_at + - email + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - invoice_tax_rates + - logo_img_path + - md_messaging_presets + - md_order_statuses + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - messagingservicesid + - production_config + - region_config + - scoreboard_target + - shopname + - shoprates + - ssbuckets + - state + - state_tax_id + - stripe_acct_id + - template_header + - textid + - updated_at + - zip_post + computed_fields: [] + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1595370737421_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1595370737421_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..e3ade79e8 --- /dev/null +++ b/hasura/migrations/1595370737421_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,50 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_update_permission +- args: + permission: + columns: + - accountingconfig + - address1 + - address2 + - appt_length + - city + - country + - created_at + - email + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - invoice_tax_rates + - logo_img_path + - md_order_statuses + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - production_config + - scoreboard_target + - shopname + - shoprates + - ssbuckets + - state + - state_tax_id + - updated_at + - zip_post + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + set: {} + role: user + table: + name: bodyshops + schema: public + type: create_update_permission diff --git a/hasura/migrations/1595370737421_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1595370737421_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..5702e6737 --- /dev/null +++ b/hasura/migrations/1595370737421_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,51 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_update_permission +- args: + permission: + columns: + - accountingconfig + - address1 + - address2 + - appt_length + - city + - country + - created_at + - email + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - invoice_tax_rates + - logo_img_path + - md_messaging_presets + - md_order_statuses + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - production_config + - scoreboard_target + - shopname + - shoprates + - ssbuckets + - state + - state_tax_id + - updated_at + - zip_post + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + set: {} + role: user + table: + name: bodyshops + schema: public + type: create_update_permission diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index 37579cafc..ec3eb9d2c 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -473,6 +473,7 @@ tables: - intakechecklist - invoice_tax_rates - logo_img_path + - md_messaging_presets - md_order_statuses - md_referral_sources - md_responsibility_centers @@ -517,6 +518,7 @@ tables: - intakechecklist - invoice_tax_rates - logo_img_path + - md_messaging_presets - md_order_statuses - md_referral_sources - md_responsibility_centers