diff --git a/crm/fcrm/doctype/crm_dropdown_item/__init__.py b/crm/fcrm/doctype/crm_dropdown_item/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/crm/fcrm/doctype/crm_dropdown_item/crm_dropdown_item.json b/crm/fcrm/doctype/crm_dropdown_item/crm_dropdown_item.json new file mode 100644 index 00000000..490acc8a --- /dev/null +++ b/crm/fcrm/doctype/crm_dropdown_item/crm_dropdown_item.json @@ -0,0 +1,94 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2024-12-27 17:42:33.089685", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "name1", + "label", + "type", + "route", + "open_in_new_window", + "hidden", + "is_standard", + "column_break_mvbq", + "icon" + ], + "fields": [ + { + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label", + "mandatory_depends_on": "eval:doc.type == 'Route'" + }, + { + "fieldname": "type", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Type", + "options": "Route\nSeparator", + "read_only_depends_on": "eval:doc.is_standard" + }, + { + "depends_on": "eval:doc.type == 'Route'", + "fieldname": "route", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Route", + "mandatory_depends_on": "eval:doc.type == 'Route'" + }, + { + "default": "0", + "fieldname": "hidden", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Hidden" + }, + { + "default": "0", + "fieldname": "is_standard", + "fieldtype": "Check", + "label": "Is Standard", + "read_only": 1 + }, + { + "fieldname": "column_break_mvbq", + "fieldtype": "Column Break" + }, + { + "description": "Add svg code or use feather icons e.g 'settings'", + "fieldname": "icon", + "fieldtype": "Code", + "label": "Icon" + }, + { + "default": "1", + "depends_on": "eval:doc.type == 'Route'", + "fieldname": "open_in_new_window", + "fieldtype": "Check", + "label": "Open in new window" + }, + { + "depends_on": "eval:doc.is_standard", + "fieldname": "name1", + "fieldtype": "Data", + "label": "Name", + "read_only": 1, + "unique": 1 + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2024-12-27 19:35:53.012508", + "modified_by": "Administrator", + "module": "FCRM", + "name": "CRM Dropdown Item", + "owner": "Administrator", + "permissions": [], + "sort_field": "creation", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_dropdown_item/crm_dropdown_item.py b/crm/fcrm/doctype/crm_dropdown_item/crm_dropdown_item.py new file mode 100644 index 00000000..1ef99ae2 --- /dev/null +++ b/crm/fcrm/doctype/crm_dropdown_item/crm_dropdown_item.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class CRMDropdownItem(Document): + pass diff --git a/crm/fcrm/doctype/fcrm_settings/fcrm_settings.json b/crm/fcrm/doctype/fcrm_settings/fcrm_settings.json index c76784ae..603c806b 100644 --- a/crm/fcrm/doctype/fcrm_settings/fcrm_settings.json +++ b/crm/fcrm/doctype/fcrm_settings/fcrm_settings.json @@ -5,19 +5,63 @@ "doctype": "DocType", "engine": "InnoDB", "field_order": [ - "restore_defaults" + "defaults_tab", + "restore_defaults", + "branding_tab", + "brand_name", + "brand_logo", + "favicon", + "dropdown_items_tab", + "dropdown_items" ], "fields": [ { "fieldname": "restore_defaults", "fieldtype": "Button", "label": "Restore Defaults" + }, + { + "fieldname": "dropdown_items", + "fieldtype": "Table", + "options": "CRM Dropdown Item" + }, + { + "fieldname": "defaults_tab", + "fieldtype": "Tab Break", + "label": "Defaults" + }, + { + "fieldname": "branding_tab", + "fieldtype": "Tab Break", + "label": "Branding" + }, + { + "description": "An image with 1:1 & 2:1 ratio is preferred", + "fieldname": "brand_logo", + "fieldtype": "Attach", + "label": "Logo" + }, + { + "fieldname": "dropdown_items_tab", + "fieldtype": "Tab Break", + "label": "Dropdown Items" + }, + { + "fieldname": "brand_name", + "fieldtype": "Data", + "label": "Name" + }, + { + "description": "An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org]", + "fieldname": "favicon", + "fieldtype": "Attach", + "label": "Favicon" } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2024-09-29 13:49:07.835379", + "modified": "2024-12-27 22:17:52.337109", "modified_by": "Administrator", "module": "FCRM", "name": "FCRM Settings", diff --git a/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py b/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py index 65e6d6f3..08a0a4b7 100644 --- a/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py +++ b/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py @@ -3,6 +3,7 @@ import frappe from frappe.model.document import Document + from crm.install import after_install @@ -10,3 +11,28 @@ class FCRMSettings(Document): @frappe.whitelist() def restore_defaults(self, force=False): after_install(force) + + +def after_migrate(): + sync_table("dropdown_items", "standard_dropdown_items") + + +def sync_table(key, hook): + crm_settings = FCRMSettings("FCRM Settings") + existing_items = {d.name1: d for d in crm_settings.get(key)} + new_standard_items = {} + + # add new items + count = 0 # maintain count because list may come from seperate apps + for item in frappe.get_hooks(hook): + if item.get("name1") not in existing_items: + crm_settings.append(key, item, count) + new_standard_items[item.get("name1")] = True + count += 1 + + # remove unused items + items = crm_settings.get(key) + items = [item for item in items if not (item.is_standard and (item.name1 not in new_standard_items))] + crm_settings.set(key, items) + + crm_settings.save() diff --git a/crm/hooks.py b/crm/hooks.py index dfc4c9d7..a1996f4b 100644 --- a/crm/hooks.py +++ b/crm/hooks.py @@ -57,7 +57,7 @@ add_to_apps_screen = [ # website user home page (by Role) # role_home_page = { -# "Role": "home_page" +# "Role": "home_page" # } website_route_rules = [ @@ -75,8 +75,8 @@ website_route_rules = [ # add methods and filters to jinja environment # jinja = { -# "methods": "crm.utils.jinja_methods", -# "filters": "crm.utils.jinja_filters" +# "methods": "crm.utils.jinja_methods", +# "filters": "crm.utils.jinja_filters" # } # Installation @@ -118,11 +118,11 @@ before_uninstall = "crm.uninstall.before_uninstall" # Permissions evaluated in scripted ways # permission_query_conditions = { -# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", +# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", # } # # has_permission = { -# "Event": "frappe.desk.doctype.event.event.has_permission", +# "Event": "frappe.desk.doctype.event.event.has_permission", # } # DocType Class @@ -155,32 +155,34 @@ doc_events = { "on_update": ["crm.api.whatsapp.on_update"], }, "CRM Deal": { - "on_update": ["crm.fcrm.doctype.erpnext_crm_settings.erpnext_crm_settings.create_customer_in_erpnext"], + "on_update": [ + "crm.fcrm.doctype.erpnext_crm_settings.erpnext_crm_settings.create_customer_in_erpnext" + ], }, "User": { "before_validate": ["crm.api.demo.validate_user"], - } + }, } # Scheduled Tasks # --------------- # scheduler_events = { -# "all": [ -# "crm.tasks.all" -# ], -# "daily": [ -# "crm.tasks.daily" -# ], -# "hourly": [ -# "crm.tasks.hourly" -# ], -# "weekly": [ -# "crm.tasks.weekly" -# ], -# "monthly": [ -# "crm.tasks.monthly" -# ], +# "all": [ +# "crm.tasks.all" +# ], +# "daily": [ +# "crm.tasks.daily" +# ], +# "hourly": [ +# "crm.tasks.hourly" +# ], +# "weekly": [ +# "crm.tasks.weekly" +# ], +# "monthly": [ +# "crm.tasks.monthly" +# ], # } # Testing @@ -192,14 +194,14 @@ doc_events = { # ------------------------------ # # override_whitelisted_methods = { -# "frappe.desk.doctype.event.event.get_events": "crm.event.get_events" +# "frappe.desk.doctype.event.event.get_events": "crm.event.get_events" # } # # each overriding function accepts a `data` argument; # generated from the base implementation of the doctype dashboard, # along with any modifications made in other Frappe apps # override_doctype_dashboards = { -# "Task": "crm.task.get_dashboard_data" +# "Task": "crm.task.get_dashboard_data" # } # exempt linked doctypes from being automatically cancelled @@ -225,29 +227,87 @@ doc_events = { # -------------------- # user_data_fields = [ -# { -# "doctype": "{doctype_1}", -# "filter_by": "{filter_by}", -# "redact_fields": ["{field_1}", "{field_2}"], -# "partial": 1, -# }, -# { -# "doctype": "{doctype_2}", -# "filter_by": "{filter_by}", -# "partial": 1, -# }, -# { -# "doctype": "{doctype_3}", -# "strict": False, -# }, -# { -# "doctype": "{doctype_4}" -# } +# { +# "doctype": "{doctype_1}", +# "filter_by": "{filter_by}", +# "redact_fields": ["{field_1}", "{field_2}"], +# "partial": 1, +# }, +# { +# "doctype": "{doctype_2}", +# "filter_by": "{filter_by}", +# "partial": 1, +# }, +# { +# "doctype": "{doctype_3}", +# "strict": False, +# }, +# { +# "doctype": "{doctype_4}" +# } # ] # Authentication and authorization # -------------------------------- # auth_hooks = [ -# "crm.auth.validate" +# "crm.auth.validate" # ] + +after_migrate = ["crm.fcrm.doctype.fcrm_settings.fcrm_settings.after_migrate"] + +standard_dropdown_items = [ + { + "name1": "app_selector", + "label": "Apps", + "type": "Route", + "route": "#", + "is_standard": 1, + }, + { + "name1": "support_link", + "label": "Support", + "type": "Route", + "icon": "life-buoy", + "route": "https://t.me/frappecrm", + "is_standard": 1, + }, + { + "name1": "docs_link", + "label": "Docs", + "type": "Route", + "icon": "book-open", + "route": "https://docs.frappe.io/crm", + "is_standard": 1, + }, + { + "name1": "toggle_theme", + "label": "Toggle theme", + "type": "Route", + "icon": "moon", + "route": "#", + "is_standard": 1, + }, + { + "name1": "settings", + "label": "Settings", + "type": "Route", + "icon": "settings", + "route": "#", + "is_standard": 1, + }, + { + "name1": "separator", + "label": "", + "type": "Separator", + "is_standard": 1, + }, + { + "name1": "logout", + "label": "Log out", + "type": "Route", + "icon": "log-out", + "route": "#", + "is_standard": 1, + }, +] diff --git a/crm/install.py b/crm/install.py index 4da0c359..6dc50be9 100644 --- a/crm/install.py +++ b/crm/install.py @@ -18,6 +18,7 @@ def after_install(force=False): add_email_template_custom_fields() add_default_industries() add_default_lead_sources() + add_standard_dropdown_items() frappe.db.commit() @@ -333,3 +334,18 @@ def add_default_lead_sources(): doc = frappe.new_doc("CRM Lead Source") doc.source_name = source doc.insert() + + +def add_standard_dropdown_items(): + crm_settings = frappe.get_single("FCRM Settings") + + # don't add dropdown items if they're already present + if crm_settings.dropdown_items: + return + + crm_settings.dropdown_items = [] + + for item in frappe.get_hooks("standard_dropdown_items"): + crm_settings.append("dropdown_items", item) + + crm_settings.save() diff --git a/frontend/src/components/BrandLogo.vue b/frontend/src/components/BrandLogo.vue new file mode 100644 index 00000000..675bc90a --- /dev/null +++ b/frontend/src/components/BrandLogo.vue @@ -0,0 +1,12 @@ + + + diff --git a/frontend/src/components/Layouts/AppSidebar.vue b/frontend/src/components/Layouts/AppSidebar.vue index ea4359bd..3d44cb97 100644 --- a/frontend/src/components/Layouts/AppSidebar.vue +++ b/frontend/src/components/Layouts/AppSidebar.vue @@ -71,7 +71,6 @@ -
Boolean(data), -}) - -provide('isFCSite', isFCSite) diff --git a/frontend/src/components/Mobile/MobileSidebar.vue b/frontend/src/components/Mobile/MobileSidebar.vue index c13da7e2..f85e5ad4 100644 --- a/frontend/src/components/Mobile/MobileSidebar.vue +++ b/frontend/src/components/Mobile/MobileSidebar.vue @@ -66,7 +66,6 @@
- Boolean(data), -}) - -provide('isFCSite', isFCSite) diff --git a/frontend/src/components/UserDropdown.vue b/frontend/src/components/UserDropdown.vue index d3686311..d9f2337c 100644 --- a/frontend/src/components/UserDropdown.vue +++ b/frontend/src/components/UserDropdown.vue @@ -1,5 +1,5 @@