From 52ac8db808b7cf6db9e03b5a0abd887483a26e11 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 13:19:06 +0530 Subject: [PATCH 01/14] refactor: remove custom list view from knowledge base --- desk/src/components/ListViewBuilder.vue | 29 ++++- .../KnowledgeBaseSubcategory.vue | 110 +++++++++--------- desk/src/types.ts | 6 + desk/tsconfig.json | 2 +- .../helpdesk/doctype/hd_article/hd_article.py | 39 +++++++ 5 files changed, 125 insertions(+), 61 deletions(-) diff --git a/desk/src/components/ListViewBuilder.vue b/desk/src/components/ListViewBuilder.vue index a08c9a581..83582e412 100644 --- a/desk/src/components/ListViewBuilder.vue +++ b/desk/src/components/ListViewBuilder.vue @@ -29,7 +29,7 @@ :rows="rows" row-key="name" :options="{ - selectable: true, + selectable: props.options.listViewSelection ?? true , showTooltip: true, resizeColumn: false, onRowClick: (row: Object) => emit('rowClick', row['name']), @@ -61,6 +61,9 @@
{{ dayjs.tz(item).fromNow() }}
+
+ +
{{ item }}
@@ -109,13 +112,16 @@ import { ListRow, ListHeader, ListHeaderItem, + Badge, } from "frappe-ui"; + import { Filter, SortBy, QuickFilters } from "@/components/view-controls"; import { dayjs } from "@/dayjs"; import FadedScrollableDiv from "./FadedScrollableDiv.vue"; import Reload from "./view-controls/Reload.vue"; import { useScreenSize } from "@/composables/screen"; import EmptyState from "./EmptyState.vue"; +import { BadgeStatus } from "@/types"; interface P { options: { @@ -126,6 +132,9 @@ interface P { icon?: HTMLElement | string; title: string; }; + hideViewControls?: boolean; + listViewSelection?: boolean; + statusMap?: Record; }; } @@ -190,6 +199,17 @@ function handleColumnConfig(column) { return column; } +const statusMap: Record = props.options + .statusMap as Record; +function handleStatusColor(status: "Published" | "Draft"): BadgeStatus { + if (!statusMap) + return { + label: status, + theme: "gray", + }; + return statusMap[status]; +} + const filterableFields = createResource({ url: "helpdesk.api.doc.get_filterable_fields", cache: ["DocField", props.options.doctype], @@ -232,7 +252,12 @@ const quickFilters = createResource({ }); const showViewControls = computed(() => { - return filterableFields.data && sortableFields.data && quickFilters.data; + return ( + !props.options.hideViewControls && + filterableFields.data && + sortableFields.data && + quickFilters.data + ); }); const listViewData = reactive({ diff --git a/desk/src/pages/knowledge-base/KnowledgeBaseSubcategory.vue b/desk/src/pages/knowledge-base/KnowledgeBaseSubcategory.vue index 706403726..723c68850 100644 --- a/desk/src/pages/knowledge-base/KnowledgeBaseSubcategory.vue +++ b/desk/src/pages/knowledge-base/KnowledgeBaseSubcategory.vue @@ -29,27 +29,11 @@ - - - - - + From 8f5e2da181d43acb3cae332965995157c6c543c3 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 13:51:19 +0530 Subject: [PATCH 06/14] fix: remove shitty list view --- desk/src/components/index.ts | 1 - desk/src/components/list-view/LV.vue | 108 ---------------- desk/src/components/list-view/LVEmpty.vue | 17 --- desk/src/components/list-view/LVHeader.vue | 40 ------ desk/src/components/list-view/LVLoading.vue | 31 ----- .../src/components/list-view/LVNavigation.vue | 36 ------ desk/src/components/list-view/LVRow.vue | 115 ------------------ .../components/list-view/LVSelectionBar.vue | 48 -------- desk/src/components/list-view/selection.ts | 16 --- desk/src/components/list-view/symbols.ts | 16 --- desk/src/components/list-view/types.ts | 6 - 11 files changed, 434 deletions(-) delete mode 100644 desk/src/components/list-view/LV.vue delete mode 100644 desk/src/components/list-view/LVEmpty.vue delete mode 100644 desk/src/components/list-view/LVHeader.vue delete mode 100644 desk/src/components/list-view/LVLoading.vue delete mode 100644 desk/src/components/list-view/LVNavigation.vue delete mode 100644 desk/src/components/list-view/LVRow.vue delete mode 100644 desk/src/components/list-view/LVSelectionBar.vue delete mode 100644 desk/src/components/list-view/selection.ts delete mode 100644 desk/src/components/list-view/symbols.ts delete mode 100644 desk/src/components/list-view/types.ts diff --git a/desk/src/components/index.ts b/desk/src/components/index.ts index edc4b21a5..339ab9153 100644 --- a/desk/src/components/index.ts +++ b/desk/src/components/index.ts @@ -1,7 +1,6 @@ export { default as AttachmentItem } from "./AttachmentItem.vue"; export { default as CommandPalette } from "./command-palette/CP.vue"; export { default as HCard } from "./HCard.vue"; -export { default as ListView } from "./list-view/LV.vue"; export { default as NestedPopover } from "./NestedPopover.vue"; export { default as Notifications } from "./notifications/Notifications.vue"; export { default as PageTitle } from "./PageTitle.vue"; diff --git a/desk/src/components/list-view/LV.vue b/desk/src/components/list-view/LV.vue deleted file mode 100644 index fba5e59b2..000000000 --- a/desk/src/components/list-view/LV.vue +++ /dev/null @@ -1,108 +0,0 @@ - - - diff --git a/desk/src/components/list-view/LVEmpty.vue b/desk/src/components/list-view/LVEmpty.vue deleted file mode 100644 index 82ec350ed..000000000 --- a/desk/src/components/list-view/LVEmpty.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/desk/src/components/list-view/LVHeader.vue b/desk/src/components/list-view/LVHeader.vue deleted file mode 100644 index 00ad57645..000000000 --- a/desk/src/components/list-view/LVHeader.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - diff --git a/desk/src/components/list-view/LVLoading.vue b/desk/src/components/list-view/LVLoading.vue deleted file mode 100644 index eb8c23fea..000000000 --- a/desk/src/components/list-view/LVLoading.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - diff --git a/desk/src/components/list-view/LVNavigation.vue b/desk/src/components/list-view/LVNavigation.vue deleted file mode 100644 index 9ef6ed398..000000000 --- a/desk/src/components/list-view/LVNavigation.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/desk/src/components/list-view/LVRow.vue b/desk/src/components/list-view/LVRow.vue deleted file mode 100644 index d0217c44c..000000000 --- a/desk/src/components/list-view/LVRow.vue +++ /dev/null @@ -1,115 +0,0 @@ - - - diff --git a/desk/src/components/list-view/LVSelectionBar.vue b/desk/src/components/list-view/LVSelectionBar.vue deleted file mode 100644 index 6145c14c0..000000000 --- a/desk/src/components/list-view/LVSelectionBar.vue +++ /dev/null @@ -1,48 +0,0 @@ - - - diff --git a/desk/src/components/list-view/selection.ts b/desk/src/components/list-view/selection.ts deleted file mode 100644 index fc77c7e5c..000000000 --- a/desk/src/components/list-view/selection.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { reactive } from "vue"; -import { Action, Key } from "./types"; - -export const selection = reactive({ - storage: new Set(), - actions: new Set(), - toggle: (key: Key) => { - if (!selection.storage.delete(key)) { - selection.storage.add(key); - } - }, - reset: () => { - selection.storage.clear(); - selection.actions.clear(); - }, -}); diff --git a/desk/src/components/list-view/symbols.ts b/desk/src/components/list-view/symbols.ts deleted file mode 100644 index b3f6d269e..000000000 --- a/desk/src/components/list-view/symbols.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { InjectionKey, Ref } from "vue"; -import { Resource, Column } from "@/types"; - -type I = { - name: string; - [key: string]: unknown; -}; -type R = Resource>; -export const CheckboxKey: InjectionKey = Symbol("Checkbox"); -export const ColumnsKey: InjectionKey> = Symbol("Columns"); -export const DocTypeKey: InjectionKey = Symbol("DocType"); -export const FilterKey: InjectionKey = Symbol("Filter"); -export const IdKey: InjectionKey = Symbol("Id"); -export const PluralKey: InjectionKey> = Symbol("Plural"); -export const ResourceKey: InjectionKey = Symbol("Resource"); -export const SingluarKey: InjectionKey> = Symbol("Singular"); diff --git a/desk/src/components/list-view/types.ts b/desk/src/components/list-view/types.ts deleted file mode 100644 index 4f67ee37f..000000000 --- a/desk/src/components/list-view/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Selection = Set; -export type Key = string; -export type Action = { - label: string; - onClick: (key: Key[]) => void; -}; From 921da06a38f477a4ca0e0aa84686e6fbece4aa37 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 14:23:20 +0530 Subject: [PATCH 07/14] chore: remove unnecessary pages and components --- desk/src/pages/CLayout.vue | 12 -- desk/src/pages/KnowledgeBasePublic.vue | 53 ----- desk/src/pages/TicketsCustomer.vue | 204 ------------------ desk/src/pages/c-layout/CLayoutNav.vue | 60 ------ .../KnowledgeBasePublicSearch.vue | 121 ----------- 5 files changed, 450 deletions(-) delete mode 100644 desk/src/pages/CLayout.vue delete mode 100644 desk/src/pages/KnowledgeBasePublic.vue delete mode 100644 desk/src/pages/TicketsCustomer.vue delete mode 100644 desk/src/pages/c-layout/CLayoutNav.vue delete mode 100644 desk/src/pages/knowledge-base/KnowledgeBasePublicSearch.vue diff --git a/desk/src/pages/CLayout.vue b/desk/src/pages/CLayout.vue deleted file mode 100644 index 986e94309..000000000 --- a/desk/src/pages/CLayout.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/desk/src/pages/KnowledgeBasePublic.vue b/desk/src/pages/KnowledgeBasePublic.vue deleted file mode 100644 index 01882415c..000000000 --- a/desk/src/pages/KnowledgeBasePublic.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - diff --git a/desk/src/pages/TicketsCustomer.vue b/desk/src/pages/TicketsCustomer.vue deleted file mode 100644 index c3c9b127d..000000000 --- a/desk/src/pages/TicketsCustomer.vue +++ /dev/null @@ -1,204 +0,0 @@ - - - diff --git a/desk/src/pages/c-layout/CLayoutNav.vue b/desk/src/pages/c-layout/CLayoutNav.vue deleted file mode 100644 index 68f5145f6..000000000 --- a/desk/src/pages/c-layout/CLayoutNav.vue +++ /dev/null @@ -1,60 +0,0 @@ - - - diff --git a/desk/src/pages/knowledge-base/KnowledgeBasePublicSearch.vue b/desk/src/pages/knowledge-base/KnowledgeBasePublicSearch.vue deleted file mode 100644 index 8e56fcee9..000000000 --- a/desk/src/pages/knowledge-base/KnowledgeBasePublicSearch.vue +++ /dev/null @@ -1,121 +0,0 @@ - - - From 39ab6a040a65490a8f02c5ac2c7dca2392ea6d02 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 14:23:33 +0530 Subject: [PATCH 08/14] chore: update tsconfig --- desk/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desk/tsconfig.json b/desk/tsconfig.json index 3cdb797c3..97555f9ee 100644 --- a/desk/tsconfig.json +++ b/desk/tsconfig.json @@ -13,6 +13,6 @@ "vite/client" ], }, - "include": ["src/*","src","src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.js", "src/**/*.jsx"], + "include": ["src","src/*","src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.js", "src/**/*.jsx","src/**/*.vue"], "exclude": ["node_modules"] } From 5b8f0b353a39bd3f3898d5241007345b1bce521c Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 19:31:13 +0530 Subject: [PATCH 09/14] refactor: notifications panel --- desk/src/components/notifications/Notifications.vue | 6 ++---- desk/src/pages/MobileNotifications.vue | 6 ++---- desk/src/stores/notification.ts | 5 ++--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/desk/src/components/notifications/Notifications.vue b/desk/src/components/notifications/Notifications.vue index 1b8fcf3b4..4356fdb33 100644 --- a/desk/src/components/notifications/Notifications.vue +++ b/desk/src/components/notifications/Notifications.vue @@ -48,13 +48,11 @@ } " > - +
- {{ - n.user_from.name - }} + {{ n.user_from }} mentioned you in ticket diff --git a/desk/src/pages/MobileNotifications.vue b/desk/src/pages/MobileNotifications.vue index bc6d78b8c..e3680d6b8 100644 --- a/desk/src/pages/MobileNotifications.vue +++ b/desk/src/pages/MobileNotifications.vue @@ -32,13 +32,11 @@ } " > - +
- {{ - n.user_from.name - }} + {{ n.user_from }} mentioned you in ticket diff --git a/desk/src/stores/notification.ts b/desk/src/stores/notification.ts index 6f99bd46e..165d8f3b8 100644 --- a/desk/src/stores/notification.ts +++ b/desk/src/stores/notification.ts @@ -1,15 +1,14 @@ import { computed, ref } from "vue"; import { defineStore } from "pinia"; -import { createResource } from "frappe-ui"; +import { createResource, createListResource } from "frappe-ui"; import { useAuthStore } from "@/stores/auth"; import { useError } from "@/composables/error"; -import { createListManager } from "@/composables/listManager"; import { Notification, Resource } from "@/types"; export const useNotificationStore = defineStore("notification", () => { const authStore = useAuthStore(); const visible = ref(false); - const resource: Resource> = createListManager({ + const resource: Resource> = createListResource({ doctype: "HD Notification", cache: "Notifications", filters: { From 8fd4ad4b371047efcb892a77c4ff96be5d053056 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 19:32:19 +0530 Subject: [PATCH 10/14] fix: list-view-builder api calls --- desk/src/components/ListViewBuilder.vue | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/desk/src/components/ListViewBuilder.vue b/desk/src/components/ListViewBuilder.vue index 306e987bc..e147850d5 100644 --- a/desk/src/components/ListViewBuilder.vue +++ b/desk/src/components/ListViewBuilder.vue @@ -143,7 +143,17 @@ interface E { (event: "rowClick", row: any): void; } -const props = defineProps

(); +const props = withDefaults(defineProps

(), { + options: () => { + return { + doctype: "", + hideViewControls: false, + selectable: true, + }; + }, +}); + +console.log(props.options.hideViewControls); const emit = defineEmits(); const { isMobileView } = useScreenSize(); @@ -213,7 +223,7 @@ function handleStatusColor(status: "Published" | "Draft"): BadgeStatus { const filterableFields = createResource({ url: "helpdesk.api.doc.get_filterable_fields", cache: ["DocField", props.options.doctype], - auto: true, + auto: !props.options.hideViewControls, params: { doctype: props.options.doctype, append_assign: true, @@ -232,7 +242,7 @@ const filterableFields = createResource({ const sortableFields = createResource({ url: "helpdesk.api.doc.sort_options", - auto: true, + auto: !props.options.hideViewControls, params: { doctype: props.options.doctype, }, @@ -240,7 +250,7 @@ const sortableFields = createResource({ const quickFilters = createResource({ url: "helpdesk.api.doc.get_quick_filters", - auto: true, + auto: !props.options.hideViewControls, params: { doctype: props.options.doctype, }, From c078a679a5e15be74b94b2268e22fab07c741f9a Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 19:33:32 +0530 Subject: [PATCH 11/14] fix: remove dependency of listManager --- .../components/desk/global/NewContactDialog.vue | 16 +++++++--------- .../knowledge-base/KnowledgeBaseCategory.vue | 10 ++++------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/desk/src/components/desk/global/NewContactDialog.vue b/desk/src/components/desk/global/NewContactDialog.vue index cc6619524..5cdf1ffed 100644 --- a/desk/src/components/desk/global/NewContactDialog.vue +++ b/desk/src/components/desk/global/NewContactDialog.vue @@ -51,6 +51,7 @@ import { ErrorMessage, createResource, Autocomplete, + createListResource, } from "frappe-ui"; import zod from "zod"; @@ -141,20 +142,17 @@ const open = computed({ }, }); -const customerResource = createResource({ - url: "helpdesk.extends.client.get_list", - params: { - doctype: "HD Customer", - fields: ["name", "customer_name"], - }, +const customerResource = createListResource({ + doctype: "HD Customer", + fields: ["name"], + cache: "customers", transform: (data) => { - let allData = data.map((option) => { + return data.map((option) => { return { label: option.name, - value: option.customer_name, + value: option.name, }; }); - return allData; }, auto: true, }); diff --git a/desk/src/pages/knowledge-base/KnowledgeBaseCategory.vue b/desk/src/pages/knowledge-base/KnowledgeBaseCategory.vue index ae6401ccc..025a2140c 100644 --- a/desk/src/pages/knowledge-base/KnowledgeBaseCategory.vue +++ b/desk/src/pages/knowledge-base/KnowledgeBaseCategory.vue @@ -44,8 +44,7 @@ > @@ -131,7 +130,6 @@ import { import { isEmpty } from "lodash"; import { AGENT_PORTAL_KNOWLEDGE_BASE_SUB_CATEGORY } from "@/router"; import { createToast } from "@/utils"; -import { createListManager } from "@/composables/listManager"; import { useError } from "@/composables/error"; import { HCard } from "@/components"; import KnowledgeBaseCategoryHeader from "./KnowledgeBaseCategoryHeader.vue"; @@ -208,9 +206,9 @@ const newSubCategory = createResource({ onError: useError({ title: "Error creating sub category" }), }); -const subCategories = createListManager({ - doctype: "HD Article Category", - filters: { +const subCategories = createResource({ + url: "helpdesk.helpdesk.doctype.hd_article_category.api.get_subcategories", + params: { parent_category: categoryId.value, }, auto: true, From f6d14cd92d1fe87f8fe1762b63fc1132b0dc0d33 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 19:34:20 +0530 Subject: [PATCH 12/14] chore: remove unnecessary pages and components --- desk/src/components/ListViewBuilder.vue | 2 - .../src/pages/KnowledgeBasePublicCategory.vue | 62 ------------------- desk/src/pages/KnowledgeBasePublicHome.vue | 44 ------------- 3 files changed, 108 deletions(-) delete mode 100644 desk/src/pages/KnowledgeBasePublicCategory.vue delete mode 100644 desk/src/pages/KnowledgeBasePublicHome.vue diff --git a/desk/src/components/ListViewBuilder.vue b/desk/src/components/ListViewBuilder.vue index e147850d5..9c291e3ce 100644 --- a/desk/src/components/ListViewBuilder.vue +++ b/desk/src/components/ListViewBuilder.vue @@ -153,8 +153,6 @@ const props = withDefaults(defineProps

(), { }, }); -console.log(props.options.hideViewControls); - const emit = defineEmits(); const { isMobileView } = useScreenSize(); const defaultEmptyState = { diff --git a/desk/src/pages/KnowledgeBasePublicCategory.vue b/desk/src/pages/KnowledgeBasePublicCategory.vue deleted file mode 100644 index ea3cccb7c..000000000 --- a/desk/src/pages/KnowledgeBasePublicCategory.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - diff --git a/desk/src/pages/KnowledgeBasePublicHome.vue b/desk/src/pages/KnowledgeBasePublicHome.vue deleted file mode 100644 index 30ca9958f..000000000 --- a/desk/src/pages/KnowledgeBasePublicHome.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - From 41539409fbd400442ad4b2f2c7941cbda06f87b7 Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 19:36:02 +0530 Subject: [PATCH 13/14] refactor: remove relevant functions and files of listManager --- desk/src/composables/listManager.ts | 96 --------- helpdesk/extends/client.py | 182 ------------------ helpdesk/extends/doc.py | 40 ---- .../doctype/hd_article_category/api.py | 25 +-- .../hd_article_category.py | 15 -- .../helpdesk/doctype/hd_ticket/hd_ticket.py | 40 ---- 6 files changed, 9 insertions(+), 389 deletions(-) delete mode 100644 desk/src/composables/listManager.ts delete mode 100644 helpdesk/extends/client.py delete mode 100644 helpdesk/extends/doc.py diff --git a/desk/src/composables/listManager.ts b/desk/src/composables/listManager.ts deleted file mode 100644 index c40ce2f1c..000000000 --- a/desk/src/composables/listManager.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ref, watch } from "vue"; -import { createListResource, createResource } from "frappe-ui"; - -const GET_LIST_METHOD = "helpdesk.extends.client.get_list"; -const GET_LIST_META_METHOD = "helpdesk.extends.client.get_list_meta"; - -type ListOptions = { - doctype: string; - fields?: Array; - filters?: object; - orderBy?: string; - pageLength?: number; - start?: number; - cache?: boolean | string | Array; - auto?: boolean; - transform?: any; -}; - -type MetaData = { - total_count: number; - total_pages: number; - current_page: number; - start_from: number; - end_at: number; - has_next_page: boolean; - has_previous_page: boolean; -}; - -export function createListManager(options: ListOptions) { - const doctype = options.doctype; - const fields = options.fields; - const filters = options.filters; - const orderBy = options.orderBy; - const pageLength = options.pageLength; - const start = options.start; - const cache = options.cache; - const auto = options.auto; - const transform = options.transform; - - const list = createListResource({ - type: "list", - url: GET_LIST_METHOD, - realtime: true, - doctype, - fields, - orderBy, - filters, - pageLength, - start, - cache, - auto, - transform, - onSuccess() { - meta.submit({ - doctype, - filters: list.filters, - limit: list.pageLength, - order_by: list.orderBy, - start: list.start, - }); - }, - }); - - Object.assign(list, { - totalCount: ref(0), - totalPages: ref(0), - currentPage: ref(0), - hasNextPage: ref(false), - hasPreviousPage: ref(false), - startFrom: ref(0), - endAt: ref(0), - }); - - const meta = createResource({ - url: GET_LIST_META_METHOD, - onSuccess: (data: MetaData) => { - list.totalCount = data.total_count; - list.totalPages = data.total_pages; - list.currentPage = data.current_page; - list.hasNextPage = data.has_next_page; - list.hasPreviousPage = data.has_previous_page; - list.startFrom = data.start_from; - list.endAt = data.end_at; - }, - }); - - watch( - () => list.list.loading, - () => { - list.hasPreviousPage = false; - list.hasNextPage = false; - } - ); - - return list; -} diff --git a/helpdesk/extends/client.py b/helpdesk/extends/client.py deleted file mode 100644 index f2839e771..000000000 --- a/helpdesk/extends/client.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import importlib -import math - -import frappe -from frappe import _ -from frappe.model.base_document import get_controller -from frappe.query_builder.functions import Count -from frappe.utils import get_user_info_for_avatar -from frappe.utils.caching import redis_cache - -from helpdesk.utils import check_permissions - -from .doc import apply_sort - - -@frappe.whitelist() -def get_list( - doctype=None, - fields=None, - filters=None, - order_by=None, - start=0, - limit=None, - group_by=None, - parent=None, - debug=False, -): - check_allowed(doctype) - check_permissions(doctype, parent) - - query = frappe.qb.get_query( - table=doctype, - fields=fields, - filters=filters, - offset=start, - limit=limit, - group_by=group_by, - order_by=order_by, - ) - - query = apply_custom_filters(doctype, query) - query = apply_hook(doctype, query) - query = apply_sort(doctype, order_by, query) - - if not fields: - query = apply_custom_select(doctype, query) - - res = query.run(as_dict=True, debug=debug) - res = transform_avatar(doctype, res) - res = transform_assign(res) - return res - - -@frappe.whitelist() -def get_list_meta( - doctype=None, - filters=None, - order_by=None, - start: int | None = 0, - limit=None, - group_by=None, - parent=None, - debug=False, -): - check_allowed(doctype) - check_permissions(doctype, parent) - - query = frappe.qb.get_query( - table=doctype, - filters=filters, - group_by=group_by, - fields=["name"], - ) - - query = apply_custom_filters(doctype, query) - query = apply_hook(doctype, query) - query = apply_sort(doctype, order_by, query) - - total_count = Count("*").as_("total_count") - query = query.select(total_count) - - res = query.run(as_dict=True, debug=debug) - total_count = res.pop().total_count - total_pages = math.ceil(total_count / limit) if limit else 1 - current_page = start // limit + 1 if start and limit else 1 - has_next_page = current_page < total_pages - has_previous_page = current_page > 1 - start_from = start + 1 - end_at = start + limit - - if end_at > total_count: - end_at = total_count - - return { - "total_count": total_count, - "total_pages": total_pages, - "current_page": current_page, - "has_next_page": has_next_page, - "has_previous_page": has_previous_page, - "start_from": start_from, - "end_at": end_at, - } - - -def apply_custom_filters(doctype: str, query): - """ - Apply custom filters to query - """ - controller = get_controller(doctype) - - if hasattr(controller, "get_list_filters"): - return_value = controller.get_list_filters(query) - if return_value is not None: - query = return_value - - return query - - -def apply_custom_select(doctype: str, query): - """ - Apply custom select logic to query - """ - controller = get_controller(doctype) - - if hasattr(controller, "get_list_select"): - return_value = controller.get_list_select(query) - if return_value is not None: - query = return_value - - return query - - -def apply_hook(doctype: str, query): - """ - Apply hooks to query - """ - try: - _module_path = "helpdesk.helpdesk.hooks." + doctype.lower() - # nosemgrep - _module = importlib.import_module(_module_path) - _class = getattr(_module, doctype) - _function = getattr(_class, "get_list_filters") - return _function(query) - except Exception: - return query - - -def transform_avatar(doctype: str, r): - m = frappe.get_meta(doctype) - f = [i for i in m.fields if i.fieldtype == "Link" and i.options == "User"] - for i in f: - for j in r: - if j.get(i.fieldname): - j[i.fieldname] = get_user_info_for_avatar(j[i.fieldname]) - return r - - -def transform_assign(r): - for row in r: - if assign := row.get("_assign"): - j = frappe.parse_json(assign) - if len(j) < 1: - continue - row["assignee"] = get_user_info_for_avatar(j.pop()) - return r - - -@redis_cache() -def check_allowed(doctype: str): - """ - Allow only `Helpdesk` doctypes. This is to prevent users from accessing - other doctypes. - - :param doctype: Doctype name - """ - allowed = ["Contact"] - if not (doctype in allowed or frappe.get_meta(doctype).module == "Helpdesk"): - text = _("You are not allowed to access {0}").format(doctype) - frappe.throw(text, frappe.PermissionError) diff --git a/helpdesk/extends/doc.py b/helpdesk/extends/doc.py deleted file mode 100644 index 76895ccb4..000000000 --- a/helpdesk/extends/doc.py +++ /dev/null @@ -1,40 +0,0 @@ -from types import FunctionType - -import frappe -from frappe.model.document import get_controller -from frappe.query_builder import Order, Query - -SORT_OPTIONS_METHOD = "sort_options" -DEFAULT_SORT_FIELD = "modified" -DEFAULT_SORT_DIRECTION = Order.desc - - -@frappe.whitelist() -def sort_options(doctype: str): - c = get_controller(doctype) - - if not hasattr(c, SORT_OPTIONS_METHOD): - return [] - - return c.sort_options().keys() - - -def apply_sort(doctype: str, order_by: str, query: Query): - controller = get_controller(doctype) - fallback = query.orderby(DEFAULT_SORT_FIELD, order=DEFAULT_SORT_DIRECTION) - - if not hasattr(controller, SORT_OPTIONS_METHOD): - return fallback - - action = controller.sort_options().get(order_by) - - if isinstance(action, FunctionType): - return action(query) - - if isinstance(action, (list, tuple)): - return query.orderby(action[0], order=action[1]) - - if isinstance(action, str): - return query.orderby(action, order=DEFAULT_SORT_DIRECTION) - - return fallback diff --git a/helpdesk/helpdesk/doctype/hd_article_category/api.py b/helpdesk/helpdesk/doctype/hd_article_category/api.py index 44c265d5c..4f5839a11 100644 --- a/helpdesk/helpdesk/doctype/hd_article_category/api.py +++ b/helpdesk/helpdesk/doctype/hd_article_category/api.py @@ -2,21 +2,14 @@ @frappe.whitelist() -def get_list_public(): - fields = ["name", "category_name", "icon"] - categories = frappe.get_list( - "HD Article Category", fields=fields, filters={"parent_category": ""} +def get_subcategories(parent_category): + sub_categories = frappe.get_all( + "HD Article Category", + filters={"parent_category": parent_category}, + fields=["name", "category_name", "icon", "description"], ) - res = [] - - for category in categories: - sub_categories = frappe.get_list( - "HD Article Category", - filters={"parent_category": category.name}, - fields=fields, + for sub_category in sub_categories: + sub_category["article_count"] = frappe.db.count( + "HD Article", {"category": sub_category["name"]} ) - category.sub_categories = sub_categories - if len(sub_categories): - res.append(category) - - return res + return sub_categories diff --git a/helpdesk/helpdesk/doctype/hd_article_category/hd_article_category.py b/helpdesk/helpdesk/doctype/hd_article_category/hd_article_category.py index 7266fda7b..f24f8f4ce 100644 --- a/helpdesk/helpdesk/doctype/hd_article_category/hd_article_category.py +++ b/helpdesk/helpdesk/doctype/hd_article_category/hd_article_category.py @@ -6,24 +6,9 @@ # from frappe import _ from frappe.model.document import Document from frappe.utils import cint -from pypika.functions import Count -from pypika.queries import Query class HDArticleCategory(Document): - @staticmethod - def get_list_select(query: Query): - QBCategory = frappe.qb.DocType("HD Article Category") - QBArticle = frappe.qb.DocType("HD Article") - count_article = ( - frappe.qb.from_(QBArticle) - .select(Count("*")) - .as_("count_article") - .where(QBArticle.category == QBCategory.name) - ) - query = query.select(QBCategory.star).select(count_article) - return query - def before_save(self): if self.idx == -1 and self.status == "Published": # index is only set if its not set already, this allows defining diff --git a/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py b/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py index cf90d4cb3..ed5a5b977 100644 --- a/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py +++ b/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py @@ -32,46 +32,6 @@ class HDTicket(Document): - @staticmethod - def get_list_select(query: Query): - QBTicket = frappe.qb.DocType("HD Ticket") - QBComment = frappe.qb.DocType("HD Ticket Comment") - QBCommunication = frappe.qb.DocType("Communication") - - count_comment = ( - frappe.qb.from_(QBComment) - .select(Count("*")) - .as_("count_comment") - .where(QBComment.reference_ticket == QBTicket.name) - ) - - count_msg_incoming = ( - frappe.qb.from_(QBCommunication) - .select(Count("*")) - .as_("count_msg_incoming") - .where(QBCommunication.reference_doctype == "HD Ticket") - .where(QBCommunication.reference_name == QBTicket.name) - .where(QBCommunication.sent_or_received == "Received") - ) - - count_msg_outgoing = ( - frappe.qb.from_(QBCommunication) - .select(Count("*")) - .as_("count_msg_outgoing") - .where(QBCommunication.reference_doctype == "HD Ticket") - .where(QBCommunication.reference_name == QBTicket.name) - .where(QBCommunication.sent_or_received == "Sent") - ) - - query = ( - query.select(QBTicket.star) - .select(count_comment) - .select(count_msg_incoming) - .select(count_msg_outgoing) - ) - - return query - @staticmethod def get_list_filters(query: Query): _is_agent = is_agent() From 70785f343b7c0ab5d6c9245c402707d90193b49d Mon Sep 17 00:00:00 2001 From: RitvikSardana Date: Mon, 23 Dec 2024 21:00:40 +0530 Subject: [PATCH 14/14] chore: code cleanup --- helpdesk/helpdesk/doctype/hd_article/hd_article.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpdesk/helpdesk/doctype/hd_article/hd_article.py b/helpdesk/helpdesk/doctype/hd_article/hd_article.py index edde674bb..9b2c63aef 100644 --- a/helpdesk/helpdesk/doctype/hd_article/hd_article.py +++ b/helpdesk/helpdesk/doctype/hd_article/hd_article.py @@ -65,7 +65,7 @@ def default_list_data(): "label": "Status", "type": "status", "key": "status", - "width": "24rem", + "width": "10rem", }, { "label": "Author",