feat: add iframe-block plugin (#1281)
* feat: iframe-block plugin done * refactor: iframe html filed type changed * refactor: remove built-in actions in the ACL * refactor: use built-in resource action * fix: add iframe-block in built-in plugins * refactor: remove id collection schema * fix: fix iframe-block permission * fix: fix iframe-block permission * fix: improve code * fix: src * fix: bug Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
98bad0c8ea
commit
6d1a4425f2
1
packages/app/client/src/plugins/iframe-block.ts
Normal file
1
packages/app/client/src/plugins/iframe-block.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from '@nocobase/plugin-iframe-block/client';
|
@ -1,66 +0,0 @@
|
||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
||||
import { useDesignable } from '../../hooks';
|
||||
|
||||
export const IframeDesigner = () => {
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { t } = useTranslation();
|
||||
const { dn } = useDesignable();
|
||||
|
||||
return (
|
||||
<GeneralSchemaDesigner>
|
||||
<SchemaSettings.ModalItem
|
||||
title={t('Edit iframe')}
|
||||
schema={
|
||||
{
|
||||
type: 'object',
|
||||
title: t('Edit chart'),
|
||||
properties: {
|
||||
url: {
|
||||
title: t('URL'),
|
||||
type: 'string',
|
||||
default: fieldSchema?.['x-component-props']?.['url'],
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
},
|
||||
height: {
|
||||
title: t('Height'),
|
||||
type: 'string',
|
||||
default: fieldSchema?.['x-component-props']?.height || '60vh',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
} as ISchema
|
||||
}
|
||||
// {{ fetchData(api, { url: 'chartData:get' }) }}
|
||||
onSubmit={async ({ url, height }) => {
|
||||
field.componentProps.url = url;
|
||||
field.componentProps.height = height;
|
||||
const componentProps = fieldSchema['x-component-props'] || {};
|
||||
componentProps['url'] = url;
|
||||
componentProps['height'] = height;
|
||||
fieldSchema['x-component-props'] = componentProps;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
'x-component-props': componentProps,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<SchemaSettings.Divider />
|
||||
<SchemaSettings.Remove
|
||||
removeParentsIfNoChildren
|
||||
breakRemoveOn={{
|
||||
'x-component': 'Grid',
|
||||
}}
|
||||
/>
|
||||
</GeneralSchemaDesigner>
|
||||
);
|
||||
};
|
@ -1,4 +1,2 @@
|
||||
export * from './dnd-context';
|
||||
export * from './iframe';
|
||||
export * from './sortable-item';
|
||||
|
||||
|
@ -164,12 +164,6 @@ export const BlockInitializers = {
|
||||
title: '{{t("Markdown")}}',
|
||||
component: 'MarkdownBlockInitializer',
|
||||
},
|
||||
{
|
||||
key: 'iframe',
|
||||
type: 'item',
|
||||
title: '{{t("Iframe")}}',
|
||||
component: 'IframeBlockInitializer',
|
||||
},
|
||||
{
|
||||
key: 'auditLogs',
|
||||
type: 'item',
|
||||
|
@ -17,7 +17,6 @@ export * from './DetailsBlockInitializer';
|
||||
export * from './FilterActionInitializer';
|
||||
export * from './FormBlockInitializer';
|
||||
export * from './G2PlotInitializer';
|
||||
export * from './IframeBlockInitializer';
|
||||
export * from './InitializerWithSwitch';
|
||||
export * from './KanbanBlockInitializer';
|
||||
export * from './MarkdownBlockInitializer';
|
||||
@ -38,4 +37,3 @@ export * from './TableSelectorInitializer';
|
||||
export * from './UpdateActionInitializer';
|
||||
export * from './UpdateSubmitActionInitializer';
|
||||
export * from './ViewActionInitializer';
|
||||
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
useAPIClient,
|
||||
useCollection,
|
||||
useCompile,
|
||||
useDesignable,
|
||||
useDesignable
|
||||
} from '..';
|
||||
import { useSchemaTemplateManager } from '../schema-templates';
|
||||
import { useBlockTemplateContext } from '../schema-templates/BlockTemplate';
|
||||
@ -574,7 +574,18 @@ SchemaSettings.ActionModalItem = React.memo((props: any) => {
|
||||
});
|
||||
|
||||
SchemaSettings.ModalItem = (props) => {
|
||||
const { hidden, title, components, scope, effects, schema, onSubmit, initialValues, ...others } = props;
|
||||
const {
|
||||
hidden,
|
||||
title,
|
||||
components,
|
||||
scope,
|
||||
effects,
|
||||
schema,
|
||||
onSubmit,
|
||||
asyncGetInitialValues,
|
||||
initialValues,
|
||||
...others
|
||||
} = props;
|
||||
const options = useContext(SchemaOptionsContext);
|
||||
const cm = useContext(CollectionManagerContext);
|
||||
if (hidden) {
|
||||
@ -583,7 +594,8 @@ SchemaSettings.ModalItem = (props) => {
|
||||
return (
|
||||
<SchemaSettings.Item
|
||||
{...others}
|
||||
onClick={() => {
|
||||
onClick={async () => {
|
||||
const values = asyncGetInitialValues ? await asyncGetInitialValues() : initialValues;
|
||||
FormDialog(schema.title || title, () => {
|
||||
return (
|
||||
<CollectionManagerContext.Provider value={cm}>
|
||||
@ -596,7 +608,7 @@ SchemaSettings.ModalItem = (props) => {
|
||||
);
|
||||
})
|
||||
.open({
|
||||
initialValues,
|
||||
initialValues: values,
|
||||
effects,
|
||||
})
|
||||
.then((values) => {
|
||||
|
@ -56,7 +56,8 @@ export function registerMiddlewares(app: Application, options: ApplicationOption
|
||||
|
||||
app.use(async (ctx, next) => {
|
||||
ctx.getBearerToken = () => {
|
||||
return ctx.get('Authorization').replace(/^Bearer\s+/gi, '');
|
||||
const token = ctx.get('Authorization').replace(/^Bearer\s+/gi, '');
|
||||
return token || ctx.query.token;
|
||||
};
|
||||
await next();
|
||||
});
|
||||
|
4
packages/plugins/iframe-block/client.d.ts
vendored
Normal file
4
packages/plugins/iframe-block/client.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// @ts-nocheck
|
||||
export * from './lib/client';
|
||||
export { default } from './lib/client';
|
||||
|
30
packages/plugins/iframe-block/client.js
Normal file
30
packages/plugins/iframe-block/client.js
Normal file
@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
|
||||
var _index = _interopRequireWildcard(require("./lib/client"));
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var _exportNames = {};
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return _index.default;
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(_index).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
||||
if (key in exports && exports[key] === _index[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return _index[key];
|
||||
}
|
||||
});
|
||||
});
|
9
packages/plugins/iframe-block/package.json
Normal file
9
packages/plugins/iframe-block/package.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-iframe-block",
|
||||
"version": "0.8.0-alpha.13",
|
||||
"main": "lib/server/index.js",
|
||||
"devDependencies": {
|
||||
"@nocobase/server": "0.8.0-alpha.13",
|
||||
"@nocobase/test": "0.8.0-alpha.13"
|
||||
}
|
||||
}
|
4
packages/plugins/iframe-block/server.d.ts
vendored
Normal file
4
packages/plugins/iframe-block/server.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// @ts-nocheck
|
||||
export * from './lib/server';
|
||||
export { default } from './lib/server';
|
||||
|
30
packages/plugins/iframe-block/server.js
Normal file
30
packages/plugins/iframe-block/server.js
Normal file
@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
|
||||
var _index = _interopRequireWildcard(require("./lib/server"));
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var _exportNames = {};
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return _index.default;
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(_index).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
||||
if (key in exports && exports[key] === _index[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return _index[key];
|
||||
}
|
||||
});
|
||||
});
|
131
packages/plugins/iframe-block/src/client/Iframe.Designer.tsx
Normal file
131
packages/plugins/iframe-block/src/client/Iframe.Designer.tsx
Normal file
@ -0,0 +1,131 @@
|
||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import { GeneralSchemaDesigner, SchemaSettings, useAPIClient, useDesignable } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const IframeDesigner = () => {
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { t } = useTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const api = useAPIClient();
|
||||
const { mode, url, htmlId, height = '60vh' } = fieldSchema['x-component-props'] || {};
|
||||
|
||||
const saveHtml = async (html: string) => {
|
||||
const options = {
|
||||
values: { html },
|
||||
};
|
||||
if (htmlId) {
|
||||
const { data } = await api.resource('iframeHtml').update?.({ ...options, filterByTk: htmlId });
|
||||
return data?.data?.[0] || { id: htmlId };
|
||||
} else {
|
||||
const { data } = await api.resource('iframeHtml').create?.(options);
|
||||
return data?.data;
|
||||
}
|
||||
};
|
||||
|
||||
const submitHandler = async ({ mode, url, html, height }) => {
|
||||
const componentProps = fieldSchema['x-component-props'] || {};
|
||||
componentProps['mode'] = mode;
|
||||
componentProps['height'] = height;
|
||||
componentProps['url'] = url;
|
||||
if (mode === 'html') {
|
||||
const data = await saveHtml(html);
|
||||
componentProps['htmlId'] = data.id;
|
||||
}
|
||||
fieldSchema['x-component-props'] = componentProps;
|
||||
field.componentProps = { ...componentProps };
|
||||
field.data = { v: uid() };
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
'x-component-props': componentProps,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<GeneralSchemaDesigner>
|
||||
<SchemaSettings.ModalItem
|
||||
title={t('Edit iframe')}
|
||||
asyncGetInitialValues={async () => {
|
||||
const values = {
|
||||
mode,
|
||||
url,
|
||||
height,
|
||||
};
|
||||
if (htmlId) {
|
||||
const { data } = await api.resource('iframeHtml').get?.({ filterByTk: htmlId });
|
||||
values['html'] = data?.data?.html || '';
|
||||
}
|
||||
return values;
|
||||
}}
|
||||
schema={
|
||||
{
|
||||
type: 'object',
|
||||
title: t('Edit iframe'),
|
||||
properties: {
|
||||
mode: {
|
||||
title: '{{t("Mode")}}',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-decorator': 'FormItem',
|
||||
required: true,
|
||||
default: 'url',
|
||||
enum: [
|
||||
{ value: 'url', label: t('URL') },
|
||||
{ value: 'html', label: t('html') },
|
||||
],
|
||||
},
|
||||
url: {
|
||||
title: t('URL'),
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
'x-reactions': {
|
||||
dependencies: ['mode'],
|
||||
fulfill: {
|
||||
state: {
|
||||
hidden: '{{$deps[0] === "html"}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
html: {
|
||||
title: t('html'),
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.TextArea',
|
||||
required: true,
|
||||
'x-reactions': {
|
||||
dependencies: ['mode'],
|
||||
fulfill: {
|
||||
state: {
|
||||
hidden: '{{$deps[0] === "url"}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
height: {
|
||||
title: t('Height'),
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
} as ISchema
|
||||
}
|
||||
onSubmit={submitHandler}
|
||||
/>
|
||||
<SchemaSettings.Divider />
|
||||
<SchemaSettings.Remove
|
||||
removeParentsIfNoChildren
|
||||
breakRemoveOn={{
|
||||
'x-component': 'Grid',
|
||||
}}
|
||||
/>
|
||||
</GeneralSchemaDesigner>
|
||||
);
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
import { observer } from '@formily/react';
|
||||
import { observer, useField } from '@formily/react';
|
||||
import { useAPIClient } from '@nocobase/client';
|
||||
import { Card } from 'antd';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -6,7 +7,7 @@ import RIframe from 'react-iframe';
|
||||
import type { IIframe } from 'react-iframe/types';
|
||||
import { IframeDesigner } from './Iframe.Designer';
|
||||
|
||||
function isNumeric(str: string) {
|
||||
function isNumeric(str: string | undefined) {
|
||||
if (typeof str !== 'string') return false; // we only process strings!
|
||||
return (
|
||||
!isNaN(str as any) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
|
||||
@ -14,15 +15,27 @@ function isNumeric(str: string) {
|
||||
); // ...and ensure strings of whitespace fail
|
||||
}
|
||||
|
||||
export const Iframe: any = observer((props: IIframe) => {
|
||||
const { url, height, ...others } = props;
|
||||
export const Iframe: any = observer((props: IIframe & { html?: string; htmlId?: number; mode: string }) => {
|
||||
const { url, htmlId, mode = 'url', height, html, ...others } = props;
|
||||
|
||||
const { t } = useTranslation();
|
||||
if (!url) {
|
||||
const api = useAPIClient();
|
||||
const field = useField();
|
||||
|
||||
const src = React.useMemo(() => {
|
||||
if (mode === 'html') {
|
||||
return `/api/iframeHtml:getHtml/${htmlId}?token=${api.auth.getToken()}&v=${field.data?.v || ''}`;
|
||||
}
|
||||
return url;
|
||||
}, [url, mode, htmlId, field.data?.v]);
|
||||
|
||||
if ((mode === 'url' && !url) || (mode === 'html' && !htmlId)) {
|
||||
return <Card style={{ marginBottom: 24 }}>{t('Please fill in the iframe URL')}</Card>;
|
||||
}
|
||||
|
||||
return (
|
||||
<RIframe
|
||||
url={url}
|
||||
url={src}
|
||||
width="100%"
|
||||
display="block"
|
||||
position="relative"
|
@ -1,9 +1,8 @@
|
||||
import { FormOutlined } from '@ant-design/icons';
|
||||
import { SchemaInitializer } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SchemaInitializer } from '../SchemaInitializer';
|
||||
|
||||
export const IframeBlockInitializer = (props) => {
|
||||
const { insert } = props;
|
||||
const { t } = useTranslation();
|
@ -0,0 +1,18 @@
|
||||
import { SchemaInitializerContext } from '@nocobase/client';
|
||||
import { useContext } from 'react';
|
||||
|
||||
export const IframeBlockInitializerProvider = (props: any) => {
|
||||
const initializes = useContext(SchemaInitializerContext);
|
||||
const mediaItem = initializes.BlockInitializers.items.find((item) => item.key === 'media');
|
||||
const hasIframeBlockInitializer = mediaItem.children.some(
|
||||
(initialize) => initialize.component === 'IframeBlockInitializer',
|
||||
);
|
||||
!hasIframeBlockInitializer &&
|
||||
mediaItem.children.push({
|
||||
key: 'iframe',
|
||||
type: 'item',
|
||||
title: '{{t("Iframe")}}',
|
||||
component: 'IframeBlockInitializer',
|
||||
});
|
||||
return props.children;
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
import { SchemaComponentOptions } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { Iframe } from './Iframe';
|
||||
import { IframeBlockInitializer } from './IframeBlockInitializer';
|
||||
import { IframeBlockInitializerProvider } from './IframeBlockInitializerProvider';
|
||||
|
||||
export const IframeBlockPlugin = (props: any) => {
|
||||
return (
|
||||
<SchemaComponentOptions components={{ Iframe, IframeBlockInitializer }}>
|
||||
<IframeBlockInitializerProvider>{props.children}</IframeBlockInitializerProvider>
|
||||
</SchemaComponentOptions>
|
||||
);
|
||||
};
|
1
packages/plugins/iframe-block/src/client/index.ts
Normal file
1
packages/plugins/iframe-block/src/client/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { IframeBlockPlugin as default } from './IframeBlockPlugin';
|
1
packages/plugins/iframe-block/src/index.ts
Normal file
1
packages/plugins/iframe-block/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './server';
|
17
packages/plugins/iframe-block/src/server/actions/index.ts
Normal file
17
packages/plugins/iframe-block/src/server/actions/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Context, Next } from '@nocobase/actions';
|
||||
import { Repository } from '@nocobase/database';
|
||||
|
||||
export async function getHtml(ctx: Context, next: Next) {
|
||||
let { filterByTk } = ctx.action.params;
|
||||
const { resourceName } = ctx.action;
|
||||
const repository = ctx.db.getRepository<any>(resourceName) as Repository;
|
||||
const model = await repository.findById(filterByTk);
|
||||
ctx.body = model.get('html');
|
||||
ctx.withoutDataWrapping = true;
|
||||
|
||||
ctx.set({
|
||||
'Content-Type': 'text/html; charset=UTF-8',
|
||||
});
|
||||
|
||||
await next();
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import { CollectionOptions } from '@nocobase/database';
|
||||
|
||||
export default {
|
||||
name: 'iframeHtml',
|
||||
createdBy: true,
|
||||
updatedBy: true,
|
||||
fields: [
|
||||
{
|
||||
type: 'uid',
|
||||
name: 'id',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'html',
|
||||
},
|
||||
],
|
||||
} as CollectionOptions;
|
1
packages/plugins/iframe-block/src/server/index.ts
Normal file
1
packages/plugins/iframe-block/src/server/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './plugin';
|
30
packages/plugins/iframe-block/src/server/plugin.ts
Normal file
30
packages/plugins/iframe-block/src/server/plugin.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { InstallOptions, Plugin } from '@nocobase/server';
|
||||
import path from 'path';
|
||||
import { getHtml } from './actions';
|
||||
|
||||
export class IframeBlockPlugin extends Plugin {
|
||||
afterAdd() {}
|
||||
|
||||
beforeLoad() {}
|
||||
|
||||
async load() {
|
||||
await this.db.import({
|
||||
directory: path.resolve(__dirname, 'collections'),
|
||||
});
|
||||
this.app.acl.allow('iframeHtml', ['get', 'create', 'update', 'destroy'], 'allowConfigure');
|
||||
this.app.acl.allow('iframeHtml', 'getHtml', 'loggedIn');
|
||||
this.app.actions({
|
||||
'iframeHtml:getHtml': getHtml,
|
||||
});
|
||||
}
|
||||
|
||||
async install(options?: InstallOptions) {}
|
||||
|
||||
async afterEnable() {}
|
||||
|
||||
async afterDisable() {}
|
||||
|
||||
async remove() {}
|
||||
}
|
||||
|
||||
export default IframeBlockPlugin;
|
@ -31,6 +31,7 @@
|
||||
"@nocobase/plugin-verification": "0.8.0-alpha.13",
|
||||
"@nocobase/plugin-workflow": "0.8.0-alpha.13",
|
||||
"@nocobase/plugin-map": "0.8.0-alpha.13",
|
||||
"@nocobase/plugin-iframe-block": "0.8.0-alpha.13",
|
||||
"@nocobase/server": "0.8.0-alpha.13"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -23,6 +23,7 @@ export class PresetNocoBase extends Plugin {
|
||||
'export',
|
||||
'import',
|
||||
'audit-logs',
|
||||
'iframe-block',
|
||||
].concat(plugins),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user