link share
parent
20b70d5d57
commit
4568663ae4
|
@ -37,7 +37,8 @@
|
|||
"yes": "Ja",
|
||||
"no": "Nein",
|
||||
"more": "Mehr",
|
||||
"pleaseInput": "Bitte eingeben"
|
||||
"pleaseInput": "Bitte eingeben",
|
||||
"pleaseInputValidUrl": "Bitte geben Sie eine gültige URL ein"
|
||||
},
|
||||
"request": {
|
||||
"inputsInvalid": {
|
||||
|
@ -363,6 +364,15 @@
|
|||
},
|
||||
"emails": {
|
||||
"title": "E-Mails"
|
||||
},
|
||||
"links": {
|
||||
"title": "Links",
|
||||
"buttonAddLink": "Link hinzufügen",
|
||||
"addLinkModal": {
|
||||
"title": "Link hinzufügen",
|
||||
"name": "Name",
|
||||
"link": "Link"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"more": "More",
|
||||
"pleaseInput": "Please input"
|
||||
"pleaseInput": "Please input",
|
||||
"pleaseInputValidUrl": "Please input a valid URL"
|
||||
},
|
||||
"request": {
|
||||
"inputsInvalid": {
|
||||
|
@ -363,7 +364,15 @@
|
|||
},
|
||||
"emails": {
|
||||
"title": "Emails"
|
||||
|
||||
},
|
||||
"links": {
|
||||
"title": "Links",
|
||||
"buttonAddLink": "Add Link",
|
||||
"addLinkModal": {
|
||||
"title": "Add Link",
|
||||
"name": "Name",
|
||||
"link": "Link"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,6 +12,10 @@ const preview = {
|
|||
changedDrawerCustomerFieldsRef: null,
|
||||
currentDrawerCallProtocols: [],
|
||||
setCurrentDrawerCallProtocols: () => {},
|
||||
currentDrawerActivityLinks: [],
|
||||
setCurrentDrawerActivityLinks: () => {},
|
||||
currentDrawerActivityLinkHistory: [],
|
||||
setCurrentDrawerActivityLinkHistory: () => {},
|
||||
};
|
||||
|
||||
const CrmContext = createContext(preview);
|
||||
|
@ -36,6 +40,13 @@ export function CrmProvider({ children }) {
|
|||
const [currentDrawerCallProtocols, setCurrentDrawerCallProtocols] = useState(
|
||||
[]
|
||||
);
|
||||
const [currentDrawerActivityLinks, setCurrentDrawerActivityLinks] = useState(
|
||||
[]
|
||||
);
|
||||
const [
|
||||
currentDrawerActivityLinkHistory,
|
||||
setCurrentDrawerActivityLinkHistory,
|
||||
] = useState([]);
|
||||
|
||||
return (
|
||||
<CrmContext.Provider
|
||||
|
@ -55,6 +66,10 @@ export function CrmProvider({ children }) {
|
|||
changedDrawerCustomerFieldsRef,
|
||||
currentDrawerCallProtocols,
|
||||
setCurrentDrawerCallProtocols,
|
||||
currentDrawerActivityLinks,
|
||||
setCurrentDrawerActivityLinks,
|
||||
currentDrawerActivityLinkHistory,
|
||||
setCurrentDrawerActivityLinkHistory,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -52,6 +52,9 @@ export const ReceivedMessagesCommands = {
|
|||
CrmCustomerCreated: 48,
|
||||
CrmCallProtocolCreated: 49,
|
||||
CrmCallProtocolDeleted: 50,
|
||||
CrmLinkCreated: 51,
|
||||
CrmLinkUsed: 52,
|
||||
CrmLinkDeleted: 53,
|
||||
};
|
||||
|
||||
// commands sent to the backend server
|
||||
|
@ -1106,6 +1109,17 @@ export function handleWebSocketMessage(
|
|||
);
|
||||
}
|
||||
break;
|
||||
case ReceivedMessagesCommands.CrmLinkCreated:
|
||||
crmContext.setCurrentDrawerActivityLinks((arr) => [...arr, body]);
|
||||
break;
|
||||
case ReceivedMessagesCommands.CrmLinkUsed:
|
||||
crmContext.setCurrentDrawerActivityLinkHistory((arr) => [...arr, body]);
|
||||
break;
|
||||
case ReceivedMessagesCommands.CrmLinkDeleted:
|
||||
crmContext.setCurrentDrawerActivityLinks((arr) =>
|
||||
arr.filter((link) => link.Id !== body)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
console.error("unknown command", cmd);
|
||||
break;
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
Empty,
|
||||
Flex,
|
||||
Popconfirm,
|
||||
List,
|
||||
} from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
|
@ -65,7 +66,7 @@ import MyModal, {
|
|||
MyModalCloseCreateButtonFooter,
|
||||
} from "../../Components/MyModal";
|
||||
import dayjs from "dayjs";
|
||||
import Markdown from "react-markdown";
|
||||
import { MyCopyIcon } from "../../Components/MyIcon";
|
||||
|
||||
const CRM_TYPE = {
|
||||
CUSTOMERS: 0,
|
||||
|
@ -684,6 +685,11 @@ function CustomerDrawer({ isOpen, setIsOpen, onClose, notificationApi }) {
|
|||
crmContext.currentDrawerCustomerRef.current = customer;
|
||||
|
||||
crmContext.setCurrentDrawerCallProtocols(data.CallProtocols);
|
||||
crmContext.setCurrentDrawerActivityLinks(data.Links);
|
||||
|
||||
if (data.LinkHistory !== null) {
|
||||
crmContext.setCurrentDrawerActivityLinkHistory(data.LinkHistory);
|
||||
}
|
||||
|
||||
formDealInfo.setFieldsValue({
|
||||
Pipeline: customer.Pipeline,
|
||||
|
@ -1214,9 +1220,19 @@ function TabContentDealInfo({ form }) {
|
|||
function TabContentActivities({ notificationApi }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
return (
|
||||
<MySupsenseFallback>
|
||||
<Tabs
|
||||
activeKey={activeTab}
|
||||
onChange={(activeKey) => setActiveTab(activeKey)}
|
||||
tabBarExtraContent={{
|
||||
right:
|
||||
activeTab === 2 ? (
|
||||
<AddLinkModal notificationApi={notificationApi} />
|
||||
) : null,
|
||||
}}
|
||||
items={[
|
||||
{
|
||||
key: 0,
|
||||
|
@ -1230,6 +1246,11 @@ function TabContentActivities({ notificationApi }) {
|
|||
label: t("crm.tabContent.activities.emails.title"),
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
label: t("crm.tabContent.activities.links.title"),
|
||||
children: <ActivityLinks notificationApi={notificationApi} />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</MySupsenseFallback>
|
||||
|
@ -1313,6 +1334,7 @@ function ActivityCallProtocols({ notificationApi }) {
|
|||
avatarWidth={56}
|
||||
userId={item.CreatedBy}
|
||||
allUsers={appContext.users}
|
||||
tooltip
|
||||
/>
|
||||
}
|
||||
title={
|
||||
|
@ -1743,6 +1765,200 @@ function CallProtocolModal({ formDealInfo, notificationApi }) {
|
|||
);
|
||||
}
|
||||
|
||||
function AddLinkModal({ notificationApi }) {
|
||||
const crmContext = useCrmContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const handleCancel = () => setIsOpen(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
{t("crm.tabContent.activities.links.buttonAddLink")}
|
||||
</Button>
|
||||
|
||||
<MyModal
|
||||
title={t("crm.tabContent.activities.links.addLinkModal.title")}
|
||||
isOpen={isOpen}
|
||||
onCancel={handleCancel}
|
||||
footer={
|
||||
<MyModalCloseCreateButtonFooter
|
||||
onCancel={handleCancel}
|
||||
onCreate={() => {
|
||||
form
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
myFetch("/crm/links", "POST", {
|
||||
CustomerId: crmContext.openDrawerCustomerId.current,
|
||||
Name: values.name,
|
||||
Url: values.link,
|
||||
})
|
||||
.then(() => {
|
||||
setIsOpen(false);
|
||||
form.resetFields();
|
||||
})
|
||||
.catch(() =>
|
||||
showUnkownErrorNotification(notificationApi, t)
|
||||
);
|
||||
})
|
||||
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<MySupsenseFallback>
|
||||
<Form form={form} layout="vertical" requiredMark={false}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label={t("crm.tabContent.activities.links.addLinkModal.name")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t("common.text.pleaseInput"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder="Instagram" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="link"
|
||||
label={t("crm.tabContent.activities.links.addLinkModal.link")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t("common.text.pleaseInput"),
|
||||
},
|
||||
{
|
||||
type: "url",
|
||||
message: t("common.text.pleaseInputValidUrl"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
type="url"
|
||||
placeholder="https://instagram.com/my_profile"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</MySupsenseFallback>
|
||||
</MyModal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ActivityLinks({ notificationApi }) {
|
||||
const appContext = useAppContext();
|
||||
const crmContext = useCrmContext();
|
||||
|
||||
if (crmContext.currentDrawerActivityLinks.length === 0) return <Empty />;
|
||||
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: "100%" }}>
|
||||
{crmContext.currentDrawerActivityLinks.map((item) => (
|
||||
<Collapse
|
||||
key={item.Id}
|
||||
items={[
|
||||
{
|
||||
key: item.Id,
|
||||
label: (
|
||||
<Flex justify="space-between">
|
||||
<Flex vertical>
|
||||
<span>{item.Name}</span>
|
||||
<a href={item.Url} target="_blank" rel="noreferrer">
|
||||
{item.Url}
|
||||
</a>
|
||||
<span>{FormatDatetime(item.CreatedAt)}</span>
|
||||
</Flex>
|
||||
|
||||
<Space>
|
||||
<span>
|
||||
{
|
||||
crmContext.currentDrawerActivityLinkHistory.filter(
|
||||
(link) => link.LinkId === item.Id
|
||||
).length
|
||||
}
|
||||
</span>
|
||||
|
||||
<MyCopyIcon
|
||||
text={`${Constants.CRM_LINK_SHARE_ADDRESS}${item.Id}`}
|
||||
notificationApi={notificationApi}
|
||||
/>
|
||||
|
||||
<MyAvatar
|
||||
avatarWidth={24}
|
||||
userId={item.CreatedBy}
|
||||
allUsers={appContext.users}
|
||||
tooltip
|
||||
/>
|
||||
|
||||
<Popconfirm
|
||||
placement="left"
|
||||
title={"Möchten Sie diesen Link wirklich löschen?"}
|
||||
cancelText={"Abbrechen"}
|
||||
okText={"Bestätigen"}
|
||||
onConfirm={() => {
|
||||
myFetch(`/crm/links/${item.Id}`, "DELETE").catch(() =>
|
||||
showUnkownErrorNotification(notificationApi, t)
|
||||
);
|
||||
}}
|
||||
>
|
||||
<DeleteOutlined style={{ color: "darkred" }} />
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
</Flex>
|
||||
),
|
||||
children: (
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
dataSource={crmContext.currentDrawerActivityLinkHistory
|
||||
.filter((link) => link.LinkId === item.Id)
|
||||
.sort((a, b) => new Date(b.UsedAt) - new Date(a.UsedAt))}
|
||||
renderItem={(item) => (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
title={
|
||||
<Flex vertical>
|
||||
<span>
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
UserAgent:{" "}
|
||||
</span>
|
||||
{item.UserAgent}
|
||||
</span>
|
||||
<span>
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
Used at:{" "}
|
||||
</span>
|
||||
{FormatDatetime(item.UsedAt)}
|
||||
</span>
|
||||
</Flex>
|
||||
}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
function TabContentNotes({ notes }) {
|
||||
const crmContext = useCrmContext();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ let roboticsApiAddress = "";
|
|||
var roboticsSwaggerAddress = "";
|
||||
var telegramBotManagerAddress = "";
|
||||
var telegramBotManagerStaticContentAddress = "";
|
||||
var crmLinkShareAddress = "";
|
||||
|
||||
if (window.location.hostname === "localhost" && window.location.port === "") {
|
||||
// for docker container testing on localhost
|
||||
|
@ -27,6 +28,7 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
|
|||
roboticsSwaggerAddress = "http://localhost/rcm/swagger/index.html";
|
||||
telegramBotManagerAddress = "http://localhost/tm/v1";
|
||||
telegramBotManagerStaticContentAddress = "http://localhost/tm/";
|
||||
crmLinkShareAddress = "http://localhost/crm/link/";
|
||||
} else if (window.location.hostname === "localhost") {
|
||||
// programming on localhost
|
||||
apiAddress = "http://localhost:50050/v1";
|
||||
|
@ -37,6 +39,7 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
|
|||
roboticsSwaggerAddress = "http://localhost:50055/swagger/index.html";
|
||||
telegramBotManagerAddress = "http://localhost:50056/v1";
|
||||
telegramBotManagerStaticContentAddress = "http://localhost:50056/";
|
||||
crmLinkShareAddress = "http://localhost:50050/v1/crm/link/";
|
||||
/*} else if (window.location.hostname === "192.168.178.93") {
|
||||
apiAddress = "http://192.168.178.93:50050/v1";
|
||||
staticContentAddress = "http://192.168.178.93:50050/";
|
||||
|
@ -51,6 +54,7 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
|
|||
roboticsSwaggerAddress = `${window.location.protocol}${window.location.hostname}/rcm/swagger/index.html`;
|
||||
telegramBotManagerAddress = `${window.location.protocol}${window.location.hostname}/tm/v1`;
|
||||
telegramBotManagerStaticContentAddress = `${window.location.protocol}${window.location.hostname}/tm/`;
|
||||
crmLinkShareAddress = `${window.location.protocol}${window.location.hostname}/api/v1/crm/link/`;
|
||||
}
|
||||
|
||||
export const Constants = {
|
||||
|
@ -76,6 +80,7 @@ export const Constants = {
|
|||
ROBOTICS_SWAGGER_ADDRESS: roboticsSwaggerAddress,
|
||||
TELEGRAM_BOT_MANAGER_ADDRESS: telegramBotManagerAddress,
|
||||
TELEGRAM_BOT_MANAGER_CONTENT_ADDRESS: telegramBotManagerStaticContentAddress,
|
||||
CRM_LINK_SHARE_ADDRESS: crmLinkShareAddress,
|
||||
ROUTE_PATHS: {
|
||||
EQUIPMENT_DOCUMENTATION: "/equipment-documentation",
|
||||
EQUIPMENT_DOCUMENTATION_VIEW: "/equipment-documentation/",
|
||||
|
|
Loading…
Reference in New Issue