You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by ro...@apache.org on 2024/06/05 08:19:23 UTC
(incubator-answer) 01/01: fix(plugins): Fix the problem that the dom obtained by hooks in the plugin is null
This is an automated email from the ASF dual-hosted git repository.
robin0716 pushed a commit to branch feat/1.3.5/embed
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
commit bdbff79b61c7addfc24663089df5c3c796949773
Author: robin <ro...@rnode.me>
AuthorDate: Wed Jun 5 16:19:10 2024 +0800
fix(plugins): Fix the problem that the dom obtained by hooks in the plugin is null
Related issue: https://github.com/apache/incubator-answer-plugins/issues/121
---
ui/src/components/Editor/index.tsx | 3 +-
ui/src/components/PluginRender/index.tsx | 2 +-
.../Questions/Detail/components/Answer/index.tsx | 3 +-
ui/src/pages/Search/components/Head/index.tsx | 3 +-
ui/src/pages/Users/Login/index.tsx | 10 ++---
ui/src/pages/Users/Register/index.tsx | 3 +-
ui/src/utils/pluginKit/index.ts | 51 ++++++++++++++--------
ui/src/utils/pluginKit/interface.ts | 31 ++++++++++++-
ui/src/utils/pluginKit/utils.ts | 38 ++--------------
9 files changed, 81 insertions(+), 63 deletions(-)
diff --git a/ui/src/components/Editor/index.tsx b/ui/src/components/Editor/index.tsx
index 8d157a68..dd004021 100644
--- a/ui/src/components/Editor/index.tsx
+++ b/ui/src/components/Editor/index.tsx
@@ -27,6 +27,7 @@ import {
import classNames from 'classnames';
+import { PluginType } from '@/utils/pluginKit';
import PluginRender from '../PluginRender';
import {
@@ -115,7 +116,7 @@ const MDEditor: ForwardRefRenderFunction<EditorRef, Props> = (
<EditorContext.Provider value={editor}>
{editor && (
<PluginRender
- type="editor"
+ type={PluginType.Editor}
className="toolbar-wrap px-3 d-flex align-items-center flex-wrap"
editor={editor}
previewElement={previewRef.current?.element}>
diff --git a/ui/src/components/PluginRender/index.tsx b/ui/src/components/PluginRender/index.tsx
index 3da9fd0b..9de283f5 100644
--- a/ui/src/components/PluginRender/index.tsx
+++ b/ui/src/components/PluginRender/index.tsx
@@ -33,7 +33,7 @@ import PluginKit, { Plugin, PluginType } from '@/utils/pluginKit';
interface Props {
slug_name?: string;
- type?: PluginType;
+ type: PluginType;
children?: ReactNode;
[prop: string]: any;
}
diff --git a/ui/src/pages/Questions/Detail/components/Answer/index.tsx b/ui/src/pages/Questions/Detail/components/Answer/index.tsx
index 474c83d6..fb4de275 100644
--- a/ui/src/pages/Questions/Detail/components/Answer/index.tsx
+++ b/ui/src/pages/Questions/Detail/components/Answer/index.tsx
@@ -59,7 +59,8 @@ const Index: FC<Props> = ({
});
const [searchParams] = useSearchParams();
const answerRef = useRef<HTMLDivElement>(null);
- useRenderHtmlPlugin(answerRef.current);
+
+ useRenderHtmlPlugin(answerRef);
const acceptAnswer = () => {
acceptanceAnswer({
diff --git a/ui/src/pages/Search/components/Head/index.tsx b/ui/src/pages/Search/components/Head/index.tsx
index cbb19283..4068b4ba 100644
--- a/ui/src/pages/Search/components/Head/index.tsx
+++ b/ui/src/pages/Search/components/Head/index.tsx
@@ -28,6 +28,7 @@ import { escapeRemove } from '@/utils';
import { pathFactory } from '@/router/pathFactory';
import { PluginRender } from '@/components';
import Pattern from '@/common/pattern';
+import { PluginType } from '@/utils/pluginKit';
interface Props {
data;
@@ -57,7 +58,7 @@ const Index: FC<Props> = ({ data }) => {
<div className="mb-3 d-flex align-items-center justify-content-between">
<h3 className="mb-0">{t('title')}</h3>
- <PluginRender type="search" slug_name="serarch_info" />
+ <PluginRender type={PluginType.Search} slug_name="serarch_info" />
</div>
<p>
<span className="text-secondary me-1">{t('keywords')}</span>
diff --git a/ui/src/pages/Users/Login/index.tsx b/ui/src/pages/Users/Login/index.tsx
index 404bb4ce..9cec9a32 100644
--- a/ui/src/pages/Users/Login/index.tsx
+++ b/ui/src/pages/Users/Login/index.tsx
@@ -37,7 +37,7 @@ import {
userCenter,
scrollToElementTop,
} from '@/utils';
-import { useCaptchaPlugin } from '@/utils/pluginKit';
+import { PluginType, useCaptchaPlugin } from '@/utils/pluginKit';
import { login, UcAgent } from '@/services';
import { setupAppTheme } from '@/utils/localize';
@@ -188,25 +188,25 @@ const Index: React.FC = () => {
{step === 1 ? (
<Col className="mx-auto" md={6} lg={4} xl={3}>
<PluginRender
- type="captcha"
+ type={PluginType.Captcha}
slug_name="captcha_basic"
className="mb-5"
/>
<PluginRender
- type="captcha"
+ type={PluginType.Captcha}
slug_name="captcha_google_v2"
className="mb-5"
/>
{ucAgentInfo ? (
<PluginRender
- type="connector"
+ type={PluginType.Connector}
slug_name="hosting_connector"
className="mb-5"
/>
) : (
<PluginRender
- type="connector"
+ type={PluginType.Connector}
slug_name="third_party_connector"
className="mb-5"
/>
diff --git a/ui/src/pages/Users/Register/index.tsx b/ui/src/pages/Users/Register/index.tsx
index 857cd9d9..4d894b6a 100644
--- a/ui/src/pages/Users/Register/index.tsx
+++ b/ui/src/pages/Users/Register/index.tsx
@@ -26,6 +26,7 @@ import { usePageTags } from '@/hooks';
import { Unactivate, WelcomeTitle, PluginRender } from '@/components';
import { guard } from '@/utils';
import { loginSettingStore } from '@/stores';
+import { PluginType } from '@/utils/pluginKit/interface';
import SignUpForm from './components/SignUpForm';
@@ -55,7 +56,7 @@ const Index: React.FC = () => {
{showForm ? (
<Col className="mx-auto" md={6} lg={4} xl={3}>
<PluginRender
- type="connector"
+ type={PluginType.Connector}
slug_name="third_party_connector"
className="mb-5"
/>
diff --git a/ui/src/utils/pluginKit/index.ts b/ui/src/utils/pluginKit/index.ts
index 87851d80..5a106523 100644
--- a/ui/src/utils/pluginKit/index.ts
+++ b/ui/src/utils/pluginKit/index.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import React from 'react';
+import React, { RefObject } from 'react';
import builtin from '@/plugins/builtin';
import * as allPlugins from '@/plugins';
@@ -26,7 +26,8 @@ import { LOGGED_TOKEN_STORAGE_KEY } from '@/common/constants';
import { getPluginsStatus } from '@/services';
import Storage from '@/utils/storage';
-import { initI18nResource, Plugin, PluginInfo, PluginType } from './utils';
+import { initI18nResource } from './utils';
+import { Plugin, PluginInfo, PluginType } from './interface';
/**
* This information is to be defined for all components.
@@ -133,19 +134,10 @@ class Plugins {
const plugins = new Plugins();
-const useRenderHtmlPlugin = (element: HTMLElement | null) => {
- plugins
- .getPlugins()
- .filter((plugin) => plugin.activated && plugin.hooks?.useRender)
- .forEach((plugin) => {
- plugin.hooks?.useRender?.forEach((hook) => {
- hook(element);
- });
- });
-};
-
const getRoutePlugins = () => {
- return plugins.getPlugins().filter((plugin) => plugin.info.type === 'route');
+ return plugins
+ .getPlugins()
+ .filter((plugin) => plugin.info.type === PluginType.Route);
};
const defaultProps = () => {
@@ -184,11 +176,36 @@ const mergeRoutePlugins = (routes) => {
return routes;
};
+/**
+ * Only used to enhance the capabilities of the markdown editor
+ * Add RefObject type to solve the problem of dom being null in hooks
+ */
+const useRenderHtmlPlugin = (
+ element: HTMLElement | RefObject<HTMLElement> | null,
+) => {
+ plugins
+ .getPlugins()
+ .filter((plugin) => {
+ return (
+ plugin.activated &&
+ plugin.hooks?.useRender &&
+ plugin.info.type === PluginType.Editor
+ );
+ })
+ .forEach((plugin) => {
+ plugin.hooks?.useRender?.forEach((hook) => {
+ hook(element);
+ });
+ });
+};
+
// Only one captcha type plug-in can be enabled at the same time
const useCaptchaPlugin = (key: Type.CaptchaKey) => {
const captcha = plugins
.getPlugins()
- .filter((plugin) => plugin.info.type === 'captcha' && plugin.activated);
+ .filter(
+ (plugin) => plugin.info.type === PluginType.Captcha && plugin.activated,
+ );
const pluginHooks = plugins.getOnePluginHooks(captcha[0]?.info.slug_name);
return pluginHooks?.useCaptcha?.({
captchaKey: key,
@@ -196,7 +213,7 @@ const useCaptchaPlugin = (key: Type.CaptchaKey) => {
});
};
-export type { Plugin, PluginInfo, PluginType };
+export type { Plugin, PluginInfo };
-export { useRenderHtmlPlugin, mergeRoutePlugins, useCaptchaPlugin };
+export { useRenderHtmlPlugin, mergeRoutePlugins, useCaptchaPlugin, PluginType };
export default plugins;
diff --git a/ui/src/utils/pluginKit/interface.ts b/ui/src/utils/pluginKit/interface.ts
index d4376764..097fb94f 100644
--- a/ui/src/utils/pluginKit/interface.ts
+++ b/ui/src/utils/pluginKit/interface.ts
@@ -16,12 +16,41 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { NamedExoticComponent, FC, RefObject } from 'react';
-export type PluginType = 'connector' | 'search' | 'editor' | 'captcha';
+import type * as Type from '@/common/interface';
+
+export enum PluginType {
+ Connector = 'connector',
+ Search = 'search',
+ Editor = 'editor',
+ Route = 'route',
+ Captcha = 'captcha',
+}
export interface PluginInfo {
slug_name: string;
type: PluginType;
name?: string;
description?: string;
+ route?: string;
+}
+
+export interface Plugin {
+ info: PluginInfo;
+ component: NamedExoticComponent | FC;
+ i18nConfig?;
+ hooks?: {
+ useRender?: Array<
+ (element: HTMLElement | RefObject<HTMLElement> | null) => void
+ >;
+ useCaptcha?: (props: { captchaKey: Type.CaptchaKey; commonProps: any }) => {
+ getCaptcha: () => Record<string, any>;
+ check: (t: () => void) => void;
+ handleCaptchaError: (error) => any;
+ close: () => Promise<void>;
+ resolveCaptchaReq: (data) => void;
+ };
+ };
+ activated?: boolean;
}
diff --git a/ui/src/utils/pluginKit/utils.ts b/ui/src/utils/pluginKit/utils.ts
index 2116e636..26118132 100644
--- a/ui/src/utils/pluginKit/utils.ts
+++ b/ui/src/utils/pluginKit/utils.ts
@@ -17,11 +17,9 @@
* under the License.
*/
-import { NamedExoticComponent, FC } from 'react';
-
import i18next from 'i18next';
-import type * as Type from '@/common/interface';
+import { PluginInfo, Plugin, PluginType } from './interface';
/**
* This information is to be defined for all components.
@@ -36,38 +34,6 @@ import type * as Type from '@/common/interface';
*/
const I18N_NS = 'plugin';
-
-export type PluginType =
- | 'connector'
- | 'search'
- | 'editor'
- | 'route'
- | 'captcha';
-export interface PluginInfo {
- slug_name: string;
- type: PluginType;
- name?: string;
- description?: string;
- route?: string;
-}
-
-export interface Plugin {
- info: PluginInfo;
- component: NamedExoticComponent | FC;
- i18nConfig?;
- hooks?: {
- useRender?: Array<(element: HTMLElement | null) => void>;
- useCaptcha?: (props: { captchaKey: Type.CaptchaKey; commonProps: any }) => {
- getCaptcha: () => Record<string, any>;
- check: (t: () => void) => void;
- handleCaptchaError: (error) => any;
- close: () => Promise<void>;
- resolveCaptchaReq: (data) => void;
- };
- };
- activated?: boolean;
-}
-
interface I18nResource {
[lng: string]: {
plugin: {
@@ -110,4 +76,6 @@ const getTransKeyPrefix = (info: PluginInfo) => {
return kp;
};
+export type { Plugin, PluginInfo, PluginType };
+
export { initI18nResource, getTransNs, getTransKeyPrefix };