Merge pull request #1276 from frappe/main-hotfix
This commit is contained in:
commit
af64b86a04
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,5 @@ dev-dist
|
||||
tags
|
||||
node_modules
|
||||
crm/public/frontend
|
||||
frontend/yarn.lock
|
||||
crm/www/crm.html
|
||||
build
|
||||
|
||||
32
crm/api/assignment_rule.py
Normal file
32
crm/api/assignment_rule.py
Normal file
@ -0,0 +1,32 @@
|
||||
import frappe
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_assignment_rules_list():
|
||||
assignment_rules = []
|
||||
for docname in frappe.get_all(
|
||||
"Assignment Rule", filters={"document_type": ["in", ["CRM Lead", "CRM Deal"]]}
|
||||
):
|
||||
doc = frappe.get_value(
|
||||
"Assignment Rule",
|
||||
docname,
|
||||
fieldname=[
|
||||
"name",
|
||||
"description",
|
||||
"disabled",
|
||||
"priority",
|
||||
],
|
||||
as_dict=True,
|
||||
)
|
||||
users_exists = bool(frappe.db.exists("Assignment Rule User", {"parent": docname.name}))
|
||||
assignment_rules.append({**doc, "users_exists": users_exists})
|
||||
return assignment_rules
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def duplicate_assignment_rule(docname, new_name):
|
||||
doc = frappe.get_doc("Assignment Rule", docname)
|
||||
doc.name = new_name
|
||||
doc.assignment_rule_name = new_name
|
||||
doc.insert()
|
||||
return doc
|
||||
@ -25,7 +25,7 @@ class CRMDeal(Document):
|
||||
add_status_change_log(self)
|
||||
if frappe.db.get_value("CRM Deal Status", self.status, "type") == "Won":
|
||||
self.closed_date = frappe.utils.nowdate()
|
||||
self.validate_forcasting_fields()
|
||||
self.validate_forecasting_fields()
|
||||
self.validate_lost_reason()
|
||||
self.update_exchange_rate()
|
||||
|
||||
@ -151,9 +151,21 @@ class CRMDeal(Document):
|
||||
if not self.probability or self.probability == 0:
|
||||
self.probability = frappe.db.get_value("CRM Deal Status", self.status, "probability") or 0
|
||||
|
||||
def validate_forcasting_fields(self):
|
||||
def update_expected_deal_value(self):
|
||||
"""
|
||||
Update the expected deal value based on the net total or total.
|
||||
"""
|
||||
if (
|
||||
frappe.db.get_single_value("FCRM Settings", "auto_update_expected_deal_value")
|
||||
and (self.net_total or self.total)
|
||||
and self.expected_deal_value
|
||||
):
|
||||
self.expected_deal_value = self.net_total or self.total
|
||||
|
||||
def validate_forecasting_fields(self):
|
||||
self.update_closed_date()
|
||||
self.update_default_probability()
|
||||
self.update_expected_deal_value()
|
||||
if frappe.db.get_single_value("FCRM Settings", "enable_forecasting"):
|
||||
if not self.expected_deal_value or self.expected_deal_value == 0:
|
||||
frappe.throw(_("Expected Deal Value is required."), frappe.MandatoryError)
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
"defaults_tab",
|
||||
"restore_defaults",
|
||||
"enable_forecasting",
|
||||
"auto_update_expected_deal_value",
|
||||
"currency_tab",
|
||||
"currency",
|
||||
"exchange_rate_provider_section",
|
||||
@ -105,12 +106,19 @@
|
||||
{
|
||||
"fieldname": "column_break_vqck",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"description": "Automatically update \"Expected Deal Value\" based on the total value of associated products in a deal",
|
||||
"fieldname": "auto_update_expected_deal_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Auto Update Expected Deal Value"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-29 11:26:50.420614",
|
||||
"modified": "2025-09-16 17:33:26.406549",
|
||||
"modified_by": "Administrator",
|
||||
"module": "FCRM",
|
||||
"name": "FCRM Settings",
|
||||
|
||||
@ -25,6 +25,8 @@ def after_install(force=False):
|
||||
add_standard_dropdown_items()
|
||||
add_default_scripts()
|
||||
create_default_manager_dashboard(force)
|
||||
create_assignment_rule_custom_fields()
|
||||
add_assignment_rule_property_setters()
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
@ -421,3 +423,80 @@ def add_default_scripts():
|
||||
for doctype in ["CRM Lead", "CRM Deal"]:
|
||||
create_product_details_script(doctype)
|
||||
create_forecasting_script()
|
||||
|
||||
|
||||
def add_assignment_rule_property_setters():
|
||||
"""Add a property setter to the Assignment Rule DocType for assign_condition and unassign_condition."""
|
||||
|
||||
default_fields = {
|
||||
"doctype": "Property Setter",
|
||||
"doctype_or_field": "DocField",
|
||||
"doc_type": "Assignment Rule",
|
||||
"property_type": "Data",
|
||||
"is_system_generated": 1,
|
||||
}
|
||||
|
||||
if not frappe.db.exists("Property Setter", {"name": "Assignment Rule-assign_condition-depends_on"}):
|
||||
frappe.get_doc(
|
||||
{
|
||||
**default_fields,
|
||||
"name": "Assignment Rule-assign_condition-depends_on",
|
||||
"field_name": "assign_condition",
|
||||
"property": "depends_on",
|
||||
"value": "eval: !doc.assign_condition_json",
|
||||
}
|
||||
).insert()
|
||||
else:
|
||||
frappe.db.set_value(
|
||||
"Property Setter",
|
||||
{"name": "Assignment Rule-assign_condition-depends_on"},
|
||||
"value",
|
||||
"eval: !doc.assign_condition_json",
|
||||
)
|
||||
if not frappe.db.exists("Property Setter", {"name": "Assignment Rule-unassign_condition-depends_on"}):
|
||||
frappe.get_doc(
|
||||
{
|
||||
**default_fields,
|
||||
"name": "Assignment Rule-unassign_condition-depends_on",
|
||||
"field_name": "unassign_condition",
|
||||
"property": "depends_on",
|
||||
"value": "eval: !doc.unassign_condition_json",
|
||||
}
|
||||
).insert()
|
||||
else:
|
||||
frappe.db.set_value(
|
||||
"Property Setter",
|
||||
{"name": "Assignment Rule-unassign_condition-depends_on"},
|
||||
"value",
|
||||
"eval: !doc.unassign_condition_json",
|
||||
)
|
||||
|
||||
|
||||
def create_assignment_rule_custom_fields():
|
||||
if not frappe.get_meta("Assignment Rule").has_field("assign_condition_json"):
|
||||
click.secho("* Installing Custom Fields in Assignment Rule")
|
||||
|
||||
create_custom_fields(
|
||||
{
|
||||
"Assignment Rule": [
|
||||
{
|
||||
"description": "Autogenerated field by CRM App",
|
||||
"fieldname": "assign_condition_json",
|
||||
"fieldtype": "Code",
|
||||
"label": "Assign Condition JSON",
|
||||
"insert_after": "assign_condition",
|
||||
"depends_on": "eval: doc.assign_condition_json",
|
||||
},
|
||||
{
|
||||
"description": "Autogenerated field by CRM App",
|
||||
"fieldname": "unassign_condition_json",
|
||||
"fieldtype": "Code",
|
||||
"label": "Unassign Condition JSON",
|
||||
"insert_after": "unassign_condition",
|
||||
"depends_on": "eval: doc.unassign_condition_json",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
frappe.clear_cache(doctype="Assignment Rule")
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Arabic\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "كمية"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "البريد الإلكتروني"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "العام الماضي"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "اسم"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr "ترتيب حسب"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "منظمة"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "هاتف"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "الحالة"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Bosnian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "Cijeli dan"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Iznos"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "Analiza kanala generisanja poslova"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "Odgovorni Posla"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr "Uređivanje događaja"
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-pošta"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Prošle godine"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Zadnja izmjena"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "Instalacija mobilne aplikacije"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Mobilni Broj"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "Moji Otvoreni Poslovi"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Naziv"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "Nisu pronađeni korisnici"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "Nije pronađena web stranica"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "Nema {0} Dostupnog"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "{0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Sortiraj prema"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organizacija"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Logo Organizacije"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organizacije"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Osoba"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefon"
|
||||
|
||||
@ -5183,7 +5183,7 @@ msgstr "Počni s uzorkom od 10 potencijalnih klijenata"
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Czech\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-15 19:47\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:03\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Danish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "Hele dagen"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Beløb"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Betrag"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Vergangenes Jahr"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Zuletzt geändert"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Kein {0} gefunden"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Sortieren nach"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Firma"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Organisationslogo"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organisationen"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Person"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefon"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:03\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Esperanto\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "crwdns158770:0crwdne158770:0"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "crwdns152751:0crwdne152751:0"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "crwdns156258:0crwdne156258:0"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "crwdns153043:0crwdne153043:0"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr "crwdns158854:0crwdne158854:0"
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "crwdns153167:0crwdne153167:0"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "crwdns153421:0crwdne153421:0"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "crwdns153423:0crwdne153423:0"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "crwdns156468:0crwdne156468:0"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "crwdns153521:0crwdne153521:0"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "crwdns153533:0crwdne153533:0"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "crwdns153535:0crwdne153535:0"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "crwdns156490:0crwdne156490:0"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "crwdns156492:0crwdne156492:0"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "crwdns153607:0{0}crwdne153607:0"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "crwdns153609:0{0}crwdne153609:0"
|
||||
@ -4112,8 +4112,8 @@ msgstr "crwdns153667:0crwdne153667:0"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "crwdns153669:0crwdne153669:0"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "crwdns153677:0crwdne153677:0"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "crwdns153681:0crwdne153681:0"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "crwdns153703:0crwdne153703:0"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "crwdns153705:0crwdne153705:0"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr "crwdns156620:0crwdne156620:0"
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "crwdns153925:0crwdne153925:0"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Spanish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Importe"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "Correo electrónico"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "El año pasado"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Ningún {0} encontrado"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Ordenar por"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organización"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Teléfono"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Estado"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-15 19:47\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:03\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Persian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "مبلغ"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "ایمیل"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "سال گذشته"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "نام"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "هیچ {0} یافت نشد"
|
||||
@ -4112,8 +4112,8 @@ msgstr "سفارش توسط"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "سازمان"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "لوگوی سازمان"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "سازمان ها"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "تلفن"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "وضعیت"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
@ -987,7 +987,7 @@ msgstr "Détails de l'appel"
|
||||
#. Label of the receiver (Link) field in DocType 'CRM Call Log'
|
||||
#: crm/fcrm/doctype/crm_call_log/crm_call_log.json
|
||||
msgid "Call Received By"
|
||||
msgstr ""
|
||||
msgstr "Appel reçu par"
|
||||
|
||||
#. Description of the 'Duration' (Duration) field in DocType 'CRM Call Log'
|
||||
#: crm/fcrm/doctype/crm_call_log/crm_call_log.json
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -1951,7 +1951,7 @@ msgstr ""
|
||||
#. Option for the 'Status' (Select) field in DocType 'CRM Task'
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
msgstr "Terminé"
|
||||
|
||||
#: frontend/src/components/Dashboard/AddChartModal.vue:33
|
||||
#: frontend/src/components/Dashboard/AddChartModal.vue:71
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "Courriel"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "L'année dernière"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr "Commandé par"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Téléphone"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Statut"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:03\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Croatian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "Cijeli dan"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Iznos"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "Analiza kanala generisanja poslova"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "Odgovorni Posla"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr "Uređivanje događaja"
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-pošta"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Prošle godine"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Zadnja izmjena"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "Instalacija mobilne aplikacije"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Mobilni Broj"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "Moji Otvoreni Poslovi"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Naziv"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "Nisu pronađeni korisnici"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "Nije pronađena web stranica"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "Nema {0} Dostupno"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Nije pronađeno {0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Sortiraj prema"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organizacija"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Logo Organizacije"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organizacije"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Osoba"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefon"
|
||||
|
||||
@ -5183,7 +5183,7 @@ msgstr "Započni s uzorkom od 10 potencijalnih klijenata"
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Jumlah"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "Analisis saluran perolehan kesepakatan"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "Pemilik kesepakatan"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Tahun Lalu"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Terakhir diubah"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "Instalasi aplikasi seluler"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Nomor Ponsel"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "Kesepakatan Terbuka Saya"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Nama"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "Pengguna tidak ditemukan"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "Situs web tidak ditemukan"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "Tidak Ada {0} yang Tersedia"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "{0} tidak ditemukan"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Urutkan Berdasarkan"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organisasi"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Logo organisasi"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organisasi"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Orang"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telepon"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr "Mulai dengan 10 contoh prospek"
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Italian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Cellulare"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefono"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Stato"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
274
crm/locale/nb.po
274
crm/locale/nb.po
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-14 19:18\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-21 20:47\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Norwegian Bokmal\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -128,20 +128,20 @@ msgstr "<b>SNARVEIER</b>"
|
||||
#: frontend/src/components/Settings/EmailTemplate/EditEmailTemplate.vue:98
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:98
|
||||
msgid "<p>Dear {{ lead_name }},</p>\\n\\n<p>This is a reminder for the payment of {{ grand_total }}.</p>\\n\\n<p>Thanks,</p>\\n<p>Frappé</p>"
|
||||
msgstr ""
|
||||
msgstr "<p>Kjære {{ lead_name }},</p>\\n\\n<p>Dette er en påminnelse om betaling av {{ grand_total }}.</p>\\n\\n<p>Takk,</p>\\n<p>Frappé</p>"
|
||||
|
||||
#. Header text in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
msgid "<span class=\"h5\"><b>PORTAL</b></span>"
|
||||
msgstr ""
|
||||
msgstr "<span class=\"h5\"><b>PORTAL</b></span>"
|
||||
|
||||
#: frontend/src/components/CommunicationArea.vue:79
|
||||
msgid "@John, can you please check this?"
|
||||
msgstr ""
|
||||
msgstr "@John, kan du sjekke dette?"
|
||||
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.py:56
|
||||
msgid "A Lead requires either a person's name or an organization's name"
|
||||
msgstr ""
|
||||
msgstr "En potensiell kunde krever enten en persons navn eller en organisasjons navn"
|
||||
|
||||
#: crm/templates/emails/helpdesk_invitation.html:5
|
||||
msgid "A new account has been created for you at {0}"
|
||||
@ -160,7 +160,7 @@ msgstr "API Nøkkel"
|
||||
|
||||
#: frontend/src/components/Settings/emailConfig.js:179
|
||||
msgid "API Key is required"
|
||||
msgstr ""
|
||||
msgstr "API-key er påkrevd"
|
||||
|
||||
#. Label of the api_secret (Password) field in DocType 'CRM Twilio Settings'
|
||||
#. Label of the api_secret (Password) field in DocType 'ERPNext CRM Settings'
|
||||
@ -174,72 +174,72 @@ msgstr "API-hemmelighet"
|
||||
#. Label of the api_token (Password) field in DocType 'CRM Exotel Settings'
|
||||
#: crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json
|
||||
msgid "API Token"
|
||||
msgstr ""
|
||||
msgstr "API-token"
|
||||
|
||||
#: frontend/src/components/Telephony/TwilioCallUI.vue:88
|
||||
msgid "Accept"
|
||||
msgstr ""
|
||||
msgstr "Aksepter"
|
||||
|
||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.js:7
|
||||
msgid "Accept Invitation"
|
||||
msgstr ""
|
||||
msgstr "Aksepter invitasjon"
|
||||
|
||||
#: frontend/src/components/Telephony/TwilioCallUI.vue:155
|
||||
msgid "Accept call"
|
||||
msgstr ""
|
||||
msgstr "Aksepter anrop"
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'CRM Invitation'
|
||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
||||
msgid "Accepted"
|
||||
msgstr ""
|
||||
msgstr "Akseptert"
|
||||
|
||||
#. Label of the accepted_at (Datetime) field in DocType 'CRM Invitation'
|
||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
||||
msgid "Accepted At"
|
||||
msgstr ""
|
||||
msgstr "Akseptert kl. "
|
||||
|
||||
#. Label of the access_key (Data) field in DocType 'FCRM Settings'
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||
msgid "Access Key"
|
||||
msgstr ""
|
||||
msgstr "Tilgangsnøkkel"
|
||||
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.py:156
|
||||
msgid "Access Key is required for Service Provider: {0}"
|
||||
msgstr ""
|
||||
msgstr "Tilgangsnøkkel er nødvendig for tjenesteleverandøren: {0}"
|
||||
|
||||
#: frontend/src/components/Settings/General/CurrencySettings.vue:97
|
||||
msgid "Access key"
|
||||
msgstr ""
|
||||
msgstr "Tilgangsnøkkel"
|
||||
|
||||
#: frontend/src/components/Settings/General/CurrencySettings.vue:101
|
||||
msgid "Access key for Exchangerate Host. Required for fetching exchange rates."
|
||||
msgstr ""
|
||||
msgstr "Tilgangsnøkkel for Exchangerate Host. Nødvendig for å hente valutakurser."
|
||||
|
||||
#: frontend/src/components/Settings/emailConfig.js:13
|
||||
msgid "Account Name"
|
||||
msgstr ""
|
||||
msgstr "Kontonavn"
|
||||
|
||||
#. Label of the account_sid (Data) field in DocType 'CRM Exotel Settings'
|
||||
#. Label of the account_sid (Data) field in DocType 'CRM Twilio Settings'
|
||||
#: crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json
|
||||
#: crm/fcrm/doctype/crm_twilio_settings/crm_twilio_settings.json
|
||||
msgid "Account SID"
|
||||
msgstr ""
|
||||
msgstr "Konto-SID"
|
||||
|
||||
#: frontend/src/components/Settings/emailConfig.js:165
|
||||
msgid "Account name is required"
|
||||
msgstr ""
|
||||
msgstr "Kontonavn er påkrevd"
|
||||
|
||||
#: frontend/src/components/CustomActions.vue:69
|
||||
#: frontend/src/components/ViewControls.vue:683
|
||||
#: frontend/src/components/ViewControls.vue:1064
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
msgstr "Handlinger"
|
||||
|
||||
#: frontend/src/pages/Deal.vue:527 frontend/src/pages/Lead.vue:384
|
||||
#: frontend/src/pages/MobileDeal.vue:430 frontend/src/pages/MobileLead.vue:337
|
||||
msgid "Activity"
|
||||
msgstr ""
|
||||
msgstr "Aktivitet"
|
||||
|
||||
#: frontend/src/components/Dashboard/AddChartModal.vue:41
|
||||
#: frontend/src/components/Modals/AddExistingUserModal.vue:55
|
||||
@ -252,7 +252,7 @@ msgstr "Legg til Konto"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssigneeSearch.vue:9
|
||||
msgid "Add Assignee"
|
||||
msgstr ""
|
||||
msgstr "Legg til rettighetshaver"
|
||||
|
||||
#: frontend/src/components/ColumnSettings.vue:68
|
||||
#: frontend/src/components/Kanban/KanbanView.vue:157
|
||||
@ -262,7 +262,7 @@ msgstr "Legg til Kolonne"
|
||||
#: frontend/src/components/Modals/AddExistingUserModal.vue:4
|
||||
#: frontend/src/components/Settings/Users.vue:21
|
||||
msgid "Add Existing User"
|
||||
msgstr ""
|
||||
msgstr "Legg til eksisterende bruker"
|
||||
|
||||
#: frontend/src/components/Controls/GridFieldsEditorModal.vue:57
|
||||
#: frontend/src/components/FieldLayoutEditor.vue:172
|
||||
@ -277,7 +277,7 @@ msgstr "Legg til Filter"
|
||||
|
||||
#: frontend/src/components/Calendar/CalendarEventPanel.vue:273
|
||||
msgid "Add Lead or Deal"
|
||||
msgstr ""
|
||||
msgstr "Legg til potensiell kunde eller avtale"
|
||||
|
||||
#: frontend/src/components/Controls/Grid.vue:324
|
||||
msgid "Add Row"
|
||||
@ -286,7 +286,7 @@ msgstr "Legg til Rad"
|
||||
#: frontend/src/components/FieldLayoutEditor.vue:197
|
||||
#: frontend/src/components/SidePanelLayoutEditor.vue:127
|
||||
msgid "Add Section"
|
||||
msgstr ""
|
||||
msgstr "Legg til seksjon"
|
||||
|
||||
#: frontend/src/components/SortBy.vue:142
|
||||
msgid "Add Sort"
|
||||
@ -388,7 +388,7 @@ msgstr ""
|
||||
#. Label of the address (Link) field in DocType 'CRM Organization'
|
||||
#: crm/fcrm/doctype/crm_organization/crm_organization.json
|
||||
msgid "Address"
|
||||
msgstr ""
|
||||
msgstr "Adresse"
|
||||
|
||||
#: frontend/src/components/Modals/AddExistingUserModal.vue:94
|
||||
#: frontend/src/components/Settings/InviteUserPage.vue:169
|
||||
@ -424,42 +424,42 @@ msgstr ""
|
||||
#: frontend/src/components/Modals/EventModal.vue:71
|
||||
#: frontend/src/composables/event.js:122
|
||||
msgid "All day"
|
||||
msgstr ""
|
||||
msgstr "Hele dagen"
|
||||
|
||||
#. Label of the amount (Currency) field in DocType 'CRM Products'
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
msgstr "Beløp"
|
||||
|
||||
#. Description of the 'Net Amount' (Currency) field in DocType 'CRM Products'
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
msgid "Amount after discount"
|
||||
msgstr ""
|
||||
msgstr "Beløp etter rabatt"
|
||||
|
||||
#: frontend/src/data/script.js:50 frontend/src/data/script.js:51
|
||||
msgid "An error occurred"
|
||||
msgstr ""
|
||||
msgstr "En feil oppstod"
|
||||
|
||||
#: frontend/src/data/document.js:63
|
||||
msgid "An error occurred while updating the document"
|
||||
msgstr ""
|
||||
msgstr "Det oppsto en feil under oppdatering av dokumentet"
|
||||
|
||||
#. Description of the 'Favicon' (Attach) field in DocType 'FCRM Settings'
|
||||
#: 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]"
|
||||
msgstr ""
|
||||
msgstr "En ikonfil med filtypen .ico. Bør være 16 x 16 px. Genereres ved hjelp av en favicon-generator. [favicon-generator.org]"
|
||||
|
||||
#. Description of the 'Logo' (Attach) field in DocType 'FCRM Settings'
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||
msgid "An image with 1:1 & 2:1 ratio is preferred"
|
||||
msgstr ""
|
||||
msgstr "Et bilde med forholdet 1:1 og 2:1 er å foretrekke"
|
||||
|
||||
#: frontend/src/components/Filter.vue:43 frontend/src/components/Filter.vue:81
|
||||
msgid "And"
|
||||
msgstr ""
|
||||
msgstr "Og"
|
||||
|
||||
#. Label of the annual_revenue (Currency) field in DocType 'CRM Deal'
|
||||
#. Label of the annual_revenue (Currency) field in DocType 'CRM Lead'
|
||||
@ -468,39 +468,39 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_organization/crm_organization.json
|
||||
msgid "Annual Revenue"
|
||||
msgstr ""
|
||||
msgstr "Årlig omsetning"
|
||||
|
||||
#: frontend/src/components/Modals/DealModal.vue:200
|
||||
#: frontend/src/components/Modals/LeadModal.vue:141
|
||||
msgid "Annual Revenue should be a number"
|
||||
msgstr ""
|
||||
msgstr "Årlig omsetning må være et tall"
|
||||
|
||||
#: frontend/src/components/Settings/General/BrandSettings.vue:69
|
||||
msgid "Appears in the left sidebar. Recommended size is 32x32 px in PNG or SVG"
|
||||
msgstr ""
|
||||
msgstr "Vises i venstre sidefelt. Anbefalt størrelse er 32x32 px i PNG eller SVG"
|
||||
|
||||
#: frontend/src/components/Settings/General/BrandSettings.vue:103
|
||||
msgid "Appears next to the title in your browser tab. Recommended size is 32x32 px in PNG or ICO"
|
||||
msgstr ""
|
||||
msgstr "Vises ved siden av tittelen i nettleserfanen. Anbefalt størrelse er 32x32 px i PNG eller ICO"
|
||||
|
||||
#: frontend/src/components/Kanban/KanbanSettings.vue:101
|
||||
#: frontend/src/components/Kanban/KanbanView.vue:46
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
msgstr "Bruk"
|
||||
|
||||
#. Label of the apply_on (Link) field in DocType 'CRM Service Level Agreement'
|
||||
#: crm/fcrm/doctype/crm_service_level_agreement/crm_service_level_agreement.json
|
||||
msgid "Apply On"
|
||||
msgstr ""
|
||||
msgstr "Bruk på"
|
||||
|
||||
#. Label of the view (Select) field in DocType 'CRM Form Script'
|
||||
#: crm/fcrm/doctype/crm_form_script/crm_form_script.json
|
||||
msgid "Apply To"
|
||||
msgstr ""
|
||||
msgstr "Bruk på"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssignmentRuleView.vue:132
|
||||
msgid "Apply on"
|
||||
msgstr ""
|
||||
msgstr "Bruk på"
|
||||
|
||||
#: frontend/src/components/Apps.vue:19
|
||||
msgid "Apps"
|
||||
@ -508,40 +508,40 @@ msgstr "Apper"
|
||||
|
||||
#: frontend/src/components/Activities/AttachmentArea.vue:128
|
||||
msgid "Are you sure you want to delete this attachment?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil slette dette vedlegget?"
|
||||
|
||||
#: frontend/src/pages/MobileContact.vue:260
|
||||
msgid "Are you sure you want to delete this contact?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du ønsker å slette denne kontakten?"
|
||||
|
||||
#: frontend/src/components/Modals/EventModal.vue:408
|
||||
#: frontend/src/pages/Calendar.vue:300
|
||||
msgid "Are you sure you want to delete this event?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil slette denne hendelsen?"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:261
|
||||
msgid "Are you sure you want to delete this organization?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil slette denne organisasjonen?"
|
||||
|
||||
#: frontend/src/components/Activities/TaskArea.vue:60
|
||||
msgid "Are you sure you want to delete this task?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil slette denne oppgaven?"
|
||||
|
||||
#: frontend/src/components/DeleteLinkedDocModal.vue:231
|
||||
msgid "Are you sure you want to delete {0} linked item(s)?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil slette {0} linkede element(er)?"
|
||||
|
||||
#: frontend/src/components/Calendar/CalendarEventPanel.vue:615
|
||||
msgid "Are you sure you want to discard unsaved changes to this event?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil forkaste ikke-lagrede endringer i denne hendelsen?"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssignmentRuleView.vue:561
|
||||
msgid "Are you sure you want to go back? Unsaved changes will be lost."
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil gå tilbake? Ikke-lagrede endringer vil gå tapt."
|
||||
|
||||
#: frontend/src/composables/frappecloud.js:24
|
||||
msgid "Are you sure you want to login to your Frappe Cloud dashboard?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil logge inn på Frappe Cloud-dashbordet ditt?"
|
||||
|
||||
#: crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.js:9
|
||||
msgid "Are you sure you want to reset 'Create Quotation from CRM Deal' Form Script?"
|
||||
@ -549,11 +549,11 @@ msgstr "Er du sikker på at du vil tilbakestille skjemaskriptet \"Opprett tilbud
|
||||
|
||||
#: frontend/src/components/Settings/General/CurrencySettings.vue:174
|
||||
msgid "Are you sure you want to set the currency as {0}? This cannot be changed later."
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil angi valutaen som {0}? Dette kan ikke endres senere."
|
||||
|
||||
#: frontend/src/components/DeleteLinkedDocModal.vue:244
|
||||
msgid "Are you sure you want to unlink {0} linked item(s)?"
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på at du vil fjerne koblingen til {0} lenkede elementer?"
|
||||
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.py:193
|
||||
msgid "Ask your manager to set up the Exchange Rate Provider, as default provider does not support currency conversion for {0} to {1}."
|
||||
@ -1067,7 +1067,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/FilesUploader/FilesUploader.vue:91
|
||||
msgid "Capture"
|
||||
msgstr ""
|
||||
msgstr "Ta bilde"
|
||||
|
||||
#: frontend/src/components/Layouts/AppSidebar.vue:561
|
||||
msgid "Capturing leads"
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -1754,7 +1754,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssigneeRules.vue:9
|
||||
msgid "Define who receives the tickets and how they’re distributed among agents."
|
||||
msgstr ""
|
||||
msgstr "Definer hvem som skal motta billettene og hvordan de skal fordeles mellom agentene."
|
||||
|
||||
#: frontend/src/components/Activities/AttachmentArea.vue:131
|
||||
#: frontend/src/components/Activities/NoteArea.vue:12
|
||||
@ -1822,7 +1822,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Settings/InviteUserPage.vue:84
|
||||
msgid "Delete invitation"
|
||||
msgstr ""
|
||||
msgstr "Slett invitasjon"
|
||||
|
||||
#: frontend/src/components/DeleteLinkedDocModal.vue:230
|
||||
msgid "Delete linked item"
|
||||
@ -1887,7 +1887,7 @@ msgstr "Detaljer"
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/components/FilesUploader/FilesUploaderArea.vue:39
|
||||
msgid "Device"
|
||||
msgstr ""
|
||||
msgstr "Enhet"
|
||||
|
||||
#: crm/fcrm/doctype/crm_form_script/crm_form_script.js:30
|
||||
msgid "Disable"
|
||||
@ -1911,7 +1911,7 @@ msgstr ""
|
||||
#. Label of the discount_percentage (Percent) field in DocType 'CRM Products'
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
msgid "Discount %"
|
||||
msgstr ""
|
||||
msgstr "Rabatt %"
|
||||
|
||||
#. Label of the discount_amount (Currency) field in DocType 'CRM Products'
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
@ -1961,7 +1961,7 @@ msgstr ""
|
||||
#: frontend/src/components/Activities/AudioPlayer.vue:166
|
||||
#: frontend/src/components/ViewControls.vue:254
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
msgstr "Last ned"
|
||||
|
||||
#: frontend/src/components/FilesUploader/FilesUploaderArea.vue:24
|
||||
msgid "Drag and drop files here or upload from"
|
||||
@ -2053,7 +2053,7 @@ msgstr "ERPNext er ikke integrert med CRM-systemet"
|
||||
|
||||
#: frontend/src/components/Settings/ERPNextSettings.vue:4
|
||||
msgid "ERPNext settings"
|
||||
msgstr "ERPNext-innstillinger"
|
||||
msgstr "ERPNext innstillinger"
|
||||
|
||||
#: frontend/src/components/Settings/ERPNextSettings.vue:5
|
||||
msgid "ERPNext settings updated"
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -2228,7 +2228,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Filter.vue:123
|
||||
msgid "Empty - Choose a field to filter by"
|
||||
msgstr ""
|
||||
msgstr "Tom - Velg et felt å filtrere etter"
|
||||
|
||||
#: frontend/src/components/SortBy.vue:130
|
||||
msgid "Empty - Choose a field to sort by"
|
||||
@ -2236,7 +2236,7 @@ msgstr ""
|
||||
|
||||
#: crm/fcrm/doctype/crm_form_script/crm_form_script.js:30
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
msgstr "Aktiver"
|
||||
|
||||
#. Label of the enable_forecasting (Check) field in DocType 'FCRM Settings'
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||
@ -2253,7 +2253,7 @@ msgstr "Aktiver utgående e-post"
|
||||
|
||||
#: frontend/src/components/Settings/General/GeneralSettings.vue:19
|
||||
msgid "Enable forecasting"
|
||||
msgstr ""
|
||||
msgstr "Aktiver prognoser"
|
||||
|
||||
#. Label of the enabled (Check) field in DocType 'CRM Exotel Settings'
|
||||
#. Label of the enabled (Check) field in DocType 'CRM Form Script'
|
||||
@ -2278,7 +2278,7 @@ msgstr "Aktivert"
|
||||
#. Label of the end_date (Date) field in DocType 'CRM Service Level Agreement'
|
||||
#: crm/fcrm/doctype/crm_service_level_agreement/crm_service_level_agreement.json
|
||||
msgid "End Date"
|
||||
msgstr ""
|
||||
msgstr "Sluttdato"
|
||||
|
||||
#. Label of the end_time (Datetime) field in DocType 'CRM Call Log'
|
||||
#. Label of the end_time (Time) field in DocType 'CRM Service Day'
|
||||
@ -2287,19 +2287,19 @@ msgstr ""
|
||||
#: frontend/src/components/Calendar/CalendarEventPanel.vue:242
|
||||
#: frontend/src/components/Modals/EventModal.vue:112
|
||||
msgid "End Time"
|
||||
msgstr ""
|
||||
msgstr "Sluttidspunkt"
|
||||
|
||||
#: frontend/src/composables/event.js:206
|
||||
msgid "End time should be after start time"
|
||||
msgstr ""
|
||||
msgstr "Sluttidspunkt må være etter starttidspunkt"
|
||||
|
||||
#: frontend/src/components/Settings/General/CurrencySettings.vue:122
|
||||
msgid "Enter access key"
|
||||
msgstr ""
|
||||
msgstr "Angi tilgangsnøkkel"
|
||||
|
||||
#: frontend/src/components/FieldLayout/Field.vue:339
|
||||
msgid "Enter {0}"
|
||||
msgstr ""
|
||||
msgstr "Angi {0}"
|
||||
|
||||
#: frontend/src/components/Filter.vue:66 frontend/src/components/Filter.vue:99
|
||||
#: frontend/src/components/Filter.vue:267
|
||||
@ -2313,12 +2313,12 @@ msgstr "Tilsvarer"
|
||||
|
||||
#: frontend/src/components/Modals/ConvertToDealModal.vue:176
|
||||
msgid "Error converting to deal: {0}"
|
||||
msgstr ""
|
||||
msgstr "Feil ved konvertering til avtale: {0}"
|
||||
|
||||
#: frontend/src/pages/Deal.vue:731 frontend/src/pages/Lead.vue:469
|
||||
#: frontend/src/pages/MobileDeal.vue:612 frontend/src/pages/MobileLead.vue:413
|
||||
msgid "Error updating field"
|
||||
msgstr ""
|
||||
msgstr "Feil ved oppdatering av felt"
|
||||
|
||||
#: crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py:279
|
||||
msgid "Error while creating customer in ERPNext, check error log for more details"
|
||||
@ -2364,11 +2364,11 @@ msgstr ""
|
||||
#. 'FCRM Settings'
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||
msgid "Exchange Rate Provider"
|
||||
msgstr ""
|
||||
msgstr "Valutakursleverandør"
|
||||
|
||||
#: frontend/src/components/Settings/General/CurrencySettings.vue:67
|
||||
msgid "Exchange rate provider"
|
||||
msgstr ""
|
||||
msgstr "Valutakursleverandør"
|
||||
|
||||
#. Option for the 'Telephony Medium' (Select) field in DocType 'CRM Call Log'
|
||||
#. Label of the exotel (Check) field in DocType 'CRM Telephony Agent'
|
||||
@ -2384,20 +2384,20 @@ msgstr ""
|
||||
|
||||
#: crm/integrations/exotel/handler.py:114
|
||||
msgid "Exotel Exception"
|
||||
msgstr ""
|
||||
msgstr "Exotel-unntak"
|
||||
|
||||
#. Label of the exotel_number (Data) field in DocType 'CRM Telephony Agent'
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
msgid "Exotel Number"
|
||||
msgstr ""
|
||||
msgstr "Exotel-nummer"
|
||||
|
||||
#: crm/integrations/exotel/handler.py:85
|
||||
msgid "Exotel Number Missing"
|
||||
msgstr ""
|
||||
msgstr "Exotel-nummer mangler"
|
||||
|
||||
#: crm/integrations/exotel/handler.py:89
|
||||
msgid "Exotel Number {0} is not valid"
|
||||
msgstr ""
|
||||
msgstr "Exotel-nummer {0} er ikke gyldig"
|
||||
|
||||
#: frontend/src/components/Settings/TelephonySettings.vue:293
|
||||
msgid "Exotel is not enabled"
|
||||
@ -2468,7 +2468,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Modals/AddExistingUserModal.vue:111
|
||||
msgid "Failed to add users"
|
||||
msgstr ""
|
||||
msgstr "Kunne ikke legge til brukere"
|
||||
|
||||
#: crm/integrations/twilio/api.py:130
|
||||
msgid "Failed to capture Twilio recording"
|
||||
@ -2488,11 +2488,11 @@ msgstr ""
|
||||
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.py:205
|
||||
msgid "Failed to fetch exchange rate from {0} to {1} on {2}. Please check your internet connection or try again later."
|
||||
msgstr ""
|
||||
msgstr "Kunne ikke hente valutakurs fra {0} til {1} på {2}. Vennligst sjekk internettforbindelsen din eller prøv igjen senere."
|
||||
|
||||
#: frontend/src/data/script.js:106
|
||||
msgid "Failed to load form controller: {0}"
|
||||
msgstr ""
|
||||
msgstr "Kunne ikke laste inn skjemakontroller: {0}"
|
||||
|
||||
#: frontend/src/components/Settings/EmailTemplate/EditEmailTemplate.vue:246
|
||||
msgid "Failed to rename template"
|
||||
@ -2523,7 +2523,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||
#: frontend/src/components/Settings/General/BrandSettings.vue:81
|
||||
msgid "Favicon"
|
||||
msgstr ""
|
||||
msgstr "Favicon"
|
||||
|
||||
#: frontend/src/components/ConditionsFilter/CFCondition.vue:38
|
||||
#: frontend/src/components/Modals/EditValueModal.vue:5
|
||||
@ -2533,7 +2533,7 @@ msgstr "Felt"
|
||||
#: frontend/src/components/Controls/GridFieldsEditorModal.vue:19
|
||||
#: frontend/src/components/Kanban/KanbanSettings.vue:48
|
||||
msgid "Fields Order"
|
||||
msgstr ""
|
||||
msgstr "Feltrekkefølge"
|
||||
|
||||
#: frontend/src/components/FilesUploader/FilesUploaderArea.vue:333
|
||||
msgid "File \"{0}\" was skipped because of invalid file type"
|
||||
@ -2541,11 +2541,11 @@ msgstr "Filen «{0}» ble hoppet over på grunn av ugyldig filtype"
|
||||
|
||||
#: frontend/src/components/FilesUploader/FilesUploaderArea.vue:354
|
||||
msgid "File \"{0}\" was skipped because only {1} uploads are allowed"
|
||||
msgstr ""
|
||||
msgstr "Filen \"{0}\" ble hoppet over fordi bare {1} -opplastinger er tillatt"
|
||||
|
||||
#: frontend/src/components/FilesUploader/FilesUploaderArea.vue:359
|
||||
msgid "File \"{0}\" was skipped because only {1} uploads are allowed for DocType \"{2}\""
|
||||
msgstr ""
|
||||
msgstr "Filen \"{0}\" ble hoppet over fordi bare {1} -opplastinger er tillatt for DocType \"{2}\""
|
||||
|
||||
#: frontend/src/components/Filter.vue:6
|
||||
msgid "Filter"
|
||||
@ -2555,7 +2555,7 @@ msgstr "Filter"
|
||||
#. Label of the filters_tab (Tab Break) field in DocType 'CRM View Settings'
|
||||
#: crm/fcrm/doctype/crm_view_settings/crm_view_settings.json
|
||||
msgid "Filters"
|
||||
msgstr ""
|
||||
msgstr "Filtre"
|
||||
|
||||
#. Label of the first_name (Data) field in DocType 'CRM Deal'
|
||||
#. Label of the first_name (Data) field in DocType 'CRM Lead'
|
||||
@ -2590,7 +2590,7 @@ msgstr ""
|
||||
#. Level Priority'
|
||||
#: crm/fcrm/doctype/crm_service_level_priority/crm_service_level_priority.json
|
||||
msgid "First Response TIme"
|
||||
msgstr ""
|
||||
msgstr "Første responstid"
|
||||
|
||||
#. Label of the first_response_time (Duration) field in DocType 'CRM Deal'
|
||||
#. Label of the first_response_time (Duration) field in DocType 'CRM Lead'
|
||||
@ -2602,7 +2602,7 @@ msgstr ""
|
||||
#: frontend/src/components/Filter.vue:130
|
||||
#: frontend/src/components/Settings/ProfileSettings.vue:78
|
||||
msgid "First name"
|
||||
msgstr ""
|
||||
msgstr "Fornavn"
|
||||
|
||||
#: frontend/src/components/Settings/EmailTemplate/EditEmailTemplate.vue:51
|
||||
#: frontend/src/components/Settings/EmailTemplate/EmailTemplates.vue:84
|
||||
@ -2617,11 +2617,11 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Settings/General/GeneralSettings.vue:100
|
||||
msgid "Forecasting disabled successfully"
|
||||
msgstr ""
|
||||
msgstr "Prognoser er deaktivert"
|
||||
|
||||
#: frontend/src/components/Settings/General/GeneralSettings.vue:99
|
||||
msgid "Forecasting enabled successfully"
|
||||
msgstr ""
|
||||
msgstr "Prognoser er aktivert"
|
||||
|
||||
#. Option for the 'Apply To' (Select) field in DocType 'CRM Form Script'
|
||||
#: crm/fcrm/doctype/crm_form_script/crm_form_script.json
|
||||
@ -2646,7 +2646,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_holiday_list/crm_holiday_list.json
|
||||
#: crm/fcrm/doctype/crm_service_day/crm_service_day.json
|
||||
msgid "Friday"
|
||||
msgstr ""
|
||||
msgstr "Fredag"
|
||||
|
||||
#. Label of the from (Data) field in DocType 'CRM Call Log'
|
||||
#. Label of the from (Data) field in DocType 'CRM Status Change Log'
|
||||
@ -2670,7 +2670,7 @@ msgstr ""
|
||||
#. Label of the from_user (Link) field in DocType 'CRM Notification'
|
||||
#: crm/fcrm/doctype/crm_notification/crm_notification.json
|
||||
msgid "From User"
|
||||
msgstr ""
|
||||
msgstr "Fra bruker"
|
||||
|
||||
#. Option for the 'SLA Status' (Select) field in DocType 'CRM Deal'
|
||||
#. Option for the 'SLA Status' (Select) field in DocType 'CRM Lead'
|
||||
@ -2689,7 +2689,7 @@ msgstr "Fullt navn"
|
||||
#: crm/api/dashboard.py:728
|
||||
#: frontend/src/components/Dashboard/AddChartModal.vue:96
|
||||
msgid "Funnel conversion"
|
||||
msgstr ""
|
||||
msgstr "Traktkonvertering"
|
||||
|
||||
#: frontend/src/components/Calendar/CalendarEventPanel.vue:196
|
||||
msgid "GMT+5:30"
|
||||
@ -2822,7 +2822,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/FieldLayoutEditor.vue:354
|
||||
msgid "Hide border"
|
||||
msgstr ""
|
||||
msgstr "Skjul grensen"
|
||||
|
||||
#: frontend/src/components/FieldLayoutEditor.vue:349
|
||||
msgid "Hide label"
|
||||
@ -2844,7 +2844,7 @@ msgstr ""
|
||||
#. Agreement'
|
||||
#: crm/fcrm/doctype/crm_service_level_agreement/crm_service_level_agreement.json
|
||||
msgid "Holiday List"
|
||||
msgstr ""
|
||||
msgstr "Ferieliste"
|
||||
|
||||
#. Label of the holiday_list_name (Data) field in DocType 'CRM Holiday List'
|
||||
#: crm/fcrm/doctype/crm_holiday_list/crm_holiday_list.json
|
||||
@ -2861,12 +2861,12 @@ msgstr ""
|
||||
#: frontend/src/components/Layouts/AppSidebar.vue:542
|
||||
#: frontend/src/components/Settings/General/HomeActions.vue:9
|
||||
msgid "Home actions"
|
||||
msgstr ""
|
||||
msgstr "Handlinger på Hjem-siden"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssignmentRuleView.vue:204
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssignmentRuleView.vue:285
|
||||
msgid "I understand, add conditions"
|
||||
msgstr ""
|
||||
msgstr "Jeg forstår, legg til betingelser"
|
||||
|
||||
#. Label of the id (Data) field in DocType 'CRM Call Log'
|
||||
#: crm/fcrm/doctype/crm_call_log/crm_call_log.json
|
||||
@ -2966,12 +2966,12 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/EmailEditor.vue:154
|
||||
msgid "Insert Email Template"
|
||||
msgstr ""
|
||||
msgstr "Sett inn e-postmal"
|
||||
|
||||
#: frontend/src/components/CommentBox.vue:49
|
||||
#: frontend/src/components/EmailEditor.vue:130
|
||||
msgid "Insert Emoji"
|
||||
msgstr ""
|
||||
msgstr "Sett inn emoji"
|
||||
|
||||
#: frontend/src/components/Layouts/AppSidebar.vue:598
|
||||
msgid "Integration"
|
||||
@ -2979,7 +2979,7 @@ msgstr "Integrasjon"
|
||||
|
||||
#: crm/integrations/exotel/handler.py:73
|
||||
msgid "Integration Not Enabled"
|
||||
msgstr ""
|
||||
msgstr "Integrasjon ikke aktivert"
|
||||
|
||||
#: frontend/src/components/Settings/Settings.vue:131
|
||||
msgctxt "FCRM"
|
||||
@ -3002,7 +3002,7 @@ msgstr ""
|
||||
|
||||
#: crm/integrations/exotel/handler.py:89
|
||||
msgid "Invalid Exotel Number"
|
||||
msgstr ""
|
||||
msgstr "Ugyldig Exotel-nummer"
|
||||
|
||||
#: crm/api/dashboard.py:73
|
||||
msgid "Invalid chart name"
|
||||
@ -3022,7 +3022,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/InvalidPage.vue:6
|
||||
msgid "Invalid page or not permitted to access"
|
||||
msgstr ""
|
||||
msgstr "Ugyldig side eller manglende rettigheter"
|
||||
|
||||
#: frontend/src/composables/event.js:203
|
||||
msgid "Invalid start or end time"
|
||||
@ -3030,11 +3030,11 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Settings/Users.vue:25
|
||||
msgid "Invite New User"
|
||||
msgstr ""
|
||||
msgstr "Inviter ny bruker"
|
||||
|
||||
#: frontend/src/components/Settings/Settings.vue:107
|
||||
msgid "Invite User"
|
||||
msgstr ""
|
||||
msgstr "Inviter bruker"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssigneeSearch.vue:78
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssigneeSearch.vue:149
|
||||
@ -3043,19 +3043,19 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Settings/InviteUserPage.vue:56
|
||||
msgid "Invite as"
|
||||
msgstr ""
|
||||
msgstr "Inviter som"
|
||||
|
||||
#: frontend/src/components/Settings/InviteUserPage.vue:29
|
||||
msgid "Invite by email"
|
||||
msgstr ""
|
||||
msgstr "Invitasjon via e-post"
|
||||
|
||||
#: frontend/src/components/Layouts/AppSidebar.vue:543
|
||||
msgid "Invite users"
|
||||
msgstr ""
|
||||
msgstr "Inviter brukere"
|
||||
|
||||
#: frontend/src/components/Settings/InviteUserPage.vue:10
|
||||
msgid "Invite users to access CRM. Specify their roles to control access and permissions"
|
||||
msgstr ""
|
||||
msgstr "Inviter brukere til å få tilgang til CRM. Spesifiser rollene deres for å kontrollere tilgang og tillatelser"
|
||||
|
||||
#: frontend/src/components/Layouts/AppSidebar.vue:359
|
||||
msgid "Invite your team"
|
||||
@ -3090,13 +3090,13 @@ msgstr "Er ERPNext installert på et annet nettsted?"
|
||||
#. Label of the is_group (Check) field in DocType 'CRM Territory'
|
||||
#: crm/fcrm/doctype/crm_territory/crm_territory.json
|
||||
msgid "Is Group"
|
||||
msgstr ""
|
||||
msgstr "Er gruppe"
|
||||
|
||||
#. Label of the is_helpdesk_in_different_site (Check) field in DocType
|
||||
#. 'Helpdesk CRM Settings'
|
||||
#: crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.json
|
||||
msgid "Is Helpdesk installed on a different site?"
|
||||
msgstr ""
|
||||
msgstr "Er Helpdesk installert på et annet nettsted?"
|
||||
|
||||
#. Label of the is_primary (Check) field in DocType 'CRM Contacts'
|
||||
#. Label of the is_primary (Check) field in DocType 'CRM Telephony Phone'
|
||||
@ -3123,7 +3123,7 @@ msgstr ""
|
||||
#. Label of the json (JSON) field in DocType 'CRM Global Settings'
|
||||
#: crm/fcrm/doctype/crm_global_settings/crm_global_settings.json
|
||||
msgid "JSON"
|
||||
msgstr ""
|
||||
msgstr "JSON"
|
||||
|
||||
#. Label of the job_title (Data) field in DocType 'CRM Deal'
|
||||
#. Label of the job_title (Data) field in DocType 'CRM Lead'
|
||||
@ -3165,7 +3165,7 @@ msgstr "Innstillinger for Kanban-tavle"
|
||||
#. Label of the key (Data) field in DocType 'CRM Invitation'
|
||||
#: crm/fcrm/doctype/crm_invitation/crm_invitation.json
|
||||
msgid "Key"
|
||||
msgstr ""
|
||||
msgstr "Nøkkel"
|
||||
|
||||
#. Label of the label (Data) field in DocType 'CRM Dropdown Item'
|
||||
#. Label of the label (Data) field in DocType 'CRM View Settings'
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3246,7 +3246,7 @@ msgstr ""
|
||||
#: frontend/src/components/Telephony/ExotelCallUI.vue:200
|
||||
#: frontend/src/pages/Tasks.vue:133
|
||||
msgid "Lead"
|
||||
msgstr ""
|
||||
msgstr "Potensiell kunde"
|
||||
|
||||
#. Label of the lead_details_tab (Tab Break) field in DocType 'CRM Deal'
|
||||
#: crm/fcrm/doctype/crm_deal/crm_deal.json
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Ingen {0} funnet"
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -4832,7 +4832,7 @@ msgstr ""
|
||||
#: frontend/src/components/ViewControls.vue:125
|
||||
#: frontend/src/pages/Dashboard.vue:36
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
msgstr "Lagre"
|
||||
|
||||
#: frontend/src/components/Modals/ViewModal.vue:40
|
||||
#: frontend/src/components/ViewControls.vue:58
|
||||
@ -4904,7 +4904,7 @@ msgstr "Velg {0}"
|
||||
|
||||
#: frontend/src/components/EmailEditor.vue:165
|
||||
msgid "Send"
|
||||
msgstr ""
|
||||
msgstr "Send"
|
||||
|
||||
#: frontend/src/components/Settings/InviteUserPage.vue:18
|
||||
msgid "Send Invites"
|
||||
@ -4934,7 +4934,7 @@ msgstr ""
|
||||
#. Label of the naming_series (Select) field in DocType 'CRM Lead'
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
msgid "Series"
|
||||
msgstr ""
|
||||
msgstr "Nummerserie"
|
||||
|
||||
#. Label of the service_provider (Select) field in DocType 'FCRM Settings'
|
||||
#: crm/fcrm/doctype/fcrm_settings/fcrm_settings.json
|
||||
@ -5177,9 +5177,9 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
msgstr "Status"
|
||||
|
||||
#. Label of the status_change_log (Table) field in DocType 'CRM Deal'
|
||||
#. Label of the status_change_log (Table) field in DocType 'CRM Lead'
|
||||
@ -5326,7 +5326,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_organization/crm_organization.json
|
||||
msgid "Territory"
|
||||
msgstr ""
|
||||
msgstr "Territorium"
|
||||
|
||||
#. Label of the territory_manager (Link) field in DocType 'CRM Territory'
|
||||
#: crm/fcrm/doctype/crm_territory/crm_territory.json
|
||||
@ -5478,7 +5478,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Modals/SidePanelModal.vue:59
|
||||
msgid "Toggle on for preview"
|
||||
msgstr ""
|
||||
msgstr "Slå på for forhåndsvisning"
|
||||
|
||||
#: frontend/src/components/Filter.vue:631
|
||||
msgid "Tomorrow"
|
||||
@ -5685,7 +5685,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/TelephonySettings.vue:23
|
||||
#: frontend/src/components/Telephony/ExotelCallUI.vue:210
|
||||
msgid "Update"
|
||||
msgstr ""
|
||||
msgstr "Oppdater"
|
||||
|
||||
#: frontend/src/components/Settings/EmailEdit.vue:74
|
||||
msgid "Update Account"
|
||||
@ -5732,7 +5732,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: crm/fcrm/doctype/crm_view_settings/crm_view_settings.json
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
msgstr "Bruker"
|
||||
|
||||
#. Label of the user_name (Data) field in DocType 'CRM Telephony Agent'
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
@ -5787,7 +5787,7 @@ msgstr ""
|
||||
#. Settings'
|
||||
#: crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json
|
||||
msgid "Webhook Verify Token"
|
||||
msgstr ""
|
||||
msgstr "Webhook-verifiseringstoken"
|
||||
|
||||
#. Label of the website (Data) field in DocType 'CRM Deal'
|
||||
#. Label of the website (Data) field in DocType 'CRM Lead'
|
||||
@ -5797,7 +5797,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_organization/crm_organization.json
|
||||
#: frontend/src/components/Modals/AboutModal.vue:52
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
msgstr "Nettsted"
|
||||
|
||||
#. Option for the 'Weekly Off' (Select) field in DocType 'CRM Holiday List'
|
||||
#. Option for the 'Workday' (Select) field in DocType 'CRM Service Day'
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Dutch\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Polish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Ostatni rok"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-15 19:46\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-17 20:27\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Montante"
|
||||
|
||||
@ -588,7 +588,7 @@ msgstr "Atribuído a"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssigneeRules.vue:5
|
||||
msgid "Assignee Rules"
|
||||
msgstr ""
|
||||
msgstr "Regras de Atribuição"
|
||||
|
||||
#: frontend/src/components/Settings/AssignmentRules/AssigneeRules.vue:75
|
||||
msgid "Assignees"
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Último ano"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Última modificação"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Nr. de Telemóvel"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "{0} não disponível"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "{0} não encontrado"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Ordenar por"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organização"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Logótipo da organização"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organizações"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Pessoa"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefone"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Estado"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Montante"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Ano passado"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr "Ordenar Por"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organização"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefone"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Russian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Не найдено {0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-09 18:08\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Serbian (Cyrillic)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "Цео дан"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Износ"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "Анализа канала за генерисање пословних
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "Власник пословне прилике"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr "Уређивање догађаја"
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "Имејл"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Прошла година"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Последњи пут измењено"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "Инсталација мобилне апликације"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Број мобилног телефона"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "Моје отворене пословне прилике"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Назив"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "Нису пронађени корисници"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "Није пронађен веб-сајт"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "Нема доступних {0}"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Није пронађен ниједан {0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Наруџбина од"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Организација"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Лого организације"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Организације"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Особа"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Телефон"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr "Започни са 10 пробних потенцијалних кли
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Статус"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-09 18:08\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Serbian (Latin)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "Ceo dan"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Iznos"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "Analiza kanala za generisanje poslovnih prilika"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "Vlasnik poslovne prilike"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr "Uređivanje događaja"
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "Imejl"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Prošla godina"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Poslednji put izmenjeno"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "Instalacija mobilne aplikacije"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Broj mobilnog telefona"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "Moje otvorene poslovne prilike"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Naziv"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "Nisu pronađeni korisnici"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "Nije pronađen veb-sajt"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "Nema dostupnih {0}"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "Nije pronađen nijedan {0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Narudžbina od"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organizacija"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Logo organizacije"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organizacije"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Osoba"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefon"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr "Započni sa 10 probnih potencijalnih klijenata"
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Swedish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr "Hela dagen"
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Belopp"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr "Affär generering kanal analys"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "Affär Ansvarig"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr "Redigerar händelse"
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-post"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Förra Året"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "Senast ändrad"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr "Mobil App Installation"
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "Mobilnummer"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "Mina Öppna Affärer"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Namn"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr "Inga användare hittades"
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr "Ingen webbplats hittades"
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "Ingen {0} Tillgänglig"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "{0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Sortera Efter"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "Organisation Logotyp"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "Organisationer"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "Person"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefon"
|
||||
|
||||
@ -5183,7 +5183,7 @@ msgstr "Börja med exempel på 10 potentiella kunder"
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:03\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Thai\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "จำนวน"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "อีเมล"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "ปีที่แล้ว"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "ชื่อ"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "ไม่พบ {0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "เรียงตาม"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "องค์กร"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "โทรศัพท์"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "สถานะ"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-11 18:51\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Turkish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "Tutar"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "E-posta"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "Geçen Yıl"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "Adı"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "{0} Bulunamadı"
|
||||
@ -4112,8 +4112,8 @@ msgstr "Sipariş Veren"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "Organizasyon"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "Telefon"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "Durum"
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Vietnamese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr ""
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr ""
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr ""
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr ""
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr ""
|
||||
@ -4112,8 +4112,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr ""
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr ""
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: shariq@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-09-07 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-07 17:34\n"
|
||||
"POT-Creation-Date: 2025-09-14 09:35+0000\n"
|
||||
"PO-Revision-Date: 2025-09-16 20:02\n"
|
||||
"Last-Translator: shariq@frappe.io\n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -430,7 +430,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_products/crm_products.json
|
||||
#: frontend/src/pages/Contact.vue:499 frontend/src/pages/MobileContact.vue:507
|
||||
#: frontend/src/pages/MobileOrganization.vue:451
|
||||
#: frontend/src/pages/Organization.vue:458
|
||||
#: frontend/src/pages/Organization.vue:472
|
||||
msgid "Amount"
|
||||
msgstr "金额"
|
||||
|
||||
@ -1645,7 +1645,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:520 frontend/src/pages/MobileContact.vue:528
|
||||
#: frontend/src/pages/MobileOrganization.vue:472
|
||||
#: frontend/src/pages/Organization.vue:479
|
||||
#: frontend/src/pages/Organization.vue:493
|
||||
msgid "Deal owner"
|
||||
msgstr "商机负责人"
|
||||
|
||||
@ -2166,8 +2166,8 @@ msgstr ""
|
||||
#: frontend/src/pages/MobileContact.vue:518
|
||||
#: frontend/src/pages/MobileOrganization.vue:462
|
||||
#: frontend/src/pages/MobileOrganization.vue:490
|
||||
#: frontend/src/pages/Organization.vue:469
|
||||
#: frontend/src/pages/Organization.vue:497
|
||||
#: frontend/src/pages/Organization.vue:483
|
||||
#: frontend/src/pages/Organization.vue:511
|
||||
msgid "Email"
|
||||
msgstr "电子邮件"
|
||||
|
||||
@ -3215,8 +3215,8 @@ msgstr "去年"
|
||||
#: frontend/src/pages/Contact.vue:525 frontend/src/pages/MobileContact.vue:533
|
||||
#: frontend/src/pages/MobileOrganization.vue:477
|
||||
#: frontend/src/pages/MobileOrganization.vue:505
|
||||
#: frontend/src/pages/Organization.vue:484
|
||||
#: frontend/src/pages/Organization.vue:512
|
||||
#: frontend/src/pages/Organization.vue:498
|
||||
#: frontend/src/pages/Organization.vue:526
|
||||
msgid "Last modified"
|
||||
msgstr "最后修改"
|
||||
|
||||
@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/Contact.vue:515 frontend/src/pages/MobileContact.vue:523
|
||||
#: frontend/src/pages/MobileOrganization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:474
|
||||
#: frontend/src/pages/Organization.vue:488
|
||||
msgid "Mobile no"
|
||||
msgstr "手机号"
|
||||
|
||||
@ -3628,7 +3628,7 @@ msgstr "我负责的开放商机"
|
||||
#: frontend/src/components/Settings/EmailTemplate/NewEmailTemplate.vue:42
|
||||
#: frontend/src/components/ViewControls.vue:779
|
||||
#: frontend/src/pages/MobileOrganization.vue:485
|
||||
#: frontend/src/pages/Organization.vue:492
|
||||
#: frontend/src/pages/Organization.vue:506
|
||||
msgid "Name"
|
||||
msgstr "名称"
|
||||
|
||||
@ -3866,7 +3866,7 @@ msgid "No users found"
|
||||
msgstr ""
|
||||
|
||||
#: frontend/src/pages/MobileOrganization.vue:281
|
||||
#: frontend/src/pages/Organization.vue:295
|
||||
#: frontend/src/pages/Organization.vue:309
|
||||
msgid "No website found"
|
||||
msgstr ""
|
||||
|
||||
@ -3882,7 +3882,7 @@ msgstr "无可用{0}"
|
||||
#: frontend/src/pages/Contacts.vue:58 frontend/src/pages/Deals.vue:234
|
||||
#: frontend/src/pages/Leads.vue:260 frontend/src/pages/MobileContact.vue:147
|
||||
#: frontend/src/pages/MobileOrganization.vue:139
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:151
|
||||
#: frontend/src/pages/Notes.vue:95 frontend/src/pages/Organization.vue:152
|
||||
#: frontend/src/pages/Organizations.vue:58 frontend/src/pages/Tasks.vue:184
|
||||
msgid "No {0} Found"
|
||||
msgstr "未找到{0}"
|
||||
@ -4112,8 +4112,8 @@ msgstr "排序依据"
|
||||
#: frontend/src/pages/MobileLead.vue:118
|
||||
#: frontend/src/pages/MobileOrganization.vue:446
|
||||
#: frontend/src/pages/MobileOrganization.vue:500
|
||||
#: frontend/src/pages/Organization.vue:453
|
||||
#: frontend/src/pages/Organization.vue:507
|
||||
#: frontend/src/pages/Organization.vue:467
|
||||
#: frontend/src/pages/Organization.vue:521
|
||||
msgid "Organization"
|
||||
msgstr "组织"
|
||||
|
||||
@ -4143,7 +4143,7 @@ msgstr "组织徽标"
|
||||
#. Label of a shortcut in the Frappe CRM Workspace
|
||||
#: crm/fcrm/workspace/frappe_crm/frappe_crm.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:205
|
||||
#: frontend/src/pages/Organization.vue:233
|
||||
#: frontend/src/pages/Organization.vue:234
|
||||
msgid "Organizations"
|
||||
msgstr "组织"
|
||||
|
||||
@ -4237,7 +4237,7 @@ msgstr "个人"
|
||||
#: crm/fcrm/doctype/crm_lead/crm_lead.json
|
||||
#: crm/fcrm/doctype/crm_telephony_agent/crm_telephony_agent.json
|
||||
#: frontend/src/pages/MobileOrganization.vue:495
|
||||
#: frontend/src/pages/Organization.vue:502
|
||||
#: frontend/src/pages/Organization.vue:516
|
||||
msgid "Phone"
|
||||
msgstr "电话"
|
||||
|
||||
@ -5177,7 +5177,7 @@ msgstr ""
|
||||
#: crm/fcrm/doctype/crm_task/crm_task.json frontend/src/pages/Contact.vue:505
|
||||
#: frontend/src/pages/MobileContact.vue:513
|
||||
#: frontend/src/pages/MobileOrganization.vue:457
|
||||
#: frontend/src/pages/Organization.vue:464
|
||||
#: frontend/src/pages/Organization.vue:478
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
|
||||
@ -15,4 +15,5 @@ crm.patches.v1_0.move_twilio_agent_to_telephony_agent
|
||||
crm.patches.v1_0.create_default_scripts # 13-06-2025
|
||||
crm.patches.v1_0.update_deal_status_probabilities
|
||||
crm.patches.v1_0.update_deal_status_type
|
||||
crm.patches.v1_0.create_default_lost_reasons
|
||||
crm.patches.v1_0.create_default_lost_reasons
|
||||
crm.patches.v1_0.add_fields_in_assignment_rule
|
||||
|
||||
9
crm/patches/v1_0/add_fields_in_assignment_rule.py
Normal file
9
crm/patches/v1_0/add_fields_in_assignment_rule.py
Normal file
@ -0,0 +1,9 @@
|
||||
from crm.install import (
|
||||
add_assignment_rule_property_setters,
|
||||
create_assignment_rule_custom_fields,
|
||||
)
|
||||
|
||||
|
||||
def execute():
|
||||
create_assignment_rule_custom_fields()
|
||||
add_assignment_rule_property_setters()
|
||||
@ -1 +1 @@
|
||||
Subproject commit 02fc126fd5c49f0ecf6cce117585f89c4ea585c3
|
||||
Subproject commit c9a0fc937cc897864857271b3708a0c675379015
|
||||
3
frontend/.gitignore
vendored
3
frontend/.gitignore
vendored
@ -2,4 +2,5 @@ node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
*.local
|
||||
components.d.ts
|
||||
10
frontend/components.d.ts
vendored
10
frontend/components.d.ts
vendored
@ -33,7 +33,7 @@ declare module 'vue' {
|
||||
Autocomplete: typeof import('./src/components/frappe-ui/Autocomplete.vue')['default']
|
||||
AvatarIcon: typeof import('./src/components/Icons/AvatarIcon.vue')['default']
|
||||
BrandLogo: typeof import('./src/components/BrandLogo.vue')['default']
|
||||
BrandSettings: typeof import('./src/components/Settings/General/BrandSettings.vue')['default']
|
||||
BrandSettings: typeof import('./src/components/Settings/BrandSettings.vue')['default']
|
||||
BulkDeleteLinkedDocModal: typeof import('./src/components/BulkDeleteLinkedDocModal.vue')['default']
|
||||
CalendarIcon: typeof import('./src/components/Icons/CalendarIcon.vue')['default']
|
||||
CallArea: typeof import('./src/components/Activities/CallArea.vue')['default']
|
||||
@ -63,7 +63,7 @@ declare module 'vue' {
|
||||
CountUpTimer: typeof import('./src/components/CountUpTimer.vue')['default']
|
||||
CreateDocumentModal: typeof import('./src/components/Modals/CreateDocumentModal.vue')['default']
|
||||
CRMLogo: typeof import('./src/components/Icons/CRMLogo.vue')['default']
|
||||
CurrencySettings: typeof import('./src/components/Settings/General/CurrencySettings.vue')['default']
|
||||
CurrencySettings: typeof import('./src/components/Settings/CurrencySettings.vue')['default']
|
||||
CustomActions: typeof import('./src/components/CustomActions.vue')['default']
|
||||
DashboardGrid: typeof import('./src/components/Dashboard/DashboardGrid.vue')['default']
|
||||
DashboardIcon: typeof import('./src/components/Icons/DashboardIcon.vue')['default']
|
||||
@ -127,11 +127,10 @@ declare module 'vue' {
|
||||
FileVideoIcon: typeof import('./src/components/Icons/FileVideoIcon.vue')['default']
|
||||
Filter: typeof import('./src/components/Filter.vue')['default']
|
||||
FilterIcon: typeof import('./src/components/Icons/FilterIcon.vue')['default']
|
||||
ForecastingSettings: typeof import('./src/components/Settings/ForecastingSettings.vue')['default']
|
||||
FormattedInput: typeof import('./src/components/Controls/FormattedInput.vue')['default']
|
||||
FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default']
|
||||
GenderIcon: typeof import('./src/components/Icons/GenderIcon.vue')['default']
|
||||
GeneralSettings: typeof import('./src/components/Settings/General/GeneralSettings.vue')['default']
|
||||
GeneralSettingsPage: typeof import('./src/components/Settings/General/GeneralSettingsPage.vue')['default']
|
||||
GlobalModals: typeof import('./src/components/Modals/GlobalModals.vue')['default']
|
||||
GoogleIcon: typeof import('./src/components/Icons/GoogleIcon.vue')['default']
|
||||
Grid: typeof import('./src/components/Controls/Grid.vue')['default']
|
||||
@ -142,7 +141,7 @@ declare module 'vue' {
|
||||
GroupByIcon: typeof import('./src/components/Icons/GroupByIcon.vue')['default']
|
||||
HeartIcon: typeof import('./src/components/Icons/HeartIcon.vue')['default']
|
||||
HelpIcon: typeof import('./src/components/Icons/HelpIcon.vue')['default']
|
||||
HomeActions: typeof import('./src/components/Settings/General/HomeActions.vue')['default']
|
||||
HomeActions: typeof import('./src/components/Settings/HomeActions.vue')['default']
|
||||
Icon: typeof import('./src/components/Icon.vue')['default']
|
||||
IconPicker: typeof import('./src/components/IconPicker.vue')['default']
|
||||
ImageUploader: typeof import('./src/components/Controls/ImageUploader.vue')['default']
|
||||
@ -229,6 +228,7 @@ declare module 'vue' {
|
||||
SmileIcon: typeof import('./src/components/Icons/SmileIcon.vue')['default']
|
||||
SortBy: typeof import('./src/components/SortBy.vue')['default']
|
||||
SortIcon: typeof import('./src/components/Icons/SortIcon.vue')['default']
|
||||
SparkleIcon: typeof import('./src/components/Icons/SparkleIcon.vue')['default']
|
||||
SquareAsterisk: typeof import('./src/components/Icons/SquareAsterisk.vue')['default']
|
||||
StepsIcon: typeof import('./src/components/Icons/StepsIcon.vue')['default']
|
||||
SuccessIcon: typeof import('./src/components/Icons/SuccessIcon.vue')['default']
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
"@tiptap/extension-paragraph": "^2.12.0",
|
||||
"@twilio/voice-sdk": "^2.10.2",
|
||||
"@vueuse/integrations": "^10.3.0",
|
||||
"frappe-ui": "^0.1.197",
|
||||
"frappe-ui": "^0.1.200",
|
||||
"gemoji": "^8.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mime": "^4.0.1",
|
||||
|
||||
454
frontend/src/components/ConditionsFilter/CFCondition.vue
Normal file
454
frontend/src/components/ConditionsFilter/CFCondition.vue
Normal file
@ -0,0 +1,454 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex gap-2"
|
||||
:class="[
|
||||
{
|
||||
'items-center': !props.isGroup,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div
|
||||
class="flex gap-2 w-full"
|
||||
:class="[
|
||||
{
|
||||
'items-center justify-between': !props.isGroup,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div :class="'text-end text-base text-gray-600'">
|
||||
<div v-if="props.itemIndex == 0" class="min-w-[66px] text-start">
|
||||
{{ __('Where') }}
|
||||
</div>
|
||||
<div v-else class="min-w-[66px] flex items-start">
|
||||
<Button
|
||||
variant="subtle"
|
||||
class="w-max"
|
||||
@click="toggleConjunction"
|
||||
icon-right="refresh-cw"
|
||||
:disabled="props.itemIndex > 2"
|
||||
:label="conjunction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!props.isGroup" class="flex items-center gap-2 w-full">
|
||||
<div id="fieldname" class="w-full">
|
||||
<Autocomplete
|
||||
:options="filterableFields.data"
|
||||
v-model="props.condition[0]"
|
||||
:placeholder="__('Field')"
|
||||
@update:modelValue="updateField"
|
||||
/>
|
||||
</div>
|
||||
<div id="operator">
|
||||
<FormControl
|
||||
v-if="!props.condition[0]"
|
||||
disabled
|
||||
type="text"
|
||||
:placeholder="__('operator')"
|
||||
class="w-[100px]"
|
||||
/>
|
||||
<FormControl
|
||||
v-else
|
||||
:disabled="!props.condition[0]"
|
||||
type="select"
|
||||
v-model="props.condition[1]"
|
||||
@change="updateOperator"
|
||||
:options="getOperators()"
|
||||
class="w-max min-w-[100px]"
|
||||
/>
|
||||
</div>
|
||||
<div id="value" class="w-full">
|
||||
<FormControl
|
||||
v-if="!props.condition[0]"
|
||||
disabled
|
||||
type="text"
|
||||
:placeholder="__('condition')"
|
||||
class="w-full"
|
||||
/>
|
||||
<component
|
||||
v-else
|
||||
:is="getValueControl()"
|
||||
v-model="props.condition[2]"
|
||||
@change="updateValue"
|
||||
:placeholder="__('condition')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<CFConditions
|
||||
v-if="props.isGroup && !(props.level == 2 || props.level == 4)"
|
||||
:conditions="props.condition"
|
||||
:isChild="true"
|
||||
:level="props.level"
|
||||
:disableAddCondition="props.disableAddCondition"
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
v-if="props.isGroup && (props.level == 2 || props.level == 4)"
|
||||
@click="show = true"
|
||||
:label="__('Open nested conditions')"
|
||||
/>
|
||||
</div>
|
||||
<div :class="'w-max'">
|
||||
<Dropdown placement="right" :options="dropdownOptions">
|
||||
<Button variant="ghost" icon="more-horizontal" />
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
v-model="show"
|
||||
:options="{ size: '3xl', title: __('Nested conditions') }"
|
||||
>
|
||||
<template #body-content>
|
||||
<CFConditions
|
||||
:conditions="props.condition"
|
||||
:isChild="true"
|
||||
:level="props.level"
|
||||
:disableAddCondition="props.disableAddCondition"
|
||||
/>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
DatePicker,
|
||||
DateRangePicker,
|
||||
DateTimePicker,
|
||||
Dialog,
|
||||
Dropdown,
|
||||
FormControl,
|
||||
Rating,
|
||||
} from 'frappe-ui'
|
||||
import { computed, defineEmits, h, ref } from 'vue'
|
||||
import GroupIcon from '~icons/lucide/group'
|
||||
import UnGroupIcon from '~icons/lucide/ungroup'
|
||||
import CFConditions from './CFConditions.vue'
|
||||
import { filterableFields } from './filterableFields'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
|
||||
const show = ref(false)
|
||||
const emit = defineEmits([
|
||||
'remove',
|
||||
'unGroupConditions',
|
||||
'toggleConjunction',
|
||||
'turnIntoGroup',
|
||||
])
|
||||
|
||||
const props = defineProps({
|
||||
condition: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
isChild: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
itemIndex: {
|
||||
type: Number,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
conjunction: {
|
||||
type: String,
|
||||
},
|
||||
disableAddCondition: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const dropdownOptions = computed(() => {
|
||||
const options = []
|
||||
|
||||
if (!props.isGroup && props.level < 4) {
|
||||
options.push({
|
||||
label: __('Turn into a group'),
|
||||
icon: () => h(GroupIcon),
|
||||
onClick: () => {
|
||||
emit('turnIntoGroup')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (props.isGroup) {
|
||||
options.push({
|
||||
label: __('Ungroup conditions'),
|
||||
icon: () => h(UnGroupIcon),
|
||||
onClick: () => {
|
||||
emit('unGroupConditions')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
options.push({
|
||||
label: __('Remove'),
|
||||
icon: 'trash-2',
|
||||
variant: 'red',
|
||||
onClick: () => emit('remove'),
|
||||
condition: () => !props.isGroup,
|
||||
})
|
||||
|
||||
options.push({
|
||||
label: __('Remove group'),
|
||||
icon: 'trash-2',
|
||||
variant: 'red',
|
||||
onClick: () => emit('remove'),
|
||||
condition: () => props.isGroup,
|
||||
})
|
||||
|
||||
return options
|
||||
})
|
||||
|
||||
const typeCheck = ['Check']
|
||||
const typeLink = ['Link', 'Dynamic Link']
|
||||
const typeNumber = ['Float', 'Int', 'Currency', 'Percent']
|
||||
const typeSelect = ['Select']
|
||||
const typeString = ['Data', 'Long Text', 'Small Text', 'Text Editor', 'Text']
|
||||
const typeDate = ['Date', 'Datetime']
|
||||
const typeRating = ['Rating']
|
||||
|
||||
function toggleConjunction() {
|
||||
emit('toggleConjunction', props.conjunction)
|
||||
}
|
||||
|
||||
const updateField = (field) => {
|
||||
props.condition[0] = field?.fieldname
|
||||
resetConditionValue()
|
||||
}
|
||||
|
||||
const resetConditionValue = () => {
|
||||
props.condition[2] = ''
|
||||
}
|
||||
|
||||
function getValueControl() {
|
||||
const [field, operator] = props.condition
|
||||
if (!field) return null
|
||||
const fieldData = filterableFields.data?.find((f) => f.fieldname == field)
|
||||
if (!fieldData) return null
|
||||
const { fieldtype, options } = fieldData
|
||||
if (operator == 'is') {
|
||||
return h(FormControl, {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: 'Set',
|
||||
value: 'set',
|
||||
},
|
||||
{
|
||||
label: 'Not Set',
|
||||
value: 'not set',
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (['like', 'not like', 'in', 'not in'].includes(operator)) {
|
||||
return h(FormControl, { type: 'text' })
|
||||
} else if (typeSelect.includes(fieldtype) || typeCheck.includes(fieldtype)) {
|
||||
const _options =
|
||||
fieldtype == 'Check' ? ['Yes', 'No'] : getSelectOptions(options)
|
||||
return h(FormControl, {
|
||||
type: 'select',
|
||||
options: _options.map((o) => ({
|
||||
label: o,
|
||||
value: o,
|
||||
})),
|
||||
})
|
||||
} else if (typeLink.includes(fieldtype)) {
|
||||
if (fieldtype == 'Dynamic Link') {
|
||||
return h(FormControl, { type: 'text' })
|
||||
}
|
||||
return h(Link, {
|
||||
class: 'form-control',
|
||||
doctype: options,
|
||||
value: props.condition[2],
|
||||
})
|
||||
} else if (typeNumber.includes(fieldtype)) {
|
||||
return h(FormControl, { type: 'number' })
|
||||
} else if (typeDate.includes(fieldtype) && operator == 'between') {
|
||||
return h(DateRangePicker, { value: props.condition[2], iconLeft: '' })
|
||||
} else if (typeDate.includes(fieldtype)) {
|
||||
return h(fieldtype == 'Date' ? DatePicker : DateTimePicker, {
|
||||
value: props.condition[2],
|
||||
iconLeft: '',
|
||||
})
|
||||
} else if (typeRating.includes(fieldtype)) {
|
||||
return h(Rating, {
|
||||
modelValue: props.condition[2] || 0,
|
||||
class: 'truncate',
|
||||
'update:modelValue': (v) => updateValue(v),
|
||||
})
|
||||
} else {
|
||||
return h(FormControl, { type: 'text' })
|
||||
}
|
||||
}
|
||||
|
||||
function updateValue(value) {
|
||||
value = value.target ? value.target.value : value
|
||||
if (props.condition[1] === 'between') {
|
||||
props.condition[2] = [value.split(',')[0], value.split(',')[1]]
|
||||
} else {
|
||||
props.condition[2] = value + ''
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectOptions(options) {
|
||||
return options.split('\n')
|
||||
}
|
||||
|
||||
function updateOperator(event) {
|
||||
let oldOperatorValue = event.target._value
|
||||
let newOperatorValue = event.target.value
|
||||
props.condition[1] = event.target.value
|
||||
if (!isSameTypeOperator(oldOperatorValue, newOperatorValue)) {
|
||||
props.condition[2] = getDefaultValue(props.condition[0])
|
||||
}
|
||||
resetConditionValue()
|
||||
}
|
||||
|
||||
function getOperators() {
|
||||
let options = []
|
||||
const field = props.condition[0]
|
||||
if (!field) return options
|
||||
const fieldData = filterableFields.data?.find((f) => f.fieldname == field)
|
||||
if (!fieldData) return options
|
||||
const { fieldtype, fieldname } = fieldData
|
||||
if (typeString.includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Equals', value: '==' },
|
||||
{ label: 'Not Equals', value: '!=' },
|
||||
{ label: 'Like', value: 'like' },
|
||||
{ label: 'Not Like', value: 'not like' },
|
||||
{ label: 'In', value: 'in' },
|
||||
{ label: 'Not In', value: 'not in' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
],
|
||||
)
|
||||
}
|
||||
if (fieldname === '_assign') {
|
||||
options = [
|
||||
{ label: 'Like', value: 'like' },
|
||||
{ label: 'Not Like', value: 'not like' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
]
|
||||
}
|
||||
if (typeNumber.includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Equals', value: '==' },
|
||||
{ label: 'Not Equals', value: '!=' },
|
||||
{ label: 'Like', value: 'like' },
|
||||
{ label: 'Not Like', value: 'not like' },
|
||||
{ label: 'In', value: 'in' },
|
||||
{ label: 'Not In', value: 'not in' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
{ label: '<', value: '<' },
|
||||
{ label: '>', value: '>' },
|
||||
{ label: '<=', value: '<=' },
|
||||
{ label: '>=', value: '>=' },
|
||||
],
|
||||
)
|
||||
}
|
||||
if (typeSelect.includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Equals', value: '==' },
|
||||
{ label: 'Not Equals', value: '!=' },
|
||||
{ label: 'In', value: 'in' },
|
||||
{ label: 'Not In', value: 'not in' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
],
|
||||
)
|
||||
}
|
||||
if (typeLink.includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Equals', value: '==' },
|
||||
{ label: 'Not Equals', value: '!=' },
|
||||
{ label: 'Like', value: 'like' },
|
||||
{ label: 'Not Like', value: 'not like' },
|
||||
{ label: 'In', value: 'in' },
|
||||
{ label: 'Not In', value: 'not in' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
],
|
||||
)
|
||||
}
|
||||
if (typeCheck.includes(fieldtype)) {
|
||||
options.push(...[{ label: 'Equals', value: '==' }])
|
||||
}
|
||||
if (['Duration'].includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Like', value: 'like' },
|
||||
{ label: 'Not Like', value: 'not like' },
|
||||
{ label: 'In', value: 'in' },
|
||||
{ label: 'Not In', value: 'not in' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
],
|
||||
)
|
||||
}
|
||||
if (typeDate.includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Equals', value: '==' },
|
||||
{ label: 'Not Equals', value: '!=' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
{ label: '>', value: '>' },
|
||||
{ label: '<', value: '<' },
|
||||
{ label: '>=', value: '>=' },
|
||||
{ label: '<=', value: '<=' },
|
||||
{ label: 'Between', value: 'between' },
|
||||
],
|
||||
)
|
||||
}
|
||||
if (typeRating.includes(fieldtype)) {
|
||||
options.push(
|
||||
...[
|
||||
{ label: 'Equals', value: '==' },
|
||||
{ label: 'Not Equals', value: '!=' },
|
||||
{ label: 'Is', value: 'is' },
|
||||
{ label: '>', value: '>' },
|
||||
{ label: '<', value: '<' },
|
||||
{ label: '>=', value: '>=' },
|
||||
{ label: '<=', value: '<=' },
|
||||
],
|
||||
)
|
||||
}
|
||||
const op = options.find((o) => o.value == props.condition[1])
|
||||
props.condition[1] = op?.value || options[0].value
|
||||
return options
|
||||
}
|
||||
|
||||
function getDefaultValue(field) {
|
||||
if (typeSelect.includes(field.fieldtype)) {
|
||||
return getSelectOptions(field.options)[0]
|
||||
}
|
||||
if (typeCheck.includes(field.fieldtype)) {
|
||||
return 'Yes'
|
||||
}
|
||||
if (typeDate.includes(field.fieldtype)) {
|
||||
return null
|
||||
}
|
||||
if (typeRating.includes(field.fieldtype)) {
|
||||
return 0
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function isSameTypeOperator(oldOperator, newOperator) {
|
||||
let textOperators = ['==', '!=', 'in', 'not in', '>', '<', '>=', '<=']
|
||||
if (
|
||||
textOperators.includes(oldOperator) &&
|
||||
textOperators.includes(newOperator)
|
||||
)
|
||||
return true
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
142
frontend/src/components/ConditionsFilter/CFConditions.vue
Normal file
142
frontend/src/components/ConditionsFilter/CFConditions.vue
Normal file
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="rounded-lg border border-outline-gray-2 p-3 flex flex-col gap-4 w-full">
|
||||
<template v-for="(condition, i) in props.conditions" :key="condition.field">
|
||||
<CFCondition
|
||||
v-if="Array.isArray(condition)"
|
||||
:condition="condition"
|
||||
:isChild="props.isChild"
|
||||
:itemIndex="i"
|
||||
@remove="removeCondition(condition)"
|
||||
@unGroupConditions="unGroupConditions(condition)"
|
||||
:level="props.level + 1"
|
||||
@toggleConjunction="toggleConjunction"
|
||||
:isGroup="isGroupCondition(condition[0])"
|
||||
:conjunction="getConjunction()"
|
||||
@turnIntoGroup="turnIntoGroup(condition)"
|
||||
:disableAddCondition="props.disableAddCondition"
|
||||
/>
|
||||
</template>
|
||||
<div v-if="props.isChild" class="flex">
|
||||
<Dropdown v-slot="{ open }" :options="dropdownOptions">
|
||||
<Button
|
||||
:disabled="props.disableAddCondition"
|
||||
:label="__('Add condition')"
|
||||
icon-left="plus"
|
||||
:icon-right="open ? 'chevron-up' : 'chevron-down'"
|
||||
/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Button, Dropdown } from 'frappe-ui'
|
||||
import { computed, watch } from 'vue'
|
||||
import CFCondition from './CFCondition.vue'
|
||||
import { filterableFields } from './filterableFields'
|
||||
|
||||
const props = defineProps({
|
||||
conditions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
isChild: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
disableAddCondition: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
doctype: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const getConjunction = () => {
|
||||
let conjunction = 'and'
|
||||
props.conditions.forEach((condition) => {
|
||||
if (typeof condition == 'string') {
|
||||
conjunction = condition
|
||||
}
|
||||
})
|
||||
return conjunction
|
||||
}
|
||||
|
||||
const turnIntoGroup = (condition) => {
|
||||
props.conditions.splice(props.conditions.indexOf(condition), 1, [condition])
|
||||
}
|
||||
|
||||
const isGroupCondition = (condition) => {
|
||||
return Array.isArray(condition)
|
||||
}
|
||||
|
||||
const dropdownOptions = computed(() => {
|
||||
const options = [
|
||||
{
|
||||
label: __('Add condition'),
|
||||
onClick: () => {
|
||||
const conjunction = getConjunction()
|
||||
props.conditions.push(conjunction, ['', '', ''])
|
||||
},
|
||||
},
|
||||
]
|
||||
if (props.level < 3) {
|
||||
options.push({
|
||||
label: __('Add condition group'),
|
||||
onClick: () => {
|
||||
const conjunction = getConjunction()
|
||||
props.conditions.push(conjunction, [[]])
|
||||
},
|
||||
})
|
||||
}
|
||||
return options
|
||||
})
|
||||
|
||||
function removeCondition(condition) {
|
||||
const conditionIndex = props.conditions.indexOf(condition)
|
||||
if (conditionIndex == 0) {
|
||||
props.conditions.splice(conditionIndex, 2)
|
||||
} else {
|
||||
props.conditions.splice(conditionIndex - 1, 2)
|
||||
}
|
||||
}
|
||||
|
||||
function unGroupConditions(condition) {
|
||||
const conjunction = getConjunction()
|
||||
const newConditions = condition.map((c) => {
|
||||
if (typeof c == 'string') {
|
||||
return conjunction
|
||||
}
|
||||
return c
|
||||
})
|
||||
|
||||
const index = props.conditions.indexOf(condition)
|
||||
if (index !== -1) {
|
||||
props.conditions.splice(index, 1, ...newConditions)
|
||||
}
|
||||
}
|
||||
|
||||
function toggleConjunction(conjunction) {
|
||||
for (let i = 0; i < props.conditions.length; i++) {
|
||||
if (typeof props.conditions[i] == 'string') {
|
||||
props.conditions[i] = conjunction == 'and' ? 'or' : 'and'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.doctype,
|
||||
(doctype) => {
|
||||
filterableFields.submit({
|
||||
doctype,
|
||||
})
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
17
frontend/src/components/ConditionsFilter/filterableFields.ts
Normal file
17
frontend/src/components/ConditionsFilter/filterableFields.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { createResource } from 'frappe-ui'
|
||||
|
||||
export const filterableFields = createResource({
|
||||
url: 'crm.api.doc.get_filterable_fields',
|
||||
transform: (data) => {
|
||||
data = data
|
||||
.filter((field) => !field.fieldname.startsWith('_'))
|
||||
.map((field) => {
|
||||
return {
|
||||
label: field.label,
|
||||
value: field.fieldname,
|
||||
...field,
|
||||
}
|
||||
})
|
||||
return data
|
||||
},
|
||||
})
|
||||
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<FileUploader
|
||||
:file-types="image_type"
|
||||
class="text-base"
|
||||
@success="
|
||||
(file) => {
|
||||
$emit('upload', file.file_url)
|
||||
@ -10,21 +9,28 @@
|
||||
>
|
||||
<template v-slot="{ progress, uploading, openFileSelector }">
|
||||
<div class="flex items-end space-x-1">
|
||||
<Button @click="openFileSelector">
|
||||
{{
|
||||
<Button
|
||||
@click="openFileSelector"
|
||||
:iconLeft="uploading ? 'cloud-upload' : ImageUpIcon"
|
||||
:label="
|
||||
uploading
|
||||
? `Uploading ${progress}%`
|
||||
? __('Uploading {0}%', [progress])
|
||||
: image_url
|
||||
? 'Change'
|
||||
: 'Upload'
|
||||
}}
|
||||
</Button>
|
||||
<Button v-if="image_url" @click="$emit('remove')">Remove</Button>
|
||||
? __('Change')
|
||||
: __('Upload')
|
||||
"
|
||||
/>
|
||||
<Button
|
||||
v-if="image_url"
|
||||
:label="__('Remove')"
|
||||
@click="$emit('remove')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</FileUploader>
|
||||
</template>
|
||||
<script setup>
|
||||
import ImageUpIcon from '~icons/lucide/image-up'
|
||||
import { FileUploader, Button } from 'frappe-ui'
|
||||
|
||||
const prop = defineProps({
|
||||
@ -33,10 +39,6 @@ const prop = defineProps({
|
||||
type: String,
|
||||
default: 'image/*',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['upload', 'remove'])
|
||||
</script>
|
||||
|
||||
19
frontend/src/components/Icons/SettingsIcon2.vue
Normal file
19
frontend/src/components/Icons/SettingsIcon2.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-settings2-icon lucide-settings-2"
|
||||
>
|
||||
<path d="M14 17H5" />
|
||||
<path d="M19 7h-9" />
|
||||
<circle cx="17" cy="17" r="3" />
|
||||
<circle cx="7" cy="7" r="3" />
|
||||
</svg>
|
||||
</template>
|
||||
16
frontend/src/components/Icons/SparkleIcon.vue
Normal file
16
frontend/src/components/Icons/SparkleIcon.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M3.37543 1.93494L4.21632 2.21494C4.35232 2.26027 4.44388 2.38738 4.44388 2.53138C4.44388 2.67538 4.35143 2.80249 4.21543 2.84783L3.37454 3.12783L3.09365 3.9696C3.04921 4.10472 2.92121 4.19716 2.7781 4.19716C2.63499 4.19716 2.50787 4.1056 2.46254 3.9696L2.18165 3.12783L1.34076 2.84783C1.20476 2.80249 1.11232 2.67538 1.11232 2.53138C1.11232 2.38738 1.20476 2.26027 1.34076 2.21494L2.18165 1.93494L2.46254 1.09316C2.55321 0.82116 3.00387 0.82116 3.09454 1.09316L3.37543 1.93494ZM8.44852 1.33394C8.3643 1.16325 8.19046 1.05518 8.00012 1.05518C7.80978 1.05518 7.63595 1.16325 7.55173 1.33394L5.67697 5.13368L1.48388 5.74214C1.29552 5.76947 1.13901 5.90137 1.08017 6.08238C1.02133 6.26339 1.07036 6.46211 1.20665 6.59497L4.24065 9.55281L3.52421 13.7284C3.49203 13.916 3.56913 14.1056 3.7231 14.2174C3.87706 14.3293 4.08119 14.3441 4.24966 14.2555L8.11188 12.2253C8.35631 12.0968 8.4503 11.7945 8.32181 11.5501C8.19333 11.3057 7.89102 11.2117 7.64659 11.3402L4.68114 12.899L5.2707 9.46284C5.29853 9.30065 5.24477 9.13514 5.12693 9.02027L2.63025 6.58626L6.08082 6.08555C6.24373 6.06191 6.38457 5.95959 6.45741 5.81196L8.00012 2.6852L9.54284 5.81196C9.61568 5.95959 9.75652 6.06191 9.91943 6.08555L13.37 6.58625L11.6235 8.2887C11.4258 8.48146 11.4218 8.79802 11.6145 8.99575C11.8073 9.19349 12.1239 9.19752 12.3216 9.00476L14.7936 6.59498C14.9299 6.46212 14.9789 6.2634 14.9201 6.08239C14.8612 5.90138 14.7047 5.76947 14.5164 5.74214L10.3233 5.13368L8.44852 1.33394ZM13.4744 11.9911L12.3517 11.6168L11.9775 10.4942C11.8557 10.1315 11.2557 10.1315 11.1339 10.4942L10.7597 11.6168L9.63702 11.9911C9.45569 12.0515 9.33302 12.2213 9.33302 12.4124C9.33302 12.6035 9.45569 12.7733 9.63702 12.8337L10.7597 13.2079L11.1339 14.3306C11.1944 14.5119 11.365 14.6346 11.5561 14.6346C11.7472 14.6346 11.917 14.5119 11.9784 14.3306L12.3526 13.2079L13.4752 12.8337C13.6566 12.7733 13.7792 12.6035 13.7792 12.4124C13.7792 12.2213 13.6566 12.0515 13.4752 11.9911H13.4744ZM13.3333 2.88883C13.3333 3.25702 13.0349 3.5555 12.6667 3.5555C12.2985 3.5555 12 3.25702 12 2.88883C12 2.52064 12.2985 2.22217 12.6667 2.22217C13.0349 2.22217 13.3333 2.52064 13.3333 2.88883Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="text-lg font-semibold text-ink-gray-8">{{
|
||||
__('Assignee Rules')
|
||||
}}</span>
|
||||
<span class="text-p-sm text-ink-gray-6">
|
||||
{{
|
||||
__('Choose how {0} are assigned among salespeople.', [documentType])
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-8 flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div class="text-base font-medium text-ink-gray-8">
|
||||
{{
|
||||
__('{0} Routing', [
|
||||
assignmentRuleData.documentType == 'CRM Lead'
|
||||
? __('Lead')
|
||||
: __('Deal'),
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-6 mt-1">
|
||||
{{
|
||||
__('Choose how {0} are assigned among the selected assignees.', [
|
||||
documentType,
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Popover placement="bottom-end">
|
||||
<template #target="{ togglePopover }">
|
||||
<div
|
||||
class="flex items-center justify-between text-base rounded h-7 py-1.5 pl-2 pr-2 border border-outline-gray-2 bg-surface-gray-2 placeholder-ink-gray-4 hover:border-outline-gray-modals hover:bg-surface-gray-3 focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors w-full dark:[color-scheme:dark] select-none min-w-40"
|
||||
@click="togglePopover()"
|
||||
>
|
||||
<div>
|
||||
{{
|
||||
documentRoutingOptions.find(
|
||||
(option) => option.value == assignmentRuleData.rule,
|
||||
)?.label
|
||||
}}
|
||||
</div>
|
||||
<FeatherIcon name="chevron-down" class="size-4" />
|
||||
</div>
|
||||
</template>
|
||||
<template #body="{ togglePopover }">
|
||||
<div
|
||||
class="p-1 text-ink-gray-7 mt-1 w-48 bg-white shadow-xl rounded"
|
||||
>
|
||||
<div
|
||||
v-for="option in documentRoutingOptions"
|
||||
:key="option.value"
|
||||
class="p-2 cursor-pointer hover:bg-gray-50 text-sm flex items-center justify-between rounded"
|
||||
@click="
|
||||
() => {
|
||||
assignmentRuleData.rule = option.value
|
||||
togglePopover()
|
||||
}
|
||||
"
|
||||
>
|
||||
<span>
|
||||
{{ option.label }}
|
||||
</span>
|
||||
<FeatherIcon
|
||||
v-if="assignmentRuleData.rule == option.value"
|
||||
name="check"
|
||||
class="size-4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-7 flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div class="text-base font-medium text-ink-gray-8">
|
||||
{{ __('Assignees') }}
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-6 mt-1">
|
||||
{{ __('Select the assignees for {0}.', [documentType]) }}
|
||||
</div>
|
||||
</div>
|
||||
<AssigneeSearch @addAssignee="validateAssignmentRule('users')" />
|
||||
</div>
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<div
|
||||
v-for="user in users"
|
||||
:key="user.name"
|
||||
class="flex items-center gap-2 text-sm bg-surface-gray-2 rounded-md p-1 w-max px-2 select-none"
|
||||
>
|
||||
<Avatar :image="user.user_image" :label="user.full_name" size="sm" />
|
||||
<div class="text-ink-gray-7">
|
||||
{{ user.full_name }}
|
||||
</div>
|
||||
<Tooltip
|
||||
v-if="user.email == assignmentRuleData.lastUser"
|
||||
:text="__('Last user assigned by this rule')"
|
||||
:hover-delay="0.35"
|
||||
:placement="'top'"
|
||||
>
|
||||
<div
|
||||
class="text-xs rounded-full select-none bg-blue-600 text-white p-0.5 px-2"
|
||||
>
|
||||
{{ __('Last') }}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Button variant="ghost" icon="x" @click="removeAssignedUser(user)" />
|
||||
</div>
|
||||
</div>
|
||||
<ErrorMessage :message="assignmentRuleErrors.users" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Avatar, Button, ErrorMessage, Popover, Tooltip } from 'frappe-ui'
|
||||
import AssigneeSearch from './AssigneeSearch.vue'
|
||||
import { computed, inject } from 'vue'
|
||||
import { usersStore } from '@/stores/users'
|
||||
|
||||
const { getUser } = usersStore()
|
||||
const assignmentRuleData = inject('assignmentRuleData')
|
||||
const assignmentRuleErrors = inject('assignmentRuleErrors')
|
||||
const validateAssignmentRule = inject('validateAssignmentRule')
|
||||
const documentType = computed(() =>
|
||||
assignmentRuleData.value.documentType == 'CRM Lead'
|
||||
? __('leads')
|
||||
: __('deals'),
|
||||
)
|
||||
|
||||
const documentRoutingOptions = [
|
||||
{
|
||||
label: 'Auto-rotate',
|
||||
value: 'Round Robin',
|
||||
},
|
||||
{
|
||||
label: 'Assign by workload',
|
||||
value: 'Load Balancing',
|
||||
},
|
||||
]
|
||||
|
||||
const removeAssignedUser = (user) => {
|
||||
assignmentRuleData.value.users = assignmentRuleData.value.users.filter(
|
||||
(u) => u.user !== user.name,
|
||||
)
|
||||
validateAssignmentRule('users')
|
||||
}
|
||||
|
||||
const users = computed(() => {
|
||||
const _users = []
|
||||
assignmentRuleData.value.users.forEach((user) => {
|
||||
_users.push(getUser(user.user))
|
||||
})
|
||||
return _users
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<Combobox :multiple="true">
|
||||
<Popover placement="bottom-end">
|
||||
<template #target="{ togglePopover }">
|
||||
<Button
|
||||
variant="subtle"
|
||||
icon-left="plus"
|
||||
@click="togglePopover()"
|
||||
:label="__('Add Assignee')"
|
||||
/>
|
||||
</template>
|
||||
<template #body="{ togglePopover }">
|
||||
<div class="mt-1 rounded-lg bg-white py-1 text-base shadow-2xl w-60">
|
||||
<div class="relative px-1.5 pt-0.5">
|
||||
<ComboboxInput
|
||||
ref="search"
|
||||
class="form-input w-full"
|
||||
type="text"
|
||||
@change="(e) => debouncedQuery(e.target.value)"
|
||||
:value="query"
|
||||
autocomplete="off"
|
||||
:placeholder="__('Search')"
|
||||
/>
|
||||
<button
|
||||
class="absolute right-1.5 inline-flex h-7 w-7 items-center justify-center"
|
||||
@click="query = ''"
|
||||
>
|
||||
<FeatherIcon name="x" class="w-4" />
|
||||
</button>
|
||||
</div>
|
||||
<ComboboxOptions class="my-2 max-h-64 overflow-y-auto px-1.5" static>
|
||||
<ComboboxOption
|
||||
v-show="usersList.length > 0"
|
||||
v-for="user in usersList"
|
||||
:key="user.username"
|
||||
:value="user"
|
||||
as="template"
|
||||
v-slot="{ active }"
|
||||
@click="
|
||||
(e) => {
|
||||
e.stopPropagation()
|
||||
addAssignee(user)
|
||||
}
|
||||
"
|
||||
>
|
||||
<li
|
||||
class="flex items-center rounded p-1.5 w-full text-base"
|
||||
:class="{ 'bg-gray-100': active }"
|
||||
>
|
||||
<div class="flex gap-2 items-center w-full select-none">
|
||||
<Avatar
|
||||
:shape="'circle'"
|
||||
:image="user.user_image"
|
||||
:label="user.full_name"
|
||||
size="lg"
|
||||
/>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="font-semibold text-ink-gray-7">
|
||||
{{ user.full_name }}
|
||||
</div>
|
||||
<div class="text-ink-gray-6">{{ user.email }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ComboboxOption>
|
||||
<li
|
||||
v-if="usersList.length == 0"
|
||||
class="mt-1.5 rounded-md p-1.5 text-base text-gray-600"
|
||||
>
|
||||
{{ __('No results found') }}
|
||||
</li>
|
||||
</ComboboxOptions>
|
||||
<div class="border-t p-1.5 pb-0.5 *:w-full">
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon-left="plus"
|
||||
class="w-full"
|
||||
:label="__('Invite agent')"
|
||||
@click="
|
||||
() => {
|
||||
inviteAgent()
|
||||
togglePopover()
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</Combobox>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Combobox,
|
||||
ComboboxInput,
|
||||
ComboboxOption,
|
||||
ComboboxOptions,
|
||||
} from '@headlessui/vue'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { Avatar, Popover } from 'frappe-ui'
|
||||
import { computed, inject, ref } from 'vue'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { globalStore } from '@/stores/global'
|
||||
import { activeSettingsPage } from '@/composables/settings'
|
||||
|
||||
const emit = defineEmits(['addAssignee'])
|
||||
const query = ref('')
|
||||
const { users } = usersStore()
|
||||
const { $dialog } = globalStore()
|
||||
const assignmentRuleData = inject('assignmentRuleData')
|
||||
|
||||
const debouncedQuery = useDebounceFn((val) => {
|
||||
query.value = val
|
||||
}, 300)
|
||||
|
||||
const usersList = computed(() => {
|
||||
let filteredUsers =
|
||||
users.data?.crmUsers?.filter((user) => user.name !== 'Administrator') || []
|
||||
|
||||
return filteredUsers
|
||||
.filter(
|
||||
(user) =>
|
||||
user.name?.includes(query.value) ||
|
||||
user.full_name?.includes(query.value),
|
||||
)
|
||||
.filter((user) => {
|
||||
return !assignmentRuleData.value.users.some((u) => u.user === user.email)
|
||||
})
|
||||
})
|
||||
|
||||
const addAssignee = (user) => {
|
||||
const userExists = assignmentRuleData.value.users.some(
|
||||
(u) => u.user === user.user,
|
||||
)
|
||||
if (!userExists) {
|
||||
assignmentRuleData.value.users.push({
|
||||
full_name: user.full_name,
|
||||
email: user.email,
|
||||
user_image: user.user_image,
|
||||
user: user.email,
|
||||
})
|
||||
emit('addAssignee', user)
|
||||
}
|
||||
}
|
||||
|
||||
const inviteAgent = () => {
|
||||
$dialog({
|
||||
title: __('Invite agent'),
|
||||
message: __(
|
||||
'You will be redirected to invite user page, unsaved changes will be lost.',
|
||||
),
|
||||
variant: 'solid',
|
||||
actions: [
|
||||
{
|
||||
label: __('Go to invite page'),
|
||||
variant: 'solid',
|
||||
onClick: (close) => {
|
||||
activeSettingsPage.value = 'Invite User'
|
||||
close()
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex p-3 items-center justify-between cursor-pointer hover:bg-surface-menu-bar rounded"
|
||||
>
|
||||
<div class="w-7/12" @click="updateStep('view', data)">
|
||||
<div class="text-base text-ink-gray-7 font-medium">{{ data.name }}</div>
|
||||
<div
|
||||
v-if="data.description && data.description.length > 0"
|
||||
class="text-p-base w-full text-ink-gray-5 mt-0.5 whitespace-nowrap overflow-ellipsis overflow-hidden"
|
||||
>
|
||||
{{ data.description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-3/12">
|
||||
<Select
|
||||
class="w-max -ml-2 bg-transparent border-0 text-ink-gray-6 focus-visible:!ring-0 bg-none"
|
||||
:options="priorityOptions"
|
||||
v-model="data.priority"
|
||||
@update:modelValue="onPriorityChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-between items-center w-2/12">
|
||||
<Switch
|
||||
size="sm"
|
||||
:modelValue="!data.disabled"
|
||||
@update:modelValue="onToggle"
|
||||
/>
|
||||
<Dropdown placement="right" :options="dropdownOptions">
|
||||
<Button
|
||||
icon="more-horizontal"
|
||||
variant="ghost"
|
||||
@click="isConfirmingDelete = false"
|
||||
/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
:options="{ title: __('Duplicate Assignment Rule') }"
|
||||
v-model="duplicateDialog.show"
|
||||
>
|
||||
<template #body-content>
|
||||
<div class="flex flex-col gap-4">
|
||||
<FormControl
|
||||
:label="__('New Assignment Rule Name')"
|
||||
type="text"
|
||||
v-model="duplicateDialog.name"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions>
|
||||
<div class="flex gap-2 justify-end">
|
||||
<Button
|
||||
variant="subtle"
|
||||
:label="__('Close')"
|
||||
@click="duplicateDialog.show = false"
|
||||
/>
|
||||
<Button variant="solid" :label="__('Duplicate')" @click="duplicate()" />
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Button,
|
||||
createResource,
|
||||
Dialog,
|
||||
Dropdown,
|
||||
FormControl,
|
||||
Select,
|
||||
Switch,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { inject, ref } from 'vue'
|
||||
|
||||
const assignmentRulesList = inject('assignmentRulesList')
|
||||
const updateStep = inject('updateStep')
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const priorityOptions = [
|
||||
{ label: 'Low', value: '0' },
|
||||
{ label: 'Low-Medium', value: '1' },
|
||||
{ label: 'Medium', value: '2' },
|
||||
{ label: 'Medium-High', value: '3' },
|
||||
{ label: 'High', value: '4' },
|
||||
]
|
||||
|
||||
const duplicateDialog = ref({
|
||||
show: false,
|
||||
name: '',
|
||||
})
|
||||
|
||||
const isConfirmingDelete = ref(false)
|
||||
|
||||
const deleteAssignmentRule = () => {
|
||||
createResource({
|
||||
url: 'frappe.client.delete',
|
||||
params: {
|
||||
doctype: 'Assignment Rule',
|
||||
name: props.data.name,
|
||||
},
|
||||
onSuccess: () => {
|
||||
assignmentRulesList.reload()
|
||||
isConfirmingDelete.value = false
|
||||
toast.success(__('Assignment rule deleted'))
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
}
|
||||
|
||||
const dropdownOptions = [
|
||||
{
|
||||
label: __('Duplicate'),
|
||||
onClick: () => {
|
||||
duplicateDialog.value = {
|
||||
show: true,
|
||||
name: props.data.name + ' (Copy)',
|
||||
}
|
||||
},
|
||||
icon: 'copy',
|
||||
},
|
||||
{
|
||||
label: __('Delete'),
|
||||
icon: 'trash-2',
|
||||
onClick: (e) => {
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
isConfirmingDelete.value = true
|
||||
},
|
||||
condition: () => !isConfirmingDelete.value,
|
||||
},
|
||||
{
|
||||
label: __('Confirm Delete'),
|
||||
icon: 'trash-2',
|
||||
theme: 'red',
|
||||
onClick: () => deleteAssignmentRule(),
|
||||
condition: () => isConfirmingDelete.value,
|
||||
},
|
||||
]
|
||||
|
||||
const duplicate = () => {
|
||||
createResource({
|
||||
url: 'crm.api.assignment_rule.duplicate_assignment_rule',
|
||||
params: {
|
||||
docname: props.data.name,
|
||||
new_name: duplicateDialog.value.name,
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
assignmentRulesList.reload()
|
||||
toast.success(__('Assignment rule duplicated'))
|
||||
duplicateDialog.value.show = false
|
||||
duplicateDialog.value.name = ''
|
||||
updateStep('view', data)
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
}
|
||||
|
||||
const onPriorityChange = () => {
|
||||
setAssignmentRuleValue('priority', props.data.priority)
|
||||
}
|
||||
|
||||
const onToggle = () => {
|
||||
if (!props.data.users_exists && props.data.disabled) {
|
||||
toast.error(__('Cannot enable rule without adding users in it'))
|
||||
return
|
||||
}
|
||||
setAssignmentRuleValue('disabled', !props.data.disabled, 'status')
|
||||
}
|
||||
|
||||
const setAssignmentRuleValue = (key, value, fieldName = undefined) => {
|
||||
createResource({
|
||||
url: 'frappe.client.set_value',
|
||||
params: {
|
||||
doctype: 'Assignment Rule',
|
||||
name: props.data.name,
|
||||
fieldname: key,
|
||||
value: value,
|
||||
},
|
||||
onSuccess: () => {
|
||||
assignmentRulesList.reload()
|
||||
toast.success(__('Assignment rule {0} updated', [fieldName || key]))
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<AssignmentRules v-if="step.screen === 'list'" />
|
||||
<AssignmentRuleView v-else-if="step.screen === 'view'" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, provide } from 'vue'
|
||||
import AssignmentRules from './AssignmentRules.vue'
|
||||
import AssignmentRuleView from './AssignmentRuleView.vue'
|
||||
|
||||
const step = ref({ screen: 'list', data: null })
|
||||
|
||||
provide('step', step)
|
||||
provide('updateStep', updateStep)
|
||||
|
||||
function updateStep(newStep, data) {
|
||||
step.value = { screen: newStep, data }
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,782 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="!getAssignmentRuleData.loading"
|
||||
class="flex flex-col h-full gap-6 px-6 py-8 text-ink-gray-8"
|
||||
>
|
||||
<div class="flex items-center justify-between px-2 w-full">
|
||||
<div class="flex items-center gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon-left="chevron-left"
|
||||
:label="
|
||||
assignmentRuleData.assignmentRuleName || __('New Assignment Rule')
|
||||
"
|
||||
size="md"
|
||||
@click="goBack()"
|
||||
class="cursor-pointer -ml-4 hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5 font-semibold text-xl hover:opacity-70 !pr-0 !max-w-96 !justify-start"
|
||||
/>
|
||||
<Badge
|
||||
:variant="'subtle'"
|
||||
:theme="'orange'"
|
||||
size="sm"
|
||||
:label="__('Unsaved')"
|
||||
v-if="isDirty"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<div
|
||||
class="flex items-center justify-between gap-2"
|
||||
@click="assignmentRuleData.disabled = !assignmentRuleData.disabled"
|
||||
>
|
||||
<Switch size="sm" :model-value="!assignmentRuleData.disabled" />
|
||||
<span class="text-sm text-ink-gray-7">{{ __('Enabled') }}</span>
|
||||
</div>
|
||||
<Button
|
||||
:disabled="Boolean(!isDirty && step.data)"
|
||||
:label="__('Save')"
|
||||
theme="gray"
|
||||
variant="solid"
|
||||
@click="saveAssignmentRule()"
|
||||
:loading="isLoading || getAssignmentRuleData.loading"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-auto px-2">
|
||||
<div class="grid grid-cols-2 gap-5">
|
||||
<div>
|
||||
<FormControl
|
||||
:type="'text'"
|
||||
size="sm"
|
||||
variant="subtle"
|
||||
:placeholder="__('Name')"
|
||||
:label="__('Name')"
|
||||
v-model="assignmentRuleData.assignmentRuleName"
|
||||
required
|
||||
maxlength="50"
|
||||
@change="validateAssignmentRule('assignmentRuleName')"
|
||||
/>
|
||||
<ErrorMessage
|
||||
:message="assignmentRuleErrors.assignmentRuleName"
|
||||
class="mt-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<FormLabel :label="__('Priority')" />
|
||||
<Popover>
|
||||
<template #target="{ togglePopover }">
|
||||
<div
|
||||
class="flex items-center justify-between text-base rounded h-7 py-1.5 pl-2 pr-2 border border-outline-gray-2 bg-surface-gray-2 placeholder-ink-gray-4 hover:border-outline-gray-modals hover:bg-surface-gray-3 focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors w-full dark:[color-scheme:dark] cursor-default"
|
||||
@click="togglePopover()"
|
||||
>
|
||||
<div>
|
||||
{{
|
||||
priorityOptions.find(
|
||||
(option) => option.value == assignmentRuleData.priority,
|
||||
)?.label
|
||||
}}
|
||||
</div>
|
||||
<FeatherIcon name="chevron-down" class="size-4" />
|
||||
</div>
|
||||
</template>
|
||||
<template #body="{ togglePopover }">
|
||||
<div
|
||||
class="p-1 text-ink-gray-6 top-1 absolute w-full bg-white shadow-2xl rounded"
|
||||
>
|
||||
<div
|
||||
v-for="option in priorityOptions"
|
||||
:key="option.value"
|
||||
class="p-2 cursor-pointer hover:bg-gray-50 text-base flex items-center justify-between rounded"
|
||||
@click="
|
||||
() => {
|
||||
assignmentRuleData.priority = option.value
|
||||
togglePopover()
|
||||
}
|
||||
"
|
||||
>
|
||||
{{ option.label }}
|
||||
<FeatherIcon
|
||||
v-if="assignmentRuleData.priority == option.value"
|
||||
name="check"
|
||||
class="size-4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
<div>
|
||||
<FormControl
|
||||
:type="'textarea'"
|
||||
size="sm"
|
||||
variant="subtle"
|
||||
:placeholder="__('Description')"
|
||||
:label="__('Description')"
|
||||
required
|
||||
maxlength="250"
|
||||
@change="validateAssignmentRule('description')"
|
||||
v-model="assignmentRuleData.description"
|
||||
/>
|
||||
<ErrorMessage
|
||||
:message="assignmentRuleErrors.description"
|
||||
class="mt-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<FormLabel :label="__('Apply on')" />
|
||||
<Select
|
||||
:options="[
|
||||
{
|
||||
label: 'Lead',
|
||||
value: 'CRM Lead',
|
||||
},
|
||||
{
|
||||
label: 'Deal',
|
||||
value: 'CRM Deal',
|
||||
},
|
||||
]"
|
||||
v-model="assignmentRuleData.documentType"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-8" />
|
||||
<div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="text-lg font-semibold text-ink-gray-8">{{
|
||||
__('Assignment condition')
|
||||
}}</span>
|
||||
<div class="flex items-center justify-between gap-6">
|
||||
<span class="text-p-sm text-ink-gray-6">
|
||||
{{
|
||||
__('Choose which {0} are affected by this assignment rule.', [
|
||||
documentType,
|
||||
])
|
||||
}}
|
||||
<a
|
||||
class="font-medium underline"
|
||||
href="https://docs.frappe.io/crm/assignment-rule"
|
||||
target="_blank"
|
||||
>{{ __('Learn about conditions') }}</a
|
||||
>
|
||||
</span>
|
||||
<div v-if="isOldSla && step.data">
|
||||
<Popover trigger="hover" :hoverDelay="0.25" placement="top-end">
|
||||
<template #target>
|
||||
<div
|
||||
class="text-sm text-ink-gray-6 flex gap-1 cursor-default text-nowrap items-center"
|
||||
>
|
||||
<span>{{ __('Old Condition') }}</span>
|
||||
<FeatherIcon name="info" class="size-4" />
|
||||
</div>
|
||||
</template>
|
||||
<template #body-main>
|
||||
<div
|
||||
class="text-sm text-ink-gray-6 p-2 bg-white rounded-md max-w-96 text-wrap whitespace-pre-wrap leading-5"
|
||||
>
|
||||
<code>{{ assignmentRuleData.assignCondition }}</code>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div
|
||||
class="flex flex-col gap-3 items-center text-center text-ink-gray-7 text-sm mb-2 border border-outline-gray-2 rounded-md p-3 py-4"
|
||||
v-if="!useNewUI && assignmentRuleData.assignCondition"
|
||||
>
|
||||
<span class="text-p-sm">
|
||||
{{ __('Conditions for this rule were created from') }}
|
||||
<a :href="deskUrl" target="_blank" class="underline">{{
|
||||
__('desk')
|
||||
}}</a>
|
||||
{{
|
||||
__(
|
||||
'which are not compatible with this UI, you will need to recreate the conditions here if you want to manage and add new conditions from this UI.',
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
<Button
|
||||
:label="__('I understand, add conditions')"
|
||||
variant="subtle"
|
||||
theme="gray"
|
||||
@click="useNewUI = true"
|
||||
/>
|
||||
</div>
|
||||
<AssignmentRulesSection
|
||||
:conditions="assignmentRuleData.assignConditionJson"
|
||||
name="assignCondition"
|
||||
:errors="assignmentRuleErrors.assignConditionError"
|
||||
:doctype="assignmentRuleData.documentType"
|
||||
v-else
|
||||
/>
|
||||
<div class="flex justify-end">
|
||||
<ErrorMessage
|
||||
:message="assignmentRuleErrors.assignCondition"
|
||||
class="mt-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-8" />
|
||||
<div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="text-lg font-semibold text-ink-gray-8">{{
|
||||
__('Unassignment condition')
|
||||
}}</span>
|
||||
<div class="flex items-center justify-between gap-6">
|
||||
<span class="text-p-sm text-ink-gray-6">
|
||||
{{
|
||||
__(
|
||||
'Choose which {0} are affected by this un-assignment rule.',
|
||||
[documentType],
|
||||
)
|
||||
}}
|
||||
<a
|
||||
class="font-medium underline"
|
||||
href="https://docs.frappe.io/crm/assignment-rule"
|
||||
target="_blank"
|
||||
>{{ __('Learn about conditions') }}</a
|
||||
>
|
||||
</span>
|
||||
<div
|
||||
v-if="
|
||||
isOldSla && step.data && assignmentRuleData.unassignCondition
|
||||
"
|
||||
>
|
||||
<Popover trigger="hover" :hoverDelay="0.25" placement="top-end">
|
||||
<template #target>
|
||||
<div
|
||||
class="text-sm text-ink-gray-6 flex gap-1 cursor-default text-nowrap items-center"
|
||||
>
|
||||
<span> {{ __('Old Condition') }} </span>
|
||||
<FeatherIcon name="info" class="size-4" />
|
||||
</div>
|
||||
</template>
|
||||
<template #body-main>
|
||||
<div
|
||||
class="text-sm text-ink-gray-6 p-2 bg-white rounded-md max-w-96 text-wrap whitespace-pre-wrap leading-5"
|
||||
>
|
||||
<code>{{ assignmentRuleData.unassignCondition }}</code>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div
|
||||
v-if="!useNewUI && assignmentRuleData.unassignCondition"
|
||||
class="flex flex-col gap-3 items-center text-center text-ink-gray-7 text-sm mb-2 border border-outline-gray-2 rounded-md p-3 py-4"
|
||||
>
|
||||
<span class="text-p-sm">
|
||||
{{ __('Conditions for this rule were created from') }}
|
||||
<a :href="deskUrl" target="_blank" class="underline">
|
||||
{{ __('desk') }}
|
||||
</a>
|
||||
{{
|
||||
__(
|
||||
'which are not compatible with this UI, you will need to recreate the conditions here if you want to manage and add new conditions from this UI.',
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
<Button
|
||||
:label="__('I understand, add conditions')"
|
||||
variant="subtle"
|
||||
theme="gray"
|
||||
@click="useNewUI = true"
|
||||
/>
|
||||
</div>
|
||||
<AssignmentRulesSection
|
||||
v-else
|
||||
:conditions="assignmentRuleData.unassignConditionJson"
|
||||
name="unassignCondition"
|
||||
:errors="assignmentRuleErrors.unassignConditionError"
|
||||
:doctype="assignmentRuleData.documentType"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-8" />
|
||||
<div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="text-lg font-semibold text-ink-gray-8">{{
|
||||
__('Assignment Schedule')
|
||||
}}</span>
|
||||
<span class="text-p-sm text-ink-gray-6">
|
||||
{{
|
||||
__('Choose the days of the week when this rule should be active.')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<AssignmentSchedule />
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-8" />
|
||||
<AssigneeRules />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex items-center h-full justify-center">
|
||||
<LoadingIndicator class="w-4" />
|
||||
</div>
|
||||
<ConfirmDialog
|
||||
v-model="showConfirmDialog.show"
|
||||
:title="showConfirmDialog.title"
|
||||
:message="showConfirmDialog.message"
|
||||
:onConfirm="showConfirmDialog.onConfirm"
|
||||
:onCancel="() => (showConfirmDialog.show = false)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
call,
|
||||
createResource,
|
||||
ErrorMessage,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
LoadingIndicator,
|
||||
Popover,
|
||||
Select,
|
||||
Switch,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import {
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
ref,
|
||||
inject,
|
||||
watch,
|
||||
provide,
|
||||
computed,
|
||||
} from 'vue'
|
||||
import AssignmentRulesSection from './AssignmentRulesSection.vue'
|
||||
import AssignmentSchedule from './AssignmentSchedule.vue'
|
||||
import AssigneeRules from './AssigneeRules.vue'
|
||||
import ConfirmDialog from 'frappe-ui/src/components/ConfirmDialog.vue'
|
||||
import { globalStore } from '@/stores/global'
|
||||
import { disableSettingModalOutsideClick } from '@/composables/settings'
|
||||
import { convertToConditions, validateConditions } from '@/utils'
|
||||
|
||||
const isDirty = ref(false)
|
||||
const initialData = ref(null)
|
||||
const isLoading = ref(false)
|
||||
const updateStep = inject('updateStep')
|
||||
const step = inject('step')
|
||||
const { $dialog } = globalStore()
|
||||
|
||||
const showConfirmDialog = ref({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
onConfirm: () => {},
|
||||
})
|
||||
const useNewUI = ref(true)
|
||||
const isOldSla = ref(false)
|
||||
const documentType = computed(() =>
|
||||
assignmentRuleData.value.documentType == 'CRM Lead'
|
||||
? __('leads')
|
||||
: __('deals'),
|
||||
)
|
||||
const deskUrl = `${window.location.origin}/app/assignment-rule/${step.value.data?.name}`
|
||||
|
||||
const defaultAssignmentDays = [
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday',
|
||||
'Sunday',
|
||||
]
|
||||
|
||||
const assignmentRuleData = ref({
|
||||
assignCondition: '',
|
||||
unassignCondition: '',
|
||||
assignConditionJson: [],
|
||||
unassignConditionJson: [],
|
||||
rule: 'Round Robin',
|
||||
priority: 1,
|
||||
users: [],
|
||||
disabled: false,
|
||||
description: '',
|
||||
name: '',
|
||||
assignmentRuleName: '',
|
||||
assignmentDays: defaultAssignmentDays,
|
||||
documentType: 'CRM Lead',
|
||||
})
|
||||
|
||||
const validateAssignmentRule = (key, skipConditionCheck = false) => {
|
||||
const validateField = (field) => {
|
||||
if (key && field !== key) return
|
||||
|
||||
switch (field) {
|
||||
case 'assignmentRuleName':
|
||||
if (assignmentRuleData.value.assignmentRuleName?.length == 0) {
|
||||
assignmentRuleErrors.value.assignmentRuleName = __('Name is required')
|
||||
} else {
|
||||
assignmentRuleErrors.value.assignmentRuleName = ''
|
||||
}
|
||||
break
|
||||
case 'description':
|
||||
assignmentRuleErrors.value.description =
|
||||
assignmentRuleData.value.description?.length > 0
|
||||
? ''
|
||||
: __('Description is required')
|
||||
break
|
||||
case 'assignCondition':
|
||||
if (skipConditionCheck) {
|
||||
break
|
||||
}
|
||||
assignmentRuleErrors.value.assignCondition =
|
||||
assignmentRuleData.value.assignConditionJson?.length > 0
|
||||
? ''
|
||||
: __('Assign condition is required')
|
||||
|
||||
if (!validateConditions(assignmentRuleData.value.assignConditionJson)) {
|
||||
assignmentRuleErrors.value.assignConditionError = __(
|
||||
'Assign conditions are invalid',
|
||||
)
|
||||
} else {
|
||||
assignmentRuleErrors.value.assignConditionError = ''
|
||||
}
|
||||
|
||||
break
|
||||
case 'unassignCondition':
|
||||
if (skipConditionCheck) {
|
||||
break
|
||||
}
|
||||
if (
|
||||
assignmentRuleData.value.unassignConditionJson?.length > 0 &&
|
||||
!validateConditions(assignmentRuleData.value.unassignConditionJson)
|
||||
) {
|
||||
assignmentRuleErrors.value.unassignConditionError = __(
|
||||
'Unassign conditions are invalid',
|
||||
)
|
||||
} else {
|
||||
assignmentRuleErrors.value.unassignConditionError = ''
|
||||
}
|
||||
break
|
||||
case 'users':
|
||||
assignmentRuleErrors.value.users =
|
||||
assignmentRuleData.value.users?.length > 0
|
||||
? ''
|
||||
: __('Users are required')
|
||||
break
|
||||
case 'assignmentDays':
|
||||
assignmentRuleErrors.value.assignmentDays =
|
||||
assignmentRuleData.value.assignmentDays?.length > 0
|
||||
? ''
|
||||
: __('Assignment days are required')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (key) {
|
||||
validateField(key)
|
||||
} else {
|
||||
Object.keys(assignmentRuleErrors.value).forEach(validateField)
|
||||
}
|
||||
|
||||
return assignmentRuleErrors.value
|
||||
}
|
||||
|
||||
const resetAssignmentRuleData = () => {
|
||||
assignmentRuleData.value = {
|
||||
assignCondition: '',
|
||||
unassignCondition: '',
|
||||
assignConditionJson: [],
|
||||
unassignConditionJson: [],
|
||||
rule: 'Round Robin',
|
||||
priority: 1,
|
||||
users: [],
|
||||
disabled: false,
|
||||
description: '',
|
||||
name: '',
|
||||
assignmentRuleName: '',
|
||||
assignmentDays: defaultAssignmentDays,
|
||||
documentType: 'CRM Lead',
|
||||
}
|
||||
}
|
||||
|
||||
const assignmentRuleErrors = ref({
|
||||
assignmentRuleName: '',
|
||||
assignCondition: '',
|
||||
assignConditionError: '',
|
||||
unassignConditionError: '',
|
||||
users: '',
|
||||
description: '',
|
||||
assignmentDays: '',
|
||||
})
|
||||
|
||||
const resetAssignmentRuleErrors = () => {
|
||||
Object.keys(assignmentRuleErrors.value).forEach((key) => {
|
||||
assignmentRuleErrors.value[key] = ''
|
||||
})
|
||||
}
|
||||
|
||||
provide('assignmentRuleData', assignmentRuleData)
|
||||
provide('assignmentRuleErrors', assignmentRuleErrors)
|
||||
provide('validateAssignmentRule', validateAssignmentRule)
|
||||
provide('resetAssignmentRuleData', resetAssignmentRuleData)
|
||||
provide('resetAssignmentRuleErrors', resetAssignmentRuleErrors)
|
||||
|
||||
const getAssignmentRuleData = createResource({
|
||||
url: 'frappe.client.get',
|
||||
params: {
|
||||
doctype: 'Assignment Rule',
|
||||
name: step.value.data?.name,
|
||||
},
|
||||
auto: Boolean(step.value.data),
|
||||
onSuccess(data) {
|
||||
assignmentRuleData.value = {
|
||||
assignCondition: data.assign_condition,
|
||||
unassignCondition: data.unassign_condition,
|
||||
assignConditionJson: JSON.parse(data.assign_condition_json || '[]'),
|
||||
unassignConditionJson: JSON.parse(data.unassign_condition_json || '[]'),
|
||||
rule: data.rule,
|
||||
priority: data.priority,
|
||||
users: data.users,
|
||||
disabled: data.disabled,
|
||||
description: data.description,
|
||||
name: data.name,
|
||||
assignmentRuleName: data.name,
|
||||
assignmentDays: data.assignment_days.map((day) => day.day),
|
||||
documentType: data.document_type,
|
||||
}
|
||||
|
||||
initialData.value = JSON.stringify(assignmentRuleData.value)
|
||||
|
||||
const conditionsAvailable =
|
||||
assignmentRuleData.value.assignCondition?.length > 0
|
||||
const conditionsJsonAvailable =
|
||||
assignmentRuleData.value.assignConditionJson?.length > 0
|
||||
|
||||
if (conditionsAvailable && !conditionsJsonAvailable) {
|
||||
useNewUI.value = false
|
||||
isOldSla.value = true
|
||||
} else {
|
||||
useNewUI.value = true
|
||||
isOldSla.value = false
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
if (!step.value.data) {
|
||||
initialData.value = JSON.stringify(assignmentRuleData.value)
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
if (isDirty.value && !showConfirmDialog.value.show) {
|
||||
$dialog({
|
||||
title: __('Unsaved changes'),
|
||||
message: __(
|
||||
'Are you sure you want to go back? Unsaved changes will be lost.',
|
||||
),
|
||||
variant: 'solid',
|
||||
actions: [
|
||||
{
|
||||
label: __('Go back'),
|
||||
variant: 'solid',
|
||||
onClick: (close) => {
|
||||
updateStep('list', null)
|
||||
close()
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
return
|
||||
}
|
||||
updateStep('list', null)
|
||||
showConfirmDialog.value.show = false
|
||||
}
|
||||
|
||||
const saveAssignmentRule = () => {
|
||||
const validationErrors = validateAssignmentRule(undefined, !useNewUI.value)
|
||||
if (Object.values(validationErrors).some((error) => error)) {
|
||||
toast.error(
|
||||
__('Invalid fields, check if all are filled in and values are correct.'),
|
||||
)
|
||||
return
|
||||
}
|
||||
if (step.value.data) {
|
||||
if (isOldSla.value && useNewUI.value) {
|
||||
showConfirmDialog.value = {
|
||||
show: true,
|
||||
title: __('Confirm overwrite'),
|
||||
message: __(
|
||||
'Your old condition will be overwritten. Are you sure you want to save?',
|
||||
),
|
||||
onConfirm: () => {
|
||||
updateAssignmentRule()
|
||||
showConfirmDialog.value.show = false
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
updateAssignmentRule()
|
||||
} else {
|
||||
createAssignmentRule()
|
||||
}
|
||||
}
|
||||
|
||||
const createAssignmentRule = () => {
|
||||
isLoading.value = true
|
||||
createResource({
|
||||
url: 'frappe.client.insert',
|
||||
params: {
|
||||
doc: {
|
||||
doctype: 'Assignment Rule',
|
||||
document_type: assignmentRuleData.value.documentType,
|
||||
rule: assignmentRuleData.value.rule,
|
||||
priority: assignmentRuleData.value.priority,
|
||||
users: assignmentRuleData.value.users,
|
||||
disabled: assignmentRuleData.value.disabled,
|
||||
description: assignmentRuleData.value.description,
|
||||
assignment_days: assignmentRuleData.value.assignmentDays.map((day) => ({
|
||||
day: day,
|
||||
})),
|
||||
name: assignmentRuleData.value.assignmentRuleName,
|
||||
assignment_rule_name: assignmentRuleData.value.assignmentRuleName,
|
||||
assign_condition: convertToConditions({
|
||||
conditions: assignmentRuleData.value.assignConditionJson,
|
||||
}),
|
||||
unassign_condition: convertToConditions({
|
||||
conditions: assignmentRuleData.value.unassignConditionJson,
|
||||
}),
|
||||
assign_condition_json: JSON.stringify(
|
||||
assignmentRuleData.value.assignConditionJson,
|
||||
),
|
||||
unassign_condition_json: JSON.stringify(
|
||||
assignmentRuleData.value.unassignConditionJson,
|
||||
),
|
||||
},
|
||||
},
|
||||
auto: true,
|
||||
onSuccess(data) {
|
||||
getAssignmentRuleData
|
||||
.submit({
|
||||
doctype: 'Assignment Rule',
|
||||
name: data.name,
|
||||
})
|
||||
.then(() => {
|
||||
isLoading.value = false
|
||||
toast.success(__('Assignment rule created'))
|
||||
})
|
||||
updateStep('view', data)
|
||||
},
|
||||
onError: () => {
|
||||
isLoading.value = false
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const priorityOptions = [
|
||||
{ label: 'Low', value: '0' },
|
||||
{ label: 'Low-Medium', value: '1' },
|
||||
{ label: 'Medium', value: '2' },
|
||||
{ label: 'Medium-High', value: '3' },
|
||||
{ label: 'High', value: '4' },
|
||||
]
|
||||
|
||||
const updateAssignmentRule = async () => {
|
||||
isLoading.value = true
|
||||
await call('frappe.client.set_value', {
|
||||
doctype: 'Assignment Rule',
|
||||
name: assignmentRuleData.value.name,
|
||||
fieldname: {
|
||||
rule: assignmentRuleData.value.rule,
|
||||
priority: assignmentRuleData.value.priority,
|
||||
users: assignmentRuleData.value.users,
|
||||
disabled: assignmentRuleData.value.disabled,
|
||||
description: assignmentRuleData.value.description,
|
||||
document_type: assignmentRuleData.value.documentType,
|
||||
assignment_days: assignmentRuleData.value.assignmentDays.map((day) => ({
|
||||
day: day,
|
||||
})),
|
||||
assign_condition: useNewUI.value
|
||||
? convertToConditions({
|
||||
conditions: assignmentRuleData.value.assignConditionJson,
|
||||
})
|
||||
: assignmentRuleData.value.assignCondition,
|
||||
unassign_condition: useNewUI.value
|
||||
? convertToConditions({
|
||||
conditions: assignmentRuleData.value.unassignConditionJson,
|
||||
})
|
||||
: assignmentRuleData.value.unassignCondition,
|
||||
assign_condition_json: useNewUI.value
|
||||
? JSON.stringify(assignmentRuleData.value.assignConditionJson)
|
||||
: null,
|
||||
unassign_condition_json: useNewUI.value
|
||||
? JSON.stringify(assignmentRuleData.value.unassignConditionJson)
|
||||
: null,
|
||||
},
|
||||
}).catch((er) => {
|
||||
const error =
|
||||
er?.messages?.[0] ||
|
||||
__('Some error occurred while updating assignment rule')
|
||||
toast.error(error)
|
||||
isLoading.value = false
|
||||
})
|
||||
if (
|
||||
assignmentRuleData.value.name !==
|
||||
assignmentRuleData.value.assignmentRuleName
|
||||
) {
|
||||
await call('frappe.client.rename_doc', {
|
||||
doctype: 'Assignment Rule',
|
||||
old_name: assignmentRuleData.value.name,
|
||||
new_name: assignmentRuleData.value.assignmentRuleName,
|
||||
}).catch(async (er) => {
|
||||
const error =
|
||||
er?.messages?.[0] ||
|
||||
__('Some error occurred while renaming assignment rule')
|
||||
toast.error(error)
|
||||
// Reset assignment rule to previous state
|
||||
await getAssignmentRuleData.reload()
|
||||
isLoading.value = false
|
||||
})
|
||||
await getAssignmentRuleData.submit({
|
||||
doctype: 'Assignment Rule',
|
||||
name: assignmentRuleData.value.assignmentRuleName,
|
||||
})
|
||||
} else {
|
||||
getAssignmentRuleData.reload()
|
||||
}
|
||||
isLoading.value = false
|
||||
toast.success(__('Assignment rule updated'))
|
||||
}
|
||||
|
||||
watch(
|
||||
assignmentRuleData,
|
||||
(newVal) => {
|
||||
if (!initialData.value) return
|
||||
isDirty.value = JSON.stringify(newVal) != initialData.value
|
||||
if (isDirty.value) {
|
||||
disableSettingModalOutsideClick.value = true
|
||||
} else {
|
||||
disableSettingModalOutsideClick.value = false
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
const beforeUnloadHandler = (event) => {
|
||||
if (!isDirty.value) return
|
||||
event.preventDefault()
|
||||
event.returnValue = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
addEventListener('beforeunload', beforeUnloadHandler)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
resetAssignmentRuleErrors()
|
||||
resetAssignmentRuleData()
|
||||
removeEventListener('beforeunload', beforeUnloadHandler)
|
||||
disableSettingModalOutsideClick.value = false
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-6 text-ink-gray-8">
|
||||
<!-- Header -->
|
||||
<div class="flex justify-between px-2 pt-2">
|
||||
<div class="flex flex-col gap-1 w-9/12">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('Assignment rules') }}
|
||||
</h2>
|
||||
<p class="text-p-base text-ink-gray-6">
|
||||
{{
|
||||
__(
|
||||
'Assignment rules automatically assign lead/deal to the right sales user based on predefined conditions',
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||
<Button
|
||||
:label="__('New')"
|
||||
icon-left="plus"
|
||||
variant="solid"
|
||||
@click="goToNew()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Assignment rules list -->
|
||||
<div class="overflow-y-auto">
|
||||
<AssignmentRulesList />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AssignmentRulesList from './AssignmentRulesList.vue'
|
||||
import { createResource } from 'frappe-ui'
|
||||
import { inject, provide } from 'vue'
|
||||
|
||||
const updateStep = inject('updateStep')
|
||||
|
||||
const assignmentRulesListData = createResource({
|
||||
url: 'crm.api.assignment_rule.get_assignment_rules_list',
|
||||
cache: ['assignmentRules', 'get_assignment_rules_list'],
|
||||
auto: true,
|
||||
})
|
||||
|
||||
provide('assignmentRulesList', assignmentRulesListData)
|
||||
|
||||
const goToNew = () => {
|
||||
updateStep('view', null)
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="assignmentRulesList.loading && !assignmentRulesList.data"
|
||||
class="flex items-center justify-center mt-12"
|
||||
>
|
||||
<LoadingIndicator class="w-4" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<div
|
||||
v-if="assignmentRulesList.data?.length === 0"
|
||||
class="flex items-center justify-center rounded-md border border-outline-gray-2 p-4"
|
||||
>
|
||||
<div class="text-sm text-ink-gray-7">
|
||||
{{ __('No items in the list') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="flex items-center py-2 px-4 text-sm text-ink-gray-5">
|
||||
<div class="w-7/12">{{ __('Assignment rule') }}</div>
|
||||
<div class="w-3/12">{{ __('Priority') }}</div>
|
||||
<div class="w-2/12">{{ __('Enabled') }}</div>
|
||||
</div>
|
||||
<div class="h-px border-t mx-4 border-outline-gray-modals" />
|
||||
<div class="overflow-y-auto px-2">
|
||||
<template
|
||||
v-for="(assignmentRule, i) in assignmentRulesList.data"
|
||||
:key="assignmentRule.name"
|
||||
>
|
||||
<AssignmentRuleListItem :data="assignmentRule" />
|
||||
<hr v-if="assignmentRulesList.data.length !== i + 1" class="mx-2" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { LoadingIndicator } from 'frappe-ui'
|
||||
import { inject } from 'vue'
|
||||
import AssignmentRuleListItem from './AssignmentRuleListItem.vue'
|
||||
|
||||
const assignmentRulesList = inject('assignmentRulesList')
|
||||
</script>
|
||||
@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<CFConditions
|
||||
v-if="props.conditions.length > 0"
|
||||
:conditions="props.conditions"
|
||||
:level="0"
|
||||
:disableAddCondition="props.errors !== ''"
|
||||
:doctype="props.doctype"
|
||||
/>
|
||||
<div
|
||||
v-if="props.conditions.length == 0"
|
||||
class="flex p-4 items-center cursor-pointer justify-center gap-2 text-sm border border-outline-gray-2 text-gray-600 rounded-md"
|
||||
@click="
|
||||
() => {
|
||||
props.conditions.push(['', '', ''])
|
||||
validateAssignmentRule(props.name)
|
||||
}
|
||||
"
|
||||
>
|
||||
<FeatherIcon name="plus" class="h-4" />
|
||||
{{ __('Add a condition') }}
|
||||
</div>
|
||||
<div class="flex items-center justify-between mt-2">
|
||||
<div class="" v-if="props.conditions.length > 0">
|
||||
<Dropdown v-slot="{ open }" :options="dropdownOptions">
|
||||
<Button
|
||||
:disabled="props.errors !== ''"
|
||||
:icon-right="open ? 'chevron-up' : 'chevron-down'"
|
||||
:label="__('Add condition')"
|
||||
/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<ErrorMessage v-if="props.conditions.length > 0" :message="props.errors" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Button, Dropdown, ErrorMessage, FeatherIcon } from 'frappe-ui'
|
||||
import { watchDebounced } from '@vueuse/core'
|
||||
import { validateConditions } from '@/utils'
|
||||
import CFConditions from '../../ConditionsFilter/CFConditions.vue'
|
||||
import { inject } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
conditions: Array,
|
||||
name: String,
|
||||
errors: String,
|
||||
doctype: String,
|
||||
})
|
||||
|
||||
const validateAssignmentRule = inject('validateAssignmentRule')
|
||||
|
||||
const getConjunction = () => {
|
||||
let conjunction = 'and'
|
||||
props.conditions.forEach((condition) => {
|
||||
if (typeof condition == 'string') {
|
||||
conjunction = condition
|
||||
}
|
||||
})
|
||||
return conjunction
|
||||
}
|
||||
|
||||
const dropdownOptions = [
|
||||
{
|
||||
label: __('Add condition'),
|
||||
onClick: () => {
|
||||
addCondition()
|
||||
},
|
||||
},
|
||||
{
|
||||
label: __('Add condition group'),
|
||||
onClick: () => {
|
||||
const conjunction = getConjunction()
|
||||
props.conditions.push(conjunction, [[]])
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const addCondition = () => {
|
||||
const isValid = validateConditions(props.conditions)
|
||||
|
||||
if (!isValid) {
|
||||
return
|
||||
}
|
||||
const conjunction = getConjunction()
|
||||
|
||||
props.conditions.push(conjunction, ['', '', ''])
|
||||
}
|
||||
|
||||
watchDebounced(
|
||||
() => [...props.conditions],
|
||||
() => {
|
||||
validateAssignmentRule(props.name)
|
||||
},
|
||||
{ deep: true, debounce: 300 },
|
||||
)
|
||||
</script>
|
||||
@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div class="rounded-md border px-2 border-outline-gray-2 text-sm">
|
||||
<div
|
||||
class="grid p-2 px-4 items-center"
|
||||
style="grid-template-columns: 3fr 1fr"
|
||||
>
|
||||
<div
|
||||
v-for="column in columns"
|
||||
:key="column.key"
|
||||
class="text-gray-600 overflow-hidden whitespace-nowrap text-ellipsis"
|
||||
>
|
||||
{{ __(column.label) }}
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<AssignmentScheduleItem
|
||||
v-for="(day, index) in days"
|
||||
:key="day.day"
|
||||
:data="day"
|
||||
:isLast="index === days.length - 1"
|
||||
/>
|
||||
</div>
|
||||
<ErrorMessage :message="assignmentRuleErrors.assignmentDays" class="mt-2" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AssignmentScheduleItem from './AssignmentScheduleItem.vue'
|
||||
import { ErrorMessage } from 'frappe-ui'
|
||||
import { onMounted, ref, inject } from 'vue'
|
||||
|
||||
const assignmentRuleData = inject('assignmentRuleData')
|
||||
const assignmentRuleErrors = inject('assignmentRuleErrors')
|
||||
|
||||
const columns = [
|
||||
{
|
||||
label: 'Days',
|
||||
key: 'day',
|
||||
},
|
||||
{
|
||||
label: 'Active',
|
||||
key: 'active',
|
||||
},
|
||||
]
|
||||
|
||||
const days = ref([
|
||||
{
|
||||
day: 'Monday',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
day: 'Tuesday',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
day: 'Wednesday',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
day: 'Thursday',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
day: 'Friday',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
day: 'Saturday',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
day: 'Sunday',
|
||||
active: false,
|
||||
},
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
assignmentRuleData.value.assignmentDays.forEach((day) => {
|
||||
const workDay = days.value.find((d) => d.day === day)
|
||||
if (workDay) {
|
||||
workDay.active = true
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div
|
||||
class="grid py-3.5 px-4 items-center"
|
||||
style="grid-template-columns: 3fr 1fr"
|
||||
>
|
||||
<div class="text-ink-gray-7 font-medium">{{ __(data.day) }}</div>
|
||||
<div class="flex justify-start">
|
||||
<Switch v-model="data.active" @update:model-value="toggleDay" />
|
||||
</div>
|
||||
</div>
|
||||
<hr v-if="!isLast" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Switch } from 'frappe-ui'
|
||||
import { inject } from 'vue'
|
||||
|
||||
const assignmentRuleData = inject('assignmentRuleData')
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
isLast: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const toggleDay = (isActive) => {
|
||||
const dayIndex = assignmentRuleData.value.assignmentDays.findIndex(
|
||||
(d) => d === props.data.day,
|
||||
)
|
||||
|
||||
if (isActive && dayIndex === -1) {
|
||||
assignmentRuleData.value.assignmentDays.push(props.data.day)
|
||||
} else {
|
||||
assignmentRuleData.value.assignmentDays.splice(dayIndex, 1)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,27 +1,18 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 px-6 py-8 text-ink-gray-8">
|
||||
<!-- Header -->
|
||||
<div class="flex px-2 justify-between">
|
||||
<div class="flex items-center gap-1 -ml-4 w-9/12">
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon-left="chevron-left"
|
||||
:label="__('Brand settings')"
|
||||
size="md"
|
||||
@click="() => emit('updateStep', 'general-settings')"
|
||||
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||
/>
|
||||
<Badge
|
||||
v-if="settings.isDirty"
|
||||
:label="__('Not Saved')"
|
||||
variant="subtle"
|
||||
theme="orange"
|
||||
/>
|
||||
<div class="flex justify-between px-2 text-ink-gray-8">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('Brand settings') }}
|
||||
</h2>
|
||||
<p class="text-p-base text-ink-gray-6">
|
||||
{{ __('Configure your brand name, logo, and favicon') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||
<Button
|
||||
:label="__('Update')"
|
||||
icon-left="plus"
|
||||
variant="solid"
|
||||
:disabled="!settings.isDirty"
|
||||
:loading="settings.loading"
|
||||
@ -36,35 +27,30 @@
|
||||
<FormControl
|
||||
type="text"
|
||||
class="w-1/2"
|
||||
size="md"
|
||||
v-model="settings.doc.brand_name"
|
||||
:label="__('Brand name')"
|
||||
:placeholder="__('Enter brand name')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- logo -->
|
||||
<div class="flex flex-col justify-between gap-4">
|
||||
<span class="text-base font-semibold text-ink-gray-8">
|
||||
{{ __('Logo') }}
|
||||
</span>
|
||||
<div class="flex flex-1 gap-5">
|
||||
<div class="flex items-center flex-1 gap-5">
|
||||
<div
|
||||
class="flex items-center justify-center rounded border border-outline-gray-modals px-10 py-2"
|
||||
class="flex items-center justify-center rounded border border-outline-gray-modals size-20"
|
||||
>
|
||||
<img
|
||||
:src="settings.doc?.brand_logo || '/assets/crm/images/logo.png'"
|
||||
v-if="settings.doc?.brand_logo"
|
||||
:src="settings.doc?.brand_logo"
|
||||
alt="Logo"
|
||||
class="size-8 rounded"
|
||||
/>
|
||||
<ImageIcon v-else class="size-5 text-ink-gray-4" />
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2">
|
||||
<ImageUploader
|
||||
label="Favicon"
|
||||
image_type="image/ico"
|
||||
:image_url="settings.doc?.brand_logo"
|
||||
@upload="(url) => (settings.doc.brand_logo = url)"
|
||||
@remove="() => (settings.doc.brand_logo = '')"
|
||||
/>
|
||||
<span class="text-p-sm text-ink-gray-6">
|
||||
<div class="flex flex-1 flex-col gap-1">
|
||||
<span class="text-base font-medium">{{ __('Brand logo') }}</span>
|
||||
<span class="text-p-base text-ink-gray-6">
|
||||
{{
|
||||
__(
|
||||
'Appears in the left sidebar. Recommended size is 32x32 px in PNG or SVG',
|
||||
@ -72,33 +58,34 @@
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<ImageUploader
|
||||
image_type="image/ico"
|
||||
:image_url="settings.doc?.brand_logo"
|
||||
@upload="(url) => (settings.doc.brand_logo = url)"
|
||||
@remove="() => (settings.doc.brand_logo = '')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- favicon -->
|
||||
<div class="flex flex-col justify-between gap-4">
|
||||
<span class="text-base font-semibold text-ink-gray-8">
|
||||
{{ __('Favicon') }}
|
||||
</span>
|
||||
<div class="flex flex-1 gap-5">
|
||||
<div class="flex items-center flex-1 gap-5">
|
||||
<div
|
||||
class="flex items-center justify-center rounded border border-outline-gray-modals px-10 py-2"
|
||||
class="flex items-center justify-center rounded border border-outline-gray-modals size-20"
|
||||
>
|
||||
<img
|
||||
:src="settings.doc?.favicon || '/assets/crm/images/logo.png'"
|
||||
v-if="settings.doc?.favicon"
|
||||
:src="settings.doc?.favicon"
|
||||
alt="Favicon"
|
||||
class="size-8 rounded"
|
||||
/>
|
||||
<ImageIcon v-else class="size-5 text-ink-gray-4" />
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2">
|
||||
<ImageUploader
|
||||
label="Favicon"
|
||||
image_type="image/ico"
|
||||
:image_url="settings.doc?.favicon"
|
||||
@upload="(url) => (settings.doc.favicon = url)"
|
||||
@remove="() => (settings.doc.favicon = '')"
|
||||
/>
|
||||
<span class="text-p-sm text-ink-gray-6">
|
||||
<div class="flex flex-1 flex-col gap-1">
|
||||
<span class="text-base font-medium">{{ __('Favicon') }}</span>
|
||||
<span class="text-p-base text-ink-gray-6">
|
||||
{{
|
||||
__(
|
||||
'Appears next to the title in your browser tab. Recommended size is 32x32 px in PNG or ICO',
|
||||
@ -106,20 +93,25 @@
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<ImageUploader
|
||||
image_type="image/ico"
|
||||
:image_url="settings.doc?.favicon"
|
||||
@upload="(url) => (settings.doc.favicon = url)"
|
||||
@remove="() => (settings.doc.favicon = '')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="errorMessage">
|
||||
<ErrorMessage :message="__(errorMessage)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import ImageIcon from '~icons/lucide/image'
|
||||
import ImageUploader from '@/components/Controls/ImageUploader.vue'
|
||||
import { FormControl, ErrorMessage } from 'frappe-ui'
|
||||
import { FormControl } from 'frappe-ui'
|
||||
import { getSettings } from '@/stores/settings'
|
||||
import { showSettings } from '@/composables/settings'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { _settings: settings, setupBrand } = getSettings()
|
||||
|
||||
@ -131,7 +123,4 @@ function updateSettings() {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const emit = defineEmits(['updateStep'])
|
||||
const errorMessage = ref('')
|
||||
</script>
|
||||
@ -1,27 +1,20 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 px-6 py-8 text-ink-gray-8">
|
||||
<!-- Header -->
|
||||
<div class="flex px-2 justify-between">
|
||||
<div class="flex items-center gap-1 -ml-4 w-9/12">
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon-left="chevron-left"
|
||||
:label="__('Currency & Exchange rate provider')"
|
||||
size="md"
|
||||
@click="() => emit('updateStep', 'general-settings')"
|
||||
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||
/>
|
||||
<Badge
|
||||
v-if="settings.isDirty"
|
||||
:label="__('Not Saved')"
|
||||
variant="subtle"
|
||||
theme="orange"
|
||||
/>
|
||||
<div class="flex justify-between px-2 text-ink-gray-8">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('Currency & Exchange rate provider') }}
|
||||
</h2>
|
||||
<p class="text-p-base text-ink-gray-6">
|
||||
{{
|
||||
__('Configure the currency and exchange rate provider for your CRM')
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||
<Button
|
||||
:label="__('Update')"
|
||||
icon-left="plus"
|
||||
variant="solid"
|
||||
:disabled="!settings.isDirty"
|
||||
:loading="settings.loading"
|
||||
@ -32,7 +25,7 @@
|
||||
|
||||
<!-- Fields -->
|
||||
<div class="flex flex-1 flex-col overflow-y-auto">
|
||||
<div class="flex items-center justify-between gap-8 p-3">
|
||||
<div class="flex items-center justify-between gap-8 py-3 px-2">
|
||||
<div class="flex flex-col">
|
||||
<div class="text-p-base font-medium text-ink-gray-7 truncate">
|
||||
{{ __('Currency') }}
|
||||
@ -61,7 +54,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-px border-t mx-2 border-outline-gray-modals" />
|
||||
<div class="flex items-center justify-between gap-8 p-3">
|
||||
<div class="flex items-center justify-between gap-8 py-3 px-2">
|
||||
<div class="flex flex-col">
|
||||
<div class="text-p-base font-medium text-ink-gray-7 truncate">
|
||||
{{ __('Exchange rate provider') }}
|
||||
@ -131,17 +124,15 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ErrorMessage, toast } from 'frappe-ui'
|
||||
import { ErrorMessage, FormControl, toast } from 'frappe-ui'
|
||||
import { getSettings } from '@/stores/settings'
|
||||
import { globalStore } from '@/stores/global'
|
||||
import { showSettings } from '@/composables/settings'
|
||||
import { ref } from 'vue'
|
||||
import FormControl from 'frappe-ui/src/components/FormControl/FormControl.vue'
|
||||
|
||||
const { _settings: settings } = getSettings()
|
||||
const { $dialog } = globalStore()
|
||||
|
||||
const emit = defineEmits(['updateStep'])
|
||||
const errorMessage = ref('')
|
||||
|
||||
function updateSettings() {
|
||||
@ -9,10 +9,14 @@
|
||||
:label="__(template.name)"
|
||||
size="md"
|
||||
@click="() => emit('updateStep', 'template-list')"
|
||||
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||
class="cursor-pointer hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5 font-semibold text-xl hover:opacity-70 !pr-0 !max-w-96 !justify-start"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||
<div class="flex item-center space-x-4 w-3/12 justify-end">
|
||||
<div class="flex items-center space-x-2">
|
||||
<Switch size="sm" v-model="template.enabled" />
|
||||
<span class="text-sm text-ink-gray-7">{{ __('Enabled') }}</span>
|
||||
</div>
|
||||
<Button
|
||||
:label="__('Update')"
|
||||
icon-left="plus"
|
||||
@ -26,13 +30,6 @@
|
||||
|
||||
<!-- Fields -->
|
||||
<div class="flex flex-1 flex-col gap-4 overflow-y-auto">
|
||||
<div
|
||||
class="flex justify-between items-center cursor-pointer border-b py-3"
|
||||
@click="() => (template.enabled = !template.enabled)"
|
||||
>
|
||||
<div class="text-base text-ink-gray-7">{{ __('Enabled') }}</div>
|
||||
<Switch v-model="template.enabled" @click.stop />
|
||||
</div>
|
||||
<div class="flex sm:flex-row flex-col gap-4">
|
||||
<div class="flex-1">
|
||||
<FormControl
|
||||
|
||||
@ -148,7 +148,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { TemplateOption } from '@/utils'
|
||||
import {
|
||||
TextInput,
|
||||
FormControl,
|
||||
@ -223,43 +222,28 @@ function getDropdownOptions(template) {
|
||||
let options = [
|
||||
{
|
||||
label: __('Duplicate'),
|
||||
component: (props) =>
|
||||
TemplateOption({
|
||||
option: __('Duplicate'),
|
||||
icon: 'copy',
|
||||
active: props.active,
|
||||
onClick: () => emit('updateStep', 'new-template', { ...template }),
|
||||
}),
|
||||
icon: 'copy',
|
||||
onClick: () => emit('updateStep', 'new-template', { ...template }),
|
||||
},
|
||||
{
|
||||
label: __('Delete'),
|
||||
component: (props) =>
|
||||
TemplateOption({
|
||||
option: __('Delete'),
|
||||
icon: 'trash-2',
|
||||
active: props.active,
|
||||
onClick: (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
confirmDelete.value = true
|
||||
},
|
||||
}),
|
||||
icon: 'trash-2',
|
||||
onClick: (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
confirmDelete.value = true
|
||||
},
|
||||
condition: () => !confirmDelete.value,
|
||||
},
|
||||
{
|
||||
label: __('Confirm Delete'),
|
||||
component: (props) =>
|
||||
TemplateOption({
|
||||
option: __('Confirm Delete'),
|
||||
icon: 'trash-2',
|
||||
active: props.active,
|
||||
theme: 'danger',
|
||||
onClick: () => deleteTemplate(template),
|
||||
}),
|
||||
icon: 'trash-2',
|
||||
theme: 'red',
|
||||
onClick: () => deleteTemplate(template),
|
||||
condition: () => confirmDelete.value,
|
||||
},
|
||||
]
|
||||
|
||||
return options.filter((option) => option.condition?.() || true)
|
||||
return options
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -11,10 +11,14 @@
|
||||
"
|
||||
size="md"
|
||||
@click="() => emit('updateStep', 'template-list')"
|
||||
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||
class="cursor-pointer hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5 font-semibold text-xl hover:opacity-70 !pr-0 !max-w-96 !justify-start"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||
<div class="flex item-center space-x-4 w-3/12 justify-end">
|
||||
<div class="flex items-center space-x-2">
|
||||
<Switch size="sm" v-model="template.enabled" />
|
||||
<span class="text-sm text-ink-gray-7">{{ __('Enabled') }}</span>
|
||||
</div>
|
||||
<Button
|
||||
:label="templateData?.name ? __('Duplicate') : __('Create')"
|
||||
icon-left="plus"
|
||||
@ -26,13 +30,6 @@
|
||||
|
||||
<!-- Fields -->
|
||||
<div class="flex flex-1 flex-col gap-4 overflow-y-auto">
|
||||
<div
|
||||
class="flex justify-between items-center cursor-pointer border-b py-3"
|
||||
@click="() => (template.enabled = !template.enabled)"
|
||||
>
|
||||
<div class="text-base text-ink-gray-7">{{ __('Enabled') }}</div>
|
||||
<Switch v-model="template.enabled" @click.stop />
|
||||
</div>
|
||||
<div class="flex sm:flex-row flex-col gap-4">
|
||||
<div class="flex-1">
|
||||
<FormControl
|
||||
|
||||
93
frontend/src/components/Settings/ForecastingSettings.vue
Normal file
93
frontend/src/components/Settings/ForecastingSettings.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 py-8 px-6 text-ink-gray-8">
|
||||
<div class="flex flex-col gap-1 px-2">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('Forecasting') }}
|
||||
</h2>
|
||||
<p class="text-p-base text-ink-gray-6">
|
||||
{{
|
||||
__(
|
||||
'Configure forecasting feature to help predict sales performance and growth',
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 flex flex-col overflow-y-auto">
|
||||
<div class="flex items-center justify-between py-3 px-2">
|
||||
<div class="flex flex-col">
|
||||
<div class="text-p-base font-medium text-ink-gray-7 truncate">
|
||||
{{ __('Enable forecasting') }}
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-5 truncate">
|
||||
{{
|
||||
__(
|
||||
'Makes "Expected Closure Date" and "Expected Deal Value" mandatory for deal value forecasting',
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Switch
|
||||
size="sm"
|
||||
v-model="settings.doc.enable_forecasting"
|
||||
@click.stop="toggleForecasting"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-px border-t mx-2 border-outline-gray-modals" />
|
||||
<div class="flex items-center justify-between py-3 px-2">
|
||||
<div class="flex flex-col">
|
||||
<div class="text-p-base font-medium text-ink-gray-7 truncate">
|
||||
{{ __('Auto update expected deal value') }}
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-5 truncate">
|
||||
{{
|
||||
__(
|
||||
'Automatically update "Expected Deal Value" based on the total value of associated products in a deal',
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Switch
|
||||
size="sm"
|
||||
v-model="settings.doc.auto_update_expected_deal_value"
|
||||
@click.stop="autoUpdateExpectedDealValue"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getSettings } from '@/stores/settings'
|
||||
import { Switch, toast } from 'frappe-ui'
|
||||
|
||||
const { _settings: settings } = getSettings()
|
||||
|
||||
function toggleForecasting() {
|
||||
settings.save.submit(null, {
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
settings.doc.enable_forecasting
|
||||
? __('Forecasting enabled successfully')
|
||||
: __('Forecasting disabled successfully'),
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function autoUpdateExpectedDealValue() {
|
||||
settings.save.submit(null, {
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
settings.doc.auto_update_expected_deal_value
|
||||
? __('Auto update of expected deal value enabled')
|
||||
: __('Auto update of expected deal value disabled'),
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('General') }}
|
||||
</h2>
|
||||
<p class="text-p-base text-ink-gray-6">
|
||||
{{ __('Configure general settings for your CRM') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 flex flex-col overflow-y-auto">
|
||||
<div
|
||||
class="flex items-center justify-between p-3 cursor-pointer hover:bg-surface-menu-bar rounded"
|
||||
@click="toggleForecasting()"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<div class="text-p-base font-medium text-ink-gray-7 truncate">
|
||||
{{ __('Enable forecasting') }}
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-5 truncate">
|
||||
{{
|
||||
__(
|
||||
'Makes "Expected Closure Date" and "Expected Deal Value" mandatory for deal value forecasting',
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Switch
|
||||
size="sm"
|
||||
v-model="settings.doc.enable_forecasting"
|
||||
@click.stop="toggleForecasting(settings.doc.enable_forecasting)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-px border-t mx-2 border-outline-gray-modals" />
|
||||
<template v-for="(setting, i) in settingsList" :key="setting.name">
|
||||
<li
|
||||
class="flex items-center justify-between p-3 cursor-pointer hover:bg-surface-menu-bar rounded"
|
||||
@click="() => emit('updateStep', setting.name)"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<div class="text-p-base font-medium text-ink-gray-7 truncate">
|
||||
{{ __(setting.label) }}
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-5 truncate">
|
||||
{{ __(setting.description) }}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<FeatherIcon name="chevron-right" class="text-ink-gray-7 size-4" />
|
||||
</div>
|
||||
</li>
|
||||
<div
|
||||
v-if="settingsList.length !== i + 1"
|
||||
class="h-px border-t mx-2 border-outline-gray-modals"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getSettings } from '@/stores/settings'
|
||||
import { Switch, toast } from 'frappe-ui'
|
||||
|
||||
const emit = defineEmits(['updateStep'])
|
||||
|
||||
const { _settings: settings } = getSettings()
|
||||
|
||||
const settingsList = [
|
||||
{
|
||||
name: 'currency-settings',
|
||||
label: 'Currency & Exchange rate provider',
|
||||
description:
|
||||
'Configure the currency and exchange rate provider for your CRM',
|
||||
},
|
||||
{
|
||||
name: 'brand-settings',
|
||||
label: 'Brand settings',
|
||||
description: 'Configure your brand name, logo and favicon',
|
||||
},
|
||||
{
|
||||
name: 'home-actions',
|
||||
label: 'Home actions',
|
||||
description: 'Configure actions that appear on the home dropdown',
|
||||
},
|
||||
]
|
||||
|
||||
function toggleForecasting(value) {
|
||||
settings.doc.enable_forecasting =
|
||||
value !== undefined ? value : !settings.doc.enable_forecasting
|
||||
|
||||
settings.save.submit(null, {
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
settings.doc.enable_forecasting
|
||||
? __('Forecasting enabled successfully')
|
||||
: __('Forecasting disabled successfully'),
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -1,34 +0,0 @@
|
||||
<template>
|
||||
<component :is="getComponent(step)" :data="data" @updateStep="updateStep" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import GeneralSettings from './GeneralSettings.vue'
|
||||
import CurrencySettings from './CurrencySettings.vue'
|
||||
import BrandSettings from './BrandSettings.vue'
|
||||
import HomeActions from './HomeActions.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const step = ref('general-settings')
|
||||
const data = ref(null)
|
||||
|
||||
function updateStep(newStep, _data) {
|
||||
step.value = newStep
|
||||
data.value = _data
|
||||
}
|
||||
|
||||
function getComponent(step) {
|
||||
switch (step) {
|
||||
case 'general-settings':
|
||||
return GeneralSettings
|
||||
case 'currency-settings':
|
||||
return CurrencySettings
|
||||
case 'brand-settings':
|
||||
return BrandSettings
|
||||
case 'home-actions':
|
||||
return HomeActions
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,21 +1,18 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
||||
<!-- Header -->
|
||||
<div class="flex justify-between">
|
||||
<div class="flex gap-1 -ml-4 w-9/12">
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon-left="chevron-left"
|
||||
:label="__('Home actions')"
|
||||
size="md"
|
||||
@click="() => emit('updateStep', 'general-settings')"
|
||||
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||
/>
|
||||
<div class="flex justify-between text-ink-gray-8">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('Home actions') }}
|
||||
</h2>
|
||||
<p class="text-p-base text-ink-gray-6">
|
||||
{{ __('Configure actions that appear on the home dropdown') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||
<Button
|
||||
:label="__('Update')"
|
||||
icon-left="plus"
|
||||
variant="solid"
|
||||
:disabled="!document.isDirty"
|
||||
:loading="document.loading"
|
||||
@ -25,7 +22,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Fields -->
|
||||
<div class="flex flex-1 flex-col gap-4 overflow-y-auto">
|
||||
<div class="flex flex-1 flex-col overflow-y-auto">
|
||||
<Grid
|
||||
v-model="document.doc.dropdown_items"
|
||||
doctype="CRM Dropdown Item"
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex h-full flex-col gap-6 py-8 px-6 text-ink-gray-8">
|
||||
<div class="flex px-2 justify-between">
|
||||
<div class="flex flex-col gap-1 w-9/12">
|
||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||
{{ __('Send invites to') }}
|
||||
@ -23,26 +23,21 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col gap-8 overflow-y-auto">
|
||||
<div class="flex-1 flex flex-col px-2 gap-8 overflow-y-auto">
|
||||
<div>
|
||||
<label class="block text-xs text-ink-gray-5 mb-1.5">
|
||||
{{ __('Invite by email') }}
|
||||
</label>
|
||||
<div
|
||||
class="p-2 group bg-surface-gray-2 hover:bg-surface-gray-3 rounded"
|
||||
>
|
||||
<MultiSelectUserInput
|
||||
class="flex-1"
|
||||
inputClass="!bg-surface-gray-2 hover:!bg-surface-gray-3 group-hover:!bg-surface-gray-3"
|
||||
:placeholder="__('john@doe.com')"
|
||||
v-model="invitees"
|
||||
:validate="validateEmail"
|
||||
:error-message="
|
||||
(value) => __('{0} is an invalid email address', [value])
|
||||
"
|
||||
:fetchUsers="false"
|
||||
/>
|
||||
</div>
|
||||
<FormControl
|
||||
type="textarea"
|
||||
label="Invite by email"
|
||||
placeholder="user1@example.com, user2@example.com, ..."
|
||||
@input="updateInvitees($event.target.value)"
|
||||
:debounce="100"
|
||||
:disabled="inviteByEmail.loading"
|
||||
:description="
|
||||
__(
|
||||
'You can invite multiple users by comma separating their email addresses',
|
||||
)
|
||||
"
|
||||
/>
|
||||
<div
|
||||
v-if="userExistMessage || inviteeExistMessage"
|
||||
class="text-xs text-ink-red-3 mt-1.5"
|
||||
@ -100,15 +95,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import MultiSelectUserInput from '@/components/Controls/MultiSelectUserInput.vue'
|
||||
import { validateEmail, convertArrayToString } from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import {
|
||||
createListResource,
|
||||
createResource,
|
||||
FormControl,
|
||||
Tooltip,
|
||||
} from 'frappe-ui'
|
||||
import { createListResource, createResource, FormControl } from 'frappe-ui'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
@ -208,6 +197,15 @@ const pendingInvitations = createListResource({
|
||||
doctype: 'CRM Invitation',
|
||||
filters: { status: 'Pending' },
|
||||
fields: ['name', 'email', 'role'],
|
||||
pageLength: 999,
|
||||
auto: true,
|
||||
})
|
||||
|
||||
function updateInvitees(value) {
|
||||
const emails = value
|
||||
.split(',')
|
||||
.map((email) => email.trim())
|
||||
.filter((email) => validateEmail(email))
|
||||
invitees.value = emails
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -3,34 +3,37 @@
|
||||
v-model="showSettings"
|
||||
:options="{ size: '5xl' }"
|
||||
@close="activeSettingsPage = ''"
|
||||
:disableOutsideClickToClose="disableSettingModalOutsideClick"
|
||||
>
|
||||
<template #body>
|
||||
<div class="flex h-[calc(100vh_-_8rem)]">
|
||||
<div class="flex flex-col p-2 w-52 shrink-0 bg-surface-gray-2">
|
||||
<h1 class="px-2 pt-2 mb-3 text-lg font-semibold text-ink-gray-8">
|
||||
<div class="flex flex-col p-1 w-52 shrink-0 bg-surface-gray-2">
|
||||
<h1 class="px-3 pt-3 pb-2 text-lg font-semibold text-ink-gray-8">
|
||||
{{ __('Settings') }}
|
||||
</h1>
|
||||
<div v-for="tab in tabs">
|
||||
<div
|
||||
v-if="!tab.hideLabel"
|
||||
class="mb-2 mt-3 flex cursor-pointer gap-1.5 px-1 text-base font-medium text-ink-gray-5 transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<span>{{ __(tab.label) }}</span>
|
||||
</div>
|
||||
<nav class="space-y-1">
|
||||
<SidebarLink
|
||||
v-for="i in tab.items"
|
||||
:icon="i.icon"
|
||||
:label="__(i.label)"
|
||||
class="w-full"
|
||||
:class="
|
||||
activeTab?.label == i.label
|
||||
? 'bg-surface-selected shadow-sm hover:bg-surface-selected'
|
||||
: 'hover:bg-surface-gray-3'
|
||||
"
|
||||
@click="activeSettingsPage = i.label"
|
||||
/>
|
||||
</nav>
|
||||
<div class="flex flex-col overflow-y-auto">
|
||||
<template v-for="tab in tabs" :key="tab.label">
|
||||
<div
|
||||
v-if="!tab.hideLabel"
|
||||
class="py-[7px] px-2 my-1 flex cursor-pointer gap-1.5 text-base text-ink-gray-5 transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<span>{{ __(tab.label) }}</span>
|
||||
</div>
|
||||
<nav class="space-y-1 px-1">
|
||||
<SidebarLink
|
||||
v-for="i in tab.items"
|
||||
:icon="i.icon"
|
||||
:label="__(i.label)"
|
||||
class="w-full"
|
||||
:class="
|
||||
activeTab?.label == i.label
|
||||
? 'bg-surface-selected shadow-sm hover:bg-surface-selected'
|
||||
: 'hover:bg-surface-gray-3'
|
||||
"
|
||||
@click="activeSettingsPage = i.label"
|
||||
/>
|
||||
</nav>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 overflow-y-auto bg-surface-modal">
|
||||
@ -41,17 +44,24 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import CircleDollarSignIcon from '~icons/lucide/circle-dollar-sign'
|
||||
import TrendingUpDownIcon from '~icons/lucide/trending-up-down'
|
||||
import SparkleIcon from '@/components/Icons/SparkleIcon.vue'
|
||||
import WhatsAppIcon from '@/components/Icons/WhatsAppIcon.vue'
|
||||
import ERPNextIcon from '@/components/Icons/ERPNextIcon.vue'
|
||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
||||
import EmailTemplateIcon from '@/components/Icons/EmailTemplateIcon.vue'
|
||||
import SettingsIcon2 from '@/components/Icons/SettingsIcon2.vue'
|
||||
import Users from '@/components/Settings/Users.vue'
|
||||
import GeneralSettingsPage from '@/components/Settings/General/GeneralSettingsPage.vue'
|
||||
import InviteUserPage from '@/components/Settings/InviteUserPage.vue'
|
||||
import ProfileSettings from '@/components/Settings/ProfileSettings.vue'
|
||||
import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
||||
import ERPNextSettings from '@/components/Settings/ERPNextSettings.vue'
|
||||
import BrandSettings from '@/components/Settings/BrandSettings.vue'
|
||||
import HomeActions from '@/components/Settings/HomeActions.vue'
|
||||
import ForecastingSettings from '@/components/Settings/ForecastingSettings.vue'
|
||||
import CurrencySettings from '@/components/Settings/CurrencySettings.vue'
|
||||
import EmailTemplatePage from '@/components/Settings/EmailTemplate/EmailTemplatePage.vue'
|
||||
import TelephonySettings from '@/components/Settings/TelephonySettings.vue'
|
||||
import EmailConfig from '@/components/Settings/EmailConfig.vue'
|
||||
@ -61,9 +71,11 @@ import {
|
||||
isWhatsappInstalled,
|
||||
showSettings,
|
||||
activeSettingsPage,
|
||||
disableSettingModalOutsideClick,
|
||||
} from '@/composables/settings'
|
||||
import { Dialog, Avatar } from 'frappe-ui'
|
||||
import { ref, markRaw, computed, watch, h } from 'vue'
|
||||
import AssignmentRulePage from './AssignmentRules/AssignmentRulePage.vue'
|
||||
|
||||
const { isManager, isTelephonyAgent, getUser } = usersStore()
|
||||
|
||||
@ -72,7 +84,7 @@ const user = computed(() => getUser() || {})
|
||||
const tabs = computed(() => {
|
||||
let _tabs = [
|
||||
{
|
||||
label: __('Settings'),
|
||||
label: __('Personal Settings'),
|
||||
hideLabel: true,
|
||||
items: [
|
||||
{
|
||||
@ -85,12 +97,32 @@ const tabs = computed(() => {
|
||||
}),
|
||||
component: markRaw(ProfileSettings),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: __('System Configuration'),
|
||||
items: [
|
||||
{
|
||||
label: __('General'),
|
||||
icon: 'settings',
|
||||
component: markRaw(GeneralSettingsPage),
|
||||
condition: () => isManager(),
|
||||
label: __('Forecasting'),
|
||||
component: markRaw(ForecastingSettings),
|
||||
icon: TrendingUpDownIcon,
|
||||
},
|
||||
{
|
||||
label: __('Currency & Exchange Rate'),
|
||||
icon: CircleDollarSignIcon,
|
||||
component: markRaw(CurrencySettings),
|
||||
},
|
||||
{
|
||||
label: __('Brand Settings'),
|
||||
icon: SparkleIcon,
|
||||
component: markRaw(BrandSettings),
|
||||
},
|
||||
],
|
||||
condition: () => isManager(),
|
||||
},
|
||||
{
|
||||
label: __('User Management'),
|
||||
items: [
|
||||
{
|
||||
label: __('Users'),
|
||||
icon: 'user',
|
||||
@ -103,6 +135,12 @@ const tabs = computed(() => {
|
||||
component: markRaw(InviteUserPage),
|
||||
condition: () => isManager(),
|
||||
},
|
||||
],
|
||||
condition: () => isManager(),
|
||||
},
|
||||
{
|
||||
label: __('Email Settings'),
|
||||
items: [
|
||||
{
|
||||
label: __('Email Accounts'),
|
||||
icon: Email2Icon,
|
||||
@ -116,6 +154,27 @@ const tabs = computed(() => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: __('Automation & Rules'),
|
||||
items: [
|
||||
{
|
||||
label: __('Assignment rules'),
|
||||
icon: markRaw(h(SettingsIcon2, { class: 'rotate-90' })),
|
||||
component: markRaw(AssignmentRulePage),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: __('Customization'),
|
||||
items: [
|
||||
{
|
||||
label: __('Home Actions'),
|
||||
component: markRaw(HomeActions),
|
||||
icon: 'home',
|
||||
},
|
||||
],
|
||||
condition: () => isManager(),
|
||||
},
|
||||
{
|
||||
label: __('Integrations', null, 'FCRM'),
|
||||
items: [
|
||||
|
||||
@ -169,8 +169,16 @@
|
||||
import AddExistingUserModal from '@/components/Modals/AddExistingUserModal.vue'
|
||||
import { activeSettingsPage } from '@/composables/settings'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { TemplateOption, DropdownOption } from '@/utils'
|
||||
import { Avatar, TextInput, toast, call, FeatherIcon, Tooltip } from 'frappe-ui'
|
||||
import { DropdownOption } from '@/utils'
|
||||
import {
|
||||
Dropdown,
|
||||
Avatar,
|
||||
TextInput,
|
||||
toast,
|
||||
call,
|
||||
FeatherIcon,
|
||||
Tooltip,
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
|
||||
const { users, isAdmin, isManager } = usersStore()
|
||||
@ -208,29 +216,19 @@ function getMoreOptions(user) {
|
||||
let options = [
|
||||
{
|
||||
label: __('Remove'),
|
||||
component: (props) =>
|
||||
TemplateOption({
|
||||
option: __('Remove'),
|
||||
icon: 'trash-2',
|
||||
active: props.active,
|
||||
onClick: (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
confirmRemove.value = true
|
||||
},
|
||||
}),
|
||||
icon: 'trash-2',
|
||||
onClick: (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
confirmRemove.value = true
|
||||
},
|
||||
condition: () => !confirmRemove.value,
|
||||
},
|
||||
{
|
||||
label: __('Confirm Remove'),
|
||||
component: (props) =>
|
||||
TemplateOption({
|
||||
option: __('Confirm Remove'),
|
||||
icon: 'trash-2',
|
||||
active: props.active,
|
||||
theme: 'danger',
|
||||
onClick: () => removeUser(user, true),
|
||||
}),
|
||||
icon: 'trash-2',
|
||||
theme: 'red',
|
||||
onClick: () => removeUser(user, true),
|
||||
condition: () => confirmRemove.value,
|
||||
},
|
||||
]
|
||||
@ -242,38 +240,35 @@ function getDropdownOptions(user) {
|
||||
let options = [
|
||||
{
|
||||
label: __('Admin'),
|
||||
component: (props) =>
|
||||
component: () =>
|
||||
DropdownOption({
|
||||
option: __('Admin'),
|
||||
icon: 'shield',
|
||||
active: props.active,
|
||||
selected: user.role === 'System Manager',
|
||||
onClick: () => updateRole(user, 'System Manager'),
|
||||
}),
|
||||
onClick: () => updateRole(user, 'System Manager'),
|
||||
condition: () => isAdmin(),
|
||||
},
|
||||
{
|
||||
label: __('Manager'),
|
||||
component: (props) =>
|
||||
component: () =>
|
||||
DropdownOption({
|
||||
option: __('Manager'),
|
||||
icon: 'briefcase',
|
||||
active: props.active,
|
||||
selected: user.role === 'Sales Manager',
|
||||
onClick: () => updateRole(user, 'Sales Manager'),
|
||||
}),
|
||||
onClick: () => updateRole(user, 'Sales Manager'),
|
||||
condition: () => isManager(),
|
||||
},
|
||||
{
|
||||
label: __('Sales User'),
|
||||
component: (props) =>
|
||||
component: () =>
|
||||
DropdownOption({
|
||||
option: __('Sales User'),
|
||||
icon: 'user-check',
|
||||
active: props.active,
|
||||
selected: user.role === 'Sales User',
|
||||
onClick: () => updateRole(user, 'Sales User'),
|
||||
}),
|
||||
onClick: () => updateRole(user, 'Sales User'),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@ -41,4 +41,7 @@ export const mobileSidebarOpened = ref(false)
|
||||
export const isMobileView = computed(() => window.innerWidth < 768)
|
||||
|
||||
export const showSettings = ref(false)
|
||||
|
||||
export const disableSettingModalOutsideClick = ref(false)
|
||||
|
||||
export const activeSettingsPage = ref('')
|
||||
|
||||
@ -462,23 +462,12 @@ export function runSequentially(functions) {
|
||||
}, Promise.resolve())
|
||||
}
|
||||
|
||||
export function DropdownOption({
|
||||
active,
|
||||
option,
|
||||
theme,
|
||||
icon,
|
||||
onClick,
|
||||
selected,
|
||||
}) {
|
||||
export function DropdownOption({ option, icon, selected }) {
|
||||
return h(
|
||||
'button',
|
||||
{
|
||||
class: [
|
||||
active ? 'bg-surface-gray-2' : 'text-ink-gray-8',
|
||||
'group flex w-full justify-between items-center rounded-md px-2 py-2 text-sm',
|
||||
theme == 'danger' ? 'text-ink-red-3 hover:bg-ink-red-1' : '',
|
||||
],
|
||||
onClick: !selected ? onClick : null,
|
||||
class:
|
||||
'group flex w-full text-ink-gray-8 justify-between items-center rounded-md px-2 py-2 text-sm hover:bg-surface-gray-2',
|
||||
},
|
||||
[
|
||||
h('div', { class: 'flex gap-2' }, [
|
||||
@ -501,31 +490,167 @@ export function DropdownOption({
|
||||
)
|
||||
}
|
||||
|
||||
export function TemplateOption({ active, option, theme, icon, onClick }) {
|
||||
return h(
|
||||
'button',
|
||||
{
|
||||
class: [
|
||||
active ? 'bg-surface-gray-2 text-ink-gray-8' : 'text-ink-gray-7',
|
||||
'group flex w-full gap-2 items-center rounded-md px-2 py-2 text-sm',
|
||||
theme == 'danger' ? 'text-ink-red-3 hover:bg-ink-red-1' : '',
|
||||
],
|
||||
onClick: onClick,
|
||||
},
|
||||
[
|
||||
icon
|
||||
? h(FeatherIcon, {
|
||||
name: icon,
|
||||
class: ['h-4 w-4 shrink-0'],
|
||||
'aria-hidden': true,
|
||||
})
|
||||
: null,
|
||||
h('span', { class: 'whitespace-nowrap' }, option),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
export function copy(obj) {
|
||||
if (!obj) return obj
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
export const convertToConditions = ({ conditions, fieldPrefix }) => {
|
||||
if (!conditions || conditions.length === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const processCondition = (condition) => {
|
||||
if (typeof condition === 'string') {
|
||||
return condition.toLowerCase()
|
||||
}
|
||||
|
||||
if (Array.isArray(condition)) {
|
||||
// Nested condition group
|
||||
if (Array.isArray(condition[0])) {
|
||||
const nestedStr = convertToConditions({
|
||||
conditions: condition,
|
||||
fieldPrefix,
|
||||
})
|
||||
return `(${nestedStr})`
|
||||
}
|
||||
|
||||
// Simple condition: [fieldname, operator, value]
|
||||
const [field, operator, value] = condition
|
||||
const fieldAccess = fieldPrefix ? `${fieldPrefix}.${field}` : field
|
||||
|
||||
const operatorMap = {
|
||||
equals: '==',
|
||||
'=': '==',
|
||||
'==': '==',
|
||||
'!=': '!=',
|
||||
'not equals': '!=',
|
||||
'<': '<',
|
||||
'<=': '<=',
|
||||
'>': '>',
|
||||
'>=': '>=',
|
||||
in: 'in',
|
||||
'not in': 'not in',
|
||||
like: 'like',
|
||||
'not like': 'not like',
|
||||
is: 'is',
|
||||
'is not': 'is not',
|
||||
between: 'between',
|
||||
}
|
||||
|
||||
let op = operatorMap[operator.toLowerCase()] || operator
|
||||
|
||||
if (
|
||||
(op === '==' || op === '!=') &&
|
||||
(String(value).toLowerCase() === 'yes' ||
|
||||
String(value).toLowerCase() === 'no')
|
||||
) {
|
||||
let checkVal = String(value).toLowerCase() === 'yes'
|
||||
if (op === '!=') {
|
||||
checkVal = !checkVal
|
||||
}
|
||||
return checkVal ? fieldAccess : `not ${fieldAccess}`
|
||||
}
|
||||
|
||||
if (op === 'is' && String(value).toLowerCase() === 'set') {
|
||||
return fieldAccess
|
||||
}
|
||||
if (
|
||||
(op === 'is' && String(value).toLowerCase() === 'not set') ||
|
||||
(op === 'is not' && String(value).toLowerCase() === 'set')
|
||||
) {
|
||||
return `not ${fieldAccess}`
|
||||
}
|
||||
|
||||
if (op === 'like') {
|
||||
return `(${fieldAccess} and "${value}" in ${fieldAccess})`
|
||||
}
|
||||
if (op === 'not like') {
|
||||
return `(${fieldAccess} and "${value}" not in ${fieldAccess})`
|
||||
}
|
||||
|
||||
if (
|
||||
op === 'between' &&
|
||||
typeof value === 'string' &&
|
||||
value.includes(',')
|
||||
) {
|
||||
const [start, end] = value.split(',').map((v) => v.trim())
|
||||
return `(${fieldAccess} >= "${start}" and ${fieldAccess} <= "${end}")`
|
||||
}
|
||||
|
||||
let valueStr = ''
|
||||
if (op === 'in' || op === 'not in') {
|
||||
let items
|
||||
if (Array.isArray(value)) {
|
||||
items = value.map((v) => `"${String(v).trim()}"`)
|
||||
} else if (typeof value === 'string') {
|
||||
items = value.split(',').map((v) => `"${v.trim()}"`)
|
||||
} else {
|
||||
items = [`"${String(value).trim()}"`]
|
||||
}
|
||||
valueStr = `[${items.join(', ')}]`
|
||||
return `(${fieldAccess} and ${fieldAccess} ${op} ${valueStr})`
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
valueStr = `"${value.replace(/"/g, '\\"')}"`
|
||||
} else if (typeof value === 'number' || typeof value === 'boolean') {
|
||||
valueStr = String(value)
|
||||
} else if (value === null || value === undefined) {
|
||||
return op === '==' || op === 'is' ? `not ${fieldAccess}` : fieldAccess
|
||||
} else {
|
||||
valueStr = `"${String(value).replace(/"/g, '\\"')}"`
|
||||
}
|
||||
|
||||
return `${fieldAccess} ${op} ${valueStr}`
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
const parts = conditions.map(processCondition)
|
||||
return parts.join(' ')
|
||||
}
|
||||
|
||||
export function validateConditions(conditions) {
|
||||
if (!Array.isArray(conditions)) return false
|
||||
|
||||
// Handle simple condition [field, operator, value]
|
||||
if (
|
||||
conditions.length === 3 &&
|
||||
typeof conditions[0] === 'string' &&
|
||||
typeof conditions[1] === 'string'
|
||||
) {
|
||||
return conditions[0] !== '' && conditions[1] !== '' && conditions[2] !== ''
|
||||
}
|
||||
|
||||
// Iterate through conditions and logical operators
|
||||
for (let i = 0; i < conditions.length; i++) {
|
||||
const item = conditions[i]
|
||||
|
||||
// Skip logical operators (they will be validated by their position)
|
||||
if (item === 'and' || item === 'or') {
|
||||
// Ensure logical operators are not at start/end and not consecutive
|
||||
if (
|
||||
i === 0 ||
|
||||
i === conditions.length - 1 ||
|
||||
conditions[i - 1] === 'and' ||
|
||||
conditions[i - 1] === 'or'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Handle nested conditions (arrays)
|
||||
if (Array.isArray(item)) {
|
||||
if (!validateConditions(item)) {
|
||||
return false
|
||||
}
|
||||
} else if (item !== undefined && item !== null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return conditions.length > 0
|
||||
}
|
||||
|
||||
@ -2,137 +2,122 @@ import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import frappeui from 'frappe-ui/vite'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
|
||||
function appPath(app) {
|
||||
const root = path.resolve(__dirname, '../..') // points to apps
|
||||
const frontendPaths = [
|
||||
// Standard frontend structure: appname/frontend/src
|
||||
path.join(root, app, 'frontend', 'src'),
|
||||
// Desk-based apps: appname/desk/src
|
||||
path.join(root, app, 'desk', 'src'),
|
||||
// Alternative frontend structures
|
||||
path.join(root, app, 'client', 'src'),
|
||||
path.join(root, app, 'ui', 'src'),
|
||||
// Direct src structure: appname/src
|
||||
path.join(root, app, 'src'),
|
||||
]
|
||||
return frontendPaths.find((srcPath) => fs.existsSync(srcPath)) || null
|
||||
}
|
||||
|
||||
function hasApp(app) {
|
||||
return fs.existsSync(appPath(app))
|
||||
}
|
||||
|
||||
// List of frontend apps used in this project
|
||||
let apps = []
|
||||
|
||||
const alias = [
|
||||
// Default "@" for this app
|
||||
{
|
||||
find: '@',
|
||||
replacement: path.resolve(__dirname, 'src'),
|
||||
},
|
||||
|
||||
// App-specific aliases like @helpdesk, @hrms, etc.
|
||||
...apps.map((app) =>
|
||||
hasApp(app)
|
||||
? { find: `@${app}`, replacement: appPath(app) }
|
||||
: { find: `@${app}`, replacement: `virtual:${app}` },
|
||||
),
|
||||
]
|
||||
|
||||
const defineFlags = Object.fromEntries(
|
||||
apps.map((app) => [
|
||||
`__HAS_${app.toUpperCase()}__`,
|
||||
JSON.stringify(hasApp(app)),
|
||||
]),
|
||||
)
|
||||
|
||||
const virtualStubPlugin = {
|
||||
name: 'virtual-empty-modules',
|
||||
resolveId(id) {
|
||||
if (id.startsWith('virtual:')) return '\0' + id
|
||||
},
|
||||
load(id) {
|
||||
if (id.startsWith('\0virtual:')) {
|
||||
return 'export default {}; export const missing = true;'
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
console.log('Generated app aliases:', alias)
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
define: defineFlags,
|
||||
plugins: [
|
||||
frappeui({
|
||||
frappeProxy: true,
|
||||
lucideIcons: true,
|
||||
jinjaBootData: true,
|
||||
buildConfig: {
|
||||
indexHtmlPath: '../crm/www/crm.html',
|
||||
emptyOutDir: true,
|
||||
sourcemap: true,
|
||||
},
|
||||
}),
|
||||
vue(),
|
||||
vueJsx(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
},
|
||||
manifest: {
|
||||
display: 'standalone',
|
||||
name: 'Frappe CRM',
|
||||
short_name: 'Frappe CRM',
|
||||
start_url: '/crm',
|
||||
description:
|
||||
'Modern & 100% Open-source CRM tool to supercharge your sales operations',
|
||||
icons: [
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'any',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
virtualStubPlugin,
|
||||
],
|
||||
resolve: { alias },
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
'feather-icons',
|
||||
'showdown',
|
||||
'tailwind.config.js',
|
||||
'prosemirror-state',
|
||||
'prosemirror-view',
|
||||
'lowlight',
|
||||
'interactjs'
|
||||
export default defineConfig(async ({ mode }) => {
|
||||
const isDev = mode === 'development'
|
||||
const frappeui = await importFrappeUIPlugin(isDev)
|
||||
|
||||
const config = {
|
||||
plugins: [
|
||||
frappeui({
|
||||
frappeProxy: true,
|
||||
lucideIcons: true,
|
||||
jinjaBootData: true,
|
||||
buildConfig: {
|
||||
indexHtmlPath: '../crm/www/crm.html',
|
||||
emptyOutDir: true,
|
||||
sourcemap: true,
|
||||
},
|
||||
}),
|
||||
vue(),
|
||||
vueJsx(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
},
|
||||
manifest: {
|
||||
display: 'standalone',
|
||||
name: 'Frappe CRM',
|
||||
short_name: 'Frappe CRM',
|
||||
start_url: '/crm',
|
||||
description:
|
||||
'Modern & 100% Open-source CRM tool to supercharge your sales operations',
|
||||
icons: [
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'any',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
'feather-icons',
|
||||
'showdown',
|
||||
'tailwind.config.js',
|
||||
'prosemirror-state',
|
||||
'prosemirror-view',
|
||||
'lowlight',
|
||||
'interactjs',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
// Add local frappe-ui alias only in development if the local frappe-ui exists
|
||||
if (isDev) {
|
||||
try {
|
||||
// Check if the local frappe-ui directory exists
|
||||
const fs = await import('node:fs')
|
||||
const localFrappeUIPath = path.resolve(__dirname, '../frappe-ui')
|
||||
if (fs.existsSync(localFrappeUIPath)) {
|
||||
config.resolve.alias['frappe-ui'] = localFrappeUIPath
|
||||
} else {
|
||||
console.warn('Local frappe-ui directory not found, using npm package')
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Error checking for local frappe-ui, using npm package:',
|
||||
error.message,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
})
|
||||
|
||||
async function importFrappeUIPlugin(isDev) {
|
||||
if (isDev) {
|
||||
try {
|
||||
const module = await import('../frappe-ui/vite')
|
||||
return module.default
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Local frappe-ui not found, falling back to npm package:',
|
||||
error.message,
|
||||
)
|
||||
}
|
||||
}
|
||||
// Fall back to npm package if local import fails
|
||||
const module = await import('frappe-ui/vite')
|
||||
return module.default
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,10 @@
|
||||
{
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"workspaces": ["frontend", "frappe-ui"],
|
||||
"scripts": {
|
||||
"postinstall": "cd frontend && yarn install",
|
||||
"dev": "cd frontend && yarn dev",
|
||||
"build": "cd frontend && yarn build",
|
||||
"disable-workspaces": "sed -i '' 's/\"workspaces\"/\"aworkspaces\"/g' package.json",
|
||||
"enable-workspaces": "sed -i '' 's/\"aworkspaces\"/\"workspaces\"/g' package.json && rm -rf node_modules ./frontend/node_modules/ frappe-ui/node_modules/ && yarn install",
|
||||
"upgrade-frappeui": "cd frontend && yarn add frappe-ui@latest && cd ..",
|
||||
"disable-workspaces-and-upgrade-frappeui": "yarn disable-workspaces && yarn upgrade-frappeui"
|
||||
"upgrade-frappeui": "cd frontend && yarn add frappe-ui@latest && cd .."
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user