diff --git a/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py b/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py index cf983d6a..53c8c77c 100644 --- a/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py +++ b/crm/fcrm/doctype/fcrm_settings/fcrm_settings.py @@ -24,9 +24,15 @@ class FCRMSettings(Document): standard_old_items = [d.name1 for d in old_items if d.is_standard] deleted_standard_items = set(standard_old_items) - set(standard_new_items) if deleted_standard_items: + standard_dropdown_items = get_standard_dropdown_items() + if not deleted_standard_items.intersection(standard_dropdown_items): + return frappe.throw(_("Cannot delete standard items {0}").format(", ".join(deleted_standard_items))) +def get_standard_dropdown_items(): + return [item.get("name1") for item in frappe.get_hooks("standard_dropdown_items")] + def after_migrate(): sync_table("dropdown_items", "standard_dropdown_items") diff --git a/crm/hooks.py b/crm/hooks.py index 1f7d2ad0..3dcc2c4c 100644 --- a/crm/hooks.py +++ b/crm/hooks.py @@ -264,22 +264,6 @@ standard_dropdown_items = [ "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", @@ -303,6 +287,14 @@ standard_dropdown_items = [ "route": "#", "is_standard": 1, }, + { + "name1": "about", + "label": "About", + "type": "Route", + "icon": "info", + "route": "#", + "is_standard": 1, + }, { "name1": "separator", "label": "", diff --git a/crm/www/crm.py b/crm/www/crm.py index c630506f..94f8142a 100644 --- a/crm/www/crm.py +++ b/crm/www/crm.py @@ -1,8 +1,10 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # GNU GPLv3 License. See license.txt - +import os +import subprocess import frappe +from frappe import safe_decode from frappe.integrations.frappe_providers.frappecloud_billing import is_fc_site from frappe.utils import cint, get_system_timezone from frappe.utils.telemetry import capture @@ -43,9 +45,41 @@ def get_boot(): "user": frappe.db.get_value("User", frappe.session.user, "time_zone") or get_system_timezone(), }, + "app_version": get_app_version(), } ) def get_default_route(): return "/crm" + + +def get_app_version(): + app = "crm" + branch = run_git_command(f"cd ../apps/{app} && git rev-parse --abbrev-ref HEAD") + commit = run_git_command(f"git -C ../apps/{app} rev-parse --short=7 HEAD") + tag = run_git_command(f"git -C ../apps/{app} describe --tags --abbrev=0") + dirty = run_git_command(f"git -C ../apps/{app} diff --quiet || echo 'dirty'") == "dirty" + commit_date = run_git_command(f"git -C ../apps/{app} log -1 --format=%cd") + commit_message = run_git_command(f"git -C ../apps/{app} log -1 --pretty=%B") + + return { + "branch": branch, + "commit": commit, + "commit_date": commit_date, + "commit_message": commit_message, + "tag": tag, + "dirty": dirty, + } + + +def run_git_command(command): + try: + with open(os.devnull, "wb") as null_stream: + result = subprocess.check_output(command, shell=True, stdin=null_stream, stderr=null_stream) + return safe_decode(result).strip() + except Exception: + frappe.log_error( + title="Git Command Error", + ) + return "" diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 29a6ae9c..c83cddab 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -8,6 +8,7 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { + AboutModal: typeof import('./src/components/Modals/AboutModal.vue')['default'] Activities: typeof import('./src/components/Activities/Activities.vue')['default'] ActivityHeader: typeof import('./src/components/Activities/ActivityHeader.vue')['default'] ActivityIcon: typeof import('./src/components/Icons/ActivityIcon.vue')['default'] @@ -151,7 +152,9 @@ declare module 'vue' { ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default'] LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default'] LucideCalendar: typeof import('~icons/lucide/calendar')['default'] + LucideInfo: typeof import('~icons/lucide/info')['default'] LucidePlus: typeof import('~icons/lucide/plus')['default'] + LucideSearch: typeof import('~icons/lucide/search')['default'] MarkAsDoneIcon: typeof import('./src/components/Icons/MarkAsDoneIcon.vue')['default'] MaximizeIcon: typeof import('./src/components/Icons/MaximizeIcon.vue')['default'] MenuIcon: typeof import('./src/components/Icons/MenuIcon.vue')['default'] @@ -221,6 +224,7 @@ declare module 'vue' { TaskPriorityIcon: typeof import('./src/components/Icons/TaskPriorityIcon.vue')['default'] TasksListView: typeof import('./src/components/ListViews/TasksListView.vue')['default'] TaskStatusIcon: typeof import('./src/components/Icons/TaskStatusIcon.vue')['default'] + TelegramIcon: typeof import('./src/components/Icons/TelegramIcon.vue')['default'] TelephonySettings: typeof import('./src/components/Settings/TelephonySettings.vue')['default'] TerritoryIcon: typeof import('./src/components/Icons/TerritoryIcon.vue')['default'] TwilioCallUI: typeof import('./src/components/Telephony/TwilioCallUI.vue')['default'] diff --git a/frontend/src/components/Icons/TelegramIcon.vue b/frontend/src/components/Icons/TelegramIcon.vue new file mode 100644 index 00000000..e05ebbd6 --- /dev/null +++ b/frontend/src/components/Icons/TelegramIcon.vue @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/frontend/src/components/Modals/AboutModal.vue b/frontend/src/components/Modals/AboutModal.vue new file mode 100644 index 00000000..b118d3f4 --- /dev/null +++ b/frontend/src/components/Modals/AboutModal.vue @@ -0,0 +1,100 @@ + + + + + + + + Frappe CRM + + + {{ appVersion.branch != 'main' ? appVersion.branch : '' }} + + ({{ appVersion.commit }}) + + {{ appVersion.tag }} + + + + + + + + + + + + + + {{ link.label }} + + + + + + © Frappe Technologies Pvt. Ltd. and contributors + + + + + + diff --git a/frontend/src/components/Modals/GlobalModals.vue b/frontend/src/components/Modals/GlobalModals.vue index 0c62c1b4..d108e81f 100644 --- a/frontend/src/components/Modals/GlobalModals.vue +++ b/frontend/src/components/Modals/GlobalModals.vue @@ -12,16 +12,19 @@ v-model="showQuickEntryModal" :doctype="quickEntryDoctype" /> +
+ © Frappe Technologies Pvt. Ltd. and contributors +