diff --git a/api/src/analytics/schemas/bot-stats.schema.ts b/api/src/analytics/schemas/bot-stats.schema.ts index 4bdb0a3d..37a6a44e 100644 --- a/api/src/analytics/schemas/bot-stats.schema.ts +++ b/api/src/analytics/schemas/bot-stats.schema.ts @@ -9,6 +9,7 @@ import { ModelDefinition, Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { BaseSchema } from '@/utils/generics/base-schema'; +import { LifecycleHookManager } from '@/utils/generics/lifecycle-hook-manager'; import { THydratedDocument } from '@/utils/types/filter.types'; export enum BotStatsType { @@ -115,9 +116,9 @@ export class BotStats extends BaseSchema { export type BotStatsDocument = THydratedDocument; -export const BotStatsModel: ModelDefinition = { +export const BotStatsModel: ModelDefinition = LifecycleHookManager.attach({ name: BotStats.name, schema: SchemaFactory.createForClass(BotStats), -}; +}); export default BotStatsModel.schema; diff --git a/api/src/nlp/schemas/nlp-sample-entity.schema.ts b/api/src/nlp/schemas/nlp-sample-entity.schema.ts index 31c2f66c..cfe25c3e 100644 --- a/api/src/nlp/schemas/nlp-sample-entity.schema.ts +++ b/api/src/nlp/schemas/nlp-sample-entity.schema.ts @@ -11,6 +11,7 @@ import { Transform, Type } from 'class-transformer'; import { Schema as MongooseSchema } from 'mongoose'; import { BaseSchema } from '@/utils/generics/base-schema'; +import { LifecycleHookManager } from '@/utils/generics/lifecycle-hook-manager'; import { TFilterPopulateFields, THydratedDocument, @@ -103,10 +104,11 @@ export class NlpSampleEntityFull extends NlpSampleEntityStub { export type NlpSampleEntityDocument = THydratedDocument; -export const NlpSampleEntityModel: ModelDefinition = { - name: NlpSampleEntity.name, - schema: SchemaFactory.createForClass(NlpSampleEntityStub), -}; +export const NlpSampleEntityModel: ModelDefinition = + LifecycleHookManager.attach({ + name: NlpSampleEntity.name, + schema: SchemaFactory.createForClass(NlpSampleEntityStub), + }); export default NlpSampleEntityModel.schema; diff --git a/frontend/src/app-components/menus/Sidebar.tsx b/frontend/src/app-components/menus/Sidebar.tsx index ca621817..cf0b505c 100644 --- a/frontend/src/app-components/menus/Sidebar.tsx +++ b/frontend/src/app-components/menus/Sidebar.tsx @@ -9,23 +9,23 @@ import { type IconDefinition } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { - List, - Theme, - styled, - Divider, Collapse, + Divider, + List, + ListItemButton, + ListItemIcon, ListItemText, ListSubheader, - ListItemButton, - SvgIconTypeMap, - ListItemIcon, Tooltip as MuiTooltip, + SvgIconTypeMap, + Theme, TooltipProps, + styled, } from "@mui/material"; // @icon import { OverridableComponent } from "@mui/material/OverridableComponent"; import Link from "next/link"; -import { useState, useEffect } from "react"; +import { useEffect, useState } from "react"; import { useTranslate } from "@/hooks/useTranslate"; import { TTranslationKeys } from "@/i18n/i18n.types"; diff --git a/frontend/src/layout/VerticalMenu.tsx b/frontend/src/layout/VerticalMenu.tsx index 0f823c3f..d826a753 100644 --- a/frontend/src/layout/VerticalMenu.tsx +++ b/frontend/src/layout/VerticalMenu.tsx @@ -205,6 +205,8 @@ const getMenuItems = (ssoEnabled: boolean): MenuItem[] => [ [EntityType.LABEL]: [PermissionAction.READ], }, }, + + // { // text: 'menu.broadcast', // href: "/subscribers/broadcast", diff --git a/widget/.eslintrc.json b/widget/.eslintrc.json index 7586d22a..334447df 100644 --- a/widget/.eslintrc.json +++ b/widget/.eslintrc.json @@ -1,16 +1,15 @@ { - "plugins": [ - "@typescript-eslint/eslint-plugin", - "import", - "react", - "license-header" - ], + "root": true, + "plugins": ["@typescript-eslint", "import", "license-header", "react"], "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", "plugin:react-hooks/recommended" ], "rules": { + "react/jsx-no-target-blank": ["off"], + "react/react-in-jsx-scope": "off", "@typescript-eslint/no-unused-vars": [ "error", { @@ -24,19 +23,17 @@ "error", { "groups": [ - "builtin", // Built-in imports (come from NodeJS native) go first - "external", // <- External imports - "unknown", // <- unknown - "index", // <- index imports - "internal", // <- Absolute imports - "parent", // <- Relative imports, the sibling and parent types they can be mingled together + "builtin", + "external", + "unknown", + "index", + "internal", + "parent", "sibling" ], "newlines-between": "always", "alphabetize": { - /* sort in ascending order. Options: ["ignore", "asc", "desc"] */ "order": "asc", - /* ignore case. Options: [true, false] */ "caseInsensitive": true } } @@ -50,8 +47,8 @@ "error", { "blankLine": "never", "prev": ["const"], "next": "const" } ], - "react/jsx-curly-brace-presence": "warn", - "react/self-closing-comp": "error", + "react/jsx-curly-brace-presence": ["warn"], + "react/self-closing-comp": ["error"], "license-header/header": [ "error", [ diff --git a/widget/.prettierrc b/widget/.prettierrc new file mode 100644 index 00000000..f3bcd4c9 --- /dev/null +++ b/widget/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": false, + "trailingComma": "all" +} diff --git a/widget/README.md b/widget/README.md index a25250ae..ed102975 100644 --- a/widget/README.md +++ b/widget/README.md @@ -1,15 +1,18 @@ # Hexabot Live Chat Widget + The [Hexabot](https://hexabot.ai/) Live Chat Widget is a React-based embeddable widget that allows users to integrate real-time chat functionality into their websites. It connects to the Hexabot API and facilitates seamless interaction between end-users and chatbots across multiple channels. [Hexabot](https://hexabot.ai/) is an open-source chatbot / agent solution that allows users to create and manage AI-powered, multi-channel, and multilingual chatbots with ease. If you would like to learn more, please visit the [official github repo](https://github.com/Hexastack/Hexabot/). ## Key Features + - **Real-Time Chat:** Engage in real-time conversations with users directly through your website. - **Customizable:** Easily customize the widget's appearance and behavior to fit your brand and website. - **Multi-Channel Support:** Integrates with multiple messaging platforms through the Hexabot API. - **Embeddable:** Simple to embed and integrate into any web page with just a few lines of code. ## Directory Structure + The Hexabot Live Chat Widget is organized into the following directory structure, under `src` we have: - **src/assets:** Static assets like icons, fonts, and images used in the widget. @@ -23,30 +26,33 @@ The Hexabot Live Chat Widget is organized into the following directory structure - **src/types:** Defines the typescript interfaces, types, and enums used. - **src/utils:** Utility functions and helpers used throughout the widget, such as formatting, validations, or data transformations. - - **/public:** Contains static files that are publicly accessible. This includes the main HTML template where the widget is embedded for local development. ## Run the Live Chat Widget ### Dev Mode + To run the widget in development mode, execute the following command at the project root level: + ```bash npm run dev:widget ``` The live chat widget will be accessible at http://localhost:5173. - ### Build for Production + To build the widget for production, execute the following command at the widget folder level: + ```bash npm run build ``` + This will generate a production-ready build in the dist folder. ## Embed Chat Widget -Once the widget is built, you can easily embed it into any webpage. Here's an example of how to add it to your website: +Once the widget is built, you can easily embed it into any webpage. Here's an example of how to add it to your website: ```js @@ -68,9 +74,11 @@ Once the widget is built, you can easily embed it into any webpage. Here's an ex ); ``` + Replace the values in apiUrl and token with your configuration details. -To prevent the website css from conflicting with the chat widget css, we can leverage the shadow dom: +To prevent the website css from conflicting with the chat widget css, we can leverage the shadow dom: + ```js @@ -84,7 +92,7 @@ To prevent the website css from conflicting with the chat widget css, we can lev document .getElementById('hb-chat-widget') .attachShadow({ mode: 'open' }) - .append( + .append( shadowContainer, createElement("link", { rel: "stylesheet", @@ -104,7 +112,7 @@ To prevent the website css from conflicting with the chat widget css, we can lev ``` -If you would like to use the official widget and benefit from updates automatically, you can consider using the cdn url: +If you would like to use the official widget and benefit from updates automatically, you can consider using the cdn url: `https://cdn.jsdelivr.net/npm/hexabot-chat-widget@2.0.4/dist/` or lastest from major version: @@ -113,20 +121,24 @@ or lastest from major version: JsDelivr uses the package published in the NPM registry : https://www.npmjs.com/package/hexabot-chat-widget ## Examples + As a proof of concept we developed a Wordpress plugin to embed the chat widget in a Wordpress website : [https://github.com/hexastack/hexabot-wordpress-live-chat-widget](https://github.com/hexastack/hexabot-wordpress-live-chat-widget) ## Customization + You can customize the look and feel of the chat widget by modifying the widget’s scss styles or behavior. The widget allows you to: - Change colors and fonts to match your website's branding. - Configure user settings like language and chatbot response preferences. -## Contributing +## Contributing + We welcome contributions from the community! Whether you want to report a bug, suggest new features, or submit a pull request, your input is valuable to us. Feel free to join us on [Discord](https://discord.gg/rNb9t2MFkG) ## License + This software is licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. diff --git a/widget/package.json b/widget/package.json index 0e84932c..8fac6ff7 100644 --- a/widget/package.json +++ b/widget/package.json @@ -34,6 +34,7 @@ "@typescript-eslint/parser": "^7.15.0", "@vitejs/plugin-react": "^4.3.1", "eslint": "^8.57.0", + "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-refresh": "^0.4.7", "sass": "^1.77.8", diff --git a/widget/public/index.html b/widget/public/index.html index b4e3f015..de6d3768 100644 --- a/widget/public/index.html +++ b/widget/public/index.html @@ -1,4 +1,4 @@ - + @@ -19,23 +19,24 @@