diff --git a/desk/package.json b/desk/package.json
index dd8eae3a3..e8a3cf378 100644
--- a/desk/package.json
+++ b/desk/package.json
@@ -17,7 +17,7 @@
"autoprefixer": "^10.4.13",
"dayjs": "^1.11.7",
"echarts": "^5.4.1",
- "frappe-ui": "^0.0.103",
+ "frappe-ui": "^0.0.105",
"vee-validate": "^4.8.2",
"vue": "^3.2.47",
"vue-echarts": "^6.5.4",
diff --git a/desk/src/pages/desk/Ticket.vue b/desk/src/pages/desk/Ticket.vue
index b325d3269..99cf92fa4 100644
--- a/desk/src/pages/desk/Ticket.vue
+++ b/desk/src/pages/desk/Ticket.vue
@@ -144,40 +144,69 @@
>
To
-
Cc
+
+
+ {{ email }}
+
+
removeFromEmailList(ccList, email)"
+ />
+
pushToEmailList(ccList, e)"
/>
-
-
Bcc
-
+
Bcc
+
+
+ {{ email }}
+
+
removeFromEmailList(bccList, email)"
+ />
+
pushToEmailList(bccList, e)"
/>
-
as
@@ -504,20 +533,13 @@ export default {
const showBcc = ref(false);
const showCcBtn = ref(true);
const showBccBtn = ref(true);
- const validateEmail = toFieldValidator(zod.string().email());
- const { value: cc, errorMessage: ccValidationError } = useField(
- "ccField",
- validateEmail
- );
- const { value: bcc, errorMessage: bccValidationError } = useField(
- "bccField",
- validateEmail
- );
+ const ccList = ref([]);
+ const bccList = ref([]);
return {
- cc,
- bcc,
+ ccList,
+ bccList,
showTextFormattingMenu,
viewportWidth,
user,
@@ -531,8 +553,6 @@ export default {
tempContent,
editingSubject,
replied,
- ccValidationError,
- bccValidationError,
showCc,
showBcc,
showCcBtn,
@@ -554,7 +574,21 @@ export default {
type: "document",
doctype: "Ticket",
name: this.ticketId,
+ onSuccess: () => {
+ this.$resources.ticket.lastCommunication.fetch();
+ },
whitelistedMethods: {
+ lastCommunication: {
+ method: "last_communication",
+ onSuccess: (data) => {
+ this.ccList = this.ccList.length
+ ? this.ccList
+ : data.cc?.split(",") || [];
+ this.bccList = this.bccList.length
+ ? this.bccList
+ : data.bcc?.split(",") || [];
+ },
+ },
markSeen: "mark_seen",
replyViaAgent: {
method: "reply_via_agent",
@@ -669,8 +703,8 @@ export default {
this.$resources.ticket.replyViaAgent.submit({
attachments: this.attachments.map((x) => x.name),
- bcc: this.bcc,
- cc: this.cc,
+ bcc: this.bccList.join(","),
+ cc: this.ccList.join(","),
message,
});
@@ -723,6 +757,28 @@ export default {
this.tempContent = content;
this.content = this.tempContent;
},
+ validateEmail(email) {
+ return zod.string().email().safeParse(email).success;
+ },
+ pushToEmailList(list, e) {
+ if (list.indexOf(e.target.value) > 0) return;
+
+ if (!this.validateEmail(e.target.value)) {
+ this.$toast({
+ title: "Invalid email",
+ icon: "x",
+ iconClasses: "text-red-500",
+ });
+
+ return;
+ }
+
+ list.push(e.currentTarget.value);
+ e.currentTarget.value = "";
+ },
+ removeFromEmailList(list, email) {
+ list.splice(list.indexOf(email), 1);
+ },
},
};
diff --git a/desk/yarn.lock b/desk/yarn.lock
index 0dc18c46e..42b1d5c04 100644
--- a/desk/yarn.lock
+++ b/desk/yarn.lock
@@ -892,10 +892,10 @@ fraction.js@^4.2.0:
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
-frappe-ui@^0.0.103:
- version "0.0.103"
- resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.0.103.tgz#54be8966b4602f66b0eee36df94e2f0137889e4d"
- integrity sha512-TEfAUsmJLzfIT28rFbl2eCA//apgOwMA12DIPOxOpUB8+mh0s6Ze5ADK1pE+/p3hJlPG9QSS8JxRXvH9t/lOKQ==
+frappe-ui@^0.0.105:
+ version "0.0.105"
+ resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.0.105.tgz#173acd4dbf8e14f1d072c1a19a4dd597af0d7833"
+ integrity sha512-/CbbpAgEHgOXQ6L69hg1hW99rHsc6Q5VKccaBSCZbczU9iWNXvnm+YZ3LggnwNiFpiJBjNsy1TqMUy448ry+oQ==
dependencies:
"@headlessui/vue" "^1.5.0"
"@popperjs/core" "^2.11.2"
diff --git a/frappedesk/frappedesk/doctype/ticket/ticket.py b/frappedesk/frappedesk/doctype/ticket/ticket.py
index ed7c10069..0e4e44712 100644
--- a/frappedesk/frappedesk/doctype/ticket/ticket.py
+++ b/frappedesk/frappedesk/doctype/ticket/ticket.py
@@ -314,6 +314,7 @@ def instantly_send_email(self):
return bool(int(check))
+ @frappe.whitelist()
def last_communication(self):
filters = {"reference_doctype": "Ticket", "reference_name": ["=", self.name]}