mirror of
https://github.com/hexastack/hexabot
synced 2025-06-04 03:26:22 +00:00
Merge branch 'main' into fix/dependencies
This commit is contained in:
commit
168766957d
2
api/package-lock.json
generated
2
api/package-lock.json
generated
@ -32,7 +32,6 @@
|
||||
"cache-manager-redis-yet": "^4.1.2",
|
||||
"connect-mongo": "^5.1.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^16.3.1",
|
||||
"express-session": "^1.17.3",
|
||||
"handlebars": "^4.7.8",
|
||||
"module-alias": "^2.2.3",
|
||||
@ -86,6 +85,7 @@
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.42.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "~3.6.1",
|
||||
|
@ -67,7 +67,6 @@
|
||||
"cache-manager-redis-yet": "^4.1.2",
|
||||
"connect-mongo": "^5.1.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^16.3.1",
|
||||
"express-session": "^1.17.3",
|
||||
"handlebars": "^4.7.8",
|
||||
"module-alias": "^2.2.3",
|
||||
@ -121,6 +120,7 @@
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.42.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "~3.6.1",
|
||||
|
@ -12,6 +12,7 @@ import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { I18nService } from '@/i18n/services/i18n.service';
|
||||
import { PluginService } from '@/plugins/plugins.service';
|
||||
import { PluginType } from '@/plugins/types';
|
||||
import { SettingType } from '@/setting/schemas/types';
|
||||
import { SettingService } from '@/setting/services/setting.service';
|
||||
import { BaseService } from '@/utils/generics/base-service';
|
||||
|
||||
@ -57,21 +58,35 @@ export class TranslationService extends BaseService<Translation> {
|
||||
PluginType.block,
|
||||
block.message.plugin,
|
||||
);
|
||||
const defaultSettings = await plugin?.getDefaultSettings();
|
||||
const defaultSettings = (await plugin?.getDefaultSettings()) || [];
|
||||
const filteredSettings = defaultSettings.filter(
|
||||
({ translatable, type }) =>
|
||||
[
|
||||
SettingType.text,
|
||||
SettingType.textarea,
|
||||
SettingType.multiple_text,
|
||||
].includes(type) &&
|
||||
(translatable === undefined || translatable === true),
|
||||
);
|
||||
const settingTypeMap = new Map(
|
||||
filteredSettings.map((setting) => [setting.label, setting.type]),
|
||||
);
|
||||
|
||||
// plugin
|
||||
Object.entries(block.message.args).forEach(([l, arg]) => {
|
||||
const setting = defaultSettings?.find(({ label }) => label === l);
|
||||
if (setting?.translatable) {
|
||||
if (Array.isArray(arg)) {
|
||||
// array of text
|
||||
strings = strings.concat(arg);
|
||||
} else if (typeof arg === 'string') {
|
||||
// text
|
||||
strings.push(arg);
|
||||
}
|
||||
for (const [key, value] of Object.entries(block.message.args)) {
|
||||
const settingType = settingTypeMap.get(key);
|
||||
|
||||
switch (settingType) {
|
||||
case SettingType.multiple_text:
|
||||
strings = strings.concat(value);
|
||||
break;
|
||||
case SettingType.text:
|
||||
case SettingType.textarea:
|
||||
strings.push(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ('text' in block.message && Array.isArray(block.message.text)) {
|
||||
// array of text
|
||||
strings = strings.concat(block.message.text);
|
||||
|
@ -47,6 +47,7 @@
|
||||
"random-seed": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/qs": "^6.9.15",
|
||||
"@types/node": "20.12.12",
|
||||
"@types/random-seed": "^0.3.5",
|
||||
"@types/react": "18.3.2",
|
||||
|
@ -20,6 +20,7 @@ import { useConfig } from "@/hooks/useConfig";
|
||||
import { useTranslate } from "@/hooks/useTranslate";
|
||||
import { Title } from "@/layout/content/Title";
|
||||
import { EntityType, RouterType } from "@/services/types";
|
||||
import { extractQueryParamsUrl } from "@/utils/URL";
|
||||
|
||||
import { getAvatarSrc } from "../helpers/mapMessages";
|
||||
import { useChat } from "../hooks/ChatContext";
|
||||
@ -53,7 +54,7 @@ export const SubscribersList = (props: {
|
||||
<Grid padding={2}>
|
||||
<Title title={t(props.assignedTo)} icon={InboxIcon} />
|
||||
</Grid>
|
||||
{subscribers?.length > 0 && (
|
||||
{subscribers?.length > 0 ? (
|
||||
<ConversationList
|
||||
scrollable
|
||||
loading={isFetching}
|
||||
@ -64,7 +65,10 @@ export const SubscribersList = (props: {
|
||||
<Conversation
|
||||
onClick={() => {
|
||||
chat.setSubscriberId(subscriber.id);
|
||||
push(`/${RouterType.INBOX}/subscribers/${subscriber.id}`);
|
||||
push({
|
||||
pathname: `/${RouterType.INBOX}/subscribers/${subscriber.id}`,
|
||||
query: extractQueryParamsUrl(window.location.href),
|
||||
});
|
||||
}}
|
||||
className="changeColor"
|
||||
key={subscriber.id}
|
||||
@ -87,6 +91,10 @@ export const SubscribersList = (props: {
|
||||
</Conversation>
|
||||
))}
|
||||
</ConversationList>
|
||||
) : (
|
||||
<Grid p={1} color="gray" textAlign="center">
|
||||
{t("message.no_result_found")}
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
@ -26,7 +26,7 @@ import { AssignedTo } from "./types";
|
||||
|
||||
export const Inbox = () => {
|
||||
const { t } = useTranslate();
|
||||
const { onSearch, searchPayload } = useSearch<ISubscriber>({
|
||||
const { onSearch, searchPayload, searchText } = useSearch<ISubscriber>({
|
||||
$or: ["first_name", "last_name"],
|
||||
});
|
||||
const [channels, setChannels] = useState<string[]>([]);
|
||||
@ -48,6 +48,7 @@ export const Inbox = () => {
|
||||
<Sidebar position="left">
|
||||
<Grid paddingX={1} paddingTop={1}>
|
||||
<Search
|
||||
value={searchText}
|
||||
onClearClick={() => onSearch("")}
|
||||
className="changeColor"
|
||||
onChange={(v) => onSearch(v)}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
@ -9,13 +9,21 @@
|
||||
import { createContext, ReactNode, useContext } from "react";
|
||||
import { FormProvider, UseFormReturn } from "react-hook-form";
|
||||
|
||||
import { IBlockAttributes, IBlock } from "@/types/block.types";
|
||||
import { IBlock, IBlockAttributes } from "@/types/block.types";
|
||||
|
||||
// Create a custom context for the block value
|
||||
const BlockContext = createContext<IBlock | undefined>(undefined);
|
||||
|
||||
// Custom hook to use block context
|
||||
export const useBlock = () => useContext(BlockContext);
|
||||
export const useBlock = () => {
|
||||
const context = useContext(BlockContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useBlock must be used within an BlockContext");
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
// This component wraps FormProvider and adds block to its context
|
||||
function BlockFormProvider({
|
||||
@ -23,7 +31,7 @@ function BlockFormProvider({
|
||||
methods,
|
||||
block,
|
||||
}: {
|
||||
methods: UseFormReturn<IBlockAttributes, any, undefined>;
|
||||
methods: UseFormReturn<IBlockAttributes>;
|
||||
block: IBlock | undefined;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
@ -7,12 +7,13 @@
|
||||
*/
|
||||
|
||||
import { debounce } from "@mui/material";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { ChangeEvent, useCallback, useEffect, useState } from "react";
|
||||
|
||||
import {
|
||||
TParamItem,
|
||||
TBuildParamProps,
|
||||
TBuildInitialParamProps,
|
||||
TBuildParamProps,
|
||||
TParamItem,
|
||||
} from "@/types/search.types";
|
||||
|
||||
const buildOrParams = <T,>({ params, searchText }: TBuildParamProps<T>) => ({
|
||||
@ -52,13 +53,38 @@ const buildNeqInitialParams = <T,>({
|
||||
);
|
||||
|
||||
export const useSearch = <T,>(params: TParamItem<T>) => {
|
||||
const [searchText, setSearchText] = useState<string>("");
|
||||
const onSearch = debounce(
|
||||
(e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | string) => {
|
||||
setSearchText(typeof e === "string" ? e : e.target.value);
|
||||
},
|
||||
300,
|
||||
const router = useRouter();
|
||||
const [searchText, setSearchText] = useState<string>(
|
||||
(router.query.search as string) || "",
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (router.query.search !== searchText) {
|
||||
setSearchText((router.query.search as string) || "");
|
||||
}
|
||||
}, [router.query.search]);
|
||||
|
||||
const updateQueryParams = useCallback(
|
||||
debounce(async (newSearchText: string) => {
|
||||
await router.replace(
|
||||
{
|
||||
pathname: router.pathname,
|
||||
query: { ...router.query, search: newSearchText || undefined },
|
||||
},
|
||||
undefined,
|
||||
{ shallow: true },
|
||||
);
|
||||
}, 300),
|
||||
[router],
|
||||
);
|
||||
const onSearch = (
|
||||
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | string,
|
||||
) => {
|
||||
const newSearchText = typeof e === "string" ? e : e.target.value;
|
||||
|
||||
setSearchText(newSearchText);
|
||||
updateQueryParams(newSearchText);
|
||||
};
|
||||
const {
|
||||
$eq: eqInitialParams,
|
||||
$iLike: iLikeParams,
|
||||
@ -67,6 +93,7 @@ export const useSearch = <T,>(params: TParamItem<T>) => {
|
||||
} = params;
|
||||
|
||||
return {
|
||||
searchText,
|
||||
onSearch,
|
||||
searchPayload: {
|
||||
where: {
|
||||
|
@ -6,6 +6,8 @@
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
import qs from "qs";
|
||||
|
||||
export const buildURL = (baseUrl: string, relativePath: string): string => {
|
||||
try {
|
||||
return new URL(relativePath).toString();
|
||||
@ -37,3 +39,12 @@ export const isAbsoluteUrl = (value: string = ""): boolean => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// todo: in the future we might need to extract this logic into a hook
|
||||
export const extractQueryParamsUrl = (fullUrl: string): string => {
|
||||
const extractedQueryParams = qs.parse(new URL(fullUrl).search, {
|
||||
ignoreQueryPrefix: true,
|
||||
});
|
||||
|
||||
return qs.stringify(extractedQueryParams);
|
||||
};
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -59,7 +59,6 @@
|
||||
"@mui/x-data-grid": "^7.3.2",
|
||||
"@projectstorm/react-canvas-core": "^7.0.3",
|
||||
"@projectstorm/react-diagrams": "^7.0.4",
|
||||
"@types/qs": "^6.9.15",
|
||||
"axios": "^1.7.7",
|
||||
"eazychart-css": "^0.2.1-alpha.0",
|
||||
"eazychart-react": "^0.8.0-alpha.0",
|
||||
@ -79,6 +78,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.12.12",
|
||||
"@types/qs": "^6.9.15",
|
||||
"@types/random-seed": "^0.3.5",
|
||||
"@types/react": "18.3.2",
|
||||
"@types/react-dom": "^18",
|
||||
@ -2824,6 +2824,7 @@
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/emoji-js/-/emoji-js-3.5.2.tgz",
|
||||
"integrity": "sha512-qPR85yjSPk2UEbdjYYNHfcOjVod7DCARSrJlPcL+cwaDFwdnmOFhPyYUvP5GaW0YZEy8mU93ZjTNgsVWz1zzlg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
@ -2877,6 +2878,7 @@
|
||||
"version": "6.9.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz",
|
||||
"integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/random-seed": {
|
||||
@ -10307,7 +10309,6 @@
|
||||
"version": "2.2.5",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@types/emoji-js": "^3.5.2",
|
||||
"autolinker": "^4.0.0",
|
||||
"dayjs": "^1.11.12",
|
||||
"emoji-js": "^3.8.0",
|
||||
@ -10317,6 +10318,7 @@
|
||||
"socket.io-client": "^4.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/emoji-js": "^3.5.2",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
||||
|
@ -20,7 +20,6 @@
|
||||
"*.{ts,tsx}": "eslint --fix -c \".eslintrc-staged.json\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/emoji-js": "^3.5.2",
|
||||
"autolinker": "^4.0.0",
|
||||
"dayjs": "^1.11.12",
|
||||
"emoji-js": "^3.8.0",
|
||||
@ -30,6 +29,7 @@
|
||||
"socket.io-client": "^4.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/emoji-js": "^3.5.2",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
||||
|
Loading…
Reference in New Issue
Block a user