Merge pull request #840 from frappe/main-hotfix
This commit is contained in:
commit
3e330431a5
@ -118,6 +118,12 @@ def invite_by_email(emails: str, role: str):
|
|||||||
for email in to_invite:
|
for email in to_invite:
|
||||||
frappe.get_doc(doctype="CRM Invitation", email=email, role=role).insert(ignore_permissions=True)
|
frappe.get_doc(doctype="CRM Invitation", email=email, role=role).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"existing_members": existing_members,
|
||||||
|
"existing_invites": existing_invites,
|
||||||
|
"to_invite": to_invite,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_file_uploader_defaults(doctype: str):
|
def get_file_uploader_defaults(doctype: str):
|
||||||
|
|||||||
@ -65,7 +65,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-09-16 19:40:19.340948",
|
"modified": "2025-05-19 17:57:24.610295",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "FCRM",
|
"module": "FCRM",
|
||||||
"name": "CRM Form Script",
|
"name": "CRM Form Script",
|
||||||
@ -83,9 +83,19 @@
|
|||||||
"role": "Sales Manager",
|
"role": "Sales Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "All",
|
||||||
|
"share": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"row_format": "Dynamic",
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class CRMInvitation(Document):
|
|||||||
if frappe.local.dev_server:
|
if frappe.local.dev_server:
|
||||||
print(f"Invite link for {self.email}: {invite_link}")
|
print(f"Invite link for {self.email}: {invite_link}")
|
||||||
|
|
||||||
title = f"Frappe CRM"
|
title = "Frappe CRM"
|
||||||
template = "crm_invitation"
|
template = "crm_invitation"
|
||||||
|
|
||||||
frappe.sendmail(
|
frappe.sendmail(
|
||||||
@ -44,12 +44,24 @@ class CRMInvitation(Document):
|
|||||||
|
|
||||||
user = self.create_user_if_not_exists()
|
user = self.create_user_if_not_exists()
|
||||||
user.append_roles(self.role)
|
user.append_roles(self.role)
|
||||||
|
if self.role == "Sales User":
|
||||||
|
self.update_module_in_user(user, "FCRM")
|
||||||
user.save(ignore_permissions=True)
|
user.save(ignore_permissions=True)
|
||||||
|
|
||||||
self.status = "Accepted"
|
self.status = "Accepted"
|
||||||
self.accepted_at = frappe.utils.now()
|
self.accepted_at = frappe.utils.now()
|
||||||
self.save(ignore_permissions=True)
|
self.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
def update_module_in_user(self, user, module):
|
||||||
|
block_modules = frappe.get_all(
|
||||||
|
"Module Def",
|
||||||
|
fields=["name as module"],
|
||||||
|
filters={"name": ["!=", module]},
|
||||||
|
)
|
||||||
|
|
||||||
|
if block_modules:
|
||||||
|
user.set("block_modules", block_modules)
|
||||||
|
|
||||||
def create_user_if_not_exists(self):
|
def create_user_if_not_exists(self):
|
||||||
if not frappe.db.exists("User", self.email):
|
if not frappe.db.exists("User", self.email):
|
||||||
first_name = self.email.split("@")[0].title()
|
first_name = self.email.split("@")[0].title()
|
||||||
|
|||||||
@ -264,7 +264,7 @@ def create_customer_in_remote_site(customer, erpnext_crm_settings):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_crm_form_script():
|
def get_crm_form_script():
|
||||||
return """
|
return """
|
||||||
async function setupForm({ doc, call, $dialog, updateField, createToast }) {
|
async function setupForm({ doc, call, $dialog, updateField, toast }) {
|
||||||
let actions = [];
|
let actions = [];
|
||||||
let is_erpnext_integration_enabled = await call("frappe.client.get_single_value", {doctype: "ERPNext CRM Settings", field: "enabled"});
|
let is_erpnext_integration_enabled = await call("frappe.client.get_single_value", {doctype: "ERPNext CRM Settings", field: "enabled"});
|
||||||
if (!["Lost", "Won"].includes(doc?.status) && is_erpnext_integration_enabled) {
|
if (!["Lost", "Won"].includes(doc?.status) && is_erpnext_integration_enabled) {
|
||||||
|
|||||||
@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Frappe CRM VERSION\n"
|
"Project-Id-Version: Frappe CRM VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||||
"POT-Creation-Date: 2025-05-04 09:35+0000\n"
|
"POT-Creation-Date: 2025-05-18 09:35+0000\n"
|
||||||
"PO-Revision-Date: 2025-05-04 09:35+0000\n"
|
"PO-Revision-Date: 2025-05-18 09:35+0000\n"
|
||||||
"Last-Translator: shariq@frappe.io\n"
|
"Last-Translator: shariq@frappe.io\n"
|
||||||
"Language-Team: shariq@frappe.io\n"
|
"Language-Team: shariq@frappe.io\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -176,8 +176,8 @@ msgstr ""
|
|||||||
msgid "Actions"
|
msgid "Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:546 frontend/src/pages/Lead.vue:532
|
#: frontend/src/pages/Deal.vue:545 frontend/src/pages/Lead.vue:531
|
||||||
#: frontend/src/pages/MobileDeal.vue:441 frontend/src/pages/MobileLead.vue:344
|
#: frontend/src/pages/MobileDeal.vue:440 frontend/src/pages/MobileLead.vue:343
|
||||||
msgid "Activity"
|
msgid "Activity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ msgstr ""
|
|||||||
msgid "Add Filter"
|
msgid "Add Filter"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Controls/Grid.vue:243
|
#: frontend/src/components/Controls/Grid.vue:310
|
||||||
msgid "Add Row"
|
msgid "Add Row"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -282,12 +282,19 @@ msgstr ""
|
|||||||
msgid "All"
|
msgid "All"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:633 frontend/src/pages/MobileContact.vue:607
|
#. Label of the amount (Currency) field in DocType 'CRM Products'
|
||||||
#: frontend/src/pages/MobileOrganization.vue:493
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
#: frontend/src/pages/Organization.vue:532
|
#: frontend/src/pages/Contact.vue:632 frontend/src/pages/MobileContact.vue:606
|
||||||
|
#: frontend/src/pages/MobileOrganization.vue:492
|
||||||
|
#: frontend/src/pages/Organization.vue:531
|
||||||
msgid "Amount"
|
msgid "Amount"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Description of the 'Net Amount' (Currency) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Amount after discount"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Description of the 'Favicon' (Attach) field in DocType 'FCRM Settings'
|
#. Description of the 'Favicon' (Attach) field in DocType 'FCRM Settings'
|
||||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||||
msgid "An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org]"
|
msgid "An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org]"
|
||||||
@ -347,12 +354,12 @@ msgstr ""
|
|||||||
msgid "Are you sure you want to delete this attachment?"
|
msgid "Are you sure you want to delete this attachment?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:321 frontend/src/pages/MobileContact.vue:292
|
#: frontend/src/pages/Contact.vue:320 frontend/src/pages/MobileContact.vue:291
|
||||||
msgid "Are you sure you want to delete this contact?"
|
msgid "Are you sure you want to delete this contact?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/MobileOrganization.vue:286
|
#: frontend/src/pages/MobileOrganization.vue:285
|
||||||
#: frontend/src/pages/Organization.vue:328
|
#: frontend/src/pages/Organization.vue:327
|
||||||
msgid "Are you sure you want to delete this organization?"
|
msgid "Are you sure you want to delete this organization?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -400,7 +407,7 @@ msgstr ""
|
|||||||
msgid "Assignment rule"
|
msgid "Assignment rule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Controls/GridFieldsEditorModal.vue:171
|
#: frontend/src/components/Controls/GridFieldsEditorModal.vue:176
|
||||||
msgid "At least one field is required"
|
msgid "At least one field is required"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -413,8 +420,8 @@ msgstr ""
|
|||||||
msgid "Attach a file"
|
msgid "Attach a file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:581 frontend/src/pages/Lead.vue:567
|
#: frontend/src/pages/Deal.vue:580 frontend/src/pages/Lead.vue:566
|
||||||
#: frontend/src/pages/MobileDeal.vue:477 frontend/src/pages/MobileLead.vue:380
|
#: frontend/src/pages/MobileDeal.vue:476 frontend/src/pages/MobileLead.vue:379
|
||||||
msgid "Attachments"
|
msgid "Attachments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -572,6 +579,16 @@ msgstr ""
|
|||||||
msgid "CRM Portal Page"
|
msgid "CRM Portal Page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Name of a DocType
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
|
msgid "CRM Product"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Name of a DocType
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "CRM Products"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Name of a DocType
|
#. Name of a DocType
|
||||||
#: crm/fcrm/doctype/crm_service_day/crm_service_day.json
|
#: crm/fcrm/doctype/crm_service_day/crm_service_day.json
|
||||||
msgid "CRM Service Day"
|
msgid "CRM Service Day"
|
||||||
@ -667,8 +684,8 @@ msgstr ""
|
|||||||
msgid "Calling..."
|
msgid "Calling..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:566 frontend/src/pages/Lead.vue:552
|
#: frontend/src/pages/Deal.vue:565 frontend/src/pages/Lead.vue:551
|
||||||
#: frontend/src/pages/MobileDeal.vue:461 frontend/src/pages/MobileLead.vue:364
|
#: frontend/src/pages/MobileDeal.vue:460 frontend/src/pages/MobileLead.vue:363
|
||||||
msgid "Calls"
|
msgid "Calls"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -723,8 +740,8 @@ msgstr ""
|
|||||||
msgid "Change image"
|
msgid "Change image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:245 frontend/src/pages/Lead.vue:271
|
#: frontend/src/pages/Lead.vue:244 frontend/src/pages/Lead.vue:270
|
||||||
#: frontend/src/pages/MobileLead.vue:110 frontend/src/pages/MobileLead.vue:137
|
#: frontend/src/pages/MobileLead.vue:109 frontend/src/pages/MobileLead.vue:136
|
||||||
msgid "Choose Existing"
|
msgid "Choose Existing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -811,8 +828,8 @@ msgstr ""
|
|||||||
msgid "Comment"
|
msgid "Comment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:556 frontend/src/pages/Lead.vue:542
|
#: frontend/src/pages/Deal.vue:555 frontend/src/pages/Lead.vue:541
|
||||||
#: frontend/src/pages/MobileDeal.vue:451 frontend/src/pages/MobileLead.vue:354
|
#: frontend/src/pages/MobileDeal.vue:450 frontend/src/pages/MobileLead.vue:353
|
||||||
msgid "Comments"
|
msgid "Comments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -861,7 +878,7 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_contacts/crm_contacts.json
|
#: crm/fcrm/doctype/crm_contacts/crm_contacts.json
|
||||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
#: frontend/src/components/Layouts/AppSidebar.vue:509
|
#: frontend/src/components/Layouts/AppSidebar.vue:509
|
||||||
#: frontend/src/pages/Lead.vue:267 frontend/src/pages/MobileLead.vue:133
|
#: frontend/src/pages/Lead.vue:266 frontend/src/pages/MobileLead.vue:132
|
||||||
msgid "Contact"
|
msgid "Contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -873,11 +890,11 @@ msgstr ""
|
|||||||
msgid "Contact Us"
|
msgid "Contact Us"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:665 frontend/src/pages/MobileDeal.vue:560
|
#: frontend/src/pages/Deal.vue:664 frontend/src/pages/MobileDeal.vue:559
|
||||||
msgid "Contact added"
|
msgid "Contact added"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:651 frontend/src/pages/MobileDeal.vue:546
|
#: frontend/src/pages/Deal.vue:650 frontend/src/pages/MobileDeal.vue:545
|
||||||
msgid "Contact already added"
|
msgid "Contact already added"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -889,7 +906,7 @@ msgstr ""
|
|||||||
msgid "Contact not found"
|
msgid "Contact not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:680 frontend/src/pages/MobileDeal.vue:575
|
#: frontend/src/pages/Deal.vue:679 frontend/src/pages/MobileDeal.vue:574
|
||||||
msgid "Contact removed"
|
msgid "Contact removed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -898,8 +915,8 @@ msgstr ""
|
|||||||
#. Label of a shortcut in the Frappe CRM Workspace
|
#. Label of a shortcut in the Frappe CRM Workspace
|
||||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||||
#: frontend/src/pages/Contact.vue:265 frontend/src/pages/MobileContact.vue:236
|
#: frontend/src/pages/Contact.vue:264 frontend/src/pages/MobileContact.vue:235
|
||||||
#: frontend/src/pages/MobileOrganization.vue:373
|
#: frontend/src/pages/MobileOrganization.vue:372
|
||||||
msgid "Contacts"
|
msgid "Contacts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -917,8 +934,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: frontend/src/components/Layouts/AppSidebar.vue:351
|
#: frontend/src/components/Layouts/AppSidebar.vue:351
|
||||||
#: frontend/src/components/ListBulkActions.vue:70
|
#: frontend/src/components/ListBulkActions.vue:70
|
||||||
#: frontend/src/pages/Lead.vue:205 frontend/src/pages/MobileLead.vue:49
|
#: frontend/src/pages/Lead.vue:204 frontend/src/pages/MobileLead.vue:49
|
||||||
#: frontend/src/pages/MobileLead.vue:96
|
#: frontend/src/pages/MobileLead.vue:95
|
||||||
msgid "Convert"
|
msgid "Convert"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -929,8 +946,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: frontend/src/components/ListBulkActions.vue:62
|
#: frontend/src/components/ListBulkActions.vue:62
|
||||||
#: frontend/src/components/ListBulkActions.vue:204
|
#: frontend/src/components/ListBulkActions.vue:204
|
||||||
#: frontend/src/pages/Lead.vue:38 frontend/src/pages/Lead.vue:216
|
#: frontend/src/pages/Lead.vue:38 frontend/src/pages/Lead.vue:215
|
||||||
#: frontend/src/pages/MobileLead.vue:92
|
#: frontend/src/pages/MobileLead.vue:91
|
||||||
msgid "Convert to Deal"
|
msgid "Convert to Deal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -946,6 +963,7 @@ msgstr ""
|
|||||||
#: frontend/src/components/Modals/AddressModal.vue:100
|
#: frontend/src/components/Modals/AddressModal.vue:100
|
||||||
#: frontend/src/components/Modals/CallLogModal.vue:104
|
#: frontend/src/components/Modals/CallLogModal.vue:104
|
||||||
#: frontend/src/components/Modals/ContactModal.vue:37
|
#: frontend/src/components/Modals/ContactModal.vue:37
|
||||||
|
#: frontend/src/components/Modals/CreateDocumentModal.vue:87
|
||||||
#: frontend/src/components/Modals/DealModal.vue:63
|
#: frontend/src/components/Modals/DealModal.vue:63
|
||||||
#: frontend/src/components/Modals/EmailTemplateModal.vue:9
|
#: frontend/src/components/Modals/EmailTemplateModal.vue:9
|
||||||
#: frontend/src/components/Modals/LeadModal.vue:34
|
#: frontend/src/components/Modals/LeadModal.vue:34
|
||||||
@ -985,7 +1003,7 @@ msgstr ""
|
|||||||
#: frontend/src/components/Controls/Link.vue:48
|
#: frontend/src/components/Controls/Link.vue:48
|
||||||
#: frontend/src/components/Modals/EmailTemplateSelectorModal.vue:55
|
#: frontend/src/components/Modals/EmailTemplateSelectorModal.vue:55
|
||||||
#: frontend/src/components/Modals/WhatsappTemplateSelectorModal.vue:45
|
#: frontend/src/components/Modals/WhatsappTemplateSelectorModal.vue:45
|
||||||
#: frontend/src/components/SidePanelLayout.vue:125
|
#: frontend/src/components/SidePanelLayout.vue:135
|
||||||
msgid "Create New"
|
msgid "Create New"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1053,7 +1071,7 @@ msgstr ""
|
|||||||
msgid "Custom statuses"
|
msgid "Custom statuses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:434
|
#: frontend/src/pages/Deal.vue:433
|
||||||
msgid "Customer created successfully"
|
msgid "Customer created successfully"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1067,8 +1085,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: frontend/src/components/Activities/DataFields.vue:6
|
#: frontend/src/components/Activities/DataFields.vue:6
|
||||||
#: frontend/src/components/Layouts/AppSidebar.vue:539
|
#: frontend/src/components/Layouts/AppSidebar.vue:539
|
||||||
#: frontend/src/pages/Deal.vue:561 frontend/src/pages/Lead.vue:547
|
#: frontend/src/pages/Deal.vue:560 frontend/src/pages/Lead.vue:546
|
||||||
#: frontend/src/pages/MobileDeal.vue:456 frontend/src/pages/MobileLead.vue:359
|
#: frontend/src/pages/MobileDeal.vue:455 frontend/src/pages/MobileLead.vue:358
|
||||||
msgid "Data"
|
msgid "Data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1103,21 +1121,21 @@ msgstr ""
|
|||||||
msgid "Deal Statuses"
|
msgid "Deal Statuses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:654 frontend/src/pages/MobileContact.vue:628
|
#: frontend/src/pages/Contact.vue:653 frontend/src/pages/MobileContact.vue:627
|
||||||
#: frontend/src/pages/MobileOrganization.vue:514
|
#: frontend/src/pages/MobileOrganization.vue:513
|
||||||
#: frontend/src/pages/Organization.vue:553
|
#: frontend/src/pages/Organization.vue:552
|
||||||
msgid "Deal owner"
|
msgid "Deal owner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:474 frontend/src/pages/MobileDeal.vue:363
|
#: frontend/src/pages/Deal.vue:473 frontend/src/pages/MobileDeal.vue:362
|
||||||
msgid "Deal updated"
|
msgid "Deal updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of a shortcut in the Frappe CRM Workspace
|
#. Label of a shortcut in the Frappe CRM Workspace
|
||||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||||
#: frontend/src/pages/Deal.vue:506 frontend/src/pages/MobileContact.vue:320
|
#: frontend/src/pages/Deal.vue:505 frontend/src/pages/MobileContact.vue:319
|
||||||
#: frontend/src/pages/MobileDeal.vue:395
|
#: frontend/src/pages/MobileDeal.vue:394
|
||||||
#: frontend/src/pages/MobileOrganization.vue:367
|
#: frontend/src/pages/MobileOrganization.vue:366
|
||||||
msgid "Deals"
|
msgid "Deals"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1191,21 +1209,21 @@ msgstr ""
|
|||||||
#: frontend/src/components/Activities/NoteArea.vue:12
|
#: frontend/src/components/Activities/NoteArea.vue:12
|
||||||
#: frontend/src/components/Activities/TaskArea.vue:55
|
#: frontend/src/components/Activities/TaskArea.vue:55
|
||||||
#: frontend/src/components/Activities/TaskArea.vue:63
|
#: frontend/src/components/Activities/TaskArea.vue:63
|
||||||
#: frontend/src/components/Controls/Grid.vue:238
|
#: frontend/src/components/Controls/Grid.vue:305
|
||||||
#: frontend/src/components/Kanban/KanbanView.vue:225
|
#: frontend/src/components/Kanban/KanbanView.vue:225
|
||||||
#: frontend/src/components/ListBulkActions.vue:96
|
#: frontend/src/components/ListBulkActions.vue:96
|
||||||
#: frontend/src/components/ListBulkActions.vue:104
|
#: frontend/src/components/ListBulkActions.vue:104
|
||||||
#: frontend/src/components/ListBulkActions.vue:186
|
#: frontend/src/components/ListBulkActions.vue:186
|
||||||
#: frontend/src/components/ViewControls.vue:1163
|
#: frontend/src/components/ViewControls.vue:1163
|
||||||
#: frontend/src/components/ViewControls.vue:1174
|
#: frontend/src/components/ViewControls.vue:1174
|
||||||
#: frontend/src/pages/Contact.vue:105 frontend/src/pages/Contact.vue:324
|
#: frontend/src/pages/Contact.vue:105 frontend/src/pages/Contact.vue:323
|
||||||
#: frontend/src/pages/MobileContact.vue:81
|
#: frontend/src/pages/MobileContact.vue:81
|
||||||
#: frontend/src/pages/MobileContact.vue:295
|
#: frontend/src/pages/MobileContact.vue:294
|
||||||
#: frontend/src/pages/MobileDeal.vue:526
|
#: frontend/src/pages/MobileDeal.vue:525
|
||||||
#: frontend/src/pages/MobileOrganization.vue:72
|
#: frontend/src/pages/MobileOrganization.vue:72
|
||||||
#: frontend/src/pages/MobileOrganization.vue:289
|
#: frontend/src/pages/MobileOrganization.vue:288
|
||||||
#: frontend/src/pages/Notes.vue:40 frontend/src/pages/Organization.vue:83
|
#: frontend/src/pages/Notes.vue:40 frontend/src/pages/Organization.vue:83
|
||||||
#: frontend/src/pages/Organization.vue:331 frontend/src/pages/Tasks.vue:368
|
#: frontend/src/pages/Organization.vue:330 frontend/src/pages/Tasks.vue:368
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1227,12 +1245,12 @@ msgstr ""
|
|||||||
msgid "Delete attachment"
|
msgid "Delete attachment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:320 frontend/src/pages/MobileContact.vue:291
|
#: frontend/src/pages/Contact.vue:319 frontend/src/pages/MobileContact.vue:290
|
||||||
msgid "Delete contact"
|
msgid "Delete contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/MobileOrganization.vue:285
|
#: frontend/src/pages/MobileOrganization.vue:284
|
||||||
#: frontend/src/pages/Organization.vue:327
|
#: frontend/src/pages/Organization.vue:326
|
||||||
msgid "Delete organization"
|
msgid "Delete organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1241,8 +1259,10 @@ msgid "Deleted successfully"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the description (Text Editor) field in DocType 'CRM Holiday'
|
#. Label of the description (Text Editor) field in DocType 'CRM Holiday'
|
||||||
|
#. Label of the description (Text Editor) field in DocType 'CRM Product'
|
||||||
#. Label of the description (Text Editor) field in DocType 'CRM Task'
|
#. Label of the description (Text Editor) field in DocType 'CRM Task'
|
||||||
#: crm/fcrm/doctype/crm_holiday/crm_holiday.json
|
#: crm/fcrm/doctype/crm_holiday/crm_holiday.json
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
#: crm/fcrm/doctype/crm_task/crm_task.json
|
#: crm/fcrm/doctype/crm_task/crm_task.json
|
||||||
#: frontend/src/components/Modals/TaskModal.vue:48
|
#: frontend/src/components/Modals/TaskModal.vue:48
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
@ -1256,9 +1276,9 @@ msgstr ""
|
|||||||
#. Label of the details (Text Editor) field in DocType 'CRM Lead Source'
|
#. Label of the details (Text Editor) field in DocType 'CRM Lead Source'
|
||||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
#: crm/fcrm/doctype/crm_lead_source/crm_lead_source.json
|
#: crm/fcrm/doctype/crm_lead_source/crm_lead_source.json
|
||||||
#: frontend/src/pages/MobileContact.vue:315
|
#: frontend/src/pages/MobileContact.vue:314
|
||||||
#: frontend/src/pages/MobileDeal.vue:435 frontend/src/pages/MobileLead.vue:338
|
#: frontend/src/pages/MobileDeal.vue:434 frontend/src/pages/MobileLead.vue:337
|
||||||
#: frontend/src/pages/MobileOrganization.vue:362
|
#: frontend/src/pages/MobileOrganization.vue:361
|
||||||
msgid "Details"
|
msgid "Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1273,11 +1293,26 @@ msgstr ""
|
|||||||
msgid "Disable"
|
msgid "Disable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the disabled (Check) field in DocType 'CRM Product'
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/CommentBox.vue:76
|
#: frontend/src/components/CommentBox.vue:76
|
||||||
#: frontend/src/components/EmailEditor.vue:158
|
#: frontend/src/components/EmailEditor.vue:158
|
||||||
msgid "Discard"
|
msgid "Discard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the discount_percentage (Percent) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Discount %"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the discount_amount (Currency) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Discount Amount"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the dt (Link) field in DocType 'CRM Form Script'
|
#. Label of the dt (Link) field in DocType 'CRM Form Script'
|
||||||
#. Label of the dt (Link) field in DocType 'CRM Global Settings'
|
#. Label of the dt (Link) field in DocType 'CRM Global Settings'
|
||||||
#. Label of the dt (Link) field in DocType 'CRM View Settings'
|
#. Label of the dt (Link) field in DocType 'CRM View Settings'
|
||||||
@ -1300,6 +1335,10 @@ msgstr ""
|
|||||||
msgid "Document not found"
|
msgid "Document not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/document.js:21
|
||||||
|
msgid "Document updated successfully"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Option for the 'Status' (Select) field in DocType 'CRM Task'
|
#. Option for the 'Status' (Select) field in DocType 'CRM Task'
|
||||||
#: crm/fcrm/doctype/crm_task/crm_task.json
|
#: crm/fcrm/doctype/crm_task/crm_task.json
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
@ -1382,7 +1421,7 @@ msgstr ""
|
|||||||
msgid "ERPNext is not integrated with the CRM"
|
msgid "ERPNext is not integrated with the CRM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/FieldLayout/Field.vue:80
|
#: frontend/src/components/FieldLayout/Field.vue:91
|
||||||
#: frontend/src/components/FieldLayoutEditor.vue:319
|
#: frontend/src/components/FieldLayoutEditor.vue:319
|
||||||
#: frontend/src/components/FieldLayoutEditor.vue:345
|
#: frontend/src/components/FieldLayoutEditor.vue:345
|
||||||
#: frontend/src/components/ListBulkActions.vue:179
|
#: frontend/src/components/ListBulkActions.vue:179
|
||||||
@ -1454,12 +1493,12 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_contacts/crm_contacts.json
|
#: crm/fcrm/doctype/crm_contacts/crm_contacts.json
|
||||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
||||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json frontend/src/pages/Contact.vue:644
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json frontend/src/pages/Contact.vue:643
|
||||||
#: frontend/src/pages/MobileContact.vue:618
|
#: frontend/src/pages/MobileContact.vue:617
|
||||||
#: frontend/src/pages/MobileOrganization.vue:504
|
#: frontend/src/pages/MobileOrganization.vue:503
|
||||||
#: frontend/src/pages/MobileOrganization.vue:532
|
#: frontend/src/pages/MobileOrganization.vue:531
|
||||||
#: frontend/src/pages/Organization.vue:543
|
#: frontend/src/pages/Organization.vue:542
|
||||||
#: frontend/src/pages/Organization.vue:571
|
#: frontend/src/pages/Organization.vue:570
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1501,8 +1540,8 @@ msgstr ""
|
|||||||
msgid "Email template"
|
msgid "Email template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:551 frontend/src/pages/Lead.vue:537
|
#: frontend/src/pages/Deal.vue:550 frontend/src/pages/Lead.vue:536
|
||||||
#: frontend/src/pages/MobileDeal.vue:446 frontend/src/pages/MobileLead.vue:349
|
#: frontend/src/pages/MobileDeal.vue:445 frontend/src/pages/MobileLead.vue:348
|
||||||
msgid "Emails"
|
msgid "Emails"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1556,7 +1595,7 @@ msgstr ""
|
|||||||
msgid "End Time"
|
msgid "End Time"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/FieldLayout/Field.vue:265
|
#: frontend/src/components/FieldLayout/Field.vue:324
|
||||||
msgid "Enter {0}"
|
msgid "Enter {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1574,28 +1613,32 @@ msgstr ""
|
|||||||
#: frontend/src/components/Settings/SettingsPage.vue:91
|
#: frontend/src/components/Settings/SettingsPage.vue:91
|
||||||
#: frontend/src/components/Settings/TelephonySettings.vue:131
|
#: frontend/src/components/Settings/TelephonySettings.vue:131
|
||||||
#: frontend/src/components/Settings/TelephonySettings.vue:156
|
#: frontend/src/components/Settings/TelephonySettings.vue:156
|
||||||
#: frontend/src/pages/Lead.vue:633 frontend/src/pages/Lead.vue:643
|
#: frontend/src/pages/Lead.vue:632 frontend/src/pages/Lead.vue:642
|
||||||
#: frontend/src/pages/MobileLead.vue:438 frontend/src/pages/MobileLead.vue:448
|
#: frontend/src/pages/MobileLead.vue:437 frontend/src/pages/MobileLead.vue:447
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:495 frontend/src/pages/MobileDeal.vue:384
|
#: frontend/src/pages/Deal.vue:494 frontend/src/pages/MobileDeal.vue:383
|
||||||
msgid "Error Updating Deal"
|
msgid "Error Updating Deal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:481 frontend/src/pages/MobileLead.vue:287
|
#: frontend/src/pages/Lead.vue:480 frontend/src/pages/MobileLead.vue:286
|
||||||
msgid "Error Updating Lead"
|
msgid "Error Updating Lead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:666
|
#: frontend/src/pages/Lead.vue:665
|
||||||
msgid "Error converting to deal"
|
msgid "Error converting to deal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:482 frontend/src/pages/MobileDeal.vue:371
|
#: frontend/src/pages/Deal.vue:481 frontend/src/pages/MobileDeal.vue:370
|
||||||
msgid "Error updating deal"
|
msgid "Error updating deal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:468 frontend/src/pages/MobileLead.vue:274
|
#: frontend/src/data/document.js:28
|
||||||
|
msgid "Error updating document"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/pages/Lead.vue:467 frontend/src/pages/MobileLead.vue:273
|
||||||
msgid "Error updating lead"
|
msgid "Error updating lead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1702,6 +1745,10 @@ msgstr ""
|
|||||||
msgid "Failed to create email account, Invalid credentials"
|
msgid "Failed to create email account, Invalid credentials"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/script.js:98
|
||||||
|
msgid "Failed to load form controller: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: crm/integrations/twilio/api.py:152
|
#: crm/integrations/twilio/api.py:152
|
||||||
msgid "Failed to update Twilio call status"
|
msgid "Failed to update Twilio call status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1979,7 +2026,9 @@ msgid "If enabled, records can be created from the incoming emails on this accou
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the image (Attach Image) field in DocType 'CRM Lead'
|
#. Label of the image (Attach Image) field in DocType 'CRM Lead'
|
||||||
|
#. Label of the image (Attach Image) field in DocType 'CRM Product'
|
||||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
msgid "Image"
|
msgid "Image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2236,11 +2285,11 @@ msgstr ""
|
|||||||
msgid "Last Year"
|
msgid "Last Year"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:659 frontend/src/pages/MobileContact.vue:633
|
#: frontend/src/pages/Contact.vue:658 frontend/src/pages/MobileContact.vue:632
|
||||||
#: frontend/src/pages/MobileOrganization.vue:519
|
#: frontend/src/pages/MobileOrganization.vue:518
|
||||||
#: frontend/src/pages/MobileOrganization.vue:547
|
#: frontend/src/pages/MobileOrganization.vue:546
|
||||||
#: frontend/src/pages/Organization.vue:558
|
#: frontend/src/pages/Organization.vue:557
|
||||||
#: frontend/src/pages/Organization.vue:586
|
#: frontend/src/pages/Organization.vue:585
|
||||||
msgid "Last modified"
|
msgid "Last modified"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2286,13 +2335,13 @@ msgstr ""
|
|||||||
msgid "Lead Statuses"
|
msgid "Lead Statuses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:460 frontend/src/pages/MobileLead.vue:266
|
#: frontend/src/pages/Lead.vue:459 frontend/src/pages/MobileLead.vue:265
|
||||||
msgid "Lead updated"
|
msgid "Lead updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of a shortcut in the Frappe CRM Workspace
|
#. Label of a shortcut in the Frappe CRM Workspace
|
||||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||||
#: frontend/src/pages/Lead.vue:492 frontend/src/pages/MobileLead.vue:298
|
#: frontend/src/pages/Lead.vue:491 frontend/src/pages/MobileLead.vue:297
|
||||||
msgid "Leads"
|
msgid "Leads"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2347,7 +2396,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: frontend/src/components/Activities/Activities.vue:22
|
#: frontend/src/components/Activities/Activities.vue:22
|
||||||
#: frontend/src/components/Activities/DataFields.vue:35
|
#: frontend/src/components/Activities/DataFields.vue:35
|
||||||
#: frontend/src/pages/Deal.vue:177 frontend/src/pages/MobileDeal.vue:111
|
#: frontend/src/pages/Deal.vue:176 frontend/src/pages/MobileDeal.vue:110
|
||||||
msgid "Loading..."
|
msgid "Loading..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2493,9 +2542,9 @@ msgstr ""
|
|||||||
msgid "Mobile app installation"
|
msgid "Mobile app installation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:649 frontend/src/pages/MobileContact.vue:623
|
#: frontend/src/pages/Contact.vue:648 frontend/src/pages/MobileContact.vue:622
|
||||||
#: frontend/src/pages/MobileOrganization.vue:509
|
#: frontend/src/pages/MobileOrganization.vue:508
|
||||||
#: frontend/src/pages/Organization.vue:548
|
#: frontend/src/pages/Organization.vue:547
|
||||||
msgid "Mobile no"
|
msgid "Mobile no"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2532,16 +2581,30 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||||
#: frontend/src/components/Modals/EmailTemplateModal.vue:24
|
#: frontend/src/components/Modals/EmailTemplateModal.vue:24
|
||||||
#: frontend/src/components/ViewControls.vue:781
|
#: frontend/src/components/ViewControls.vue:781
|
||||||
#: frontend/src/pages/MobileOrganization.vue:527
|
#: frontend/src/pages/MobileOrganization.vue:526
|
||||||
#: frontend/src/pages/Organization.vue:566
|
#: frontend/src/pages/Organization.vue:565
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the naming_series (Select) field in DocType 'CRM Deal'
|
#. Label of the naming_series (Select) field in DocType 'CRM Deal'
|
||||||
|
#. Label of the naming_series (Select) field in DocType 'CRM Product'
|
||||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
msgid "Naming Series"
|
msgid "Naming Series"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the net_amount (Currency) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Net Amount"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the net_total (Currency) field in DocType 'CRM Deal'
|
||||||
|
#. Label of the net_total (Currency) field in DocType 'CRM Lead'
|
||||||
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
|
msgid "Net Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Activities/ActivityHeader.vue:82
|
#: frontend/src/components/Activities/ActivityHeader.vue:82
|
||||||
msgid "New"
|
msgid "New"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2604,14 +2667,18 @@ msgstr ""
|
|||||||
msgid "New WhatsApp Message"
|
msgid "New WhatsApp Message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:283 frontend/src/pages/MobileLead.vue:150
|
#: frontend/src/pages/Lead.vue:282 frontend/src/pages/MobileLead.vue:149
|
||||||
msgid "New contact will be created based on the person's details"
|
msgid "New contact will be created based on the person's details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:258 frontend/src/pages/MobileLead.vue:124
|
#: frontend/src/pages/Lead.vue:257 frontend/src/pages/MobileLead.vue:123
|
||||||
msgid "New organization will be created based on the data in details section"
|
msgid "New organization will be created based on the data in details section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/components/Modals/CreateDocumentModal.vue:83
|
||||||
|
msgid "New {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Filter.vue:655
|
#: frontend/src/components/Filter.vue:655
|
||||||
msgid "Next 6 Months"
|
msgid "Next 6 Months"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2646,7 +2713,7 @@ msgstr ""
|
|||||||
msgid "No Answer"
|
msgid "No Answer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Controls/Grid.vue:231
|
#: frontend/src/components/Controls/Grid.vue:298
|
||||||
msgid "No Data"
|
msgid "No Data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2661,7 +2728,7 @@ msgid "No changes made"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Modals/SidePanelModal.vue:51
|
#: frontend/src/components/Modals/SidePanelModal.vue:51
|
||||||
#: frontend/src/pages/Deal.vue:262 frontend/src/pages/MobileDeal.vue:199
|
#: frontend/src/pages/Deal.vue:261 frontend/src/pages/MobileDeal.vue:198
|
||||||
msgid "No contacts added"
|
msgid "No contacts added"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2673,7 +2740,7 @@ msgstr ""
|
|||||||
msgid "No label"
|
msgid "No label"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:726
|
#: frontend/src/pages/Deal.vue:725
|
||||||
msgid "No mobile number set"
|
msgid "No mobile number set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2686,7 +2753,7 @@ msgstr ""
|
|||||||
msgid "No phone number set"
|
msgid "No phone number set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:721
|
#: frontend/src/pages/Deal.vue:720
|
||||||
msgid "No primary contact set"
|
msgid "No primary contact set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2699,16 +2766,16 @@ msgstr ""
|
|||||||
msgid "No website set"
|
msgid "No website set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/SidePanelLayout.vue:116
|
#: frontend/src/components/SidePanelLayout.vue:126
|
||||||
msgid "No {0} Available"
|
msgid "No {0} Available"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/CallLogs.vue:56 frontend/src/pages/Contact.vue:165
|
#: frontend/src/pages/CallLogs.vue:56 frontend/src/pages/Contact.vue:164
|
||||||
#: frontend/src/pages/Contacts.vue:59 frontend/src/pages/Deals.vue:235
|
#: frontend/src/pages/Contacts.vue:59 frontend/src/pages/Deals.vue:235
|
||||||
#: frontend/src/pages/EmailTemplates.vue:60 frontend/src/pages/Leads.vue:261
|
#: frontend/src/pages/EmailTemplates.vue:60 frontend/src/pages/Leads.vue:261
|
||||||
#: frontend/src/pages/MobileContact.vue:154
|
#: frontend/src/pages/MobileContact.vue:153
|
||||||
#: frontend/src/pages/MobileOrganization.vue:143
|
#: frontend/src/pages/MobileOrganization.vue:142
|
||||||
#: frontend/src/pages/Notes.vue:92 frontend/src/pages/Organization.vue:157
|
#: frontend/src/pages/Notes.vue:92 frontend/src/pages/Organization.vue:156
|
||||||
#: frontend/src/pages/Organizations.vue:59 frontend/src/pages/Tasks.vue:184
|
#: frontend/src/pages/Organizations.vue:59 frontend/src/pages/Tasks.vue:184
|
||||||
msgid "No {0} Found"
|
msgid "No {0} Found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2777,8 +2844,8 @@ msgstr ""
|
|||||||
msgid "Not allowed to set primary contact for Deal"
|
msgid "Not allowed to set primary contact for Deal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:256 frontend/src/pages/Deal.vue:418
|
#: frontend/src/pages/Contact.vue:255 frontend/src/pages/Deal.vue:417
|
||||||
#: frontend/src/pages/Lead.vue:426 frontend/src/pages/Organization.vue:245
|
#: frontend/src/pages/Lead.vue:425 frontend/src/pages/Organization.vue:244
|
||||||
msgid "Not permitted"
|
msgid "Not permitted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2788,8 +2855,8 @@ msgstr ""
|
|||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:576 frontend/src/pages/Lead.vue:562
|
#: frontend/src/pages/Deal.vue:575 frontend/src/pages/Lead.vue:561
|
||||||
#: frontend/src/pages/MobileDeal.vue:472 frontend/src/pages/MobileLead.vue:375
|
#: frontend/src/pages/MobileDeal.vue:471 frontend/src/pages/MobileLead.vue:374
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2836,10 +2903,10 @@ msgstr ""
|
|||||||
msgid "Old Parent"
|
msgid "Old Parent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Contact.vue:304 frontend/src/pages/Lead.vue:596
|
#: frontend/src/pages/Contact.vue:303 frontend/src/pages/Lead.vue:595
|
||||||
#: frontend/src/pages/MobileContact.vue:275
|
#: frontend/src/pages/MobileContact.vue:274
|
||||||
#: frontend/src/pages/MobileOrganization.vue:269
|
#: frontend/src/pages/MobileOrganization.vue:268
|
||||||
#: frontend/src/pages/Organization.vue:311
|
#: frontend/src/pages/Organization.vue:310
|
||||||
msgid "Only PNG and JPG images are allowed"
|
msgid "Only PNG and JPG images are allowed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2894,13 +2961,13 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
#: frontend/src/components/Layouts/AppSidebar.vue:510
|
#: frontend/src/components/Layouts/AppSidebar.vue:510
|
||||||
#: frontend/src/pages/Contact.vue:628 frontend/src/pages/Lead.vue:241
|
#: frontend/src/pages/Contact.vue:627 frontend/src/pages/Lead.vue:240
|
||||||
#: frontend/src/pages/MobileContact.vue:602
|
#: frontend/src/pages/MobileContact.vue:601
|
||||||
#: frontend/src/pages/MobileLead.vue:106
|
#: frontend/src/pages/MobileLead.vue:105
|
||||||
#: frontend/src/pages/MobileOrganization.vue:488
|
#: frontend/src/pages/MobileOrganization.vue:487
|
||||||
#: frontend/src/pages/MobileOrganization.vue:542
|
#: frontend/src/pages/MobileOrganization.vue:541
|
||||||
#: frontend/src/pages/Organization.vue:527
|
#: frontend/src/pages/Organization.vue:526
|
||||||
#: frontend/src/pages/Organization.vue:581
|
#: frontend/src/pages/Organization.vue:580
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2927,15 +2994,15 @@ msgstr ""
|
|||||||
msgid "Organization logo"
|
msgid "Organization logo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/MobileOrganization.vue:216
|
#: frontend/src/pages/MobileOrganization.vue:215
|
||||||
#: frontend/src/pages/Organization.vue:258
|
#: frontend/src/pages/Organization.vue:257
|
||||||
msgid "Organization updated"
|
msgid "Organization updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of a shortcut in the Frappe CRM Workspace
|
#. Label of a shortcut in the Frappe CRM Workspace
|
||||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||||
#: frontend/src/pages/MobileOrganization.vue:223
|
#: frontend/src/pages/MobileOrganization.vue:222
|
||||||
#: frontend/src/pages/Organization.vue:265
|
#: frontend/src/pages/Organization.vue:264
|
||||||
msgid "Organizations"
|
msgid "Organizations"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3012,8 +3079,8 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||||
#: frontend/src/pages/MobileOrganization.vue:537
|
#: frontend/src/pages/MobileOrganization.vue:536
|
||||||
#: frontend/src/pages/Organization.vue:576
|
#: frontend/src/pages/Organization.vue:575
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3055,11 +3122,11 @@ msgstr ""
|
|||||||
msgid "Please enter a valid URL"
|
msgid "Please enter a valid URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:634 frontend/src/pages/MobileLead.vue:439
|
#: frontend/src/pages/Lead.vue:633 frontend/src/pages/MobileLead.vue:438
|
||||||
msgid "Please select an existing contact"
|
msgid "Please select an existing contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Lead.vue:644 frontend/src/pages/MobileLead.vue:449
|
#: frontend/src/pages/Lead.vue:643 frontend/src/pages/MobileLead.vue:448
|
||||||
msgid "Please select an existing organization"
|
msgid "Please select an existing organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3074,11 +3141,11 @@ msgstr ""
|
|||||||
msgid "Position"
|
msgid "Position"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:206 frontend/src/pages/MobileDeal.vue:143
|
#: frontend/src/pages/Deal.vue:205 frontend/src/pages/MobileDeal.vue:142
|
||||||
msgid "Primary"
|
msgid "Primary"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:695 frontend/src/pages/MobileDeal.vue:590
|
#: frontend/src/pages/Deal.vue:694 frontend/src/pages/MobileDeal.vue:589
|
||||||
msgid "Primary contact set"
|
msgid "Primary contact set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3104,6 +3171,32 @@ msgstr ""
|
|||||||
msgid "Probability"
|
msgid "Probability"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the product_code (Link) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Product"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the product_code (Data) field in DocType 'CRM Product'
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
|
msgid "Product Code"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the product_name (Data) field in DocType 'CRM Product'
|
||||||
|
#. Label of the product_name (Data) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Product Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the products_tab (Tab Break) field in DocType 'CRM Deal'
|
||||||
|
#. Label of the products (Table) field in DocType 'CRM Deal'
|
||||||
|
#. Label of the products_tab (Tab Break) field in DocType 'CRM Lead'
|
||||||
|
#. Label of the products (Table) field in DocType 'CRM Lead'
|
||||||
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
|
msgid "Products"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/Layouts/AppSidebar.vue:497
|
#: frontend/src/components/Layouts/AppSidebar.vue:497
|
||||||
#: frontend/src/components/Settings/Settings.vue:85
|
#: frontend/src/components/Settings/Settings.vue:85
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
@ -3126,6 +3219,11 @@ msgstr ""
|
|||||||
msgid "Public view"
|
msgid "Public view"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the qty (Float) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Quantity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Option for the 'Status' (Select) field in DocType 'CRM Call Log'
|
#. Option for the 'Status' (Select) field in DocType 'CRM Call Log'
|
||||||
#: crm/fcrm/doctype/crm_call_log/crm_call_log.json
|
#: crm/fcrm/doctype/crm_call_log/crm_call_log.json
|
||||||
msgid "Queued"
|
msgid "Queued"
|
||||||
@ -3149,6 +3247,11 @@ msgstr ""
|
|||||||
msgid "Quick entry layout"
|
msgid "Quick entry layout"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the rate (Currency) field in DocType 'CRM Products'
|
||||||
|
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||||
|
msgid "Rate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the read (Check) field in DocType 'CRM Notification'
|
#. Label of the read (Check) field in DocType 'CRM Notification'
|
||||||
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
||||||
msgid "Read"
|
msgid "Read"
|
||||||
@ -3213,7 +3316,7 @@ msgstr ""
|
|||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:631
|
#: frontend/src/pages/Deal.vue:630
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3493,7 +3596,7 @@ msgstr ""
|
|||||||
msgid "Section"
|
msgid "Section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/FieldLayout/Field.vue:263
|
#: frontend/src/components/FieldLayout/Field.vue:322
|
||||||
msgid "Select {0}"
|
msgid "Select {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3547,7 +3650,7 @@ msgstr ""
|
|||||||
msgid "Set an organization"
|
msgid "Set an organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:639 frontend/src/pages/MobileDeal.vue:534
|
#: frontend/src/pages/Deal.vue:638 frontend/src/pages/MobileDeal.vue:533
|
||||||
msgid "Set as Primary Contact"
|
msgid "Set as Primary Contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3670,6 +3773,11 @@ msgstr ""
|
|||||||
msgid "Standard Form Scripts can not be modified, duplicate the Form Script instead."
|
msgid "Standard Form Scripts can not be modified, duplicate the Form Script instead."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the standard_rate (Currency) field in DocType 'CRM Product'
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
|
msgid "Standard Selling Rate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/ViewControls.vue:633
|
#: frontend/src/components/ViewControls.vue:633
|
||||||
msgid "Standard Views"
|
msgid "Standard Views"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3708,10 +3816,10 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
||||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
#: crm/fcrm/doctype/crm_lead_status/crm_lead_status.json
|
#: crm/fcrm/doctype/crm_lead_status/crm_lead_status.json
|
||||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:639
|
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:638
|
||||||
#: frontend/src/pages/MobileContact.vue:613
|
#: frontend/src/pages/MobileContact.vue:612
|
||||||
#: frontend/src/pages/MobileOrganization.vue:499
|
#: frontend/src/pages/MobileOrganization.vue:498
|
||||||
#: frontend/src/pages/Organization.vue:538
|
#: frontend/src/pages/Organization.vue:537
|
||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3772,6 +3880,7 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_global_settings/crm_global_settings.json
|
#: crm/fcrm/doctype/crm_global_settings/crm_global_settings.json
|
||||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
||||||
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
||||||
|
#: crm/fcrm/doctype/crm_product/crm_product.json
|
||||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||||
#: crm/fcrm/doctype/crm_twilio_settings/crm_twilio_settings.json
|
#: crm/fcrm/doctype/crm_twilio_settings/crm_twilio_settings.json
|
||||||
#: crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.json
|
#: crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.json
|
||||||
@ -3793,8 +3902,8 @@ msgstr ""
|
|||||||
msgid "Task"
|
msgid "Task"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:571 frontend/src/pages/Lead.vue:557
|
#: frontend/src/pages/Deal.vue:570 frontend/src/pages/Lead.vue:556
|
||||||
#: frontend/src/pages/MobileDeal.vue:467 frontend/src/pages/MobileLead.vue:370
|
#: frontend/src/pages/MobileDeal.vue:466 frontend/src/pages/MobileLead.vue:369
|
||||||
msgid "Tasks"
|
msgid "Tasks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3939,11 +4048,25 @@ msgstr ""
|
|||||||
msgid "Took a call with John Doe and discussed the new project."
|
msgid "Took a call with John Doe and discussed the new project."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the total (Currency) field in DocType 'CRM Deal'
|
||||||
|
#. Label of the total (Currency) field in DocType 'CRM Lead'
|
||||||
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the total_holidays (Int) field in DocType 'CRM Holiday List'
|
#. Label of the total_holidays (Int) field in DocType 'CRM Holiday List'
|
||||||
#: crm/fcrm/doctype/crm_holiday_list/crm_holiday_list.json
|
#: crm/fcrm/doctype/crm_holiday_list/crm_holiday_list.json
|
||||||
msgid "Total Holidays"
|
msgid "Total Holidays"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Description of the 'Net Total' (Currency) field in DocType 'CRM Deal'
|
||||||
|
#. Description of the 'Net Total' (Currency) field in DocType 'CRM Lead'
|
||||||
|
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||||
|
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||||
|
msgid "Total after discount"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Option for the 'Weekly Off' (Select) field in DocType 'CRM Holiday List'
|
#. Option for the 'Weekly Off' (Select) field in DocType 'CRM Holiday List'
|
||||||
#. Option for the 'Workday' (Select) field in DocType 'CRM Service Day'
|
#. Option for the 'Workday' (Select) field in DocType 'CRM Service Day'
|
||||||
#: crm/fcrm/doctype/crm_holiday_list/crm_holiday_list.json
|
#: crm/fcrm/doctype/crm_holiday_list/crm_holiday_list.json
|
||||||
@ -4029,6 +4152,7 @@ msgstr ""
|
|||||||
#: frontend/src/components/FieldLayoutEditor.vue:26
|
#: frontend/src/components/FieldLayoutEditor.vue:26
|
||||||
#: frontend/src/components/Modals/AddressModal.vue:8
|
#: frontend/src/components/Modals/AddressModal.vue:8
|
||||||
#: frontend/src/components/Modals/CallLogModal.vue:8
|
#: frontend/src/components/Modals/CallLogModal.vue:8
|
||||||
|
#: frontend/src/components/Modals/CreateDocumentModal.vue:8
|
||||||
#: frontend/src/components/Section.vue:21
|
#: frontend/src/components/Section.vue:21
|
||||||
#: frontend/src/components/SidePanelLayoutEditor.vue:19
|
#: frontend/src/components/SidePanelLayoutEditor.vue:19
|
||||||
msgid "Untitled"
|
msgid "Untitled"
|
||||||
@ -4037,9 +4161,9 @@ msgstr ""
|
|||||||
#: frontend/src/components/ColumnSettings.vue:134
|
#: frontend/src/components/ColumnSettings.vue:134
|
||||||
#: frontend/src/components/Modals/AssignmentModal.vue:17
|
#: frontend/src/components/Modals/AssignmentModal.vue:17
|
||||||
#: frontend/src/components/Modals/EmailTemplateModal.vue:9
|
#: frontend/src/components/Modals/EmailTemplateModal.vue:9
|
||||||
#: frontend/src/components/Modals/NoteModal.vue:8
|
#: frontend/src/components/Modals/NoteModal.vue:6
|
||||||
#: frontend/src/components/Modals/TaskModal.vue:8
|
#: frontend/src/components/Modals/TaskModal.vue:6
|
||||||
#: frontend/src/components/Settings/GeneralSettings.vue:112
|
#: frontend/src/components/Settings/GeneralSettings.vue:113
|
||||||
#: frontend/src/components/Settings/ProfileSettings.vue:71
|
#: frontend/src/components/Settings/ProfileSettings.vue:71
|
||||||
#: frontend/src/components/Settings/SettingsPage.vue:31
|
#: frontend/src/components/Settings/SettingsPage.vue:31
|
||||||
#: frontend/src/components/Settings/TelephonySettings.vue:70
|
#: frontend/src/components/Settings/TelephonySettings.vue:70
|
||||||
@ -4134,8 +4258,8 @@ msgstr ""
|
|||||||
msgid "Website"
|
msgid "Website"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/MobileOrganization.vue:308
|
#: frontend/src/pages/MobileOrganization.vue:307
|
||||||
#: frontend/src/pages/Organization.vue:354
|
#: frontend/src/pages/Organization.vue:353
|
||||||
msgid "Website not found"
|
msgid "Website not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4165,8 +4289,8 @@ msgstr ""
|
|||||||
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
||||||
#: frontend/src/components/Layouts/AppSidebar.vue:562
|
#: frontend/src/components/Layouts/AppSidebar.vue:562
|
||||||
#: frontend/src/components/Settings/Settings.vue:124
|
#: frontend/src/components/Settings/Settings.vue:124
|
||||||
#: frontend/src/pages/Deal.vue:586 frontend/src/pages/Lead.vue:572
|
#: frontend/src/pages/Deal.vue:585 frontend/src/pages/Lead.vue:571
|
||||||
#: frontend/src/pages/MobileDeal.vue:482 frontend/src/pages/MobileLead.vue:385
|
#: frontend/src/pages/MobileDeal.vue:481 frontend/src/pages/MobileLead.vue:384
|
||||||
msgid "WhatsApp"
|
msgid "WhatsApp"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4421,8 +4545,8 @@ msgstr ""
|
|||||||
msgid "{0} assigned a {1} {2} to you"
|
msgid "{0} assigned a {1} {2} to you"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Deal.vue:496 frontend/src/pages/Lead.vue:482
|
#: frontend/src/pages/Deal.vue:495 frontend/src/pages/Lead.vue:481
|
||||||
#: frontend/src/pages/MobileDeal.vue:385 frontend/src/pages/MobileLead.vue:288
|
#: frontend/src/pages/MobileDeal.vue:384 frontend/src/pages/MobileLead.vue:287
|
||||||
msgid "{0} is a required field"
|
msgid "{0} is a required field"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4433,3 +4557,23 @@ msgstr ""
|
|||||||
msgid "{0} is an invalid email address"
|
msgid "{0} is an invalid email address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/script.js:233
|
||||||
|
msgid "⚠️ Avoid using \"trigger\" as a field name — it conflicts with the built-in trigger() method."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/script.js:245
|
||||||
|
msgid "⚠️ Method \"{0}\" not found in class."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/script.js:75
|
||||||
|
msgid "⚠️ No class found for doctype: {0}, it is mandatory to have a class for the parent doctype. it can be empty, but it should be present."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/script.js:168
|
||||||
|
msgid "⚠️ No data found for parent field: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/data/script.js:176
|
||||||
|
msgid "⚠️ No row found for idx: {0} in parent field: {1}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<h2>You have been invited to join Frappe CRM</h2>
|
<p>You have been invited to join Frappe CRM</p>
|
||||||
<p>
|
<p>
|
||||||
<a class="btn btn-primary" href="{{ invite_link }}">Accept Invitation</a>
|
<a class="btn btn-primary" href="{{ invite_link }}">Accept Invitation</a>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 3423aa5b5c38d3a1b143ae8ab08cbde7360f9a7c
|
Subproject commit 8b615c0e899d75b99c7d36ec6df97b5d0386b2ca
|
||||||
3
frontend/components.d.ts
vendored
3
frontend/components.d.ts
vendored
@ -150,6 +150,7 @@ declare module 'vue' {
|
|||||||
ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default']
|
ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default']
|
||||||
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
||||||
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
||||||
|
LucideCalendar: typeof import('~icons/lucide/calendar')['default']
|
||||||
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
||||||
MarkAsDoneIcon: typeof import('./src/components/Icons/MarkAsDoneIcon.vue')['default']
|
MarkAsDoneIcon: typeof import('./src/components/Icons/MarkAsDoneIcon.vue')['default']
|
||||||
MaximizeIcon: typeof import('./src/components/Icons/MaximizeIcon.vue')['default']
|
MaximizeIcon: typeof import('./src/components/Icons/MaximizeIcon.vue')['default']
|
||||||
@ -174,6 +175,7 @@ declare module 'vue' {
|
|||||||
OrganizationsIcon: typeof import('./src/components/Icons/OrganizationsIcon.vue')['default']
|
OrganizationsIcon: typeof import('./src/components/Icons/OrganizationsIcon.vue')['default']
|
||||||
OrganizationsListView: typeof import('./src/components/ListViews/OrganizationsListView.vue')['default']
|
OrganizationsListView: typeof import('./src/components/ListViews/OrganizationsListView.vue')['default']
|
||||||
OutboundCallIcon: typeof import('./src/components/Icons/OutboundCallIcon.vue')['default']
|
OutboundCallIcon: typeof import('./src/components/Icons/OutboundCallIcon.vue')['default']
|
||||||
|
Password: typeof import('./src/components/Controls/Password.vue')['default']
|
||||||
PauseIcon: typeof import('./src/components/Icons/PauseIcon.vue')['default']
|
PauseIcon: typeof import('./src/components/Icons/PauseIcon.vue')['default']
|
||||||
PhoneIcon: typeof import('./src/components/Icons/PhoneIcon.vue')['default']
|
PhoneIcon: typeof import('./src/components/Icons/PhoneIcon.vue')['default']
|
||||||
PinIcon: typeof import('./src/components/Icons/PinIcon.vue')['default']
|
PinIcon: typeof import('./src/components/Icons/PinIcon.vue')['default']
|
||||||
@ -208,6 +210,7 @@ declare module 'vue' {
|
|||||||
SmileIcon: typeof import('./src/components/Icons/SmileIcon.vue')['default']
|
SmileIcon: typeof import('./src/components/Icons/SmileIcon.vue')['default']
|
||||||
SortBy: typeof import('./src/components/SortBy.vue')['default']
|
SortBy: typeof import('./src/components/SortBy.vue')['default']
|
||||||
SortIcon: typeof import('./src/components/Icons/SortIcon.vue')['default']
|
SortIcon: typeof import('./src/components/Icons/SortIcon.vue')['default']
|
||||||
|
SquareAsterisk: typeof import('./src/components/Icons/SquareAsterisk.vue')['default']
|
||||||
StepsIcon: typeof import('./src/components/Icons/StepsIcon.vue')['default']
|
StepsIcon: typeof import('./src/components/Icons/StepsIcon.vue')['default']
|
||||||
SuccessIcon: typeof import('./src/components/Icons/SuccessIcon.vue')['default']
|
SuccessIcon: typeof import('./src/components/Icons/SuccessIcon.vue')['default']
|
||||||
TableMultiselectInput: typeof import('./src/components/Controls/TableMultiselectInput.vue')['default']
|
TableMultiselectInput: typeof import('./src/components/Controls/TableMultiselectInput.vue')['default']
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
"name": "crm-ui",
|
"name": "crm-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build --base=/assets/crm/frontend/ && yarn copy-html-entry",
|
"build": "vite build --base=/assets/crm/frontend/ && yarn copy-html-entry",
|
||||||
@ -9,9 +10,10 @@
|
|||||||
"serve": "vite preview"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tiptap/extension-paragraph": "^2.12.0",
|
||||||
"@twilio/voice-sdk": "^2.10.2",
|
"@twilio/voice-sdk": "^2.10.2",
|
||||||
"@vueuse/integrations": "^10.3.0",
|
"@vueuse/integrations": "^10.3.0",
|
||||||
"frappe-ui": "^0.1.121",
|
"frappe-ui": "^0.1.145",
|
||||||
"gemoji": "^8.1.0",
|
"gemoji": "^8.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mime": "^4.0.1",
|
"mime": "^4.0.1",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<Layout v-if="session().isLoggedIn">
|
<FrappeUIProvider>
|
||||||
<router-view />
|
<Layout v-if="session().isLoggedIn">
|
||||||
</Layout>
|
<router-view />
|
||||||
<Dialogs />
|
</Layout>
|
||||||
<Toasts />
|
<Dialogs />
|
||||||
|
</FrappeUIProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Dialogs } from '@/utils/dialogs'
|
import { Dialogs } from '@/utils/dialogs'
|
||||||
import { sessionStore as session } from '@/stores/session'
|
import { sessionStore as session } from '@/stores/session'
|
||||||
import { setTheme } from '@/stores/theme'
|
import { setTheme } from '@/stores/theme'
|
||||||
import { Toasts, setConfig } from 'frappe-ui'
|
import { FrappeUIProvider, setConfig } from 'frappe-ui'
|
||||||
import { computed, defineAsyncComponent, onMounted } from 'vue'
|
import { computed, defineAsyncComponent, onMounted } from 'vue'
|
||||||
|
|
||||||
const MobileLayout = defineAsyncComponent(
|
const MobileLayout = defineAsyncComponent(
|
||||||
|
|||||||
@ -216,6 +216,13 @@
|
|||||||
:options="field.options"
|
:options="field.options"
|
||||||
@change="(e) => fieldChange(e.target.value, field, row)"
|
@change="(e) => fieldChange(e.target.value, field, row)"
|
||||||
/>
|
/>
|
||||||
|
<Password
|
||||||
|
v-else-if="field.fieldtype === 'Password'"
|
||||||
|
variant="outline"
|
||||||
|
:value="row[field.fieldname]"
|
||||||
|
:disabled="Boolean(field.read_only)"
|
||||||
|
@change="fieldChange($event.target.value, field, row)"
|
||||||
|
/>
|
||||||
<FormattedInput
|
<FormattedInput
|
||||||
v-else-if="field.fieldtype === 'Int'"
|
v-else-if="field.fieldtype === 'Int'"
|
||||||
class="[&_input]:text-right"
|
class="[&_input]:text-right"
|
||||||
@ -325,6 +332,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Password from '@/components/Controls/Password.vue'
|
||||||
import FormattedInput from '@/components/Controls/FormattedInput.vue'
|
import FormattedInput from '@/components/Controls/FormattedInput.vue'
|
||||||
import GridFieldsEditorModal from '@/components/Controls/GridFieldsEditorModal.vue'
|
import GridFieldsEditorModal from '@/components/Controls/GridFieldsEditorModal.vue'
|
||||||
import GridRowFieldsModal from '@/components/Controls/GridRowFieldsModal.vue'
|
import GridRowFieldsModal from '@/components/Controls/GridRowFieldsModal.vue'
|
||||||
|
|||||||
@ -58,6 +58,21 @@
|
|||||||
class="p-1.5 max-h-[12rem] overflow-y-auto"
|
class="p-1.5 max-h-[12rem] overflow-y-auto"
|
||||||
static
|
static
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-if="!options.length"
|
||||||
|
class="flex gap-2 rounded px-2 py-1 text-base text-ink-gray-5"
|
||||||
|
>
|
||||||
|
<FeatherIcon
|
||||||
|
v-if="fetchContacts"
|
||||||
|
name="search"
|
||||||
|
class="h-4"
|
||||||
|
/>
|
||||||
|
{{
|
||||||
|
fetchContacts
|
||||||
|
? __('No results found')
|
||||||
|
: __('Type an email address to add')
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
<ComboboxOption
|
<ComboboxOption
|
||||||
v-for="option in options"
|
v-for="option in options"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
@ -137,6 +152,10 @@ const props = defineProps({
|
|||||||
type: Function,
|
type: Function,
|
||||||
default: (value) => `${value} is an Invalid value`,
|
default: (value) => `${value} is an Invalid value`,
|
||||||
},
|
},
|
||||||
|
fetchContacts: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const values = defineModel()
|
const values = defineModel()
|
||||||
@ -191,17 +210,19 @@ const filterOptions = createResource({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
let searchedContacts = filterOptions.data || []
|
let searchedContacts = props.fetchContacts ? filterOptions.data : []
|
||||||
if (!searchedContacts.length && query.value) {
|
if (!searchedContacts?.length && query.value) {
|
||||||
searchedContacts.push({
|
searchedContacts.push({
|
||||||
label: query.value,
|
label: query.value,
|
||||||
value: query.value,
|
value: query.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return searchedContacts
|
return searchedContacts || []
|
||||||
})
|
})
|
||||||
|
|
||||||
function reload(val) {
|
function reload(val) {
|
||||||
|
if (!props.fetchContacts) return
|
||||||
|
|
||||||
filterOptions.update({
|
filterOptions.update({
|
||||||
params: { txt: val },
|
params: { txt: val },
|
||||||
})
|
})
|
||||||
|
|||||||
32
frontend/src/components/Controls/Password.vue
Normal file
32
frontend/src/components/Controls/Password.vue
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<template>
|
||||||
|
<FormControl
|
||||||
|
:type="show ? 'text' : 'password'"
|
||||||
|
:value="modelValue || value"
|
||||||
|
v-bind="$attrs"
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<Button v-show="showEye" class="!h-4" @click="show = !show">
|
||||||
|
<FeatherIcon :name="show ? 'eye-off' : 'eye'" class="h-3" />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</FormControl>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { FormControl } from 'frappe-ui'
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const show = ref(false)
|
||||||
|
const showEye = computed(() => {
|
||||||
|
let v = props.modelValue || props.value
|
||||||
|
return !v?.includes('*')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@ -136,7 +136,6 @@
|
|||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
v-else-if="field.fieldtype === 'Datetime'"
|
v-else-if="field.fieldtype === 'Datetime'"
|
||||||
:value="data[field.fieldname]"
|
:value="data[field.fieldname]"
|
||||||
icon-left=""
|
|
||||||
:formatter="(date) => getFormat(date, '', true, true)"
|
:formatter="(date) => getFormat(date, '', true, true)"
|
||||||
:placeholder="getPlaceholder(field)"
|
:placeholder="getPlaceholder(field)"
|
||||||
input-class="border-none"
|
input-class="border-none"
|
||||||
@ -144,7 +143,6 @@
|
|||||||
/>
|
/>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
v-else-if="field.fieldtype === 'Date'"
|
v-else-if="field.fieldtype === 'Date'"
|
||||||
icon-left=""
|
|
||||||
:value="data[field.fieldname]"
|
:value="data[field.fieldname]"
|
||||||
:formatter="(date) => getFormat(date, '', true)"
|
:formatter="(date) => getFormat(date, '', true)"
|
||||||
:placeholder="getPlaceholder(field)"
|
:placeholder="getPlaceholder(field)"
|
||||||
@ -161,11 +159,18 @@
|
|||||||
:description="field.description"
|
:description="field.description"
|
||||||
@change="fieldChange($event.target.value, field)"
|
@change="fieldChange($event.target.value, field)"
|
||||||
/>
|
/>
|
||||||
<FormattedInput
|
<Password
|
||||||
v-else-if="['Int'].includes(field.fieldtype)"
|
v-else-if="field.fieldtype === 'Password'"
|
||||||
type="number"
|
|
||||||
:placeholder="getPlaceholder(field)"
|
|
||||||
:value="data[field.fieldname]"
|
:value="data[field.fieldname]"
|
||||||
|
:placeholder="getPlaceholder(field)"
|
||||||
|
:description="field.description"
|
||||||
|
@change="fieldChange($event.target.value, field)"
|
||||||
|
/>
|
||||||
|
<FormattedInput
|
||||||
|
v-else-if="field.fieldtype === 'Int'"
|
||||||
|
type="text"
|
||||||
|
:placeholder="getPlaceholder(field)"
|
||||||
|
:value="data[field.fieldname] || '0'"
|
||||||
:disabled="Boolean(field.read_only)"
|
:disabled="Boolean(field.read_only)"
|
||||||
:description="field.description"
|
:description="field.description"
|
||||||
@change="fieldChange($event.target.value, field)"
|
@change="fieldChange($event.target.value, field)"
|
||||||
@ -209,6 +214,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Password from '@/components/Controls/Password.vue'
|
||||||
import FormattedInput from '@/components/Controls/FormattedInput.vue'
|
import FormattedInput from '@/components/Controls/FormattedInput.vue'
|
||||||
import EditIcon from '@/components/Icons/EditIcon.vue'
|
import EditIcon from '@/components/Icons/EditIcon.vue'
|
||||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||||
|
|||||||
@ -104,7 +104,7 @@
|
|||||||
import FilesUploaderArea from '@/components/FilesUploader/FilesUploaderArea.vue'
|
import FilesUploaderArea from '@/components/FilesUploader/FilesUploaderArea.vue'
|
||||||
import FilesUploadHandler from './filesUploaderHandler'
|
import FilesUploadHandler from './filesUploaderHandler'
|
||||||
import { isMobileView } from '@/composables/settings'
|
import { isMobileView } from '@/composables/settings'
|
||||||
import { createToast } from '@/utils'
|
import { toast } from 'frappe-ui'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -165,12 +165,7 @@ function attachFiles() {
|
|||||||
function uploadViaWebLink() {
|
function uploadViaWebLink() {
|
||||||
let fileUrl = filesUploaderArea.value.webLink
|
let fileUrl = filesUploaderArea.value.webLink
|
||||||
if (!fileUrl) {
|
if (!fileUrl) {
|
||||||
createToast({
|
toast.error(__('Please enter a valid URL'))
|
||||||
title: __('Error'),
|
|
||||||
title: __('Please enter a valid URL'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fileUrl = decodeURI(fileUrl)
|
fileUrl = decodeURI(fileUrl)
|
||||||
|
|||||||
@ -126,8 +126,13 @@
|
|||||||
import FileTextIcon from '@/components/Icons/FileTextIcon.vue'
|
import FileTextIcon from '@/components/Icons/FileTextIcon.vue'
|
||||||
import FileAudioIcon from '@/components/Icons/FileAudioIcon.vue'
|
import FileAudioIcon from '@/components/Icons/FileAudioIcon.vue'
|
||||||
import FileVideoIcon from '@/components/Icons/FileVideoIcon.vue'
|
import FileVideoIcon from '@/components/Icons/FileVideoIcon.vue'
|
||||||
import { createToast, formatDate, convertSize } from '@/utils'
|
import { formatDate, convertSize } from '@/utils'
|
||||||
import { FormControl, CircularProgressBar, createResource } from 'frappe-ui'
|
import {
|
||||||
|
FormControl,
|
||||||
|
CircularProgressBar,
|
||||||
|
createResource,
|
||||||
|
toast,
|
||||||
|
} from 'frappe-ui'
|
||||||
import { ref, onMounted, watch, onUnmounted } from 'vue'
|
import { ref, onMounted, watch, onUnmounted } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -324,24 +329,18 @@ function checkRestrictions(file) {
|
|||||||
|
|
||||||
if (!isCorrectType) {
|
if (!isCorrectType) {
|
||||||
console.warn('File skipped because of invalid file type', file)
|
console.warn('File skipped because of invalid file type', file)
|
||||||
createToast({
|
toast.warning(
|
||||||
title: __('File "{0}" was skipped because of invalid file type', [
|
__('File "{0}" was skipped because of invalid file type', [file.name]),
|
||||||
file.name,
|
)
|
||||||
]),
|
|
||||||
icon: 'alert-circle',
|
|
||||||
iconClasses: 'text-orange-600',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (!validFileSize) {
|
if (!validFileSize) {
|
||||||
console.warn('File skipped because of invalid file size', file.size, file)
|
console.warn('File skipped because of invalid file size', file.size, file)
|
||||||
createToast({
|
toast.warning(
|
||||||
title: __('File "{0}" was skipped because size exceeds {1} MB', [
|
__('File "{0}" was skipped because size exceeds {1} MB', [
|
||||||
file.name,
|
file.name,
|
||||||
maxFileSize / (1024 * 1024),
|
maxFileSize / (1024 * 1024),
|
||||||
]),
|
]),
|
||||||
icon: 'alert-circle',
|
)
|
||||||
iconClasses: 'text-orange-600',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return isCorrectType && validFileSize
|
return isCorrectType && validFileSize
|
||||||
@ -363,11 +362,7 @@ function showMaxFilesNumberWarning(file, maxNumberOfFiles) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
createToast({
|
toast.warning(message)
|
||||||
title: message,
|
|
||||||
icon: 'alert-circle',
|
|
||||||
iconClasses: 'text-orange-600',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFile(name) {
|
function removeFile(name) {
|
||||||
|
|||||||
19
frontend/src/components/Icons/SquareAsterisk.vue
Normal file
19
frontend/src/components/Icons/SquareAsterisk.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-square-asterisk-icon lucide-square-asterisk"
|
||||||
|
>
|
||||||
|
<rect width="18" height="18" x="3" y="3" rx="2" />
|
||||||
|
<path d="M12 8v8" />
|
||||||
|
<path d="m8.5 14 7-4" />
|
||||||
|
<path d="m8.5 10 7 4" />
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
@ -150,6 +150,7 @@ import Section from '@/components/Section.vue'
|
|||||||
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
||||||
import PinIcon from '@/components/Icons/PinIcon.vue'
|
import PinIcon from '@/components/Icons/PinIcon.vue'
|
||||||
import UserDropdown from '@/components/UserDropdown.vue'
|
import UserDropdown from '@/components/UserDropdown.vue'
|
||||||
|
import SquareAsterisk from '@/components/Icons/SquareAsterisk.vue'
|
||||||
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
||||||
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
||||||
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
|
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
|
||||||
@ -168,6 +169,8 @@ import {
|
|||||||
unreadNotificationsCount,
|
unreadNotificationsCount,
|
||||||
notificationsStore,
|
notificationsStore,
|
||||||
} from '@/stores/notifications'
|
} from '@/stores/notifications'
|
||||||
|
import { usersStore } from '@/stores/users'
|
||||||
|
import { sessionStore } from '@/stores/session'
|
||||||
import { showSettings, activeSettingsPage } from '@/composables/settings'
|
import { showSettings, activeSettingsPage } from '@/composables/settings'
|
||||||
import { FeatherIcon, call } from 'frappe-ui'
|
import { FeatherIcon, call } from 'frappe-ui'
|
||||||
import {
|
import {
|
||||||
@ -299,16 +302,18 @@ function getIcon(routeName, icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// onboarding
|
// onboarding
|
||||||
|
const { user } = sessionStore()
|
||||||
|
const { users, isManager } = usersStore()
|
||||||
const { isOnboardingStepsCompleted, setUp } = useOnboarding('frappecrm')
|
const { isOnboardingStepsCompleted, setUp } = useOnboarding('frappecrm')
|
||||||
|
|
||||||
async function getFirstLead() {
|
async function getFirstLead() {
|
||||||
let firstLead = localStorage.getItem('firstLead')
|
let firstLead = localStorage.getItem('firstLead' + user)
|
||||||
if (firstLead) return firstLead
|
if (firstLead) return firstLead
|
||||||
return await call('crm.api.onboarding.get_first_lead')
|
return await call('crm.api.onboarding.get_first_lead')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFirstDeal() {
|
async function getFirstDeal() {
|
||||||
let firstDeal = localStorage.getItem('firstDeal')
|
let firstDeal = localStorage.getItem('firstDeal' + user)
|
||||||
if (firstDeal) return firstDeal
|
if (firstDeal) return firstDeal
|
||||||
return await call('crm.api.onboarding.get_first_deal')
|
return await call('crm.api.onboarding.get_first_deal')
|
||||||
}
|
}
|
||||||
@ -317,6 +322,17 @@ const showIntermediateModal = ref(false)
|
|||||||
const currentStep = ref({})
|
const currentStep = ref({})
|
||||||
|
|
||||||
const steps = reactive([
|
const steps = reactive([
|
||||||
|
{
|
||||||
|
name: 'setup_your_password',
|
||||||
|
title: __('Setup your password'),
|
||||||
|
icon: markRaw(SquareAsterisk),
|
||||||
|
completed: false,
|
||||||
|
onClick: () => {
|
||||||
|
minimize.value = true
|
||||||
|
showSettings.value = true
|
||||||
|
activeSettingsPage.value = 'Profile'
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'create_first_lead',
|
name: 'create_first_lead',
|
||||||
title: __('Create your first lead'),
|
title: __('Create your first lead'),
|
||||||
@ -337,12 +353,14 @@ const steps = reactive([
|
|||||||
showSettings.value = true
|
showSettings.value = true
|
||||||
activeSettingsPage.value = 'Invite Members'
|
activeSettingsPage.value = 'Invite Members'
|
||||||
},
|
},
|
||||||
|
condition: () => isManager(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'convert_lead_to_deal',
|
name: 'convert_lead_to_deal',
|
||||||
title: __('Convert lead to deal'),
|
title: __('Convert lead to deal'),
|
||||||
icon: markRaw(ConvertIcon),
|
icon: markRaw(ConvertIcon),
|
||||||
completed: false,
|
completed: false,
|
||||||
|
dependsOn: 'create_first_lead',
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
minimize.value = true
|
minimize.value = true
|
||||||
|
|
||||||
@ -410,6 +428,7 @@ const steps = reactive([
|
|||||||
title: __('Add your first comment'),
|
title: __('Add your first comment'),
|
||||||
icon: markRaw(CommentIcon),
|
icon: markRaw(CommentIcon),
|
||||||
completed: false,
|
completed: false,
|
||||||
|
dependsOn: 'create_first_lead',
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
minimize.value = true
|
minimize.value = true
|
||||||
let deal = await getFirstDeal()
|
let deal = await getFirstDeal()
|
||||||
@ -430,6 +449,7 @@ const steps = reactive([
|
|||||||
title: __('Send email'),
|
title: __('Send email'),
|
||||||
icon: markRaw(EmailIcon),
|
icon: markRaw(EmailIcon),
|
||||||
completed: false,
|
completed: false,
|
||||||
|
dependsOn: 'create_first_lead',
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
minimize.value = true
|
minimize.value = true
|
||||||
let deal = await getFirstDeal()
|
let deal = await getFirstDeal()
|
||||||
@ -450,6 +470,7 @@ const steps = reactive([
|
|||||||
title: __('Change deal status'),
|
title: __('Change deal status'),
|
||||||
icon: markRaw(StepsIcon),
|
icon: markRaw(StepsIcon),
|
||||||
completed: false,
|
completed: false,
|
||||||
|
dependsOn: 'convert_lead_to_deal',
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
minimize.value = true
|
minimize.value = true
|
||||||
|
|
||||||
@ -478,7 +499,18 @@ const steps = reactive([
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
onMounted(() => setUp(steps))
|
onMounted(async () => {
|
||||||
|
await users.promise
|
||||||
|
|
||||||
|
const filteredSteps = steps.filter((step) => {
|
||||||
|
if (step.condition) {
|
||||||
|
return step.condition()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
setUp(filteredSteps)
|
||||||
|
})
|
||||||
|
|
||||||
// help center
|
// help center
|
||||||
const articles = ref([
|
const articles = ref([
|
||||||
@ -517,9 +549,7 @@ const articles = ref([
|
|||||||
{
|
{
|
||||||
title: __('Capturing leads'),
|
title: __('Capturing leads'),
|
||||||
opened: false,
|
opened: false,
|
||||||
subArticles: [
|
subArticles: [{ name: 'web-form', title: __('Web form') }],
|
||||||
{ name: 'web-form', title: __('Web form') },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: __('Views'),
|
title: __('Views'),
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
||||||
import AssignmentModal from '@/components/Modals/AssignmentModal.vue'
|
import AssignmentModal from '@/components/Modals/AssignmentModal.vue'
|
||||||
import { setupListCustomizations, createToast } from '@/utils'
|
import { setupListCustomizations } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { capture } from '@/telemetry'
|
import { capture } from '@/telemetry'
|
||||||
import { call } from 'frappe-ui'
|
import { call, toast } from 'frappe-ui'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
@ -75,11 +75,7 @@ function convertToDeal(selections, unselectAll) {
|
|||||||
call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
||||||
lead: name,
|
lead: name,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
createToast({
|
toast.success(__('Converted successfully'))
|
||||||
title: __('Converted successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
list.value.reload()
|
list.value.reload()
|
||||||
unselectAll()
|
unselectAll()
|
||||||
close()
|
close()
|
||||||
@ -110,11 +106,7 @@ function deleteValues(selections, unselectAll) {
|
|||||||
items: JSON.stringify(Array.from(selections)),
|
items: JSON.stringify(Array.from(selections)),
|
||||||
doctype: props.doctype,
|
doctype: props.doctype,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
createToast({
|
toast.success(__('Deleted successfully'))
|
||||||
title: __('Deleted successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
unselectAll()
|
unselectAll()
|
||||||
list.value.reload()
|
list.value.reload()
|
||||||
close()
|
close()
|
||||||
@ -154,11 +146,7 @@ function clearAssignemnts(selections, unselectAll) {
|
|||||||
names: JSON.stringify(Array.from(selections)),
|
names: JSON.stringify(Array.from(selections)),
|
||||||
ignore_permissions: true,
|
ignore_permissions: true,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
createToast({
|
toast.success(__('Assignment cleared successfully'))
|
||||||
title: __('Assignment cleared successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
reload(unselectAll)
|
reload(unselectAll)
|
||||||
close()
|
close()
|
||||||
})
|
})
|
||||||
@ -215,7 +203,8 @@ function bulkActions(selections, unselectAll) {
|
|||||||
selections,
|
selections,
|
||||||
unselectAll,
|
unselectAll,
|
||||||
call,
|
call,
|
||||||
createToast,
|
createToast: toast.create,
|
||||||
|
toast,
|
||||||
$dialog,
|
$dialog,
|
||||||
router,
|
router,
|
||||||
}),
|
}),
|
||||||
@ -235,7 +224,8 @@ onMounted(async () => {
|
|||||||
let customization = await setupListCustomizations(list.value.data, {
|
let customization = await setupListCustomizations(list.value.data, {
|
||||||
list: list.value,
|
list: list.value,
|
||||||
call,
|
call,
|
||||||
createToast,
|
createToast: toast.create,
|
||||||
|
toast,
|
||||||
$dialog,
|
$dialog,
|
||||||
$socket,
|
$socket,
|
||||||
router,
|
router,
|
||||||
|
|||||||
@ -46,6 +46,7 @@ import EditIcon from '@/components/Icons/EditIcon.vue'
|
|||||||
import FieldLayout from '@/components/FieldLayout/FieldLayout.vue'
|
import FieldLayout from '@/components/FieldLayout/FieldLayout.vue'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
|
import { sessionStore } from '@/stores/session'
|
||||||
import { isMobileView } from '@/composables/settings'
|
import { isMobileView } from '@/composables/settings'
|
||||||
import { capture } from '@/telemetry'
|
import { capture } from '@/telemetry'
|
||||||
import { createResource } from 'frappe-ui'
|
import { createResource } from 'frappe-ui'
|
||||||
@ -57,6 +58,7 @@ const props = defineProps({
|
|||||||
defaults: Object,
|
defaults: Object,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { user } = sessionStore()
|
||||||
const { getUser, isManager } = usersStore()
|
const { getUser, isManager } = usersStore()
|
||||||
const { getLeadStatus, statusOptions } = statusesStore()
|
const { getLeadStatus, statusOptions } = statusesStore()
|
||||||
const { updateOnboardingStep } = useOnboarding('frappecrm')
|
const { updateOnboardingStep } = useOnboarding('frappecrm')
|
||||||
@ -169,7 +171,7 @@ function createNewLead() {
|
|||||||
show.value = false
|
show.value = false
|
||||||
router.push({ name: 'Lead', params: { leadId: data.name } })
|
router.push({ name: 'Lead', params: { leadId: data.name } })
|
||||||
updateOnboardingStep('create_first_lead', true, false, () => {
|
updateOnboardingStep('create_first_lead', true, false, () => {
|
||||||
localStorage.setItem('firstLead', data.name)
|
localStorage.setItem('firstLead' + user, data.name)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
|
|||||||
@ -93,9 +93,8 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, reactive, ref } from 'vue'
|
import { computed, reactive, ref } from 'vue'
|
||||||
import { createResource } from 'frappe-ui'
|
import { createResource, toast } from 'frappe-ui'
|
||||||
import CircleAlert from '~icons/lucide/circle-alert'
|
import CircleAlert from '~icons/lucide/circle-alert'
|
||||||
import { createToast } from '@/utils'
|
|
||||||
import {
|
import {
|
||||||
customProviderFields,
|
customProviderFields,
|
||||||
popularProviderFields,
|
popularProviderFields,
|
||||||
@ -139,11 +138,7 @@ const addEmailRes = createResource({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
createToast({
|
toast.success(__('Email account created successfully'))
|
||||||
title: __('Email account created successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-green-600',
|
|
||||||
})
|
|
||||||
emit('update:step', 'email-list')
|
emit('update:step', 'email-list')
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
|
|||||||
@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, reactive, ref } from 'vue'
|
import { computed, reactive, ref } from 'vue'
|
||||||
import { call } from 'frappe-ui'
|
import { call, toast } from 'frappe-ui'
|
||||||
import EmailProviderIcon from './EmailProviderIcon.vue'
|
import EmailProviderIcon from './EmailProviderIcon.vue'
|
||||||
import {
|
import {
|
||||||
emailIcon,
|
emailIcon,
|
||||||
@ -92,7 +92,6 @@ import {
|
|||||||
validateInputs,
|
validateInputs,
|
||||||
incomingOutgoingFields,
|
incomingOutgoingFields,
|
||||||
} from './emailConfig'
|
} from './emailConfig'
|
||||||
import { createToast } from '@/utils'
|
|
||||||
import CircleAlert from '~icons/lucide/circle-alert'
|
import CircleAlert from '~icons/lucide/circle-alert'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -148,11 +147,7 @@ async function updateAccount() {
|
|||||||
const values = updatedEmailAccount
|
const values = updatedEmailAccount
|
||||||
|
|
||||||
if (!nameChanged && !otherFieldsChanged) {
|
if (!nameChanged && !otherFieldsChanged) {
|
||||||
createToast({
|
toast.info(__('No changes made'))
|
||||||
title: __('No changes made'),
|
|
||||||
icon: 'info',
|
|
||||||
iconClasses: 'text-blue-600',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,11 +205,7 @@ async function callSetValue(values) {
|
|||||||
|
|
||||||
function succesHandler() {
|
function succesHandler() {
|
||||||
emit('update:step', 'email-list')
|
emit('update:step', 'email-list')
|
||||||
createToast({
|
toast.success(__('Email account updated successfully'))
|
||||||
title: __('Email account updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-green-600',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorHandler() {
|
function errorHandler() {
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
:error-message="
|
:error-message="
|
||||||
(value) => __('{0} is an invalid email address', [value])
|
(value) => __('{0} is an invalid email address', [value])
|
||||||
"
|
"
|
||||||
|
:fetchContacts="false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<FormControl
|
<FormControl
|
||||||
@ -127,10 +128,17 @@ const inviteByEmail = createResource({
|
|||||||
role: role.value,
|
role: role.value,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess(data) {
|
||||||
|
if (data?.existing_invites?.length) {
|
||||||
|
error.value = __('Agent with email {0} already exists', [
|
||||||
|
data.existing_invites.join(', '),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
role.value = 'Sales User'
|
||||||
|
error.value = null
|
||||||
|
}
|
||||||
|
|
||||||
invitees.value = []
|
invitees.value = []
|
||||||
role.value = 'Sales User'
|
|
||||||
error.value = null
|
|
||||||
pendingInvitations.reload()
|
pendingInvitations.reload()
|
||||||
updateOnboardingStep('invite_your_team')
|
updateOnboardingStep('invite_your_team')
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,7 +57,7 @@
|
|||||||
v-model="profile.email"
|
v-model="profile.email"
|
||||||
:disabled="true"
|
:disabled="true"
|
||||||
/>
|
/>
|
||||||
<FormControl
|
<Password
|
||||||
class="w-full"
|
class="w-full"
|
||||||
label="Set new password"
|
label="Set new password"
|
||||||
v-model="profile.new_password"
|
v-model="profile.new_password"
|
||||||
@ -77,13 +77,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Password from '@/components/Controls/Password.vue'
|
||||||
import ProfileImageEditor from '@/components/Settings/ProfileImageEditor.vue'
|
import ProfileImageEditor from '@/components/Settings/ProfileImageEditor.vue'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { createToast } from '@/utils'
|
import { Dialog, Avatar, createResource, ErrorMessage, toast } from 'frappe-ui'
|
||||||
import { Dialog, Avatar, createResource, ErrorMessage } from 'frappe-ui'
|
import { useOnboarding } from 'frappe-ui/frappe'
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
|
|
||||||
const { getUser, users } = usersStore()
|
const { getUser, users } = usersStore()
|
||||||
|
const { updateOnboardingStep } = useOnboarding('frappecrm')
|
||||||
|
|
||||||
const user = computed(() => getUser() || {})
|
const user = computed(() => getUser() || {})
|
||||||
|
|
||||||
@ -95,6 +97,13 @@ const error = ref('')
|
|||||||
|
|
||||||
function updateUser() {
|
function updateUser() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
|
let passwordUpdated = false
|
||||||
|
|
||||||
|
if (profile.value.new_password) {
|
||||||
|
passwordUpdated = true
|
||||||
|
}
|
||||||
|
|
||||||
const fieldname = {
|
const fieldname = {
|
||||||
first_name: profile.value.first_name,
|
first_name: profile.value.first_name,
|
||||||
last_name: profile.value.last_name,
|
last_name: profile.value.last_name,
|
||||||
@ -111,15 +120,14 @@ function updateUser() {
|
|||||||
},
|
},
|
||||||
auto: true,
|
auto: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
if (passwordUpdated) {
|
||||||
|
updateOnboardingStep('setup_your_password')
|
||||||
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
error.value = ''
|
error.value = ''
|
||||||
profile.value.new_password = ''
|
profile.value.new_password = ''
|
||||||
showEditProfilePhotoModal.value = false
|
showEditProfilePhotoModal.value = false
|
||||||
createToast({
|
toast.success(__('Profile updated successfully'))
|
||||||
title: __('Profile updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
users.reload()
|
users.reload()
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
|
|||||||
@ -42,9 +42,10 @@ import {
|
|||||||
createResource,
|
createResource,
|
||||||
Spinner,
|
Spinner,
|
||||||
Badge,
|
Badge,
|
||||||
|
toast,
|
||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { createToast, getRandom } from '@/utils'
|
import { getRandom } from '@/utils'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -79,20 +80,10 @@ const data = createDocumentResource({
|
|||||||
auto: true,
|
auto: true,
|
||||||
setValue: {
|
setValue: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
createToast({
|
toast.success(__(props.successMessage))
|
||||||
title: __('Success'),
|
|
||||||
text: __(props.successMessage),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(err.message + ': ' + err.messages[0])
|
||||||
title: __('Error'),
|
|
||||||
text: err.message + ': ' + err.messages[0],
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -87,7 +87,8 @@ import {
|
|||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { defaultCallingMedium } from '@/composables/settings'
|
import { defaultCallingMedium } from '@/composables/settings'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { createToast, getRandom } from '@/utils'
|
import { toast } from 'frappe-ui'
|
||||||
|
import { getRandom } from '@/utils'
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
|
|
||||||
const { isManager, isAgent } = usersStore()
|
const { isManager, isAgent } = usersStore()
|
||||||
@ -119,20 +120,10 @@ const twilio = createDocumentResource({
|
|||||||
auto: true,
|
auto: true,
|
||||||
setValue: {
|
setValue: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
createToast({
|
toast.success(__('Twilio settings updated successfully'))
|
||||||
title: __('Success'),
|
|
||||||
text: __('Twilio settings updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(err.message + ': ' + err.messages[0])
|
||||||
title: __('Error'),
|
|
||||||
text: err.message + ': ' + err.messages[0],
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -144,20 +135,10 @@ const exotel = createDocumentResource({
|
|||||||
auto: true,
|
auto: true,
|
||||||
setValue: {
|
setValue: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
createToast({
|
toast.success(__('Exotel settings updated successfully'))
|
||||||
title: __('Success'),
|
|
||||||
text: __('Exotel settings updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(err.message + ': ' + err.messages[0])
|
||||||
title: __('Error'),
|
|
||||||
text: err.message + ': ' + err.messages[0],
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -294,12 +275,7 @@ async function updateMedium() {
|
|||||||
})
|
})
|
||||||
mediumChanged.value = false
|
mediumChanged.value = false
|
||||||
error.value = ''
|
error.value = ''
|
||||||
createToast({
|
toast.success(__('Default calling medium updated successfully'))
|
||||||
title: __('Success'),
|
|
||||||
text: __('Default calling medium updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const error = ref('')
|
const error = ref('')
|
||||||
|
|||||||
@ -275,11 +275,20 @@
|
|||||||
"
|
"
|
||||||
:disabled="Boolean(field.read_only)"
|
:disabled="Boolean(field.read_only)"
|
||||||
/>
|
/>
|
||||||
|
<Password
|
||||||
|
v-else-if="field.fieldtype === 'Password'"
|
||||||
|
class="form-control"
|
||||||
|
:value="document.doc[field.fieldname]"
|
||||||
|
:placeholder="field.placeholder"
|
||||||
|
:debounce="500"
|
||||||
|
@change.stop="fieldChange($event.target.value, field)"
|
||||||
|
:disabled="Boolean(field.read_only)"
|
||||||
|
/>
|
||||||
<FormattedInput
|
<FormattedInput
|
||||||
v-else-if="field.fieldtype === 'Int'"
|
v-else-if="field.fieldtype === 'Int'"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
v-model="document.doc[field.fieldname]"
|
:value="document.doc[field.fieldname] || '0'"
|
||||||
:placeholder="field.placeholder"
|
:placeholder="field.placeholder"
|
||||||
:debounce="500"
|
:debounce="500"
|
||||||
@change.stop="fieldChange($event.target.value, field)"
|
@change.stop="fieldChange($event.target.value, field)"
|
||||||
@ -366,6 +375,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Password from '@/components/Controls/Password.vue'
|
||||||
import FormattedInput from '@/components/Controls/FormattedInput.vue'
|
import FormattedInput from '@/components/Controls/FormattedInput.vue'
|
||||||
import Section from '@/components/Section.vue'
|
import Section from '@/components/Section.vue'
|
||||||
import NestedPopover from '@/components/NestedPopover.vue'
|
import NestedPopover from '@/components/NestedPopover.vue'
|
||||||
|
|||||||
@ -35,7 +35,9 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="isDefaultMedium" class="text-sm text-ink-gray-4">
|
<div v-if="isDefaultMedium" class="text-sm text-ink-gray-4">
|
||||||
{{ __('You can change the default calling medium from the settings') }}
|
{{
|
||||||
|
__('You can change the default calling medium from the settings')
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -51,8 +53,7 @@ import {
|
|||||||
defaultCallingMedium,
|
defaultCallingMedium,
|
||||||
} from '@/composables/settings'
|
} from '@/composables/settings'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { createToast } from '@/utils'
|
import { FormControl, call, toast } from 'frappe-ui'
|
||||||
import { FormControl, call } from 'frappe-ui'
|
|
||||||
import { nextTick, ref, watch } from 'vue'
|
import { nextTick, ref, watch } from 'vue'
|
||||||
|
|
||||||
const { setMakeCall } = globalStore()
|
const { setMakeCall } = globalStore()
|
||||||
@ -107,13 +108,9 @@ async function setDefaultCallingMedium() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
defaultCallingMedium.value = callMedium.value
|
defaultCallingMedium.value = callMedium.value
|
||||||
createToast({
|
toast.success(
|
||||||
title: __('Default calling medium set successfully to {0}', [
|
__('Default calling medium set successfully to {0}', [callMedium.value]),
|
||||||
callMedium.value,
|
)
|
||||||
]),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@ -244,11 +244,10 @@ import NoteIcon from '@/components/Icons/NoteIcon.vue'
|
|||||||
import TaskIcon from '@/components/Icons/TaskIcon.vue'
|
import TaskIcon from '@/components/Icons/TaskIcon.vue'
|
||||||
import TaskPanel from '@/components/Telephony/TaskPanel.vue'
|
import TaskPanel from '@/components/Telephony/TaskPanel.vue'
|
||||||
import CountUpTimer from '@/components/CountUpTimer.vue'
|
import CountUpTimer from '@/components/CountUpTimer.vue'
|
||||||
import { createToast } from '@/utils'
|
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { sessionStore } from '@/stores/session'
|
import { sessionStore } from '@/stores/session'
|
||||||
import { useDraggable, useWindowSize } from '@vueuse/core'
|
import { useDraggable, useWindowSize } from '@vueuse/core'
|
||||||
import { TextEditor, Avatar, Button, createResource } from 'frappe-ui'
|
import { TextEditor, Avatar, Button, createResource, toast } from 'frappe-ui'
|
||||||
import { ref, onBeforeUnmount, watch, nextTick } from 'vue'
|
import { ref, onBeforeUnmount, watch, nextTick } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
@ -413,12 +412,7 @@ function makeOutgoingCall(number) {
|
|||||||
showSmallCallPopup.value = false
|
showSmallCallPopup.value = false
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
createToast({
|
toast.error(err.messages[0])
|
||||||
title: 'Error',
|
|
||||||
text: err.messages[0],
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-red-600',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -312,11 +312,12 @@ import { globalStore } from '@/stores/global'
|
|||||||
import { viewsStore } from '@/stores/views'
|
import { viewsStore } from '@/stores/views'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
import { isEmoji, createToast } from '@/utils'
|
import { isEmoji } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
createResource,
|
createResource,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
|
toast,
|
||||||
call,
|
call,
|
||||||
FeatherIcon,
|
FeatherIcon,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
@ -727,12 +728,7 @@ const updateQuickFilters = createResource({
|
|||||||
|
|
||||||
quickFilters.update({ params: { doctype: props.doctype, cached: false } })
|
quickFilters.update({ params: { doctype: props.doctype, cached: false } })
|
||||||
quickFilters.reload()
|
quickFilters.reload()
|
||||||
|
toast.success(__('Quick Filters updated successfully'))
|
||||||
createToast({
|
|
||||||
title: __('Quick Filters updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { getScript } from '@/data/script'
|
import { getScript } from '@/data/script'
|
||||||
import { createToast, runSequentially } from '@/utils'
|
import { runSequentially } from '@/utils'
|
||||||
import { createDocumentResource } from 'frappe-ui'
|
import { createDocumentResource, toast } from 'frappe-ui'
|
||||||
|
|
||||||
const documentsCache = {}
|
const documentsCache = {}
|
||||||
const controllersCache = {}
|
const controllersCache = {}
|
||||||
@ -17,19 +17,11 @@ export function useDocument(doctype, docname) {
|
|||||||
onSuccess: () => setupFormScript(),
|
onSuccess: () => setupFormScript(),
|
||||||
setValue: {
|
setValue: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
createToast({
|
toast.success(__('Document updated successfully'))
|
||||||
title: __('Document updated successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(__('Error updating document'))
|
||||||
title: __('Error updating document'),
|
console.error(err)
|
||||||
text: err.messages[0],
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-red-600',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
import { createToast } from '@/utils'
|
import { call, createListResource, toast } from 'frappe-ui'
|
||||||
import { call, createListResource } from 'frappe-ui'
|
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
const { $dialog, $socket, makeCall } = globalStore()
|
const { $dialog, $socket, makeCall } = globalStore()
|
||||||
|
|
||||||
helpers.createDialog = $dialog
|
helpers.createDialog = $dialog
|
||||||
helpers.createToast = createToast
|
helpers.toast = toast
|
||||||
helpers.socket = $socket
|
helpers.socket = $socket
|
||||||
helpers.router = router
|
helpers.router = router
|
||||||
helpers.call = call
|
helpers.call = call
|
||||||
|
|||||||
@ -186,7 +186,7 @@ import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
|||||||
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
||||||
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
||||||
import AddressModal from '@/components/Modals/AddressModal.vue'
|
import AddressModal from '@/components/Modals/AddressModal.vue'
|
||||||
import { formatDate, timeAgo, createToast } from '@/utils'
|
import { formatDate, timeAgo } from '@/utils'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
@ -204,6 +204,7 @@ import {
|
|||||||
createResource,
|
createResource,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, computed, h } from 'vue'
|
import { ref, computed, h } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
@ -522,11 +523,7 @@ async function setAsPrimary(field, value) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
contact.reload()
|
contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,11 +536,7 @@ async function createNew(field, value) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
contact.reload()
|
contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,11 +549,7 @@ async function editOption(doctype, name, fieldname, value) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
contact.reload()
|
contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,11 +559,7 @@ async function deleteOption(doctype, name) {
|
|||||||
name,
|
name,
|
||||||
})
|
})
|
||||||
await contact.reload()
|
await contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateField(fieldname, value) {
|
async function updateField(fieldname, value) {
|
||||||
@ -584,11 +569,7 @@ async function updateField(fieldname, value) {
|
|||||||
fieldname,
|
fieldname,
|
||||||
value,
|
value,
|
||||||
})
|
})
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
|
|
||||||
contact.reload()
|
contact.reload()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,7 +89,7 @@
|
|||||||
@click="
|
@click="
|
||||||
deal.data.email
|
deal.data.email
|
||||||
? openEmailBox()
|
? openEmailBox()
|
||||||
: _errorMessage(__('No email set'))
|
: toast.error(__('No email set'))
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
@ -103,7 +103,7 @@
|
|||||||
@click="
|
@click="
|
||||||
deal.data.website
|
deal.data.website
|
||||||
? openWebsite(deal.data.website)
|
? openWebsite(deal.data.website)
|
||||||
: _errorMessage(__('No website set'))
|
: toast.error(__('No website set'))
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
@ -332,10 +332,8 @@ import SLASection from '@/components/SLASection.vue'
|
|||||||
import CustomActions from '@/components/CustomActions.vue'
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import {
|
import {
|
||||||
openWebsite,
|
openWebsite,
|
||||||
createToast,
|
|
||||||
setupAssignees,
|
setupAssignees,
|
||||||
setupCustomizations,
|
setupCustomizations,
|
||||||
errorMessage as _errorMessage,
|
|
||||||
copyToClipboard,
|
copyToClipboard,
|
||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
@ -353,6 +351,7 @@ import {
|
|||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
call,
|
call,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { useOnboarding } from 'frappe-ui/frappe'
|
import { useOnboarding } from 'frappe-ui/frappe'
|
||||||
import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue'
|
import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue'
|
||||||
@ -401,8 +400,9 @@ const deal = createResource({
|
|||||||
$dialog,
|
$dialog,
|
||||||
$socket,
|
$socket,
|
||||||
router,
|
router,
|
||||||
|
toast,
|
||||||
updateField,
|
updateField,
|
||||||
createToast,
|
createToast: toast.create,
|
||||||
deleteDoc: deleteDeal,
|
deleteDoc: deleteDeal,
|
||||||
resource: {
|
resource: {
|
||||||
deal,
|
deal,
|
||||||
@ -429,11 +429,7 @@ const organization = createResource({
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
$socket.on('crm_customer_created', () => {
|
$socket.on('crm_customer_created', () => {
|
||||||
createToast({
|
toast.success(__('Customer created successfully'))
|
||||||
title: __('Customer created successfully'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (deal.data) {
|
if (deal.data) {
|
||||||
@ -469,20 +465,11 @@ function updateDeal(fieldname, value, callback) {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deal.reload()
|
deal.reload()
|
||||||
reload.value = true
|
reload.value = true
|
||||||
createToast({
|
toast.success(__('Deal updated'))
|
||||||
title: __('Deal updated'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
callback?.()
|
callback?.()
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(__('Error updating deal: {0}', [err.messages?.[0]]))
|
||||||
title: __('Error updating deal'),
|
|
||||||
text: __(err.messages?.[0]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -490,12 +477,7 @@ function updateDeal(fieldname, value, callback) {
|
|||||||
function validateRequired(fieldname, value) {
|
function validateRequired(fieldname, value) {
|
||||||
let meta = deal.data.fields_meta || {}
|
let meta = deal.data.fields_meta || {}
|
||||||
if (meta[fieldname]?.reqd && !value) {
|
if (meta[fieldname]?.reqd && !value) {
|
||||||
createToast({
|
toast.error(__('{0} is a required field', [meta[fieldname].label]))
|
||||||
title: __('Error Updating Deal'),
|
|
||||||
text: __('{0} is a required field', [meta[fieldname].label]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -646,11 +628,7 @@ function contactOptions(contact) {
|
|||||||
|
|
||||||
async function addContact(contact) {
|
async function addContact(contact) {
|
||||||
if (dealContacts.data?.find((c) => c.name === contact)) {
|
if (dealContacts.data?.find((c) => c.name === contact)) {
|
||||||
createToast({
|
toast.error(__('Contact already added'))
|
||||||
title: __('Contact already added'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-3',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,11 +638,7 @@ async function addContact(contact) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
dealContacts.reload()
|
dealContacts.reload()
|
||||||
createToast({
|
toast.success(__('Contact added'))
|
||||||
title: __('Contact added'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,11 +649,7 @@ async function removeContact(contact) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
dealContacts.reload()
|
dealContacts.reload()
|
||||||
createToast({
|
toast.success(__('Contact removed'))
|
||||||
title: __('Contact removed'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,11 +660,7 @@ async function setPrimaryContact(contact) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
dealContacts.reload()
|
dealContacts.reload()
|
||||||
createToast({
|
toast.success(__('Primary contact set'))
|
||||||
title: __('Primary contact set'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,12 +683,12 @@ function triggerCall() {
|
|||||||
let mobile_no = primaryContact.mobile_no || null
|
let mobile_no = primaryContact.mobile_no || null
|
||||||
|
|
||||||
if (!primaryContact) {
|
if (!primaryContact) {
|
||||||
_errorMessage(__('No primary contact set'))
|
toast.error(__('No primary contact set'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mobile_no) {
|
if (!mobile_no) {
|
||||||
_errorMessage(__('No mobile number set'))
|
toast.error(__('No mobile number set'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -124,7 +124,7 @@
|
|||||||
() =>
|
() =>
|
||||||
lead.data.mobile_no
|
lead.data.mobile_no
|
||||||
? makeCall(lead.data.mobile_no)
|
? makeCall(lead.data.mobile_no)
|
||||||
: _errorMessage(__('No phone number set'))
|
: toast.error(__('No phone number set'))
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<PhoneIcon class="h-4 w-4" />
|
<PhoneIcon class="h-4 w-4" />
|
||||||
@ -139,7 +139,7 @@
|
|||||||
@click="
|
@click="
|
||||||
lead.data.email
|
lead.data.email
|
||||||
? openEmailBox()
|
? openEmailBox()
|
||||||
: _errorMessage(__('No email set'))
|
: toast.error(__('No email set'))
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
@ -153,7 +153,7 @@
|
|||||||
@click="
|
@click="
|
||||||
lead.data.website
|
lead.data.website
|
||||||
? openWebsite(lead.data.website)
|
? openWebsite(lead.data.website)
|
||||||
: _errorMessage(__('No website set'))
|
: toast.error(__('No website set'))
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
@ -344,14 +344,13 @@ import SLASection from '@/components/SLASection.vue'
|
|||||||
import CustomActions from '@/components/CustomActions.vue'
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import {
|
import {
|
||||||
openWebsite,
|
openWebsite,
|
||||||
createToast,
|
|
||||||
setupAssignees,
|
setupAssignees,
|
||||||
setupCustomizations,
|
setupCustomizations,
|
||||||
errorMessage as _errorMessage,
|
|
||||||
copyToClipboard,
|
copyToClipboard,
|
||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
|
import { sessionStore } from '@/stores/session'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
@ -373,6 +372,7 @@ import {
|
|||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
call,
|
call,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { useOnboarding } from 'frappe-ui/frappe'
|
import { useOnboarding } from 'frappe-ui/frappe'
|
||||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||||
@ -380,6 +380,7 @@ import { useRouter, useRoute } from 'vue-router'
|
|||||||
import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
||||||
|
|
||||||
const { brand } = getSettings()
|
const { brand } = getSettings()
|
||||||
|
const { user } = sessionStore()
|
||||||
const { isManager } = usersStore()
|
const { isManager } = usersStore()
|
||||||
const { $dialog, $socket, makeCall } = globalStore()
|
const { $dialog, $socket, makeCall } = globalStore()
|
||||||
const { statusOptions, getLeadStatus, getDealStatus } = statusesStore()
|
const { statusOptions, getLeadStatus, getDealStatus } = statusesStore()
|
||||||
@ -413,8 +414,9 @@ const lead = createResource({
|
|||||||
$dialog,
|
$dialog,
|
||||||
$socket,
|
$socket,
|
||||||
router,
|
router,
|
||||||
|
toast,
|
||||||
updateField,
|
updateField,
|
||||||
createToast,
|
createToast: toast.create,
|
||||||
deleteDoc: deleteLead,
|
deleteDoc: deleteLead,
|
||||||
resource: { lead, sections },
|
resource: { lead, sections },
|
||||||
call,
|
call,
|
||||||
@ -455,20 +457,11 @@ function updateLead(fieldname, value, callback) {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
lead.reload()
|
lead.reload()
|
||||||
reload.value = true
|
reload.value = true
|
||||||
createToast({
|
toast.success(__('Lead updated successfully'))
|
||||||
title: __('Lead updated'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
callback?.()
|
callback?.()
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(err.messages?.[0] || __('Error updating lead'))
|
||||||
title: __('Error updating lead'),
|
|
||||||
text: __(err.messages?.[0]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -476,12 +469,7 @@ function updateLead(fieldname, value, callback) {
|
|||||||
function validateRequired(fieldname, value) {
|
function validateRequired(fieldname, value) {
|
||||||
let meta = lead.data.fields_meta || {}
|
let meta = lead.data.fields_meta || {}
|
||||||
if (meta[fieldname]?.reqd && !value) {
|
if (meta[fieldname]?.reqd && !value) {
|
||||||
createToast({
|
toast.error(__('{0} is a required field', [meta[fieldname].label]))
|
||||||
title: __('Error Updating Lead'),
|
|
||||||
text: __('{0} is a required field', [meta[fieldname].label]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -628,22 +616,12 @@ const existingOrganization = ref('')
|
|||||||
|
|
||||||
async function convertToDeal() {
|
async function convertToDeal() {
|
||||||
if (existingContactChecked.value && !existingContact.value) {
|
if (existingContactChecked.value && !existingContact.value) {
|
||||||
createToast({
|
toast.error(__('Please select an existing contact'))
|
||||||
title: __('Error'),
|
|
||||||
text: __('Please select an existing contact'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingOrganizationChecked.value && !existingOrganization.value) {
|
if (existingOrganizationChecked.value && !existingOrganization.value) {
|
||||||
createToast({
|
toast.error(__('Please select an existing organization'))
|
||||||
title: __('Error'),
|
|
||||||
text: __('Please select an existing organization'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,12 +639,7 @@ async function convertToDeal() {
|
|||||||
existing_contact: existingContact.value,
|
existing_contact: existingContact.value,
|
||||||
existing_organization: existingOrganization.value,
|
existing_organization: existingOrganization.value,
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
createToast({
|
toast.error(__('Error converting to deal: {0}', [err.messages?.[0]]))
|
||||||
title: __('Error converting to deal'),
|
|
||||||
text: __(err.messages?.[0]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
if (_deal) {
|
if (_deal) {
|
||||||
showConvertToDealModal.value = false
|
showConvertToDealModal.value = false
|
||||||
@ -675,7 +648,7 @@ async function convertToDeal() {
|
|||||||
existingContact.value = ''
|
existingContact.value = ''
|
||||||
existingOrganization.value = ''
|
existingOrganization.value = ''
|
||||||
updateOnboardingStep('convert_lead_to_deal', true, false, () => {
|
updateOnboardingStep('convert_lead_to_deal', true, false, () => {
|
||||||
localStorage.setItem('firstDeal', _deal)
|
localStorage.setItem('firstDeal' + user, _deal)
|
||||||
})
|
})
|
||||||
capture('convert_lead_to_deal')
|
capture('convert_lead_to_deal')
|
||||||
router.push({ name: 'Deal', params: { dealId: _deal } })
|
router.push({ name: 'Deal', params: { dealId: _deal } })
|
||||||
|
|||||||
@ -169,7 +169,7 @@ import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
|||||||
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
||||||
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
||||||
import AddressModal from '@/components/Modals/AddressModal.vue'
|
import AddressModal from '@/components/Modals/AddressModal.vue'
|
||||||
import { formatDate, timeAgo, createToast } from '@/utils'
|
import { formatDate, timeAgo } from '@/utils'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
@ -189,6 +189,7 @@ import {
|
|||||||
createResource,
|
createResource,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, computed, h } from 'vue'
|
import { ref, computed, h } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
@ -496,11 +497,7 @@ async function setAsPrimary(field, value) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
contact.reload()
|
contact.reload()
|
||||||
createToast({
|
toast.success(___('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,11 +510,7 @@ async function createNew(field, value) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
contact.reload()
|
contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,11 +523,7 @@ async function editOption(doctype, name, fieldname, value) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
contact.reload()
|
contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,11 +533,7 @@ async function deleteOption(doctype, name) {
|
|||||||
name,
|
name,
|
||||||
})
|
})
|
||||||
await contact.reload()
|
await contact.reload()
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateField(fieldname, value) {
|
async function updateField(fieldname, value) {
|
||||||
@ -558,11 +543,7 @@ async function updateField(fieldname, value) {
|
|||||||
fieldname,
|
fieldname,
|
||||||
value,
|
value,
|
||||||
})
|
})
|
||||||
createToast({
|
toast.success(__('Contact updated'))
|
||||||
title: 'Contact updated',
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
|
|
||||||
contact.reload()
|
contact.reload()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -256,7 +256,7 @@ import Link from '@/components/Controls/Link.vue'
|
|||||||
import SidePanelLayout from '@/components/SidePanelLayout.vue'
|
import SidePanelLayout from '@/components/SidePanelLayout.vue'
|
||||||
import SLASection from '@/components/SLASection.vue'
|
import SLASection from '@/components/SLASection.vue'
|
||||||
import CustomActions from '@/components/CustomActions.vue'
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import { createToast, setupAssignees, setupCustomizations } from '@/utils'
|
import { setupAssignees, setupCustomizations } from '@/utils'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
@ -278,6 +278,7 @@ import {
|
|||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
call,
|
call,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, computed, h, onMounted } from 'vue'
|
import { ref, computed, h, onMounted } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
@ -314,8 +315,9 @@ const deal = createResource({
|
|||||||
$dialog,
|
$dialog,
|
||||||
$socket,
|
$socket,
|
||||||
router,
|
router,
|
||||||
|
toast,
|
||||||
updateField,
|
updateField,
|
||||||
createToast,
|
createToast: toast.create,
|
||||||
deleteDoc: deleteDeal,
|
deleteDoc: deleteDeal,
|
||||||
resource: {
|
resource: {
|
||||||
deal,
|
deal,
|
||||||
@ -358,20 +360,11 @@ function updateDeal(fieldname, value, callback) {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deal.reload()
|
deal.reload()
|
||||||
reload.value = true
|
reload.value = true
|
||||||
createToast({
|
toast.success(__('Deal updated'))
|
||||||
title: __('Deal updated'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
callback?.()
|
callback?.()
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(err.messages?.[0] || __('Error updating deal'))
|
||||||
title: __('Error updating deal'),
|
|
||||||
text: __(err.messages?.[0]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -379,12 +372,7 @@ function updateDeal(fieldname, value, callback) {
|
|||||||
function validateRequired(fieldname, value) {
|
function validateRequired(fieldname, value) {
|
||||||
let meta = deal.data.fields_meta || {}
|
let meta = deal.data.fields_meta || {}
|
||||||
if (meta[fieldname]?.reqd && !value) {
|
if (meta[fieldname]?.reqd && !value) {
|
||||||
createToast({
|
toast.error(__('{0} is a required field', [meta[fieldname].label]))
|
||||||
title: __('Error Updating Deal'),
|
|
||||||
text: __('{0} is a required field', [meta[fieldname].label]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -541,11 +529,7 @@ function contactOptions(contact) {
|
|||||||
|
|
||||||
async function addContact(contact) {
|
async function addContact(contact) {
|
||||||
if (dealContacts.data?.find((c) => c.name === contact)) {
|
if (dealContacts.data?.find((c) => c.name === contact)) {
|
||||||
createToast({
|
toast.error(__('Contact already added'))
|
||||||
title: __('Contact already added'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-3',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,11 +539,7 @@ async function addContact(contact) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
dealContacts.reload()
|
dealContacts.reload()
|
||||||
createToast({
|
toast.success(__('Contact added'))
|
||||||
title: __('Contact added'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,11 +550,7 @@ async function removeContact(contact) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
dealContacts.reload()
|
dealContacts.reload()
|
||||||
createToast({
|
toast.success(__('Contact removed'))
|
||||||
title: __('Contact removed'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,11 +561,7 @@ async function setPrimaryContact(contact) {
|
|||||||
})
|
})
|
||||||
if (d) {
|
if (d) {
|
||||||
dealContacts.reload()
|
dealContacts.reload()
|
||||||
createToast({
|
toast.success(__('Primary contact set'))
|
||||||
title: __('Primary contact set'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -173,7 +173,7 @@ import Link from '@/components/Controls/Link.vue'
|
|||||||
import SidePanelLayout from '@/components/SidePanelLayout.vue'
|
import SidePanelLayout from '@/components/SidePanelLayout.vue'
|
||||||
import SLASection from '@/components/SLASection.vue'
|
import SLASection from '@/components/SLASection.vue'
|
||||||
import CustomActions from '@/components/CustomActions.vue'
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import { createToast, setupAssignees, setupCustomizations } from '@/utils'
|
import { setupAssignees, setupCustomizations } from '@/utils'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
@ -196,6 +196,7 @@ import {
|
|||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
call,
|
call,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, computed, onMounted, watch } from 'vue'
|
import { ref, computed, onMounted, watch } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
@ -225,8 +226,9 @@ const lead = createResource({
|
|||||||
$dialog,
|
$dialog,
|
||||||
$socket,
|
$socket,
|
||||||
router,
|
router,
|
||||||
|
toast,
|
||||||
updateField,
|
updateField,
|
||||||
createToast,
|
createToast: toast.create,
|
||||||
deleteDoc: deleteLead,
|
deleteDoc: deleteLead,
|
||||||
resource: {
|
resource: {
|
||||||
lead,
|
lead,
|
||||||
@ -261,20 +263,11 @@ function updateLead(fieldname, value, callback) {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
lead.reload()
|
lead.reload()
|
||||||
reload.value = true
|
reload.value = true
|
||||||
createToast({
|
toast.success(__('Lead updated successfully'))
|
||||||
title: __('Lead updated'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
callback?.()
|
callback?.()
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
createToast({
|
toast.error(__(err.messages?.[0] || 'Error updating lead'))
|
||||||
title: __('Error updating lead'),
|
|
||||||
text: __(err.messages?.[0]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -282,12 +275,7 @@ function updateLead(fieldname, value, callback) {
|
|||||||
function validateRequired(fieldname, value) {
|
function validateRequired(fieldname, value) {
|
||||||
let meta = lead.data.fields_meta || {}
|
let meta = lead.data.fields_meta || {}
|
||||||
if (meta[fieldname]?.reqd && !value) {
|
if (meta[fieldname]?.reqd && !value) {
|
||||||
createToast({
|
toast.error(__('{0} is a required field', [meta[fieldname].label]))
|
||||||
title: __('Error Updating Lead'),
|
|
||||||
text: __('{0} is a required field', [meta[fieldname].label]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -433,22 +421,12 @@ const existingOrganization = ref('')
|
|||||||
|
|
||||||
async function convertToDeal() {
|
async function convertToDeal() {
|
||||||
if (existingContactChecked.value && !existingContact.value) {
|
if (existingContactChecked.value && !existingContact.value) {
|
||||||
createToast({
|
toast.error(__('Please select an existing contact'))
|
||||||
title: __('Error'),
|
|
||||||
text: __('Please select an existing contact'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingOrganizationChecked.value && !existingOrganization.value) {
|
if (existingOrganizationChecked.value && !existingOrganization.value) {
|
||||||
createToast({
|
toast.error(__('Please select an existing organization'))
|
||||||
title: __('Error'),
|
|
||||||
text: __('Please select an existing organization'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -165,7 +165,7 @@ import { globalStore } from '@/stores/global'
|
|||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { formatDate, timeAgo, createToast } from '@/utils'
|
import { formatDate, timeAgo } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
Avatar,
|
Avatar,
|
||||||
@ -179,6 +179,7 @@ import {
|
|||||||
createDocumentResource,
|
createDocumentResource,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
createResource,
|
createResource,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { h, computed, ref } from 'vue'
|
import { h, computed, ref } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
@ -207,17 +208,6 @@ const organization = createDocumentResource({
|
|||||||
auto: true,
|
auto: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
async function updateField(fieldname, value) {
|
|
||||||
await organization.setValue.submit({
|
|
||||||
[fieldname]: value,
|
|
||||||
})
|
|
||||||
createToast({
|
|
||||||
title: __('Organization updated'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const breadcrumbs = computed(() => {
|
const breadcrumbs = computed(() => {
|
||||||
let items = [{ label: __('Organizations'), route: { name: 'Organizations' } }]
|
let items = [{ label: __('Organizations'), route: { name: 'Organizations' } }]
|
||||||
|
|
||||||
@ -302,12 +292,7 @@ async function deleteOrganization() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openWebsite() {
|
function openWebsite() {
|
||||||
if (!organization.doc.website)
|
if (!organization.doc.website) toast.error(__('No website found'))
|
||||||
createToast({
|
|
||||||
title: __('Website not found'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
else window.open(organization.doc.website, '_blank')
|
else window.open(organization.doc.website, '_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -192,7 +192,7 @@ import { globalStore } from '@/stores/global'
|
|||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { formatDate, timeAgo, createToast } from '@/utils'
|
import { formatDate, timeAgo } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
@ -205,6 +205,7 @@ import {
|
|||||||
createDocumentResource,
|
createDocumentResource,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
createResource,
|
createResource,
|
||||||
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { h, computed, ref } from 'vue'
|
import { h, computed, ref } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
@ -249,17 +250,6 @@ const organization = createDocumentResource({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
async function updateField(fieldname, value) {
|
|
||||||
await organization.setValue.submit({
|
|
||||||
[fieldname]: value,
|
|
||||||
})
|
|
||||||
createToast({
|
|
||||||
title: __('Organization updated'),
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const breadcrumbs = computed(() => {
|
const breadcrumbs = computed(() => {
|
||||||
let items = [{ label: __('Organizations'), route: { name: 'Organizations' } }]
|
let items = [{ label: __('Organizations'), route: { name: 'Organizations' } }]
|
||||||
|
|
||||||
@ -348,12 +338,7 @@ function website(url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openWebsite() {
|
function openWebsite() {
|
||||||
if (!organization.doc.website)
|
if (!organization.doc.website) toast.error(__('No website found'))
|
||||||
createToast({
|
|
||||||
title: __('Website not found'),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
else window.open(organization.doc.website, '_blank')
|
else window.open(organization.doc.website, '_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,13 +7,6 @@ import { getMeta } from '@/stores/meta'
|
|||||||
import { toast, dayjsLocal, dayjs } from 'frappe-ui'
|
import { toast, dayjsLocal, dayjs } from 'frappe-ui'
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
|
|
||||||
export function createToast(options) {
|
|
||||||
toast({
|
|
||||||
position: 'bottom-right',
|
|
||||||
...options,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatTime(seconds) {
|
export function formatTime(seconds) {
|
||||||
const days = Math.floor(seconds / (3600 * 24))
|
const days = Math.floor(seconds / (3600 * 24))
|
||||||
const hours = Math.floor((seconds % (3600 * 24)) / 3600)
|
const hours = Math.floor((seconds % (3600 * 24)) / 3600)
|
||||||
@ -209,34 +202,20 @@ export async function setupListCustomizations(data, obj = {}) {
|
|||||||
return { actions, bulkActions }
|
return { actions, bulkActions }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function errorMessage(title, message) {
|
|
||||||
createToast({
|
|
||||||
title: title || 'Error',
|
|
||||||
text: message,
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function copyToClipboard(text) {
|
export function copyToClipboard(text) {
|
||||||
if (navigator.clipboard && window.isSecureContext) {
|
if (navigator.clipboard && window.isSecureContext) {
|
||||||
navigator.clipboard.writeText(text).then(show_success_alert)
|
navigator.clipboard.writeText(text).then(showSuccessAlert)
|
||||||
} else {
|
} else {
|
||||||
let input = document.createElement('textarea')
|
let input = document.createElement('textarea')
|
||||||
document.body.appendChild(input)
|
document.body.appendChild(input)
|
||||||
input.value = text
|
input.value = text
|
||||||
input.select()
|
input.select()
|
||||||
document.execCommand('copy')
|
document.execCommand('copy')
|
||||||
show_success_alert()
|
showSuccessAlert()
|
||||||
document.body.removeChild(input)
|
document.body.removeChild(input)
|
||||||
}
|
}
|
||||||
function show_success_alert() {
|
function showSuccessAlert() {
|
||||||
createToast({
|
toast.success(__('Copied to clipboard'))
|
||||||
title: 'Copied to clipboard',
|
|
||||||
text: text,
|
|
||||||
icon: 'check',
|
|
||||||
iconClasses: 'text-ink-green-3',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
module.exports = {
|
import frappeUIPreset from 'frappe-ui/src/tailwind/preset'
|
||||||
presets: [require('frappe-ui/src/tailwind/preset')],
|
|
||||||
|
export default {
|
||||||
|
presets: [frappeUIPreset],
|
||||||
content: [
|
content: [
|
||||||
'./index.html',
|
'./index.html',
|
||||||
'./src/**/*.{vue,js,ts,jsx,tsx}',
|
'./src/**/*.{vue,js,ts,jsx,tsx}',
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"workspaces": ["frontend", "frappe-ui"],
|
"workspaces": ["frontend", "frappe-ui"],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "cd frontend && yarn install",
|
"postinstall": "cd frontend && yarn install",
|
||||||
|
|||||||
66
yarn.lock
66
yarn.lock
@ -1236,6 +1236,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.10.3.tgz#7744abd4a954f35265af351f1be9b545e819c66d"
|
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.10.3.tgz#7744abd4a954f35265af351f1be9b545e819c66d"
|
||||||
integrity sha512-wAG/0/UsLeZLmshWb6rtWNXKJftcmnned91/HLccHVQAuQZ1UWH+wXeQKu/mtodxEO7JcU2mVPR9mLGQkK0McQ==
|
integrity sha512-wAG/0/UsLeZLmshWb6rtWNXKJftcmnned91/HLccHVQAuQZ1UWH+wXeQKu/mtodxEO7JcU2mVPR9mLGQkK0McQ==
|
||||||
|
|
||||||
|
"@tiptap/core@^2.11.7":
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.12.0.tgz#e0bc9255865db53682e83d843c8fef19596a8899"
|
||||||
|
integrity sha512-3qX8oGVKFFZzQ0vit+ZolR6AJIATBzmEmjAA0llFhWk4vf3v64p1YcXcJsOBsr5scizJu5L6RYWEFatFwqckRg==
|
||||||
|
|
||||||
"@tiptap/extension-blockquote@^2.10.3":
|
"@tiptap/extension-blockquote@^2.10.3":
|
||||||
version "2.10.3"
|
version "2.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.10.3.tgz#ee29925930ac9a5b129d3ad262bb45afcc23b318"
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.10.3.tgz#ee29925930ac9a5b129d3ad262bb45afcc23b318"
|
||||||
@ -1268,6 +1273,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.10.3.tgz#5ff1b1e563c4eda44677df444c523de1e5258fa4"
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.10.3.tgz#5ff1b1e563c4eda44677df444c523de1e5258fa4"
|
||||||
integrity sha512-yiDVNg22fYkzsFk5kBlDSHcjwVJgajvO/M5fDXA+Hfxwo2oNcG6aJyyHXFe+UaXTVjdkPej0J6kcMKrTMCiFug==
|
integrity sha512-yiDVNg22fYkzsFk5kBlDSHcjwVJgajvO/M5fDXA+Hfxwo2oNcG6aJyyHXFe+UaXTVjdkPej0J6kcMKrTMCiFug==
|
||||||
|
|
||||||
|
"@tiptap/extension-code-block@^2.11.9":
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.12.0.tgz#73bceaa90ba54de65ade42db5a28cc299c16158b"
|
||||||
|
integrity sha512-1D7cYAjgxEFHdfC/35Ooi4GqWKB5sszbW8iI7N16XILNln26xb0d5KflXqYrwr9CN/ZnZoCl2o6YsP7xEObcZA==
|
||||||
|
|
||||||
"@tiptap/extension-code@^2.10.3":
|
"@tiptap/extension-code@^2.10.3":
|
||||||
version "2.10.3"
|
version "2.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.10.3.tgz#b9fb04be2d51760f011ec7a060d4e2e3eefe392c"
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.10.3.tgz#b9fb04be2d51760f011ec7a060d4e2e3eefe392c"
|
||||||
@ -1362,6 +1372,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.10.3.tgz#128c8fcd46d2e854d214c7f566e6212f2ebff6f1"
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.10.3.tgz#128c8fcd46d2e854d214c7f566e6212f2ebff6f1"
|
||||||
integrity sha512-sNkTX/iN+YoleDiTJsrWSBw9D7c4vsYwnW5y/G5ydfuJMIRQMF78pWSIWZFDRNOMkgK5UHkhu9anrbCFYgBfaA==
|
integrity sha512-sNkTX/iN+YoleDiTJsrWSBw9D7c4vsYwnW5y/G5ydfuJMIRQMF78pWSIWZFDRNOMkgK5UHkhu9anrbCFYgBfaA==
|
||||||
|
|
||||||
|
"@tiptap/extension-paragraph@^2.12.0":
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.12.0.tgz#35987cfa842f254e67ecec403441578a1b2189a1"
|
||||||
|
integrity sha512-QNK5cgewCunWFxpLlbvvoO1rrLgEtNKxiY79fctP9toV+e59R+1i1Q9lXC1O5mOfDgVxCb6uFDMsqmKhFjpPog==
|
||||||
|
|
||||||
"@tiptap/extension-placeholder@^2.0.3":
|
"@tiptap/extension-placeholder@^2.0.3":
|
||||||
version "2.10.3"
|
version "2.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.10.3.tgz#eeb2b2f1916619e334af7d2a9d6885f77bb4ab78"
|
resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.10.3.tgz#eeb2b2f1916619e334af7d2a9d6885f77bb4ab78"
|
||||||
@ -2267,6 +2282,14 @@ eastasianwidth@^0.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
||||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||||
|
|
||||||
|
echarts@^5.6.0:
|
||||||
|
version "5.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.6.0.tgz#2377874dca9fb50f104051c3553544752da3c9d6"
|
||||||
|
integrity sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==
|
||||||
|
dependencies:
|
||||||
|
tslib "2.3.0"
|
||||||
|
zrender "5.6.1"
|
||||||
|
|
||||||
ejs@^3.1.6:
|
ejs@^3.1.6:
|
||||||
version "3.1.10"
|
version "3.1.10"
|
||||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
|
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
|
||||||
@ -2542,15 +2565,18 @@ fraction.js@^4.3.7:
|
|||||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||||
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||||
|
|
||||||
frappe-ui@^0.1.121:
|
frappe-ui@^0.1.145:
|
||||||
version "0.1.121"
|
version "0.1.145"
|
||||||
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.121.tgz#a8d37f300228edfcbb6b4fffb343f0773dcfd933"
|
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.145.tgz#19ec429badf85f3f2c45a85ec13c3c462ec11ee9"
|
||||||
integrity sha512-gvtKKZECPD2MU5X4MwPUKr2hSOs1+s1DA9laP3aPnmH0ukJRSFEhDOyjCMfH9k6ZdAe/vZCIbT4XucxLq/fOEA==
|
integrity sha512-DnnSJREu/EpUAJGNFaXEUF3re0hQMmLBOX/MSW9AsQtnCJwXkO5VbH/dyVHAZjqdb9Do3CNQF33/HB4NibNI8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@floating-ui/vue" "^1.1.6"
|
||||||
"@headlessui/vue" "^1.7.14"
|
"@headlessui/vue" "^1.7.14"
|
||||||
"@popperjs/core" "^2.11.2"
|
"@popperjs/core" "^2.11.2"
|
||||||
"@tailwindcss/forms" "^0.5.3"
|
"@tailwindcss/forms" "^0.5.3"
|
||||||
"@tailwindcss/typography" "^0.5.16"
|
"@tailwindcss/typography" "^0.5.16"
|
||||||
|
"@tiptap/core" "^2.11.7"
|
||||||
|
"@tiptap/extension-code-block" "^2.11.9"
|
||||||
"@tiptap/extension-code-block-lowlight" "^2.11.5"
|
"@tiptap/extension-code-block-lowlight" "^2.11.5"
|
||||||
"@tiptap/extension-color" "^2.0.3"
|
"@tiptap/extension-color" "^2.0.3"
|
||||||
"@tiptap/extension-highlight" "^2.0.3"
|
"@tiptap/extension-highlight" "^2.0.3"
|
||||||
@ -2571,12 +2597,16 @@ frappe-ui@^0.1.121:
|
|||||||
"@tiptap/vue-3" "^2.0.3"
|
"@tiptap/vue-3" "^2.0.3"
|
||||||
"@vueuse/core" "^10.4.1"
|
"@vueuse/core" "^10.4.1"
|
||||||
dayjs "^1.11.13"
|
dayjs "^1.11.13"
|
||||||
|
echarts "^5.6.0"
|
||||||
feather-icons "^4.28.0"
|
feather-icons "^4.28.0"
|
||||||
idb-keyval "^6.2.0"
|
idb-keyval "^6.2.0"
|
||||||
lowlight "^3.3.0"
|
lowlight "^3.3.0"
|
||||||
lucide-static "^0.479.0"
|
lucide-static "^0.479.0"
|
||||||
ora "5.4.1"
|
ora "5.4.1"
|
||||||
prettier "^3.3.2"
|
prettier "^3.3.2"
|
||||||
|
prosemirror-model "^1.25.1"
|
||||||
|
prosemirror-state "^1.4.3"
|
||||||
|
prosemirror-view "^1.39.2"
|
||||||
radix-vue "^1.5.3"
|
radix-vue "^1.5.3"
|
||||||
reka-ui "^2.0.2"
|
reka-ui "^2.0.2"
|
||||||
showdown "^2.1.0"
|
showdown "^2.1.0"
|
||||||
@ -3732,6 +3762,13 @@ prosemirror-model@^1.0.0, prosemirror-model@^1.19.0, prosemirror-model@^1.20.0,
|
|||||||
dependencies:
|
dependencies:
|
||||||
orderedmap "^2.0.0"
|
orderedmap "^2.0.0"
|
||||||
|
|
||||||
|
prosemirror-model@^1.25.1:
|
||||||
|
version "1.25.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.25.1.tgz#aeae9f1ec79fcaa76f6fc619800d91fbcf726870"
|
||||||
|
integrity sha512-AUvbm7qqmpZa5d9fPKMvH1Q5bqYQvAZWOGRvxsB6iFLyycvC9MwNemNVjHVrWgjaoxAfY8XVg7DbvQ/qxvI9Eg==
|
||||||
|
dependencies:
|
||||||
|
orderedmap "^2.0.0"
|
||||||
|
|
||||||
prosemirror-schema-basic@^1.2.3:
|
prosemirror-schema-basic@^1.2.3:
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz#649c349bb21c61a56febf9deb71ac68fca4cedf2"
|
resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz#649c349bb21c61a56febf9deb71ac68fca4cedf2"
|
||||||
@ -3792,6 +3829,15 @@ prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, pros
|
|||||||
prosemirror-state "^1.0.0"
|
prosemirror-state "^1.0.0"
|
||||||
prosemirror-transform "^1.1.0"
|
prosemirror-transform "^1.1.0"
|
||||||
|
|
||||||
|
prosemirror-view@^1.39.2:
|
||||||
|
version "1.39.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.39.3.tgz#54fa4b8ab4fd75ad0075dc6dc0be1745429d5a5c"
|
||||||
|
integrity sha512-bY/7kg0LzRE7ytR0zRdSMWX3sknEjw68l836ffLPMh0OG3OYnNuBDUSF3v0vjvnzgYjgY9ZH/RypbARURlcMFA==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.20.0"
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
prosemirror-transform "^1.1.0"
|
||||||
|
|
||||||
punycode.js@^2.3.1:
|
punycode.js@^2.3.1:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
|
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
|
||||||
@ -4463,6 +4509,11 @@ ts-interface-checker@^0.1.9:
|
|||||||
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
|
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
|
||||||
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
|
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
|
||||||
|
|
||||||
|
tslib@2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
|
||||||
|
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
|
||||||
|
|
||||||
tslib@^2.0.0, tslib@^2.8.0:
|
tslib@^2.0.0, tslib@^2.8.0:
|
||||||
version "2.8.1"
|
version "2.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||||
@ -4984,3 +5035,10 @@ yaml@^2.3.4:
|
|||||||
version "2.6.1"
|
version "2.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773"
|
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773"
|
||||||
integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==
|
integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==
|
||||||
|
|
||||||
|
zrender@5.6.1:
|
||||||
|
version "5.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.6.1.tgz#e08d57ecf4acac708c4fcb7481eb201df7f10a6b"
|
||||||
|
integrity sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==
|
||||||
|
dependencies:
|
||||||
|
tslib "2.3.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user