diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/EmbedLayout.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/EmbedLayout.tsx new file mode 100644 index 000000000..3b0502d72 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/EmbedLayout.tsx @@ -0,0 +1,30 @@ +import { css } from '@nocobase/client'; +import { Layout } from 'antd'; +import React from 'react'; +import { Outlet } from 'react-router-dom'; + +export const EmbedLayout = () => ( + + div { + position: relative; + } + .ant-layout-footer { + position: absolute; + bottom: 0; + text-align: center; + width: 100%; + z-index: 0; + padding: 0px 50px; + } + `} + > + + + +); diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/EmbedPage.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/EmbedPage.tsx new file mode 100644 index 000000000..38ab74da9 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/EmbedPage.tsx @@ -0,0 +1,33 @@ +import { AdminProvider } from '@nocobase/client'; +import React, { useEffect } from 'react'; +import { useLocation, useMatch, useNavigate } from 'react-router-dom'; +import { NotAuthorityResult } from './NotAuthorityResult'; +import { EmbedLayout } from './EmbedLayout'; +import { useEmbedToken } from './useEmbedToken'; + +export const EmbedPage = () => { + const embedToken = useEmbedToken(); + const navigate = useNavigate(); + const location = useLocation(); + const match = useMatch('/embed/:name'); + // FIXME + useEffect( + () => () => { + setTimeout(() => { + match && + setTimeout(() => { + window.location.pathname !== location.pathname && navigate('/embed/not-authorized'); + }); + }); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ); + return !embedToken || location.pathname === '/embed/not-authorized' ? ( + + ) : ( + + + + ); +}; diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/EmbedSchemaComponent.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/EmbedSchemaComponent.tsx new file mode 100644 index 000000000..3ba815cf0 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/EmbedSchemaComponent.tsx @@ -0,0 +1,8 @@ +import { RemoteSchemaComponent } from '@nocobase/client'; +import React from 'react'; +import { useParams } from 'react-router-dom'; + +export function EmbedSchemaComponent() { + const params = useParams(); + return ; +} diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/NotAuthorityResult.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/NotAuthorityResult.tsx new file mode 100644 index 000000000..d9af4f2a8 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/NotAuthorityResult.tsx @@ -0,0 +1,6 @@ +import { Result } from 'antd'; +import React from 'react'; + +export function NotAuthorityResult() { + return ; +} diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/index.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/index.tsx new file mode 100644 index 000000000..32eade2f9 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/index.tsx @@ -0,0 +1,18 @@ +import { Plugin } from '@nocobase/client'; +import { usePageSettingsProps } from './usePageSettingsProps'; +import { EmbedSchemaComponent } from './EmbedSchemaComponent'; +import { EmbedPage } from './EmbedPage'; + +const keyEmbed = 'embed'; +const pathEmbed = `/${keyEmbed}`; +export class EmbedPlugin extends Plugin { + async load() { + this.router.add(keyEmbed, { path: pathEmbed, Component: EmbedPage }); + this.router.add(`${keyEmbed}.page`, { path: `${pathEmbed}/:name`, Component: EmbedSchemaComponent }); + this.router.add(`${keyEmbed}.notAuthorized`, { path: `${pathEmbed}/not-authorized`, element: null }); + this.schemaSettingsManager.addItem('PageSettings', keyEmbed, { + type: 'item', + useComponentProps: usePageSettingsProps, + }); + } +} diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/useEmbedToken.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/useEmbedToken.tsx new file mode 100644 index 000000000..aedcb6751 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/useEmbedToken.tsx @@ -0,0 +1,8 @@ +import { useAPIClient } from '@nocobase/client'; + +export function useEmbedToken() { + const url = new URL(window.location.href); + const api = useAPIClient(); + const token = url.searchParams.get('token'); + return token && api.auth.setToken(token), api.auth.getToken(); +} diff --git a/packages/plugins/@hera/plugin-core/src/client/embed/usePageSettingsProps.tsx b/packages/plugins/@hera/plugin-core/src/client/embed/usePageSettingsProps.tsx new file mode 100644 index 000000000..90baa06f5 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/embed/usePageSettingsProps.tsx @@ -0,0 +1,30 @@ +import { useFieldSchema } from '@nocobase/schema'; +import { App } from 'antd'; +import { useMatch } from 'react-router-dom'; +import { useTranslation } from '../locale'; + +export function usePageSettingsProps() { + const isAdmin = useMatch('/admin/:name'); + const isEmbed = useMatch('/embed/:name'); + const currentRoute = isAdmin || isEmbed; + const fieldSchema = useFieldSchema(); + const { message, notification } = App.useApp(); + const { t } = useTranslation(); + return { + title: t('Copy embedded link'), + onClick: () => { + const link = window.location.href + .replace('/admin', '/embed') + .replace(currentRoute.params.name, fieldSchema['x-uid']) + .replace(window.location.search || '', ''); + navigator.clipboard + .writeText(link) + .then(() => { + message.success(t('Copy successful')); + }) + .catch((error) => { + notification.error({ message: t('Copy Failed'), description: error.message, placement: 'topRight' }); + }); + }, + }; +} diff --git a/packages/plugins/@hera/plugin-core/src/client/index.tsx b/packages/plugins/@hera/plugin-core/src/client/index.tsx index c7c91b2fb..646a60c1e 100644 --- a/packages/plugins/@hera/plugin-core/src/client/index.tsx +++ b/packages/plugins/@hera/plugin-core/src/client/index.tsx @@ -74,6 +74,7 @@ import { useCustomPresets1, } from './schema-settings/SchemaSettingsDatePresets'; import { SchemaSettingsSubmitDataType } from './schema-settings/SchemaSettingsSubmitDataType'; +import { EmbedPlugin } from './embed'; export { usePDFViewerRef } from './schema-initializer'; export * from './components/custom-components/custom-components'; @@ -82,6 +83,7 @@ export class PluginCoreClient extends Plugin { async afterAdd() { await this.app.pm.add(GroupBlockPlugin); + await this.app.pm.add(EmbedPlugin); } async registerSettings() {