import { Dayjs } from "dayjs"; import { Component, ComputedRef, InjectionKey, Ref } from "vue"; import type { AssignmentRule, ODCustomer, ODTicket } from "./types/doctypes"; interface ResourceOptions { method?: string; url: string; initialData?: T; auto?: boolean; cache?: string | string[]; debounce?: number; params?: any; makeParams?: (params: any) => any; onFetch?: (params: any) => void; beforeSubmit?: (params: any) => void; validate?: (params: any) => string | void; onError?: (error: Error) => void; onSuccess?: (data: T) => void; onData?: (data: T) => void; transform?: (data: any) => T; resourceFetcher?: (options: any) => Promise; } export interface Resource { method: string | undefined; url: string; data: T | null; previousData: T | null; loading: boolean; fetched: boolean; error: Error | null; promise: Promise | null; auto: boolean; params: any; fetch: ( params?: any, tempOptions?: Partial> ) => Promise; reload: ( params?: any, tempOptions?: Partial> ) => Promise; submit: ( params?: any, tempOptions?: Partial> ) => Promise; reset: () => void; update: (options: { method?: string; url?: string; params?: any; auto?: boolean; }) => void; setData: (data: T | ((currentData: T) => T)) => void; } export interface ListResourceOptions { doctype: string; fields?: string[]; filters?: Record; orFilters?: Record; orderBy?: string; start?: number; pageLength?: number; groupBy?: string; parent?: string; debug?: number; auto?: boolean; url?: string; cache?: any; realtime?: boolean; onSuccess?: (data: any) => void; onError?: (error: any) => void; onData?: (data: any) => void; transform?: (data: any) => any; fetchOne?: { onSuccess?: (data: any) => void; onError?: (error: any) => void; }; insert?: { onSuccess?: (data: any) => void; onError?: (error: any) => void; }; setValue?: { onSuccess?: (data: any) => void; onError?: (error: any) => void; }; delete?: { onSuccess?: (data: any) => void; onError?: (error: any) => void; }; runDocMethod?: { onSuccess?: (data: any) => void; onError?: (error: any) => void; }; } export interface ListResource { doctype: string; fields?: string[]; filters?: Record; orFilters?: Record; orderBy?: string; start: number; pageLength: number; groupBy?: string; parent?: string; debug: number; originalData: T[] | null; dataMap: Record; data: T[] | null; hasPreviousPage: boolean; hasNextPage: boolean; auto?: boolean; list: Resource; fetchOne: Resource; insert: Resource; setValue: Resource; delete: Resource; runDocMethod: Resource; loading: boolean; update: (updatedOptions: Partial) => void; fetch: () => void; reload: () => Promise; setData: (data: T[] | ((data: T[]) => T[])) => void; transform: (data: T[]) => T[]; getRow: (name: string) => T; previous: () => void; next: () => void; } export interface Error { exc_type: string; exc: string; response: string; status: string; messages: string; stack: string; message: string; } export interface Comment { commented_by: string; content: string; is_pinned: boolean; name: string; creation: string; } export interface Communication { creation: string; content: string; name: string; sender: string; bcc?: string; cc?: string; sent_or_received?: "Sent" | "Received"; email_account?: string; sender_full_name?: string; sender_mail_id?: string; } export interface Activity { action: string; name: string; owner: string; creation: string; } export interface Contact { full_name: string; name: string; company_name?: string; email_id?: string; image?: string; mobile_no?: string; phone?: string; } export interface CustomField { fieldname: string; label: string; value: string; route: string; } export interface ViewLog { name: string; viewed_by: string; creation: string; } export interface Ticket { _assign: string; assignee: UserInfo; agent_group: string; customer: string; modified: string; name: string; priority: string; raised_by: string; resolution_by: string; response_by: string; first_responded_on: string; resolution_date: string; resolution_time: number; status: string; subject: string; ticket_type: string; via_customer_portal: string; agreement_status: string; creation: string; feedback_rating?: number; feedback_extra?: string; contact: Contact; comments: Comment[]; communications: Communication[]; history: Activity[]; template: Template; views: ViewLog[]; _customActions: Function[]; is_merged?: boolean; status_category: "Open" | "Paused" | "Resolved"; } export interface DocField { fieldname: string; fieldtype: string; label: string; name: string; options: string; } export interface Filter { field?: DocField; fieldname: string; operator: string; label: string; value: boolean | number | string; } export interface AutoCompleteItem { label: string; value: string; } export interface Field { fieldname: string; fieldtype: string; label: string; options: string; required: 0 | 1; description?: null; url_method?: string; link_filters?: string; filters?: string; display_via_depends_on?: string; mandatory_via_depends_on?: string; disabled?: boolean; placeholder?: string | null; readonly?: boolean; } export type FieldValue = string | number | boolean | null | undefined | Dayjs; export interface Template { about: string; fields: Field[]; } export type Column = { key: string; label: string; icon?: string; align?: string; width?: string; text?: string; }; export type File = { file_name: string; name: string; file_url: string; is_private: boolean; attached_to_doctype?: string; attached_to_field?: string; attached_to_name?: string; }; export type UserInfo = { email: string; image: string; name: string; }; export interface RenderField { label: string; name: string; type: string; placeholder?: string; description?: string; } export interface EmailService { name: string; icon: string; info: string; link: string; custom: boolean; } export type EmailStep = "email-list" | "email-add" | "email-edit"; export interface EmailAccount { email_account_name: string; email_id: string; service: string; api_key?: string; api_secret?: string; password?: string; frappe_mail_site?: string; enable_outgoing?: boolean; enable_incoming?: boolean; default_outgoing?: boolean; default_incoming?: boolean; } export type TicketTab = | "activity" | "email" | "comment" | "details" | "call" | "analytics"; export interface TabObject { value: TicketTab; label: string; iconLeft: Component; condition?: () => boolean; } export interface RootCategory { category_id: string; category_name: string; } export interface Article { name: string; title: string; title_slug: string; category_name: string; category: string; published_on: string; author: Author; subtitle: string; article_image: string | null; _user_tags: string | null; status: string; visibility: string; creation: string; content: string; modified: string; } export interface Author { name: string; image: string | null; email: string; } export interface Category { categoryName: string; articles: Article[]; authors?: { [key: string]: Author; }; children?: Article[]; } export interface View { filters: string; order_by: string; columns: string; rows: string; dt?: string; type?: string; route_name?: string; user?: string; icon?: string; label?: string; is_default?: boolean; pinned?: boolean; public?: boolean; group_by_field?: string; list_group_by?: string; name: string; is_customer_portal?: boolean; } export interface ViewType { view_type: string; group_by_field: string; name: string; } export interface Breadcrumb { label: string; route?: { name: string; params?: Record; }; } export interface FieldCriteriaState { selectedParentField: string; selectedChildField: string; childFields: any[]; parentFieldValues: any[]; childFieldValues: any[]; currentParentSelection: string; childSelections: any; initialChildSelections: any; parentSearch: string; childSearch: string; enabled: boolean; } interface ResourceBase { data: any; error: any; fetched: boolean; loading: boolean; params: any; previousData: any; promise: Promise | null; submit: (params?: any) => void; } interface DocumentResourceOptions { doctype: string; name: string; auto?: boolean; whitelistedMethods?: Record; onError?: (error: any) => void; onSuccess?: (data: T) => void; transform?: (doc: T) => T; delete?: { onSuccess?: () => void; onError?: (error: any) => void; }; setValue?: { onSuccess?: () => void; onError?: (error: any) => void; }; } export interface DocumentResource { // Configuration auto: boolean; doctype: string; name: string; isDirty: boolean; promise: Promise | null; // Main document data doc: T; originalDoc: T; // Core methods reload(): void; update(options: Partial>): void; // Sub-resources get: ResourceBase & { data: T; params: { doctype: string; name: string; }; }; setValue: ResourceBase & { submit: ( values: Partial, options?: { onSuccess?: () => void; onError?: (error: any) => void } ) => void; }; setValueDebounced: ResourceBase & { submit: (values: Partial) => void; }; save: ResourceBase; delete: ResourceBase; // Dynamic whitelisted methods [methodName: string]: any; } export interface Customizations { fields: { fieldname: string; required?: number; placeholder?: string; url_method?: string; }[]; _form_script: string[]; _customActions?: any; _customOnChange?: any; } export interface TicketContact { name: string; email_id: string; phone: string; mobile_no: string; image: string; } // A ticket assignee enriched with their agent status by get_ticket_assignees. // Non-agent assignees only carry `name`. export interface TicketAssignee { name: string; agent_name?: string; user_image?: string; availability?: string; availability_changed_on?: string; } // A TicketAssignee plus the option fields AssignTo keeps when an agent is // picked from the dropdown (image/label come from AgentOption). export interface LocalAssignee extends TicketAssignee { image?: string; label?: string; } export type RecentTicket = Record< "subject" | "status" | "priority" | "name" | "creation", string >; export type SimilarTicket = Record< "subject" | "status" | "priority" | "name" | "creation", string >; export interface RecentSimilarTicket { recent_tickets: RecentTicket[]; similar_tickets: SimilarTicket[]; } export interface ODSettings { brandName: string; brandLogo: string; favicon: string; autoCloseAfterDays: string; autoCloseStatus: string; autoCloseTickets: string; assignWithinTeam: boolean; doNotRestrictTicketsWithoutAnAgentGroup: boolean; restrictTicketsByAgentGroup: boolean; updateStatusTo: string; autoUpdateStatus: boolean; isFeedbackMandatory: boolean; allowAnyoneToCreateTickets: boolean; defaultTicketType: string; skipEmailWorkflow: boolean; disableSavedRepliesGlobalScope: boolean; enableOutsideHoursBanner: boolean; outsideWorkingHoursBannerMessage: string; } export interface HolidayList { name: string; description: string; } export interface SlaPolicy { name: string; description: string; default_sla: boolean; enabled: boolean; rank: number; creation: string; } export interface Team { name: string; team: string; disabled: boolean; } export interface SavedReply { name: string; title: string; message: string; scope: string; teams: Team[]; /** JSON-encoded SavedReplyAction[] */ actions: string; owner: string; } export type SavedReplyActionType = | "Set Status" | "Set Priority" | "Set Team" | "Set Ticket Type" | "Assign Agent" | "Assign to Me" | "Add Tag" | "Remove Tag" | "Add Comment"; export interface SavedReplyAction { action_type: SavedReplyActionType; value: string; label?: string; /** Title of the saved reply that staged this action */ source?: string; /** Value the saved reply shipped, so an edited comment can be restored */ original_value?: string; } export interface RenderedSavedReply { title: string; message: string; actions: SavedReplyAction[]; } export type APIOptions = DropdownOption[] | string[] | []; export type DropdownOption = { label: string; value: string | number; }; export interface AgentOption { value: string; label: string; image?: string; availability?: string; availability_changed_on?: string; } // symbols export const TicketSymbol: InjectionKey< ComputedRef> > = Symbol("ticket"); export const AssigneeSymbol: InjectionKey< ComputedRef[]>> > = Symbol("assignees"); export const CustomizationSymbol: InjectionKey< ComputedRef> > = Symbol("customizations"); export const TicketContactSymbol: InjectionKey< ComputedRef> > = Symbol("ticketContact"); export const RecentSimilarTicketsSymbol: InjectionKey< ComputedRef> > = Symbol("recentSimilarTickets"); export const AssignmentRuleListResourceSymbol: InjectionKey< Resource > = Symbol("assignmentRuleListResource"); export const ODSettingsSymbol: InjectionKey> = Symbol("odSettings"); export const HolidayListResourceSymbol: InjectionKey< ListResource > = Symbol("holidayListResource"); export const SlaPolicyListResourceSymbol: InjectionKey< ListResource > = Symbol("slaPolicyListResource"); export const TeamListResourceSymbol: InjectionKey> = Symbol("teamListResource"); export const SavedReplyListResourceSymbol: InjectionKey< ListResource > = Symbol("savedReplyListResource"); export const CustomerResourceSymbol: InjectionKey< DocumentResource > = Symbol("customerResource"); declare global { interface Window { is_fc_site: boolean; date_format: string; time_format: string; session_user: string; timezone: Record<"user" | "system", string>; agent: string | null; default_country: string; apps: string[]; telemetry: { enabled: boolean }; customer_home_page: string; } } export interface CustomerContact { contact_name: string; is_primary: 0 | 1; is_manager: 0 | 1; email_id: string | null; mobile_no: string | null; image: string | null; last_active: string; modified?: string; ticket_count: number; } export interface NewContactState { firstName: string; lastName: string; image: string; email: string; phone: string; timezone: string; customer: string; invite: boolean; } export interface ContactEmailEntry { email_id: string; isPrimary: boolean; key: number; } export interface ContactPhoneEntry { phone: string; isPrimary: boolean; key: number; } export interface EditContactState { firstName: string; lastName: string; image: string; emails: ContactEmailEntry[]; phones: ContactPhoneEntry[]; customers: string[]; customer: string; timezone: string; } export interface LineChart { percentage_change: number; total: number; data: { date: string; count: number }[]; }