UNPKG

@aslaluroba/help-center

Version:

A powerful and customizable help center widget for Angular applications with real-time chat functionality, AI assistance, multi-language support, and user feedback collection.

630 lines (617 loc) 23.2 kB
import * as _angular_core from '@angular/core'; import { OnInit, OnDestroy, ElementRef, InjectionToken, PipeTransform } from '@angular/core'; import { Observable } from 'rxjs'; type Language = 'en' | 'ar'; interface TokenResponse { token: string; expiresIn: number; } interface Option { id: string; helpScreenId: string; parentOptionId: string | null; nestedOptions: Option[]; title: string; paragraphs: string[]; chatWithUs: boolean; assistantId?: string; assistant?: { id: string; tenantId: string; tenant: { id: string; name: string; key: string; }; name: string; openAIAssistantId: string; greeting: string; closing: string; }; hasNestedOptions: boolean; order: number; icon?: string; } interface Message { id: string | number; sender: 'user' | 'assistant' | 'agent'; senderType: number; messageContent: string; sentAt: Date; isSeen: boolean; attachmentIds?: string[]; isReviewMessage?: boolean; } interface Tenant { id: string; name: string; key: string; logoUrl?: string | null; autoCloseSessions?: boolean; autoCloseSessionsAfter?: number; settings?: { description?: string; theme?: { primaryColor?: string; secondaryColor?: string; }; }; } interface Assistant { id: string; tenantId: string; tenant: Tenant; name: string; openAIAssistantId: string; greeting: string; closing: string; } interface HelpScreenFile { id: string; name: string; url: string; type: string; size?: number; } interface HelpScreenOption { id: string; helpScreenId: string; parentOptionId: string | null; nestedOptions: HelpScreenOption[]; title: string; paragraphs: string[]; files: HelpScreenFile[]; chatWithUs: boolean; assistantId?: string; assistant?: Assistant; hasNestedOptions: boolean; order: number; icon?: string; } interface HelpScreenData { id: string; tenantId: string; tenant: Tenant; title: string; description: string; options: HelpScreenOption[]; chatWithUs: boolean; } interface PresignUploadRequestDto { name: string; contentType: string; sizeBytes: number; pathData: { type: number; chatSessionId: string; }; } interface PresignUploadResponse { id: string; uploadUrl: string; path: string; expiresAt: string; } interface PresignDownloadResponse { id: string; name: string; downloadUrl: string; contentType: string; expiresAt: string; } interface SelectedFileDto { file: File; previewUrl: string; uploading: boolean; uploadedId: string | null; error: string | null; } interface UploadResult { fileId: string; success: boolean; error?: string; } declare class HelpCenterWidgetComponent implements OnInit, OnDestroy { getToken: _angular_core.InputSignal<() => Promise<string>>; helpScreenId: _angular_core.InputSignal<string>; showArrow: _angular_core.InputSignal<boolean>; messageLabel: _angular_core.InputSignal<string | null>; currentLang: _angular_core.InputSignal<string>; primaryColor: _angular_core.InputSignal<string>; logoUrl: _angular_core.InputSignal<string>; chatMessagesContainer: ElementRef; isRTL: _angular_core.Signal<boolean>; isPopupOpen: _angular_core.WritableSignal<boolean>; helpScreenData: _angular_core.WritableSignal<HelpScreenData | null>; status: _angular_core.WritableSignal<"failed" | "idle" | "loading" | "succeeded">; error: _angular_core.WritableSignal<string | null>; showArrowAnimation: _angular_core.WritableSignal<boolean>; showTooltip: _angular_core.WritableSignal<boolean>; sessionId: _angular_core.WritableSignal<string | null>; isAblyConnected: _angular_core.WritableSignal<boolean>; isChatClosed: _angular_core.WritableSignal<boolean>; showChat: _angular_core.WritableSignal<boolean>; messageText: _angular_core.WritableSignal<string>; isTyping: _angular_core.WritableSignal<boolean>; messages: _angular_core.WritableSignal<Message[]>; showHelpScreenData: _angular_core.WritableSignal<boolean>; chatIsLoading: _angular_core.WritableSignal<boolean>; ablyToken: _angular_core.WritableSignal<string | null>; needsAgent: _angular_core.WritableSignal<boolean>; assistantStatus: _angular_core.WritableSignal<"typing" | "idle">; selectedOption: _angular_core.WritableSignal<Option | null>; selectedNestedOption: _angular_core.WritableSignal<Option | null>; showEndChatConfirmation: _angular_core.WritableSignal<boolean>; showStartNewChatConfirmation: _angular_core.WritableSignal<boolean>; showReviewDialog: _angular_core.WritableSignal<boolean>; isSubmittingReview: _angular_core.WritableSignal<boolean>; isStartingNewChat: _angular_core.WritableSignal<boolean>; pendingNewChatOption: _angular_core.WritableSignal<Option | null>; hasUserSentMessages: _angular_core.WritableSignal<boolean>; closedSessionIdForReview: _angular_core.WritableSignal<string | null>; waitingForSessionEndConfirmation: _angular_core.WritableSignal<boolean>; private isClosingChatSession; private apiService; private translationService; private themeService; private chatSessionService; private actionHandlerService; private fileUploadService; private destroyRef; private themeEffectRef?; private languageEffectRef?; constructor(); /** * Registers action handlers for AI response actions. * This uses the ActionHandlerService for extensible, maintainable action handling. */ private registerActionHandlers; ngOnInit(): void; ngOnDestroy(): void; handleTogglePopup(): Promise<void>; private fetchHelpScreenData; createChatSession(option?: Option): Promise<{ chatSession: { id: string; }; ablyToken: string; }>; sendMessage(event?: { text: string; attachmentIds: string[]; pendingFiles?: File[]; } | string): Promise<void>; /** * Called when user attaches files but there is no session yet. * Creates a session so that chat-input can upload the files; send stays disabled until upload completes. */ handleRequestSessionForAttachments(): Promise<void>; handleReceiveMessage(message: string | { content: string; attachments?: string[]; }, senderType: number, needsAgent: boolean): void; private getSenderType; private hasActiveChatSession; private isWelcomeMessage; handleStartNewChat(option: Option): Promise<void>; private startNewChatSession; handleStartChat(option: Option): Promise<void>; handleEndChat(): Promise<void>; confirmEndChat(): Promise<void>; handleReviewSubmit(reviewData: { rating: number; comment: string; }): Promise<void>; handleReviewClose(): void; handleReviewSkip(): Promise<void>; private endChatSession; private closeSessionOnly; cancelEndChat(): void; closeEndChat(): void; confirmStartNewChat(): Promise<void>; cancelStartNewChat(): void; closeStartNewChat(): void; private clearCurrentChat; private startNewChatWithOption; handleClosePopup(): Promise<void>; handleMinimizePopup(): void; handleCloseArrowAnimation(): void; handleBack(): void; handleShowChat(): void; selectOption(option: Option): void; selectNestedOption(nestedOption: Option): void; handleShowHelpScreenData(): void; private scrollTimeout?; private scrollToBottom; getDirection(): "ltr" | "rtl"; get helpScreenDataList(): { icon: string; title: string; description: string; actionLabel: string; action: (() => Promise<void>) | null; }[]; navigateToUrl(url: string): void; private addReviewMessageToChat; handleEndSessionReceived(): void; private handleEndSessionConfirmed; handleReviewSubmitFromChat(reviewData: { rating: number; comment: string; }): Promise<void>; handleReviewSkipFromChat(): Promise<void>; static ɵfac: _angular_core.ɵɵFactoryDeclaration<HelpCenterWidgetComponent, never>; static ɵcmp: _angular_core.ɵɵComponentDeclaration<HelpCenterWidgetComponent, "app-help-center-widget", never, { "getToken": { "alias": "getToken"; "required": true; "isSignal": true; }; "helpScreenId": { "alias": "helpScreenId"; "required": true; "isSignal": true; }; "showArrow": { "alias": "showArrow"; "required": false; "isSignal": true; }; "messageLabel": { "alias": "messageLabel"; "required": false; "isSignal": true; }; "currentLang": { "alias": "currentLang"; "required": false; "isSignal": true; }; "primaryColor": { "alias": "primaryColor"; "required": false; "isSignal": true; }; "logoUrl": { "alias": "logoUrl"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>; } /** * URL for the loading screen animated logo (e.g. animatedLogo.gif). * When using the library as an npm package, copy the library's assets to your app * (see README "Assets setup") or provide your own URL here. */ declare const HELP_CENTER_LOADING_LOGO_URL: InjectionToken<string>; type GetTokenFn = () => Promise<string>; /** * Service for managing help center configuration. * * Stores configuration such as API base URL and token retrieval function. * This service is used internally by other services to access configuration. * * @publicApi */ declare class HelpCenterConfigService { private _apiBaseUrl; private _getTokenFn?; setApiBaseUrl(url: string): void; getApiBaseUrl(): string; setGetTokenFn(fn: GetTokenFn): void; getTokenFn(): GetTokenFn | undefined; static ɵfac: _angular_core.ɵɵFactoryDeclaration<HelpCenterConfigService, never>; static ɵprov: _angular_core.ɵɵInjectableDeclaration<HelpCenterConfigService>; } /** * Service for handling API requests with automatic authentication token management. * * Features: * - Automatic token refresh on expiry * - Token validation and format checking * - Secure token storage using sessionStorage * - Endpoint validation to prevent SSRF attacks * * @publicApi */ declare class ApiService { private getTokenFunction; private baseUrl; /** * Initialize the API service with authentication configuration. * * This must be called before making any API requests. The service will use * the provided token function to fetch and refresh tokens automatically. * * @param config Configuration object containing token function and optional base URL * @throws Error if getToken function is not provided * * @example * ```typescript * apiService.initialize({ * getToken: async () => { * const response = await fetch('/auth/token'); * const data = await response.json(); * return data.token; * }, * baseUrl: 'https://api.example.com' * }); * ``` */ initialize(config: ApiConfig): void; /** * Validate token format * JWT tokens must have exactly 3 parts separated by dots (header.payload.signature) */ private validateToken; /** * Retrieves a valid authentication token, fetching a new one if expired. * * Tokens are cached for 15 minutes. The service provides backward compatibility: * - Checks localStorage first for existing tokens (backward compatibility) * - Falls back to sessionStorage if no token found in localStorage * - New tokens are stored in sessionStorage (preferred) or localStorage (fallback) * - Automatically migrates tokens from localStorage to sessionStorage when found * * After expiry, a new token is automatically fetched using the configured getToken function. * * @param forceRefresh If true, forces a new token fetch even if current token is valid * @returns Promise resolving to a valid authentication token * @throws Error if API service is not initialized or token format is invalid */ getValidToken(forceRefresh?: boolean): Promise<string>; private fetchWithAuth; /** * Validate endpoint to prevent SSRF vulnerabilities * * Protects against: * - Absolute URLs with any protocol (case-insensitive) * - Protocol-relative URLs * - Dangerous protocols (ftp, file, data, javascript, etc.) * - URL-encoded path traversal * - Double-encoded attacks */ private validateEndpoint; /** * Makes an authenticated API request with automatic token management. * * This method automatically: * - Validates the endpoint to prevent SSRF attacks * - Adds authentication headers with a valid token * - Retries with a fresh token if authentication fails * - Handles errors and returns appropriate error messages * * @param endpoint API endpoint path (relative to baseUrl) * @param method HTTP method (default: 'GET') * @param body Request body object (will be JSON stringified) * @param customHeaders Additional headers to include in the request * @returns Promise resolving to the Response object * @throws Error if endpoint validation fails, request fails, or authentication fails * * @example * ```typescript * // GET request * const response = await apiService.apiRequest('client/help-screens/123'); * const data = await response.json(); * * // POST request * const response = await apiService.apiRequest( * 'client/chat-sessions', * 'POST', * { helpScreenId: '123' } * ); * ``` */ apiRequest<T = unknown>(endpoint: string, method?: string, body?: T | null, customHeaders?: Record<string, string>): Promise<Response>; static ɵfac: _angular_core.ɵɵFactoryDeclaration<ApiService, never>; static ɵprov: _angular_core.ɵɵInjectableDeclaration<ApiService>; } /** * Service for retrieving authentication tokens from the configured token function. * * This service acts as a wrapper around the configured token retrieval function, * providing a consistent interface for token management. * * @publicApi */ declare class TokenService { private config; /** * Retrieves an authentication token using the configured token function. * * @returns Promise resolving to a TokenResponse containing the token and expiry time * @throws Error if no token function is configured */ getToken(): Promise<TokenResponse>; static ɵfac: _angular_core.ɵɵFactoryDeclaration<TokenService, never>; static ɵprov: _angular_core.ɵɵInjectableDeclaration<TokenService>; } type TranslationKey = 'ChatIntroMessage' | 'BabylaiTitle' | 'BabylaiDescription' | 'ChatNow' | 'TryBableAI' | 'ContactUs' | 'HelpCenter' | 'BabylAI' | 'ChatPlaceholder' | 'PoweredByBabylAI' | 'EndChat' | 'LeavingDialogTitle' | 'LeavingDialogBody' | 'StartNewChatDialogTitle' | 'StartNewChatDialogBody' | 'ReviewDialogTitle' | 'ReviewDialogDescription' | 'ReviewDialogRatingLabel' | 'ReviewDialogCommentLabel' | 'ReviewDialogCommentPlaceholder' | 'ReviewDialogSubmitButton' | 'ReviewDialogSkipButton' | 'Confirm' | 'Cancel' | 'Close' | 'Back' | 'title' | 'ErrorFetchingHelpScreen' | 'ErrorSendingMessage' | 'ErrorStartingChat' | 'ErrorEndingChat' | 'ErrorSubmittingReview' | 'ErrorClosingChat' | 'ErrorCreatingSession' | 'ErrorNetworkFailure' | 'ErrorUnknown' | 'ErrorMessageTooLong' | 'ErrorMessageEmpty' | 'CloseChat' | 'Continue'; /** * Service for managing translations and language switching. * * Supports multiple languages (currently English and Arabic) with RTL support. * Provides reactive language changes through Observable pattern. * * @publicApi */ declare class TranslationService { private translations; private _currentLang; readonly currentLang: Observable<Language>; /** * Translates a translation key to the current language. * * @param key Translation key to look up * @returns Translated string in the current language, or the key itself if translation not found * * @example * ```typescript * const message = translationService.translate('ChatNow'); * // Returns 'Let\'s Chat' in English or 'دعنا نتحدث' in Arabic * ``` */ translate(key: TranslationKey): string; /** * Sets the current language for translations. * * @param lang Language code ('en' or 'ar') * * @example * ```typescript * translationService.setLanguage('ar'); // Switch to Arabic * ``` */ setLanguage(lang: Language): void; /** * Gets the current language code. * * @returns Current language code ('en' or 'ar') */ getCurrentLang(): Language; static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslationService, never>; static ɵprov: _angular_core.ɵɵInjectableDeclaration<TranslationService>; } /** * Service for managing chat session lifecycle and operations. * * Handles: * - Chat session creation and management * - Ably connection management * - Message sending operations * * @publicApi */ declare class ChatSessionService { private apiService; private actionHandlerService; /** * Creates a new chat session with the specified option. * * @param option The help screen option to create a chat session for * @param helpScreenId The help screen ID * @param currentLang Current language code for API headers * @returns Promise resolving to session data including sessionId and ablyToken * @throws Error if session creation fails */ createSession(option: Option, helpScreenId: string, currentLang: string): Promise<{ chatSession: { id: string; }; ablyToken: string; }>; /** * Establishes Ably real-time connection for a chat session. * * @param sessionId The chat session ID * @param ablyToken The Ably authentication token * @param onMessageReceived Callback function for received messages * @param tenantId The tenant ID for the connection * @param option Optional option for token refresh (needed for token renewal) * @param helpScreenId Optional help screen ID for token refresh * @param currentLang Optional current language for token refresh * @param onActionReceived Optional callback function for handling action types */ establishAblyConnection(sessionId: string, ablyToken: string, onMessageReceived: (message: string | { content: string; attachments?: string[]; }, senderType: number, needsAgent: boolean) => void, tenantId: string, option?: Option, helpScreenId?: string, currentLang?: string, onActionReceived?: (actionType: string, messageData: any) => void | Promise<void>): Promise<void>; /** * Sends a message in an active chat session. * * @param sessionId The chat session ID * @param messageContent The message content to send * @param currentLang Current language code for API headers * @throws Error if message sending fails */ sendMessage(sessionId: string, messageContent: string, currentLang: string, attachmentIds?: string[]): Promise<void>; /** * Closes a chat session. * * @param sessionId The chat session ID to close * @param currentLang Current language code for API headers * @returns Promise resolving to the close response * @throws Error if session closing fails */ closeSession(sessionId: string, currentLang: string): Promise<unknown>; /** * Submits a review for a chat session. * * @param sessionId The chat session ID * @param rating Rating value (1-5) * @param comment Review comment (10-500 characters) * @param currentLang Current language code for API headers * @throws Error if review submission fails */ submitReview(sessionId: string, rating: number, comment: string, currentLang: string): Promise<void>; /** * Stops the Ably connection. */ stopConnection(): Promise<void>; /** * Checks if Ably connection is active. * * @returns True if connection is active, false otherwise */ isConnectionActive(): boolean; static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatSessionService, never>; static ɵprov: _angular_core.ɵɵInjectableDeclaration<ChatSessionService>; } /** * Service for managing language switching. * * Provides a simplified interface for switching between supported languages. * This service wraps TranslationService for easier language management. * * @publicApi */ declare class LanguageService { private translationService; /** * Switches the application language. * * @param language Language code to switch to ('en' or 'ar') * * @example * ```typescript * languageService.switchLanguage('ar'); // Switch to Arabic * ``` */ switchLanguage(language: Language): void; /** * Gets the current application language. * * @returns Current language code ('en' or 'ar') */ getCurrentLang(): Language; static ɵfac: _angular_core.ɵɵFactoryDeclaration<LanguageService, never>; static ɵprov: _angular_core.ɵɵInjectableDeclaration<LanguageService>; } /** * Angular pipe for translating keys in templates. * * Usage in templates: * ```html * {{ 'ChatNow' | translate }} * ``` * * @publicApi */ declare class TranslatePipe implements PipeTransform { private translationService; /** * Transforms a translation key into the translated string for the current language. * * @param key Translation key to look up * @returns Translated string in the current language */ transform(key: TranslationKey): string; static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslatePipe, never>; static ɵpipe: _angular_core.ɵɵPipeDeclaration<TranslatePipe, "translate", true>; } /** * Configuration interface for API service initialization * * @publicApi */ interface ApiConfig { /** * Function that returns a promise resolving to an authentication token * This function is called when tokens need to be refreshed */ getToken: () => Promise<string>; /** * Optional base URL for API requests * Defaults to 'https://babylai.net/api' if not provided * Should use HTTPS in production environments */ baseUrl?: string; } export { ApiService, ChatSessionService, HELP_CENTER_LOADING_LOGO_URL, HelpCenterConfigService, HelpCenterWidgetComponent, LanguageService, TokenService, TranslatePipe, TranslationService }; export type { ApiConfig, Assistant, GetTokenFn, HelpScreenData, HelpScreenFile, HelpScreenOption, Language, Message, Option, PresignDownloadResponse, PresignUploadRequestDto, PresignUploadResponse, SelectedFileDto, Tenant, TokenResponse, TranslationKey, UploadResult }; //# sourceMappingURL=aslaluroba-help-center.d.ts.map