diff --git a/packages/plugins/@hera/plugin-websocket/.npmignore b/packages/plugins/@hera/plugin-websocket/.npmignore new file mode 100644 index 000000000..65f5e8779 --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/.npmignore @@ -0,0 +1,2 @@ +/node_modules +/src diff --git a/packages/plugins/@hera/plugin-websocket/README.md b/packages/plugins/@hera/plugin-websocket/README.md new file mode 100644 index 000000000..2c1048977 --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/README.md @@ -0,0 +1 @@ +# @hera/plugin-websocket diff --git a/packages/plugins/@hera/plugin-websocket/client.d.ts b/packages/plugins/@hera/plugin-websocket/client.d.ts new file mode 100644 index 000000000..6c459cbac --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/client.d.ts @@ -0,0 +1,2 @@ +export * from './dist/client'; +export { default } from './dist/client'; diff --git a/packages/plugins/@hera/plugin-websocket/client.js b/packages/plugins/@hera/plugin-websocket/client.js new file mode 100644 index 000000000..b6e3be70e --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/client.js @@ -0,0 +1 @@ +module.exports = require('./dist/client/index.js'); diff --git a/packages/plugins/@hera/plugin-websocket/package.json b/packages/plugins/@hera/plugin-websocket/package.json new file mode 100644 index 000000000..3b068656d --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/package.json @@ -0,0 +1,18 @@ +{ + "name": "@hera/plugin-websocket", + "version": "0.0.1", + "main": "dist/server/index.js", + "dependencies": {}, + "devDependencies": { + "react-use-websocket": "^4.8.1", + "@formily/antd-v5": "1.x", + "@formily/core": "^2.2.27", + "@formily/react": "^2.2.27", + "@formily/shared": "^2.2.27" + }, + "peerDependencies": { + "@nocobase/client": "0.x", + "@nocobase/server": "0.x", + "@nocobase/test": "0.x" + } +} \ No newline at end of file diff --git a/packages/plugins/@hera/plugin-websocket/server.d.ts b/packages/plugins/@hera/plugin-websocket/server.d.ts new file mode 100644 index 000000000..c41081ddc --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/server.d.ts @@ -0,0 +1,2 @@ +export * from './dist/server'; +export { default } from './dist/server'; diff --git a/packages/plugins/@hera/plugin-websocket/server.js b/packages/plugins/@hera/plugin-websocket/server.js new file mode 100644 index 000000000..972842039 --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/server.js @@ -0,0 +1 @@ +module.exports = require('./dist/server/index.js'); diff --git a/packages/plugins/@hera/plugin-websocket/src/client/index.tsx b/packages/plugins/@hera/plugin-websocket/src/client/index.tsx new file mode 100644 index 000000000..d64f1362c --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/src/client/index.tsx @@ -0,0 +1,14 @@ +import { Plugin } from '@nocobase/client'; +import { WebsocketBlockHelper } from './schema-initializer/WebsocketBlockInitializer'; + +export class PluginWebsocketClient extends Plugin { + async afterAdd() {} + + async beforeLoad() {} + + async load() { + await new WebsocketBlockHelper(this.app).load(); + } +} + +export default PluginWebsocketClient; diff --git a/packages/plugins/@hera/plugin-websocket/src/client/schema-initializer/WebsocketBlockInitializer.tsx b/packages/plugins/@hera/plugin-websocket/src/client/schema-initializer/WebsocketBlockInitializer.tsx new file mode 100644 index 000000000..dabfe0ec6 --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/src/client/schema-initializer/WebsocketBlockInitializer.tsx @@ -0,0 +1,143 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { PrinterOutlined } from '@ant-design/icons'; +import { + Application, + SchemaInitializer, + SchemaInitializerItem, + SchemaSettings, + SchemaToolbar, + useSchemaInitializer, + useSchemaInitializerItem, +} from '@nocobase/client'; +import useWebSocket, { ReadyState } from 'react-use-websocket'; +import { useFieldSchema } from '@formily/react'; + +export class WebsocketBlockHelper { + constructor(private app: Application) {} + async load() { + this.app.schemaInitializerManager.addItem('page:addBlock', 'dataBlocks.groupBlock', { + title: 'Websocket', + Component: 'WebsocketBlockInitializer', + }); + this.app.schemaSettingsManager.add(websocketBlockSettings); + this.app.schemaInitializerManager.add(WebsocketActionInitializer); + this.app.addComponents({ + WebsocketBlockInitializer, + WebsocketBlockToolbar, + WebsocketBlock, + }); + const WebsocketBlockItem = { + title: 'Websocket', + name: 'websocketBlock', + Component: 'WebsocketBlockInitializer', + type: 'item', + }; + this.app.schemaInitializerManager.get('popup:common:addBlock').add(WebsocketBlockItem.name, WebsocketBlockItem); + } +} + +const WebsocketBlock: React.FC = () => { + //Public API that will echo messages sent to it back to the client + const [socketUrl, setSocketUrl] = useState('wss://echo.websocket.org'); + const [messageHistory, setMessageHistory] = useState[]>([]); + + const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl); + + useEffect(() => { + if (lastMessage !== null) { + setMessageHistory((prev) => prev.concat(lastMessage)); + } + }, [lastMessage]); + + const handleClickChangeSocketUrl = useCallback(() => setSocketUrl('wss://demos.kaazing.com/echo'), []); + + const handleClickSendMessage = useCallback(() => sendMessage('Hello'), []); + + const connectionStatus = { + [ReadyState.CONNECTING]: 'Connecting', + [ReadyState.OPEN]: 'Open', + [ReadyState.CLOSING]: 'Closing', + [ReadyState.CLOSED]: 'Closed', + [ReadyState.UNINSTANTIATED]: 'Uninstantiated', + }[readyState]; + + return ( +
+ + + The WebSocket is currently {connectionStatus} + {lastMessage ? Last message: {lastMessage.data} : null} + +
+ ); +}; + +const WebsocketActionInitializer = new SchemaInitializer({ + name: 'WebsocketActionInitializer', + title: 'Configure actions', + icon: 'SettingOutlined', + style: { + marginLeft: 8, + }, + items: [ + { + name: 'enbaleActions', + type: 'itemGroup', + title: 'Enable actions', + children: [], + }, + ], +}); + +const WebsocketBlockInitializer = () => { + const { insert } = useSchemaInitializer(); + const itemConfig = useSchemaInitializerItem(); + return ( + } + onClick={() => { + insert({ + type: 'void', + 'x-toolbar': 'WebsocketBlockToolbar', + 'x-settings': 'websocketBlockSettings', + 'x-component': 'CardItem', + properties: { + actions: { + type: 'void', + 'x-initializer': 'WebsocketActionInitializer', + 'x-component': 'ActionBar', + 'x-component-props': {}, + properties: {}, + }, + viewer: { + type: 'void', + 'x-component': 'WebsocketBlock', + }, + }, + }); + }} + /> + ); +}; + +export const websocketBlockSettings = new SchemaSettings({ + name: 'websocketBlockSettings', + items: [ + { + name: 'remove', + type: 'remove', + }, + ], +}); + +export const WebsocketBlockToolbar = (props) => { + const fieldSchema = useFieldSchema(); + return ; +}; diff --git a/packages/plugins/@hera/plugin-websocket/src/index.ts b/packages/plugins/@hera/plugin-websocket/src/index.ts new file mode 100644 index 000000000..7e74612df --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/src/index.ts @@ -0,0 +1,2 @@ +export * from './server'; +export { default } from './server'; diff --git a/packages/plugins/@hera/plugin-websocket/src/server/collections/.gitkeep b/packages/plugins/@hera/plugin-websocket/src/server/collections/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@hera/plugin-websocket/src/server/index.ts b/packages/plugins/@hera/plugin-websocket/src/server/index.ts new file mode 100644 index 000000000..b68aea57f --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/src/server/index.ts @@ -0,0 +1 @@ +export { default } from './plugin'; diff --git a/packages/plugins/@hera/plugin-websocket/src/server/plugin.ts b/packages/plugins/@hera/plugin-websocket/src/server/plugin.ts new file mode 100644 index 000000000..521f3ded5 --- /dev/null +++ b/packages/plugins/@hera/plugin-websocket/src/server/plugin.ts @@ -0,0 +1,19 @@ +import { Plugin } from '@nocobase/server'; + +export class PluginWebsocketServer extends Plugin { + async afterAdd() {} + + async beforeLoad() {} + + async load() {} + + async install() {} + + async afterEnable() {} + + async afterDisable() {} + + async remove() {} +} + +export default PluginWebsocketServer; diff --git a/yarn.lock b/yarn.lock index 05142f270..44cb85307 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18023,7 +18023,22 @@ matchdep@^2.0.0: resolve "^1.4.0" stack-trace "0.0.10" -"mathjs2@npm:mathjs@^10.6.0", mathjs@^10.6.0, mathjs@^10.6.1: +"mathjs2@npm:mathjs@^10.6.0": + version "10.6.4" + resolved "https://registry.npmmirror.com/mathjs/-/mathjs-10.6.4.tgz#1b87a1268781d64f0c8b4e5e1b36cf7ecf58bb05" + integrity sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA== + dependencies: + "@babel/runtime" "^7.18.6" + complex.js "^2.1.1" + decimal.js "^10.3.1" + escape-latex "^1.2.0" + fraction.js "^4.2.0" + javascript-natural-sort "^0.7.1" + seedrandom "^3.0.5" + tiny-emitter "^2.1.0" + typed-function "^2.1.0" + +mathjs@^10.6.0, mathjs@^10.6.1: version "10.6.4" resolved "https://registry.npmmirror.com/mathjs/-/mathjs-10.6.4.tgz#1b87a1268781d64f0c8b4e5e1b36cf7ecf58bb05" integrity sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA== @@ -22633,6 +22648,11 @@ react-to-print@^2.14.7: resolved "https://registry.npmmirror.com/react-to-print/-/react-to-print-2.14.15.tgz#edb4ce8a92205cf37fd8c3d57de829034aa5c911" integrity sha512-SKnwOzU2cJ8eaAkoJO7+gNhvfEDmm+Y34IdcHsjtHioUevUPhprqbVtvNJlZ2JkGJ8ExK2QNWM9pXECTDR5D8w== +react-use-websocket@^4.8.1: + version "4.8.1" + resolved "https://registry.npmmirror.com/react-use-websocket/-/react-use-websocket-4.8.1.tgz#be06a0bc956c6d56391a29cbe2caa6ae8edb5615" + integrity sha512-FTXuG5O+LFozmu1BRfrzl7UIQngECvGJmL7BHsK4TYXuVt+mCizVA8lT0hGSIF0Z0TedF7bOo1nRzOUdginhDw== + react@18.*, react@18.1.0, react@18.x, react@^18.0.0, react@^18.2.0: version "18.2.0" resolved "https://registry.npmmirror.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"