diff --git a/.eslintrc.js b/.eslintrc.js index f1b6c7b..b22d43b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -31,6 +31,16 @@ module.exports = { '@typescript-eslint/indent': 0, 'import/no-cycle': 0, '@typescript-eslint/no-shadow': 0, - 'max-len': ["error", {"code": 180}] - } + 'max-len': ['error', { code: 180 }], + 'comma-dangle': [ + 'warn', + { + objects: 'always', + arrays: 'always', + imports: 'never', + functions: 'never', + }, + ], + semi: ['error', 'always'], + }, }; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c644ba5..281c877 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,13 +2,19 @@ # These owners will be the default owners for everything in # the repo. Unless a later match takes precedence -* @leoyuan @alvarto +* @liujuping @JackLian @alvarto /packages/plugin-manual/ @alvarto -/packages/base-monaco-editor/ @alvarto @wangshihao111 -/packages/plugin-code-editor/ @alvarto +/packages/base-monaco-editor/ @alvarto @wangshihao111 @SuSunSam +/packages/plugin-code-editor/ @alvarto @SuSunSam /packages/plugin-schema/ @alvarto -/packages/plugin-components-pane/ @mark-ck -/packages/plugin-datasource-pane/ @xingmolu -/packages/plugin-zh-en/ @leoyuan -/packages/plugin-undo-redo/ @leoyuan +/packages/plugin-components-pane/ @mark-ck @love999262 +/packages/plugin-datasource-pane/ @YSMJ1994 +/packages/plugin-zh-en/ @JackLian @liujuping +/packages/plugin-undo-redo/ @JackLian @liujuping +/packages/plugin-resource-tabs/ @JackLian @liujuping +/packages/plugin-set-ref-prop/ @JackLian @liujuping +/packages/plugin-view-manager-pane/ @JackLian @liujuping +/packages/base-monaco-editor/ @hzd822 +/packages/plugin-multiple-editor/ @hzd822 +/packages/action-block @liujuping \ No newline at end of file diff --git a/.github/workflows/deprecate npm.yml b/.github/workflows/deprecate npm.yml new file mode 100644 index 0000000..ea096ec --- /dev/null +++ b/.github/workflows/deprecate npm.yml @@ -0,0 +1,32 @@ +name: deprecate Package Version + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to be deleted package@version' + required: true + +jobs: + delete-package-version: + runs-on: ubuntu-latest + if: >- + github.ref == 'refs/heads/main' && + (github.actor == 'JackLian' || github.actor == 'liujuping') + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '14' + + - name: deprecate Package Version + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + npm deprecate ${{ github.event.inputs.version }} "This version is deprecated. Please consider upgrading to a newer version." diff --git a/.github/workflows/publish beta npm.yml b/.github/workflows/publish beta npm.yml new file mode 100644 index 0000000..01ab685 --- /dev/null +++ b/.github/workflows/publish beta npm.yml @@ -0,0 +1,38 @@ +name: Publish Beta NPM Packages +on: + workflow_dispatch: + inputs: + packagePath: + description: 'Path to the package (e.g., action-block)' + required: true + betaVersion: + description: 'Beta version number (e.g., 1.0.1-beta.0)' + required: true + +jobs: + publish-package: + runs-on: ubuntu-latest + if: >- + github.actor == 'JackLian' || github.actor == 'liujuping' + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' # 或者您希望的任何版本 + + - name: Change to Package Directory + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + npm install --legacy-peer-deps + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + cd packages/${{ github.event.inputs.packagePath }} + npm install --legacy-peer-deps + npm run build + npm version ${{ github.event.inputs.betaVersion }} + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + npm publish --tag beta \ No newline at end of file diff --git a/.github/workflows/publish npm.yml b/.github/workflows/publish npm.yml new file mode 100644 index 0000000..5ada959 --- /dev/null +++ b/.github/workflows/publish npm.yml @@ -0,0 +1,51 @@ +name: Publish NPM Packages +on: + workflow_dispatch: + inputs: + packagePath: + description: 'Path to the package (e.g., action-block)' + required: true + versionType: + description: 'Version update type (major, minor, patch)' + required: true + default: 'patch' + +jobs: + publish-package: + runs-on: ubuntu-latest + if: >- + github.ref == 'refs/heads/main' && + (github.actor == 'JackLian' || github.actor == 'liujuping') + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' # 或者您希望的任何版本 + + - name: Publish Package + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + npm install --legacy-peer-deps + cd packages/${{ github.event.inputs.packagePath }} + npm install --legacy-peer-deps + npm version ${{ github.event.inputs.versionType }} + npm run build + + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + npm publish + + echo "PACKAGE_NAME=$(node -p "require('./package.json').name")" >> $GITHUB_ENV + echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + + git add package.json + git commit -m "Bump version to ${PACKAGE_VERSION}" + + git tag -a "${PACKAGE_NAME}@${PACKAGE_VERSION}" -m "Release ${PACKAGE_NAME} version ${PACKAGE_VERSION}" + git push origin "${PACKAGE_NAME}@${PACKAGE_VERSION}" \ No newline at end of file diff --git a/demo/build.json b/demo/build.json deleted file mode 100644 index 11f88e5..0000000 --- a/demo/build.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "entry": { - "index": "src/index" - }, - "vendor": false, - "devServer": { - "hot": false - }, - "publicPath": "public", - "externals": { - "react": "var window.React", - "react-dom": "var window.ReactDOM", - "prop-types": "var window.PropTypes", - "@alifd/next": "var window.Next", - "@alilc/lowcode-engine": "var window.AliLowCodeEngine", - "@alilc/lowcode-editor-core": "var window.AliLowCodeEngine.common.editorCabin", - "@alilc/lowcode-editor-skeleton": "var window.AliLowCodeEngine.common.skeletonCabin", - "@alilc/lowcode-designer": "var window.AliLowCodeEngine.common.designerCabin", - "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", - "@ali/lowcode-engine": "var window.AliLowCodeEngine", - "moment": "var window.moment", - "lodash": "var window._" - }, - "plugins": [ - [ - "build-plugin-react-app" - ], - [ - "build-plugin-moment-locales", - { - "locales": [ - "zh-cn" - ] - } - ], - "./build.plugin.js" - ] -} diff --git a/demo/build.plugin.js b/demo/build.plugin.js deleted file mode 100644 index 12882de..0000000 --- a/demo/build.plugin.js +++ /dev/null @@ -1,58 +0,0 @@ -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); - -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = ({ onGetWebpackConfig }) => { - onGetWebpackConfig((config) => { - config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [ - { - configFile: './tsconfig.json', - }, - ]); - - config.merge({ - node: { - fs: 'empty', - }, - }); - config.merge({ - entry: { - index: require.resolve('./src/index.ts'), - preview: require.resolve('./src/preview.tsx'), - }, - }); - config - .plugin('index') - .use(HtmlWebpackPlugin, [ - { - inject: false, - templateParameters: { - }, - template: require.resolve('./public/index.html'), - filename: 'index.html', - }, - ]); - config - .plugin('preview') - .use(HtmlWebpackPlugin, [ - { - inject: false, - templateParameters: { - }, - template: require.resolve('./public/preview.html'), - filename: 'preview.html', - }, - ]); - - config.plugins.delete('hot'); - config.devServer.hot(false); - - config.module // fixes https://github.com/graphql/graphql-js/issues/1272 - .rule('mjs$') - .test(/\.mjs$/) - .include - .add(/node_modules/) - .end() - .type('javascript/auto'); - }); -}; diff --git a/demo/package.json b/demo/package.json deleted file mode 100644 index 6d61e11..0000000 --- a/demo/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@alilc/lowcode-plugins-demo", - "version": "1.0.0", - "description": "Low-Code Engine 低代码搭建引擎 Demo 项目", - "repository": "git@github.com:alibaba/lowcode-demo.git", - "license": "MIT", - "main": "index.js", - "scripts": { - "start": "build-scripts start --disable-reload", - "build": "build-scripts build", - "pub": "node ./scripts/watchdog.js && npm pub" - }, - "files": [ - "build" - ], - "config": {}, - "dependencies": { - "@alilc/lowcode-plugin-code-editor": "^1.0.1", - "@alilc/lowcode-plugin-code-generator": "^1.0.1", - "@alilc/lowcode-plugin-components-pane": "^1.0.2", - "@alilc/lowcode-plugin-datasource-pane": "1.0.0", - "@alilc/lowcode-plugin-inject": "^1.0.0", - "@alilc/lowcode-plugin-manual": "^1.0.0", - "@alilc/lowcode-plugin-schema": "^1.0.0", - "@alilc/lowcode-plugin-simulator-select": "^1.0.0", - "@alilc/lowcode-plugin-undo-redo": "^1.0.0", - "@alilc/lowcode-plugin-zh-en": "^1.0.0", - "@alilc/lowcode-react-renderer": "^1.0.0", - "@alilc/lowcode-setter-behavior": "^1.0.0", - "@alilc/lowcode-setter-title": "^1.0.2" - }, - "devDependencies": { - "@alilc/lowcode-engine": "^1.0.0", - "@alilc/lowcode-types": "^1.0.0", - "@alib/build-scripts": "^0.1.18", - "@types/events": "^3.0.0", - "@types/react": "^16.8.3", - "@types/react-dom": "^16.8.2", - "@types/streamsaver": "^2.0.0", - "build-plugin-fusion": "^0.1.0", - "build-plugin-moment-locales": "^0.1.0", - "build-plugin-react-app": "^1.1.2", - "tsconfig-paths-webpack-plugin": "^3.2.0" - } -} diff --git a/demo/public/favicon.png b/demo/public/favicon.png deleted file mode 100644 index 307ffbd..0000000 Binary files a/demo/public/favicon.png and /dev/null differ diff --git a/demo/public/index.html b/demo/public/index.html deleted file mode 100644 index 9695d3d..0000000 --- a/demo/public/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - 阿里低代码引擎 Demo - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/demo/public/mock-pages.json b/demo/public/mock-pages.json deleted file mode 100644 index 8e20f2f..0000000 --- a/demo/public/mock-pages.json +++ /dev/null @@ -1 +0,0 @@ -{"success":true,"content":[{"gmtModified":"2021-03-06 00:40:54","formUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentNavUuid":"NAV-SYSTEM-PARENT-UUID","hidden":"n","navUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","navType":"PAGE","isIndex":"n","isNew":"n","gmtCreate":"2021-03-06 00:27:26","title":{"en_US":"页面1","zh_CN":"页面1","type":"i18n"},"relateUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentId":0,"listOrder":0,"id":556103}]} \ No newline at end of file diff --git a/demo/public/mock/info.json b/demo/public/mock/info.json deleted file mode 100644 index 006209b..0000000 --- a/demo/public/mock/info.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "info": "Hello AliLowCode!!" -} \ No newline at end of file diff --git a/demo/public/preview.html b/demo/public/preview.html deleted file mode 100644 index 798b156..0000000 --- a/demo/public/preview.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 预览低代码 - - - - -
- - - - - - - - - - diff --git a/demo/src/index.ts b/demo/src/index.ts deleted file mode 100644 index 4607725..0000000 --- a/demo/src/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { init } from '@alilc/lowcode-engine'; -import registerPlugins from './universal/plugin'; -import './universal/global.scss'; - - -const preference = new Map(); -preference.set('DataSourcePane', { - importPlugins: [], - dataSourceTypes: [ - { - type: 'fetch' - }, - { - type: 'jsonp', - } - ] -}); - -(async function main() { - await registerPlugins(); - - init(document.getElementById('lce-container')!, { - // designMode: 'live', - // locale: 'zh-CN', - enableCondition: true, - enableCanvasLock: true, - // 默认绑定变量 - supportVariableGlobally: true, - // simulatorUrl 在当 engine-core.js 同一个路径下时是不需要配置的!!! - // 这里因为用的是 unpkg,在不同 npm 包,engine-core.js 和 react-simulator-renderer.js 是不同路径 - simulatorUrl: [ - 'https://alifd.alicdn.com/npm/@alilc/lowcode-react-simulator-renderer@beta/dist/css/react-simulator-renderer.css', - 'https://alifd.alicdn.com/npm/@alilc/lowcode-react-simulator-renderer@beta/dist/js/react-simulator-renderer.js' - ] - }, preference); -})(); diff --git a/demo/src/preview.tsx b/demo/src/preview.tsx deleted file mode 100644 index 27627ff..0000000 --- a/demo/src/preview.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import ReactDOM from 'react-dom'; -import React, { useState } from 'react'; -import { Loading } from '@alifd/next'; -import { buildComponents, assetBundle, AssetLevel, AssetLoader } from '@alilc/lowcode-utils'; -import ReactRenderer from '@alilc/lowcode-react-renderer'; -import { injectComponents } from '@alilc/lowcode-plugin-inject'; - -const SamplePreview = () => { - const [data, setData] = useState({}); - - async function init() { - const packages = JSON.parse(window.localStorage.getItem('packages') || ''); - const projectSchema = JSON.parse(window.localStorage.getItem('projectSchema') || ''); - const { componentsMap: componentsMapArray, componentsTree } = projectSchema; - const componentsMap: any = {}; - componentsMapArray.forEach((component: any) => { - componentsMap[component.componentName] = component; - }); - const schema = componentsTree[0]; - - const libraryMap = {}; - const libraryAsset = []; - packages.forEach(({ package: _package, library, urls, renderUrls }) => { - libraryMap[_package] = library; - if (renderUrls) { - libraryAsset.push(renderUrls); - } else if (urls) { - libraryAsset.push(urls); - } - }); - - const vendors = [assetBundle(libraryAsset, AssetLevel.Library)]; - - // TODO asset may cause pollution - const assetLoader = new AssetLoader(); - await assetLoader.load(libraryAsset); - const components = await injectComponents(buildComponents(libraryMap, componentsMap)); - - setData({ - schema, - components, - }); - } - - const { schema, components } = data; - - if (!schema || !components) { - init(); - return ; - } - - return ( -
- -
- ); -}; - -ReactDOM.render(, document.getElementById('ice-container')); diff --git a/demo/src/universal/global.scss b/demo/src/universal/global.scss deleted file mode 100644 index 02906a3..0000000 --- a/demo/src/universal/global.scss +++ /dev/null @@ -1,55 +0,0 @@ -body { - font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma, Arial, PingFang SC-Light, Microsoft YaHei; - font-size: 12px; - * { - box-sizing: border-box; - } -} - -body, #lce-container { - position: fixed; - left: 0; - right: 0; - bottom: 0; - top: 0; - box-sizing: border-box; - padding: 0; - margin: 0; - overflow: hidden; - text-rendering: optimizeLegibility; - -webkit-user-select: none; - -webkit-user-drag: none; - -webkit-text-size-adjust: none; - -webkit-touch-callout: none; - -webkit-font-smoothing: antialiased; - #engine { - width: 100%; - height: 100%; - } -} - -html { - min-width: 1024px; -} - -.save-sample { - width: 80px; - height: 30px; - background-color: #5584FF; - border: none; - outline: none; - border-radius: 4px; - color: white; - cursor: pointer; -} - -.load-assets { - width: 100px; - height: 30px; - background-color: #5584FF; - border: none; - outline: none; - border-radius: 4px; - color: white; - cursor: pointer; -} diff --git a/demo/tsconfig.json b/demo/tsconfig.json deleted file mode 100644 index 23314ab..0000000 --- a/demo/tsconfig.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "declaration": true, - "lib": ["es2015", "dom"], - // Target latest version of ECMAScript. - "target": "esnext", - // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. - "module": "esnext", - // Search under node_modules for non-relative imports. - "moduleResolution": "node", - // Process & infer types from .js files. - "allowJs": true, - // Report errors in .js files. - "checkJs": false, - // Don't emit; allow Babel to transform files. - // "noEmit": true, - // Enable strictest settings like strictNullChecks & noImplicitAny. - "strict": true, - // Allow default imports from modules with no default export. This does not affect code emit, just typechecking. - "allowSyntheticDefaultImports": true, - // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. - "esModuleInterop": true, - // Specify JSX code generation: 'preserve', 'react-native', or 'react'. - "jsx": "preserve", - // Import emit helpers (e.g. __extends, __rest, etc..) from tslib - "importHelpers": true, - // Enables experimental support for ES7 decorators. - "experimentalDecorators": true, - // Generates corresponding .map file. - "sourceMap": true, - // Disallow inconsistently-cased references to the same file. - "forceConsistentCasingInFileNames": true, - // Allow json import - "resolveJsonModule": true, - // skip type checking of declaration files - "skipLibCheck": true, - "outDir": "lib" - }, - "include": [ - "./src/" - ], - "exclude": ["**/test", "**/lib", "**/es", "node_modules"] -} diff --git a/package.json b/package.json index 58231d4..761e9e0 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,9 @@ } }, "devDependencies": { - "lerna": "^4.x", "f2elint": "^2.0.1", "husky": "^7.0.4", + "lerna": "^4.x", "typescript": "^3.2.2" }, "engines": { @@ -54,5 +54,6 @@ }, "resolutions": { "@builder/babel-preset-ice": "1.0.1" - } -} + }, + "repository": "https://github.com/alibaba/lowcode-plugins.git" +} \ No newline at end of file diff --git a/packages/action-block/.gitignore b/packages/action-block/.gitignore deleted file mode 100644 index 77dfbd1..0000000 --- a/packages/action-block/.gitignore +++ /dev/null @@ -1,104 +0,0 @@ -# project custom -build -dist -lib -es -package-lock.json -yarn.lock -deploy-space/packages -deploy-space/.env - - -# IDE -.vscode -.idea - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release -lib - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# mac config files -.DS_Store - -# codealike -codealike.json diff --git a/packages/action-block/package.json b/packages/action-block/package.json index 25e37fa..e9c0c00 100644 --- a/packages/action-block/package.json +++ b/packages/action-block/package.json @@ -1,8 +1,13 @@ { "name": "@alilc/action-block", - "version": "1.0.0-beta.0", + "version": "1.0.1", "description": "", "main": "lib/index.js", + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/action-block" + }, "scripts": { "start": "build-scripts start", "build": "build-scripts build", @@ -22,5 +27,5 @@ "build-plugin-fusion": "^0.1.22", "build-plugin-moment-locales": "^0.1.3" }, - "homepage": "https://unpkg.com/@alilc/action-block@1.0.0-beta.0/build/index.html" + "homepage": "https://unpkg.com/@alilc/action-block@1.0.1/build/index.html" } diff --git a/packages/action-block/src/index.tsx b/packages/action-block/src/index.tsx index 02e69eb..22eaa46 100644 --- a/packages/action-block/src/index.tsx +++ b/packages/action-block/src/index.tsx @@ -30,7 +30,7 @@ const SaveAsBlock = (props: SaveAsBlockProps) => { React.useEffect(() => { const generateImage = async () => { let dom2 = node.getDOMNode(); - console.log('html2canvas: ', html2canvas); + // console.log('html2canvas: ', html2canvas); const canvas = await html2canvas?.(dom2, { scale: 0.5 }); const dataUrl = canvas.toDataURL(); setSrc(dataUrl); @@ -106,7 +106,7 @@ export default { }, title: '新增', action(node: Node) { - console.log('node: ', node); + // console.log('node: ', node); dialog = Dialog.show({ v2: true, title: "保存为区块", @@ -116,4 +116,4 @@ export default { }, }, important: true, -}; \ No newline at end of file +}; diff --git a/packages/base-monaco-editor/package.json b/packages/base-monaco-editor/package.json index bbbf077..6dfa41a 100644 --- a/packages/base-monaco-editor/package.json +++ b/packages/base-monaco-editor/package.json @@ -1,8 +1,9 @@ { "name": "@alilc/lowcode-plugin-base-monaco-editor", - "version": "1.1.1", + "version": "1.1.2", "description": "代码编辑组件,monaco-editor 的低代码适配封装", "publishConfig": { + "registry": "https://registry.npmjs.org/", "access": "public" }, "files": [ @@ -62,5 +63,10 @@ "commit-msg": "f2elint commit-msg-scan" } }, - "homepage": "https://unpkg.com/@alilc/lowcode-plugin-base-monaco-editor@1.1.1/build/index.html" + "homepage": "https://unpkg.com/@alilc/lowcode-plugin-base-monaco-editor@1.1.2/build/index.html", + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/base-monaco-editor" + } } diff --git a/packages/base-monaco-editor/src/helper.ts b/packages/base-monaco-editor/src/helper.ts index 614ee8d..5180c52 100644 --- a/packages/base-monaco-editor/src/helper.ts +++ b/packages/base-monaco-editor/src/helper.ts @@ -44,6 +44,7 @@ export interface IGeneralManacoEditorProps { enableOutline?: boolean; /** style of wrapper */ style?: CSSProperties; + overrideServices?: oEditor.IEditorOverrideServices; enhancers?: EditorEnhancer[]; } @@ -113,7 +114,7 @@ const DIFF_EDITOR_INITIAL_OPTIONS: oEditor.IStandaloneDiffEditorConstructionOpti export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorProps) => { const { - editorDidMount, editorWillMount, theme, value, path, language, saveViewState, defaultValue, enhancers, + editorDidMount, editorWillMount, theme, value, path, language, saveViewState, defaultValue, enhancers, overrideServices } = props; const [isEditorReady, setIsEditorReady] = useState(false); @@ -196,7 +197,7 @@ export const useEditor = (type: 'single' | 'diff', props: I automaticLayout: true, ...INITIAL_OPTIONS, ...optionRef.current, - }); + }, overrideServices); editor.setModel(model); } else { const originalModel = monaco @@ -211,7 +212,7 @@ export const useEditor = (type: 'single' | 'diff', props: I automaticLayout: true, ...DIFF_EDITOR_INITIAL_OPTIONS, ...optionRef.current, - }); + }, overrideServices); editor.setModel({ original: originalModel, modified: modifiedModel }); } diff --git a/packages/plugin-block/.gitignore b/packages/plugin-block/.gitignore deleted file mode 100644 index 77dfbd1..0000000 --- a/packages/plugin-block/.gitignore +++ /dev/null @@ -1,104 +0,0 @@ -# project custom -build -dist -lib -es -package-lock.json -yarn.lock -deploy-space/packages -deploy-space/.env - - -# IDE -.vscode -.idea - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release -lib - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# mac config files -.DS_Store - -# codealike -codealike.json diff --git a/packages/plugin-block/package.json b/packages/plugin-block/package.json index 2c79be7..6c27ed4 100644 --- a/packages/plugin-block/package.json +++ b/packages/plugin-block/package.json @@ -22,5 +22,10 @@ "build-plugin-fusion": "^0.1.22", "build-plugin-moment-locales": "^0.1.3" }, - "homepage": "https://unpkg.com/@alilc/lowcode-plugin-block@1.0.0-beta.0/build/index.html" + "homepage": "https://unpkg.com/@alilc/lowcode-plugin-block@1.0.0-beta.0/build/index.html", + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/plugin-block" + } } diff --git a/packages/plugin-block/src/index.tsx b/packages/plugin-block/src/index.tsx index afd3b29..dfbbb71 100644 --- a/packages/plugin-block/src/index.tsx +++ b/packages/plugin-block/src/index.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; -import { ILowCodePluginContext } from '@alilc/lowcode-engine'; +import { IPublicModelPluginContext } from '@alilc/lowcode-types'; import { default as BlockPane } from './pane'; -const LowcodePluginCusPlugin = (ctx: ILowCodePluginContext) => { +const LowcodePluginCusPlugin = (ctx: IPublicModelPluginContext) => { return { // 插件名,注册环境下唯一 name: 'LowcodePluginCusPlugin', diff --git a/packages/plugin-code-editor/.editorconfig b/packages/plugin-code-editor/.editorconfig new file mode 100644 index 0000000..3192996 --- /dev/null +++ b/packages/plugin-code-editor/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +quote_type = single + +[*.md] +trim_trailing_whitespace = false diff --git a/packages/plugin-code-editor/.eslintignore b/packages/plugin-code-editor/.eslintignore new file mode 100644 index 0000000..36c1703 --- /dev/null +++ b/packages/plugin-code-editor/.eslintignore @@ -0,0 +1,7 @@ +node_modules/ +build/ +dist/ +**/*.min.js +**/*-min.js +**/*.bundle.js +*.js diff --git a/packages/plugin-code-editor/.eslintrc.js b/packages/plugin-code-editor/.eslintrc.js new file mode 100644 index 0000000..0245b1d --- /dev/null +++ b/packages/plugin-code-editor/.eslintrc.js @@ -0,0 +1,11 @@ +module.exports = { + extends: [ + 'eslint-config-ali/typescript/react', + 'prettier', + 'prettier/@typescript-eslint', + 'prettier/react', + ], + rules: { + 'no-param-reassign': 0, + }, +}; diff --git a/packages/plugin-code-editor/.gitignore b/packages/plugin-code-editor/.gitignore deleted file mode 100644 index 77dfbd1..0000000 --- a/packages/plugin-code-editor/.gitignore +++ /dev/null @@ -1,104 +0,0 @@ -# project custom -build -dist -lib -es -package-lock.json -yarn.lock -deploy-space/packages -deploy-space/.env - - -# IDE -.vscode -.idea - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release -lib - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# mac config files -.DS_Store - -# codealike -codealike.json diff --git a/packages/plugin-code-editor/CHANGELOG.md b/packages/plugin-code-editor/CHANGELOG.md index ce9b400..a8f5cba 100644 --- a/packages/plugin-code-editor/CHANGELOG.md +++ b/packages/plugin-code-editor/CHANGELOG.md @@ -1,3 +1,12 @@ +## 1.0.5 / 2022-11-28 + +- Fix 修正 UIPaaS 中针对 source 的异常提示问题 + +## 1.0.4 / 2022-11-18 + +- Fix 修正输入 / 粘贴时光标位置错误的 bug +- Fix 修复当上下文没有 originCode 时,通过 schema 中的局部 source 字段无法恢复 state 的问题 + ## 1.0.3 / 2022-07-11 - Fix 源码面板高度塌陷的 [bug](https://github.com/alibaba/lowcode-engine/issues/803) diff --git a/packages/plugin-code-editor/build.js b/packages/plugin-code-editor/build.js new file mode 100644 index 0000000..9bcddea --- /dev/null +++ b/packages/plugin-code-editor/build.js @@ -0,0 +1,22 @@ +module.exports = { + plugins: [ + [ + 'build-plugin-fusion', + { + themePackage: '@alifd/theme-lowcode-light', + }, + ], + [ + '@alilc/build-plugin-alt', + { + type: 'plugin', + // 开启注入调试模式,see:https://www.yuque.com/lce/doc/ulvlkz + inject: true, + // 配置要打开的页面,在注入调试模式下,不配置此项的话不会打开浏览器 + // 支持直接使用官方 demo 项目:https://lowcode-engine.cn/demo/index.html + // openUrl: 'https://lowcode-engine.cn/demo/index.html?debug', + }, + ], + './build.plugin.js', + ], +}; diff --git a/packages/plugin-code-editor/package.json b/packages/plugin-code-editor/package.json index 14ef6d9..340bc01 100644 --- a/packages/plugin-code-editor/package.json +++ b/packages/plugin-code-editor/package.json @@ -1,7 +1,7 @@ { "name": "@alilc/lowcode-plugin-code-editor", "author": "59174526@qq.com & humphry.huang9@gmail.com", - "version": "1.0.3", + "version": "1.0.9", "description": "CodeEditor", "files": [ "es", @@ -12,11 +12,12 @@ "types": "lib/index.d.ts", "README": "README.md", "scripts": { - "start": "build-scripts start", + "start": "build-scripts start --config build.js", "prepublishOnly": "npm run build", - "build": "build-scripts build" + "build": "build-scripts build --config build.js" }, "publishConfig": { + "registry": "https://registry.npmjs.org/", "access": "public" }, "dependencies": { @@ -24,7 +25,7 @@ "@alilc/lowcode-plugin-base-monaco-editor": "^1.1.1", "@babel/core": "^7.15.8", "@babel/parser": "^7.15.8", - "@babel/preset-env": "^7.15.8", + "@babel/preset-env": "7.22.9", "@babel/preset-react": "^7.14.5", "@babel/standalone": "^7.15.8", "@babel/traverse": "^7.15.4", @@ -49,5 +50,10 @@ "@types/react-dom": "^16.9.4", "build-plugin-fusion": "^0.1.22" }, - "license": "MIT" + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/plugin-code-editor" + } } diff --git a/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.less b/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.less index ab8f7b3..5a9324d 100644 --- a/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.less +++ b/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.less @@ -1,7 +1,4 @@ -.container { - min-width: 300px; -} -.actions { +.plugin-code-editor-errorBoundary-actions { margin: 12px auto; width: fit-content; text-align: center; diff --git a/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.tsx b/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.tsx index fabd328..72159fd 100644 --- a/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.tsx +++ b/packages/plugin-code-editor/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -1,7 +1,7 @@ import React, { Component, ErrorInfo, Suspense } from 'react'; import { Loading, Message, Button } from '@alifd/next'; -import styles from './ErrorBoundary.less'; +import './ErrorBoundary.less'; interface ErrorBoundaryProps { onCatch?: (error: Error, info: ErrorInfo) => void; @@ -41,7 +41,7 @@ export class ErrorBoundary extends Component

详细错误: {errorInfo || '未知原因'}

-
+
diff --git a/packages/plugin-code-editor/src/components/JSEditor/JsEditor.tsx b/packages/plugin-code-editor/src/components/JSEditor/JsEditor.tsx index c84a816..4b0acfd 100644 --- a/packages/plugin-code-editor/src/components/JSEditor/JsEditor.tsx +++ b/packages/plugin-code-editor/src/components/JSEditor/JsEditor.tsx @@ -178,8 +178,14 @@ export class JsEditor extends PureComponent { if (!monacoEditor || !monaco) { return; } - const count = monacoEditor.getModel()?.getLineCount() ?? 0; - const range = new monaco.Range(count, 1, count, 1); + + // 找到最后一个 },在他前面插入新的 function 字符串 + const matches = monacoEditor.getModel()?.findMatches('}'); + let range = {} + if(matches && matches.length > 0) { + const { startLineNumber, startColumn } = matches[matches.length - 1]?.range || {} + range = new monaco.Range(startLineNumber, startColumn, startLineNumber, startColumn); + } const functionCode = params.template ? params.template : @@ -248,10 +254,9 @@ export class JsEditor extends PureComponent { return; } - const pos = monacoEditor.getPosition(); + // const pos = monacoEditor.getPosition(); this.setState({ errorInfo, hasError, code: newCode, errorLocation }, () => { - monacoEditor.setPosition(pos); - + // monacoEditor.setPosition(pos); // update error decorations if (this.lastErrorDecoration) { monacoEditor.deltaDecorations( diff --git a/packages/plugin-code-editor/src/config/default-code.ts b/packages/plugin-code-editor/src/config/default-code.ts index 3765874..bf7ea44 100644 --- a/packages/plugin-code-editor/src/config/default-code.ts +++ b/packages/plugin-code-editor/src/config/default-code.ts @@ -1,5 +1,5 @@ export const defaultCode = ` - export default class LowcodeComponent extends Component { + export default class Page extends Component { // 可以在 state 中定义搭建所需要的 State state = { test: 1, diff --git a/packages/plugin-code-editor/src/index.tsx b/packages/plugin-code-editor/src/index.tsx index 766a74c..c40e74e 100644 --- a/packages/plugin-code-editor/src/index.tsx +++ b/packages/plugin-code-editor/src/index.tsx @@ -1,8 +1,9 @@ import { CodeEditorPane } from './pane'; -import { project, ILowCodePluginContext } from '@alilc/lowcode-engine'; +import { project } from '@alilc/lowcode-engine'; import icon from './icon'; +import { IPublicModelPluginContext } from '@alilc/lowcode-types'; -const plugin = (ctx: ILowCodePluginContext) => { +const plugin = (ctx: IPublicModelPluginContext) => { return { name: 'codeEditor', width: 600, @@ -14,7 +15,7 @@ const plugin = (ctx: ILowCodePluginContext) => { }, // 插件的初始化函数,在引擎初始化之后会立刻调用 init() { - const schemaDock = ctx.skeleton.add({ + const codeEditorDock = ctx.skeleton.add({ area: 'leftArea', name: 'codeEditor', type: 'PanelDock', @@ -35,9 +36,9 @@ const plugin = (ctx: ILowCodePluginContext) => { ), }); - schemaDock && schemaDock.disable(); + codeEditorDock && codeEditorDock.disable(); project.onSimulatorRendererReady(() => { - schemaDock.enable(); + codeEditorDock.enable(); }); }, }; diff --git a/packages/plugin-code-editor/src/pane/index.tsx b/packages/plugin-code-editor/src/pane/index.tsx index 6f229b5..dae3b0c 100644 --- a/packages/plugin-code-editor/src/pane/index.tsx +++ b/packages/plugin-code-editor/src/pane/index.tsx @@ -94,7 +94,7 @@ export const CodeEditorPane = memo(({ project, event, skeleton }: CodeEditorPane useEffect(() => { // load schema on open - eventRef.current?.on('skeleton.panel-dock.active', (pluginName) => { + skeletonRef.current?.onShowPanel((pluginName: string) => { if (pluginName === 'codeEditor') { const schema = lowcodeProjectRef.current?.exportSchema(common.designerCabin.TransformStage.Save); if (!schema) { @@ -109,7 +109,7 @@ export const CodeEditorPane = memo(({ project, event, skeleton }: CodeEditorPane }); // save schema when panel closed - eventRef.current?.on('skeleton.panel-dock.unactive', (pluginName) => { + skeletonRef.current?.onHidePanel((pluginName: string) => { if (pluginName === 'codeEditor') { saveSchemaRef.current?.(); } diff --git a/packages/plugin-code-editor/src/types/methods.ts b/packages/plugin-code-editor/src/types/methods.ts index 2e62f08..093941f 100644 --- a/packages/plugin-code-editor/src/types/methods.ts +++ b/packages/plugin-code-editor/src/types/methods.ts @@ -1,7 +1,8 @@ +import { JSFunction, JSExpression } from '@alilc/lowcode-types'; +export type Method = JSExpression | JSFunction & { + source: string; +} + export interface Methods { - [key: string]: { - type: 'JSFunction'; - value: string; - originalCode: string; - }; + [key: string]: Method; } diff --git a/packages/plugin-code-editor/src/types/state.ts b/packages/plugin-code-editor/src/types/state.ts index d994852..ff85180 100644 --- a/packages/plugin-code-editor/src/types/state.ts +++ b/packages/plugin-code-editor/src/types/state.ts @@ -1,6 +1,6 @@ import { JSExpression } from '@alilc/lowcode-types'; -export interface IState extends JSExpression{ - // 原始代码 - originCode: string; +export interface IState extends JSExpression { + // 原始代码 + source: string; } \ No newline at end of file diff --git a/packages/plugin-code-editor/src/typeings.d.ts b/packages/plugin-code-editor/src/typings.d.ts similarity index 100% rename from packages/plugin-code-editor/src/typeings.d.ts rename to packages/plugin-code-editor/src/typings.d.ts diff --git a/packages/plugin-code-editor/src/utils/evaluate.ts b/packages/plugin-code-editor/src/utils/evaluate.ts new file mode 100644 index 0000000..d4b7db7 --- /dev/null +++ b/packages/plugin-code-editor/src/utils/evaluate.ts @@ -0,0 +1,32 @@ +interface Expr { + type: string; + value: string | number; + extType?: string; +} + +type ExprType = Expr | string; + +function getExprStr(expr: ExprType) { + if (typeof expr === 'string') { + return expr; + } + return expr && (expr as Expr).value; +} + +function getEvalExpressionStr(expr: ExprType): string | undefined { + const exprStr = getExprStr(expr); + if (exprStr == undefined) { + return exprStr; + } else if (exprStr === '') { + return undefined; + } + return `(function(){return (${exprStr})}).call($scope)`; +} + +export function evaluate(expr: ExprType) { + const evalExprStr = getEvalExpressionStr(expr); + const code = `with($scope || {}) { return ${evalExprStr} }`; + const fn = new Function('$scope', code); + // 暂时不传递 $scope + return fn(); +} diff --git a/packages/plugin-code-editor/src/utils/get-methods.ts b/packages/plugin-code-editor/src/utils/get-methods.ts index 72579f7..cd890b2 100644 --- a/packages/plugin-code-editor/src/utils/get-methods.ts +++ b/packages/plugin-code-editor/src/utils/get-methods.ts @@ -54,8 +54,7 @@ export const getMethods = (ast: Node) => { methods[name] = { type: 'JSFunction', value: compiledCode, - // 这里的 originalCode 直接放在全局,不挂在局部 - // originalCode: codeStr, + source: codeStr, }; }, }); diff --git a/packages/plugin-code-editor/src/utils/schema-to-code.ts b/packages/plugin-code-editor/src/utils/schema-to-code.ts index 166ae6b..986ed9a 100644 --- a/packages/plugin-code-editor/src/utils/schema-to-code.ts +++ b/packages/plugin-code-editor/src/utils/schema-to-code.ts @@ -1,14 +1,14 @@ - import { js_beautify, css_beautify } from 'js-beautify'; -import { isJSExpression, ProjectSchema, RootSchema, JSFunction, JSExpression } from '@alilc/lowcode-types'; +import { isJSExpression, ProjectSchema, RootSchema } from '@alilc/lowcode-types'; import { Dialog } from '@alifd/next'; import { IState } from '../types'; -import { defaultStateCode, WORDS } from '../config'; +import { WORDS } from '../config'; +import type { Method } from '../types/methods'; const js_beautify_config = { indent_size: 2, indent_empty_lines: true, e4x: true }; const initCode = (componentSchema: RootSchema | undefined) => { - const code = `class LowcodeComponent extends Component { + const code = `class Page extends Component { ${initStateCode(componentSchema)} ${initLifeCycleCode(componentSchema)} ${initMethodsCode(componentSchema)} @@ -30,34 +30,24 @@ export const schema2CssCode = (schema: ProjectSchema) => { }; export const beautifyCSS = (input?: string): string => { - return input ? css_beautify(input, { indent_size: 2 }) : '' + return input ? css_beautify(input, { indent_size: 2 }) : ''; } function initStateCode(componentSchema: RootSchema | undefined) { if (componentSchema?.state) { - let states: Record = {}; - let needNotice = false; - Object.keys(componentSchema.state).forEach((item) => { - const state = componentSchema.state?.[item]; + let statesStr = 'state = {\n'; + Object.keys(componentSchema.state).forEach((key) => { + const state = componentSchema.state?.[key]; if (typeof state === 'object' && isJSExpression(state)) { - states[item] = (state as IState).originCode || state.value; // 兼容历史数据 - if (!(state as IState).originCode) { - needNotice = true; - } + statesStr += `"${key}": ${(state as IState).source || state.value},\n`; } else { - states[item] = state; // 兼容历史数据 + statesStr += `"${key}": ${typeof state === 'string' ? '"' + state + '"' : state},,\n`; } }); - if (needNotice) { - Dialog.alert({ - title: WORDS.title, - content: WORDS.irreparableState, - }); - } - return `state = ${JSON.stringify(states)}`; + statesStr += '}'; + return statesStr; } - return defaultStateCode; } function initLifeCycleCode(componentSchema: RootSchema | undefined) { @@ -100,10 +90,10 @@ function initMethodsCode(componentSchema: RootSchema | undefined) { } } -function createFunctionCode(functionName: string, functionNode: JSFunction | JSExpression) { +function createFunctionCode(functionName: string, functionNode: Method) { if (functionNode?.type === 'JSExpression' || functionNode?.type === 'JSFunction') { // 读取原始代码 - let functionCode = functionNode.originalCode; + let functionCode = functionNode.source; if (functionCode) { functionCode = functionCode.replace(/function/, ''); } else { diff --git a/packages/plugin-code-editor/src/utils/state-parser.ts b/packages/plugin-code-editor/src/utils/state-parser.ts index 439e964..872eb2b 100644 --- a/packages/plugin-code-editor/src/utils/state-parser.ts +++ b/packages/plugin-code-editor/src/utils/state-parser.ts @@ -18,7 +18,6 @@ export const stateParser = (ast: Node) => { // get state identifier or literal if (path.isIdentifier({ name: 'state' }) || path.isLiteral({ value: 'state' })) { const properties = path.container?.value?.properties; - // console.log('properties', properties); if (properties) { properties.forEach((property) => { // creat empty AST @@ -26,7 +25,7 @@ export const stateParser = (ast: Node) => { code.program.body.push(t.variableDeclaration('var', [ t.variableDeclarator(t.identifier('name'), property.value), ])); - + const codeStr = babelTransformFromAst(code).code; const compiledCode = transformJS(codeStr, defaultBabelConfig).code; if (compiledCode) { diff --git a/packages/plugin-code-editor/src/utils/transform.ts b/packages/plugin-code-editor/src/utils/transform.ts index 7f18e94..faed277 100644 --- a/packages/plugin-code-editor/src/utils/transform.ts +++ b/packages/plugin-code-editor/src/utils/transform.ts @@ -1,4 +1,3 @@ - import { transform } from './babel'; import { TransformResult } from '../types'; diff --git a/packages/plugin-components-pane/.gitignore b/packages/plugin-components-pane/.gitignore deleted file mode 100644 index 8523c97..0000000 --- a/packages/plugin-components-pane/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# See https://help.github.com/ignore-files/ for more about ignoring files. - -# dependencies -node_modules/ - -# production -build/ -dist/ -tmp/ -lib/ -es/ - -# misc -.idea/ -.happypack -.DS_Store -*.swp -*.dia~ -.ice - -npm-debug.log* -yarn-debug.log* -yarn-error.log* -index.module.scss.d.ts - -node_modules diff --git a/packages/plugin-components-pane/build.json b/packages/plugin-components-pane/build.json index 90ae90f..36f5196 100644 --- a/packages/plugin-components-pane/build.json +++ b/packages/plugin-components-pane/build.json @@ -1,6 +1,14 @@ { "plugins": [ "build-plugin-component", + [ + "@alilc/build-plugin-alt", + { + "type": "plugin", + "inject": true, + "openUrl": "https://lowcode-engine.cn/demo/index.html?debug" + } + ], "build-plugin-fusion", [ "build-plugin-moment-locales", diff --git a/packages/plugin-components-pane/demo/demo.hbs b/packages/plugin-components-pane/demo/demo.hbs index bcca41a..f5147dd 100644 --- a/packages/plugin-components-pane/demo/demo.hbs +++ b/packages/plugin-components-pane/demo/demo.hbs @@ -11,9 +11,9 @@ - - - + + + @@ -21,4 +21,4 @@
- \ No newline at end of file + diff --git a/packages/plugin-components-pane/package.json b/packages/plugin-components-pane/package.json index 33b0615..7f12a94 100644 --- a/packages/plugin-components-pane/package.json +++ b/packages/plugin-components-pane/package.json @@ -1,6 +1,6 @@ { "name": "@alilc/lowcode-plugin-components-pane", - "version": "1.0.3", + "version": "2.0.4", "description": "低代码组件面板", "files": [ "es/", @@ -31,19 +31,20 @@ ], "license": "ISC", "devDependencies": { - "@alib/build-scripts": "^0.1.3", + "@alib/build-scripts": "^0.1.32", "@alifd/next": "^1.23.12", "@svgr/webpack": "^5.5.0", "@types/react": "^16.9.13", "@types/react-dom": "^16.9.4", "@typescript-eslint/parser": "^4.28.3", - "build-plugin-component": "^0.2.7-1", + "build-plugin-component": "^1.12.0", "build-plugin-fusion": "^0.1.0", "build-plugin-moment-locales": "^0.1.0", "eventemitter3": "^4.0.7", "f2elint": "^1.2.0", "html-webpack-plugin": "^5.3.2", "moment": "^2.29.1", + "@alilc/build-plugin-alt": "^1.0.0", "react-dom": "^16.0.0" }, "husky": { @@ -57,5 +58,10 @@ "classnames": "^2.3.1", "lodash.debounce": "^4.0.8", "react": "^16.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/plugin-components-pane" } } diff --git a/packages/plugin-components-pane/src/components/Component/index.tsx b/packages/plugin-components-pane/src/components/Component/index.tsx index 5fae255..681a414 100644 --- a/packages/plugin-components-pane/src/components/Component/index.tsx +++ b/packages/plugin-components-pane/src/components/Component/index.tsx @@ -2,12 +2,13 @@ import React from 'react'; import cls from 'classnames/bind'; import Svg from '../../Icon/Component'; import style from './index.module.scss'; -import { getTextReader, StandardComponentMeta } from '../../utils/transform'; +import { Text, StandardComponentMeta } from '../../utils/transform'; const cx = cls.bind(style); interface Props { data: StandardComponentMeta; + t: (input: Text) => string; } interface State { @@ -37,7 +38,7 @@ export default class Component extends React.Component { constructor(props) { super(props); - this.t = getTextReader('zh_CN'); + this.t = props.t; } renderIcon() { diff --git a/packages/plugin-components-pane/src/components/Tab/index.module.scss b/packages/plugin-components-pane/src/components/Tab/index.module.scss index b443fca..ffa7ab5 100644 --- a/packages/plugin-components-pane/src/components/Tab/index.module.scss +++ b/packages/plugin-components-pane/src/components/Tab/index.module.scss @@ -6,6 +6,7 @@ position: relative; flex-grow: 0; flex-shrink: 0; + overflow-x: scroll; .items { display: flex; diff --git a/packages/plugin-components-pane/src/index.tsx b/packages/plugin-components-pane/src/index.tsx index a6130a7..6b26af8 100644 --- a/packages/plugin-components-pane/src/index.tsx +++ b/packages/plugin-components-pane/src/index.tsx @@ -1,308 +1,29 @@ -import React from 'react'; -import { Search } from '@alifd/next'; -import { PluginProps } from '@alilc/lowcode-types'; -import cls from 'classnames/bind'; -import debounce from 'lodash.debounce'; -import style from './index.module.scss'; -import IconOfPane from './Icon'; -import Category from './components/Category'; -import List from './components/List'; -import Component from './components/Component'; -import Tab from './components/Tab'; -import ComponentManager from './store'; -import transform, { getTextReader, SortedGroups, Text } from './utils/transform'; - -const { material, common, project, event } = window.AliLowCodeEngine || {}; - -const isNewEngineVersion = !!material; - -const store = new ComponentManager(); - -const cx = cls.bind(style); - -interface ComponentPaneProps extends PluginProps { - [key: string]: any; -} - -interface ComponentPaneState { - groups: SortedGroups[]; - filter: SortedGroups[]; - keyword: string; -} - -export default class ComponentPane extends React.Component { - static displayName = 'LowcodeComponentPane'; - - static defaultProps = { - lang: 'zh_CN', - }; - - state: ComponentPaneState = { - groups: [], - filter: [], - keyword: '', - }; - - store = store; - - t: (input: Text) => string; - - getStrKeywords: (keywords: Text[]) => string; - - getFilteredComponents = debounce(() => { - const { groups = [], keyword } = this.state; - if (!keyword) { - this.setState({ - filter: groups, +import { IPublicModelPluginContext } from '@alilc/lowcode-types'; +import ComponentsPane from './pane'; +const ComponentPanelPlugin = (ctx: IPublicModelPluginContext) => { + return { + async init() { + const { skeleton, project } = ctx; + // 注册组件面板 + const componentsPane = skeleton.add({ + area: 'leftArea', + type: 'PanelDock', + name: 'componentsPane', + content: ComponentsPane, + contentProps: {}, + props: { + align: 'top', + icon: 'zujianku', + description: '组件库', + }, }); - return; - } - - const filter = groups.map((group) => ({ - ...group, - categories: group.categories - .map((category) => ({ - ...category, - components: category.components.filter((c) => { - const strTitle = this.t(c.title); - const strComponentName = this.t(c.componentName); - const strDescription = this.t(c.description); - const strKeywords = this.getStrKeywords(c.keywords); - const keyToSearch = `${strTitle}#${strComponentName}#${strDescription}#${strKeywords}`.toLowerCase(); - return keyToSearch.includes(keyword); - }), - })) - .filter((c) => c?.components?.length), - })); - - this.setState({ - filter, - }); - }, 200); - - constructor(props) { - super(props); - this.t = getTextReader(props.lang); - this.getStrKeywords = (keywords: Text[]): string => { - if (typeof keywords === 'string') { - return keywords; - } - if (keywords && Array.isArray(keywords) && keywords.length) { - return keywords.map(keyword => this.t(keyword)).join('-'); - } - return ''; - }; - } - - componentDidMount() { - const { editor } = this.props; - if (!editor) { - this.initComponentList(); - return; - } - const assets = isNewEngineVersion ? material.getAssets() : editor.get('assets'); - if (assets) { - this.initComponentList(); - } else { - console.warn('[ComponentsPane]: assets not ready, wait for assets ready event.') - } - - if (isNewEngineVersion) { - event.on('trunk.change', this.initComponentList.bind(this)); - material.onChangeAssets(this.initComponentList.bind(this)); - } else { - editor.on('trunk.change', this.initComponentList.bind(this)); - editor.once('editor.ready', this.initComponentList.bind(this)); - editor.on('designer.incrementalAssetsReady', this.initComponentList.bind(this)); - } - } - - /** - * 初始化组件列表 - * TODO: 无副作用,可多次执行 - */ - initComponentList() { - const { editor } = this.props; - const rawData = isNewEngineVersion ? material.getAssets() : editor.get('assets'); - - const meta = transform(rawData); - - const { groups, snippets } = meta; - - this.store.setSnippets(snippets); - - this.setState({ - groups, - filter: groups, - }); - } - - registerAdditive = (shell: HTMLDivElement | null) => { - if (!shell || shell.dataset.registered) { - return; - } - - function getSnippetId(elem: any) { - if (!elem) { - return null; - } - while (shell !== elem) { - if (elem.classList.contains('snippet')) { - return elem.dataset.id; - } - elem = elem.parentNode; - } - return null; - } - - const { editor } = this.props; - const designer = !isNewEngineVersion ? editor?.get('designer') : null; - const _dragon = isNewEngineVersion ? common.designerCabin.dragon : designer?.dragon; - if (!_dragon || (!isNewEngineVersion && !designer)) { - return; - } - - // eslint-disable-next-line - const click = (e: Event) => {}; - - shell.addEventListener('click', click); - - _dragon.from(shell, (e: Event) => { - const doc = isNewEngineVersion ? project.getCurrentDocument() : designer?.currentDocument; - const id = getSnippetId(e.target); - if (!doc || !id) { - return false; - } - - const dragTarget = { - type: 'nodedata', - data: this.store.getSnippetById(id), - }; - - return dragTarget; - }); - - shell.dataset.registered = 'true'; + componentsPane?.disable?.(); + project.onSimulatorRendererReady(() => { + componentsPane?.enable?.(); + }) + }, }; - - handleSearch = (keyword = '') => { - this.setState({ - keyword: keyword.toLowerCase(), - }); - this.getFilteredComponents(); - }; - - renderEmptyContent() { - return ( -
- -
暂无组件,请在物料站点添加
-
- ) - } - - renderContent() { - const { filter = [], keyword } = this.state; - const hasContent = filter.filter(item => { - return item?.categories?.filter(category => { - return category?.components?.length; - }).length; - }).length; - if (!hasContent) { - return this.renderEmptyContent(); - } - if (keyword) { - return ( -
- {filter.map((group) => { - const { categories } = group; - {return categories.map((category) => { - const { components } = category; - const cname = this.t(category.name); - return ( - - - {components.map((component) => { - const { componentName, snippets = [] } = component; - return snippets.filter(snippet => snippet.id).map(snippet => { - return ( - - ); - }); - })} - - - ); - })} - })} -
- ) - } - return ( - - {filter.map((group) => { - const { categories } = group; - return ( - -
- {categories.map((category) => { - const { components } = category; - const cname = this.t(category.name); - return ( - - - {components.map((component) => { - const { componentName, snippets = [] } = component; - return snippets.filter(snippet => snippet.id).map(snippet => { - return ( - - ); - }); - })} - - - ); - })} -
-
- ); - })} -
- ); - } - - render() { - return ( -
-
- -
- {this.renderContent()} -
- ); - } } +ComponentPanelPlugin.pluginName = 'ComponentPanelPlugin'; +export default ComponentPanelPlugin; -export const PaneIcon = IconOfPane; diff --git a/packages/plugin-components-pane/src/index.module.scss b/packages/plugin-components-pane/src/pane/index.module.scss similarity index 87% rename from packages/plugin-components-pane/src/index.module.scss rename to packages/plugin-components-pane/src/pane/index.module.scss index 2d8c140..d63baaf 100644 --- a/packages/plugin-components-pane/src/index.module.scss +++ b/packages/plugin-components-pane/src/pane/index.module.scss @@ -33,4 +33,9 @@ line-height: 2; } } + + > .filtered-content { + overflow-y: overlay; + overflow-x: hidden; + } } diff --git a/packages/plugin-components-pane/src/pane/index.tsx b/packages/plugin-components-pane/src/pane/index.tsx new file mode 100644 index 0000000..eacb5db --- /dev/null +++ b/packages/plugin-components-pane/src/pane/index.tsx @@ -0,0 +1,321 @@ +import React from 'react'; +import { Search } from '@alifd/next'; +import { PluginProps } from '@alilc/lowcode-types'; +import cls from 'classnames/bind'; +import debounce from 'lodash.debounce'; +import style from './index.module.scss'; +import IconOfPane from '../Icon'; +import Category from '../components/Category'; +import List from '../components/List'; +import Component from '../components/Component'; +import Tab from '../components/Tab'; +import ComponentManager from '../store'; +import transform, { getTextReader, SortedGroups, Text, StandardComponentMeta, SnippetMeta, createI18n } from '../utils/transform'; + +const { material, common, project, event } = window.AliLowCodeEngine || {}; + +const isNewEngineVersion = !!material; + +const store = new ComponentManager(); + +const cx = cls.bind(style); + +interface ComponentPaneProps extends PluginProps { + [key: string]: any; +} + +interface ComponentPaneState { + groups: SortedGroups[]; + filter: SortedGroups[]; + keyword: string; +} + +export default class ComponentPane extends React.Component { + static displayName = 'LowcodeComponentPane'; + + static defaultProps = { + lang: 'zh_CN', + }; + + state: ComponentPaneState = { + groups: [], + filter: [], + keyword: '', + }; + + store = store; + + t: (input: Text) => string; + + getStrKeywords: (keywords: Text[]) => string; + + getKeyToSearch (c:StandardComponentMeta|SnippetMeta){ + const strTitle = this.t(c.title); + const strComponentName = this.t((c as SnippetMeta).schema?.componentName); + const strDescription = "description" in c ? this.t(c.description):''; + const strKeywords = "keywords" in c ? this.getStrKeywords(c.keywords||[]):''; + return `${strTitle}#${strComponentName}#${strDescription}#${strKeywords}`.toLowerCase(); + } + + getFilteredComponents = debounce(() => { + const { groups = [], keyword } = this.state; + if (!keyword) { + this.setState({ + filter: groups, + }); + return; + } + + + + const filter = groups.map((group) => ({ + ...group, + categories: group.categories + .map((category) => ({ + ...category, + components: category.components.filter((c) => { + let keyToSearch = this.getKeyToSearch(c); + if(c.snippets){ + c.snippets.map((item)=>{ + keyToSearch += `_${this.getKeyToSearch(item)}` + }) + } + return keyToSearch.includes(keyword); + }), + })) + .filter((c) => c?.components?.length), + })); + + this.setState({ + filter, + }); + }, 200); + + constructor(props) { + super(props); + this.t = getTextReader(props.lang); + this.getStrKeywords = (keywords: Text[]): string => { + if (typeof keywords === 'string') { + return keywords; + } + if (keywords && Array.isArray(keywords) && keywords.length) { + return keywords.map(keyword => this.t(keyword)).join('-'); + } + return ''; + }; + } + + componentDidMount() { + const { editor } = this.props; + if (!editor) { + this.initComponentList(); + return; + } + const assets = isNewEngineVersion ? material.getAssets() : editor.get('assets'); + if (assets) { + this.initComponentList(); + } else { + console.warn('[ComponentsPane]: assets not ready, wait for assets ready event.') + } + + if (isNewEngineVersion) { + event.on('trunk.change', this.initComponentList.bind(this)); + material.onChangeAssets(this.initComponentList.bind(this)); + } else { + editor.on('trunk.change', this.initComponentList.bind(this)); + editor.once('editor.ready', this.initComponentList.bind(this)); + editor.on('designer.incrementalAssetsReady', this.initComponentList.bind(this)); + } + } + + /** + * 初始化组件列表 + * TODO: 无副作用,可多次执行 + */ + initComponentList() { + const { editor } = this.props; + const rawData = isNewEngineVersion ? material.getAssets() : editor.get('assets'); + + const meta = transform(rawData, this.t); + + const { groups, snippets } = meta; + + this.store.setSnippets(snippets); + + this.setState({ + groups, + filter: groups, + }); + } + + registerAdditive = (shell: HTMLDivElement | null) => { + if (!shell || shell.dataset.registered) { + return; + } + + function getSnippetId(elem: any) { + if (!elem) { + return null; + } + while (shell !== elem) { + if (elem.classList.contains('snippet')) { + return elem.dataset.id; + } + elem = elem.parentNode; + } + return null; + } + + const { editor } = this.props; + const designer = !isNewEngineVersion ? editor?.get('designer') : null; + const _dragon = isNewEngineVersion ? common.designerCabin.dragon : designer?.dragon; + if (!_dragon || (!isNewEngineVersion && !designer)) { + return; + } + + // eslint-disable-next-line + const click = (e: Event) => {}; + + shell.addEventListener('click', click); + + _dragon.from(shell, (e: Event) => { + const doc = isNewEngineVersion ? project.getCurrentDocument() : designer?.currentDocument; + const id = getSnippetId(e.target); + if (!doc || !id) { + return false; + } + + const dragTarget = { + type: 'nodedata', + data: this.store.getSnippetById(id), + }; + + return dragTarget; + }); + + shell.dataset.registered = 'true'; + }; + + handleSearch = (keyword = '') => { + this.setState({ + keyword: keyword.toLowerCase(), + }); + this.getFilteredComponents(); + }; + + renderEmptyContent() { + return ( +
+ +
{this.t(createI18n('暂无组件,请在物料站点添加', 'No components, please add materials'))}
+
+ ) + } + + renderContent() { + const { filter = [], keyword } = this.state; + const hasContent = filter.filter(item => { + return item?.categories?.filter(category => { + return category?.components?.length; + }).length; + }).length; + if (!hasContent) { + return this.renderEmptyContent(); + } + if (keyword) { + return ( +
+ {filter.map((group) => { + const { categories } = group; + {return categories.map((category) => { + const { components } = category; + const cname = this.t(category.name); + return ( + + + {components.map((component) => { + const { componentName, snippets = [] } = component; + return snippets.filter(snippet => snippet.id && this.getKeyToSearch(snippet).toLowerCase().includes(keyword)).map(snippet => { + return ( + + ); + }); + })} + + + ); + })} + })} +
+ ) + } + return ( + + {filter.map((group) => { + const { categories } = group; + return ( + +
+ {categories.map((category) => { + const { components } = category; + const cname = this.t(category.name); + return ( + + + {components.map((component) => { + const { componentName, snippets = [] } = component; + return snippets.filter(snippet => snippet.id).map(snippet => { + return ( + + ); + }); + })} + + + ); + })} +
+
+ ); + })} +
+ ); + } + + render() { + return ( +
+
+ +
+ {this.renderContent()} +
+ ); + } +} + +export const PaneIcon = IconOfPane; diff --git a/packages/plugin-components-pane/src/utils/transform.ts b/packages/plugin-components-pane/src/utils/transform.ts index 7406842..69f3f59 100644 --- a/packages/plugin-components-pane/src/utils/transform.ts +++ b/packages/plugin-components-pane/src/utils/transform.ts @@ -51,8 +51,7 @@ export interface IgnoreComponents { [key: string]: string[]; } -export default function transform(raw: any) { - const t = getTextReader('zh_CN'); +export default function transform(raw: any, t: (input: Text) => string) { let groupList: Text[] = []; let categoryList: Text[] = []; let ignoreComponents: IgnoreComponents = {}; @@ -136,7 +135,7 @@ export default function transform(raw: any) { const { sort } = stdComponent; const { group, category, priority = 0 } = sort; - const hasGroup = textExistIn(group, groupList); + const hasGroup = textExistIn(group, groupList, t); if (hasGroup) { if (!map[t(group)]) { @@ -319,7 +318,6 @@ export function pipe(arr: any[]) { }; } -export function textExistIn(text: Text, arr: Text[]) { - const t = getTextReader('zh_CN'); +export function textExistIn(text: Text, arr: Text[], t: (input: Text) => string) { return !!arr.find((item) => t(item) === t(text)); } diff --git a/packages/plugin-datasource-pane/.gitignore b/packages/plugin-datasource-pane/.gitignore deleted file mode 100644 index 77dfbd1..0000000 --- a/packages/plugin-datasource-pane/.gitignore +++ /dev/null @@ -1,104 +0,0 @@ -# project custom -build -dist -lib -es -package-lock.json -yarn.lock -deploy-space/packages -deploy-space/.env - - -# IDE -.vscode -.idea - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release -lib - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# mac config files -.DS_Store - -# codealike -codealike.json diff --git a/packages/plugin-datasource-pane/README.md b/packages/plugin-datasource-pane/README.md index 576385d..42a853b 100644 --- a/packages/plugin-datasource-pane/README.md +++ b/packages/plugin-datasource-pane/README.md @@ -89,7 +89,104 @@ type DataSourceType = { ## 定制导入插件 -WIP +### 导入组件示例 + +导入组件引入方式参考 pluginProps +``` +import { DataSourceImportPluginTest } from './DataSourceImportPluginTest'; + +{ + ... + importPlugins: [ + { + name: '这里可以导入', + title: '这里可以导入', + component: DataSourceImportPluginTest, + componentProps: { + onImport: (res) => { + console.log('ceshi ') + + }, + onCancel: () => { + console.log('ceshi2 ') + + } + } + } + ], + exportPlugins: [], + formComponents: { }, + ... +} + +// DataSourceImportPluginTest.jsx + +/** + * 源码导入插件 + * @todo editor 关联 types,并提供详细的出错信息 + */ +import React, { PureComponent } from 'react'; +import { Button } from '@alifd/next'; +import _noop from 'lodash/noop'; +import _isArray from 'lodash/isArray'; +import _last from 'lodash/last'; +import _isPlainObject from 'lodash/isPlainObject'; +import { RuntimeDataSourceConfig as DataSourceConfig } from '@alilc/lowcode-datasource-types'; +import { JSONSchema6 } from 'json-schema'; +import type { ComponentType } from 'react'; +export interface DataSourceType { + type: string; + schema: JSONSchema6; + plugin?: ComponentType; +} +export interface DataSourcePaneImportPluginComponentProps { + dataSourceTypes: DataSourceType[]; + onImport?: (dataSourceList: DataSourceConfig[]) => void; + onCancel?: () => void; +} +export interface DataSourceImportPluginCodeProps + extends DataSourcePaneImportPluginComponentProps { + defaultValue?: DataSourceConfig[]; +} +export interface DataSourceImportPluginCodeState { + code: string; + isCodeValid: boolean; +} +export class DataSourceImportPluginCode extends PureComponent< + DataSourceImportPluginCodeProps, + DataSourceImportPluginCodeState +> { + handleComplete = () => { + console.log('确认') + }; + onCancel = () => { + console.log('取消') + }; + render() { + return ( +
+ 此处代码可以自定义 +

+ + +

+
+ ); + } +} + +``` + +具体的 component 可参考 DataSourceImportPluginCode + [查看](https://github.com/alibaba/lowcode-plugins/blob/main/packages/plugin-datasource-pane/src/components/DataSourceImportPluginCode/DataSourceImportPluginCode.tsx) + + demo 截图 + ![Alt](https://user-images.githubusercontent.com/14235113/186659341-dff511e8-f032-423c-8be7-e0cc281f3964.png) + + + ## 定制导出插件 diff --git a/packages/plugin-datasource-pane/build.js b/packages/plugin-datasource-pane/build.js new file mode 100644 index 0000000..fc2fa16 --- /dev/null +++ b/packages/plugin-datasource-pane/build.js @@ -0,0 +1,23 @@ +module.exports = { + plugins: [ + 'build-plugin-component', + 'build-plugin-fusion', + [ + 'build-plugin-moment-locales', + { + locales: ['zh-cn'], + }, + ], + [ + '@alilc/build-plugin-alt', + { + type: 'plugin', + // 开启注入调试模式,see:https://www.yuque.com/lce/doc/ulvlkz + inject: true, + // 配置要打开的页面,在注入调试模式下,不配置此项的话不会打开浏览器 + // 支持直接使用官方 demo 项目:https://lowcode-engine.cn/demo/index.html + openUrl: 'https://lowcode-engine.cn/demo/index.html?debug', + }, + ], + ], +}; diff --git a/packages/plugin-datasource-pane/build.json b/packages/plugin-datasource-pane/build.json deleted file mode 100644 index b2fe2de..0000000 --- a/packages/plugin-datasource-pane/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "plugins": [ - "build-plugin-component", - "build-plugin-fusion", - [ - "build-plugin-moment-locales", - { - "locales": ["zh-cn"] - } - ] - ] -} diff --git a/packages/plugin-datasource-pane/package.json b/packages/plugin-datasource-pane/package.json index eae676c..898bd5f 100644 --- a/packages/plugin-datasource-pane/package.json +++ b/packages/plugin-datasource-pane/package.json @@ -1,14 +1,14 @@ { "name": "@alilc/lowcode-plugin-datasource-pane", - "version": "1.0.6", + "version": "1.0.11", "description": "低代码引擎数据源面板", "main": "lib/index.js", "files": [ "lib" ], "scripts": { - "start": "build-scripts start", - "build": "build-scripts build", + "start": "build-scripts start --config build.js", + "build": "build-scripts build --config build.js", "test": "ava", "test:snapshot": "ava --update-snapshots" }, @@ -26,7 +26,7 @@ "devDependencies": { "@alib/build-scripts": "^0.1.32", "@alifd/theme-lowcode-light": "^0.2.1", - "@alilc/build-plugin-alt": "^1.0.0", + "@alilc/build-plugin-alt": "^1.2.2", "@alilc/lowcode-engine": "beta", "@alilc/lowcode-shell": "^1.0.0", "@alilc/lowcode-types": "beta", @@ -74,5 +74,10 @@ "traverse": "^0.6.6", "xstate": "^4.26.0" }, - "homepage": "https://unpkg.com/@alilc/lowcode-plugin-datasource-pane@1.0.6/build/index.html" + "homepage": "https://unpkg.com/@alilc/lowcode-plugin-datasource-pane@1.0.11/build/index.html", + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/plugin-datasource-pane" + } } diff --git a/packages/plugin-datasource-pane/src/components/DataSourceForm/DataSourceForm.tsx b/packages/plugin-datasource-pane/src/components/DataSourceForm/DataSourceForm.tsx index 7dc035e..4597b79 100644 --- a/packages/plugin-datasource-pane/src/components/DataSourceForm/DataSourceForm.tsx +++ b/packages/plugin-datasource-pane/src/components/DataSourceForm/DataSourceForm.tsx @@ -42,11 +42,7 @@ const SCHEMA = { type: { title: '类型', type: 'string', - editable: false, readOnly: true, - hidden: true, - display: 'hidden', - visible: false, 'x-decorator': 'FormItem', 'x-component-props': { // labelWidth: 300, @@ -90,7 +86,7 @@ const SCHEMA = { type: 'string', title: '请求方法', required: true, - enum: ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE'].map((i) => ({ + enum: ['GET', 'POST', 'OPTIONS', 'PUT', 'PATCH', 'DELETE'].map((i) => ({ label: i, value: i, })), @@ -199,8 +195,10 @@ export class DataSourceForm extends PureComponent { + return new Promise((resolve, reject) => { + const { isCodeValid, code } = this.state; + + if (!isCodeValid) reject(new Error('导入格式有误')); + + // 只 resolve 通过 schema 校验的数据 + resolve(this.deriveValue(JSON.parse(code))); + }); + }; + private monacoRef: any; constructor(props: DataSourceImportPluginCodeProps) { @@ -75,7 +89,8 @@ export class DataSourceImportPluginCode extends PureComponent< (type) => type.type === dataSource.type, ); if (!dataSourceType) return false; - return ajv.validate(dataSourceType.schema, dataSource); + // 处理下默认为空的情况,向下兼容 + return ajv.validate(dataSourceType.schema || {}, dataSource); }); }; @@ -86,10 +101,11 @@ export class DataSourceImportPluginCode extends PureComponent< .getModelMarkers() .find((marker: editor.IMarker) => marker.owner === 'json') ) { + Message.success("检验成功,点击右上方确定完成导入!") this.setState({ isCodeValid: true }); - const model: any = _last(this.monacoRef.getModels()); - if (!model) return; - this.props.onImport?.(this.deriveValue(JSON.parse(model.getValue()))); + // const model: any = _last(this.monacoRef.getModels()); + // if (!model) return; + // this.props.onImport?.(this.deriveValue(JSON.parse(model.getValue()))); return; } } @@ -108,10 +124,14 @@ export class DataSourceImportPluginCode extends PureComponent< } }; - handleEditorDidMount = (isFullscreen, editor, monaco) => { - this.monacoRef = monaco?.editor; + /* @author daifuyang + ** @description:修复编辑器挂载事件 + */ + handleEditorDidMount = (editor: MonacoEditor, monaco: MonacoEditor) => { + this.monacoRef = editor?.editor; }; + render() { const { onCancel = _noop } = this.props; const { code, isCodeValid } = this.state; @@ -133,7 +153,7 @@ export class DataSourceImportPluginCode extends PureComponent<

diff --git a/packages/plugin-datasource-pane/src/components/Forms/form-lazy-obj.tsx b/packages/plugin-datasource-pane/src/components/Forms/form-lazy-obj.tsx index 45cc7a5..0d65f38 100644 --- a/packages/plugin-datasource-pane/src/components/Forms/form-lazy-obj.tsx +++ b/packages/plugin-datasource-pane/src/components/Forms/form-lazy-obj.tsx @@ -48,9 +48,15 @@ export const FormLazyObj = observer((props: FormLazyObjProps) => { setSelectedProperties((selectedProperties) => selectedProperties.concat(propertyKey)); }, []); + /* 改成formily内部支持 */ const handleRemove = useCallback((propertyKey) => { - setSelectedProperties((selectedProperties) => selectedProperties.filter((i) => i !== propertyKey)); - }, []); + field?.form?.query(propertyKey)?.take()?.setState((state) => { + state.visible = !state.visible; + }); + // setSelectedProperties((selectedProperties) => + // selectedProperties.filter((i) => i !== propertyKey) + // ); + }, [field]); const addition = useMemo(() => { if (properties.length === 0) return null; diff --git a/packages/plugin-datasource-pane/src/index.tsx b/packages/plugin-datasource-pane/src/index.tsx index 9347532..838ada5 100644 --- a/packages/plugin-datasource-pane/src/index.tsx +++ b/packages/plugin-datasource-pane/src/index.tsx @@ -1,10 +1,10 @@ -import { ILowCodePluginContext } from '@alilc/lowcode-engine'; import DataSourcePanePlugin from './pane'; import { DataSourcePaneImportPlugin, DataSourceType, } from './types'; +import { IPublicModelPluginContext } from '@alilc/lowcode-types'; export interface Options { importPlugins?: DataSourcePaneImportPlugin[]; @@ -13,7 +13,7 @@ export interface Options { } // TODO: 2.0插件传参修改,不支持直接options: Options -const plugin = (ctx: ILowCodePluginContext) => { +const plugin = (ctx: IPublicModelPluginContext, options: Options) => { return { name: 'com.alibaba.lowcode.datasource.pane', width: 300, @@ -25,8 +25,8 @@ const plugin = (ctx: ILowCodePluginContext) => { }, // 插件的初始化函数,在引擎初始化之后会立刻调用 init() { - const dataSourceTypes = ctx.preference.getPreferenceValue('dataSourceTypes'); - const importPlugins = ctx.preference.getPreferenceValue('importPlugins'); + const dataSourceTypes = ctx.preference.getPreferenceValue('dataSourceTypes') || options.dataSourceTypes; + const importPlugins = ctx.preference.getPreferenceValue('importPlugins') || options.importPlugins; const schemaDock = ctx.skeleton.add({ area: 'leftArea', name: 'dataSourcePane', @@ -39,19 +39,15 @@ const plugin = (ctx: ILowCodePluginContext) => { width: '300px', // title: '源码面板', }, - content: ( - - ), + content: DataSourcePanePlugin, + contentProps: { + importPlugins, + dataSourceTypes, + event: ctx.event, + project: ctx.project, + logger: ctx.logger, + setters: ctx.setters, + }, }); schemaDock && schemaDock.disable(); diff --git a/packages/plugin-datasource-pane/src/pane/DataSourcePane.tsx b/packages/plugin-datasource-pane/src/pane/DataSourcePane.tsx index bee17e3..bb74ecc 100644 --- a/packages/plugin-datasource-pane/src/pane/DataSourcePane.tsx +++ b/packages/plugin-datasource-pane/src/pane/DataSourcePane.tsx @@ -9,8 +9,6 @@ import { } from '@alilc/lowcode-datasource-types'; import { Button, Message, Dialog } from '@alifd/next'; import _isArray from 'lodash/isArray'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import { DndProvider } from 'react-dnd'; import { createStateMachine } from '../utils/stateMachine'; import { DataSourcePaneContext } from '../utils/panel-context'; import { DataSourceFilter } from '../components/DataSourceFilter'; @@ -72,11 +70,11 @@ export class DataSourcePane extends PureComponent< listMode: DataSourcePanelMode.NORMAL, }; - detailRef? = createRef(); + detailRef ?= createRef(); - exportRef? = createRef(); + exportRef ?= createRef(); - importRef? = createRef(); + importRef ?= createRef(); private send = (...args: any[]) => { this.context.stateService.send(...args); @@ -86,7 +84,7 @@ export class DataSourcePane extends PureComponent< this.serviceS = this.context?.stateService?.subscribe?.((state: any) => { this.setState({ current: state }); // 监听导入成功事件 - if (state.changed && (state.value === 'idle' || state.event?.type === "FINISH_IMPORT")) { + if (state.changed && (state.value === 'idle' || state.event?.type === 'FINISH_IMPORT')) { // TODO add hook this.props.onSchemaChange?.({ list: state.context.dataSourceList, @@ -95,7 +93,11 @@ export class DataSourcePane extends PureComponent< }); this.send({ type: 'UPDATE_DS', payload: this.props.initialSchema?.list }); } - + componentDidUpdate(newValue:DataSourcePaneProps) { + if (this.props.initialSchema !== newValue.initialSchema) { + this.send({ type: 'UPDATE_DS', payload: this.props.initialSchema?.list }); + } + } componentWillUnmount() { this.serviceS?.unsubscribe?.(); } @@ -223,8 +225,8 @@ export class DataSourcePane extends PureComponent< } const repeatedDataSourceList = data.filter( (item) => !!this.state.current.context.dataSourceList.find( - (dataSource: DataSourceConfig) => dataSource.id === item.id, - ), + (dataSource: DataSourceConfig) => dataSource.id === item.id, + ), ); if (repeatedDataSourceList.length > 0) { Dialog.confirm({ @@ -239,14 +241,14 @@ export class DataSourcePane extends PureComponent< } importDataSourceList(); }).catch(err => { - console.warn(err?.message) + console.warn(err?.message); }); } }; renderDetail = () => { const { current } = this.state; - const { dataSourceTypes = [] } = this.props; + const { dataSourceTypes = [], importPlugins = [], exportPlugins = [], formComponents = [] } = this.props; let content = null; if (current.matches('detail.edit')) { @@ -282,7 +284,11 @@ export class DataSourcePane extends PureComponent< } else if (current.matches('detail.import')) { // TODO // pluginName - content = ; + const currentPluginName = current.context.detail?.data?.pluginName?.name; + const importPlugin = importPlugins?.find((item) => item.name === currentPluginName); + const Component = (importPlugin ? importPlugin.component : ImportDetail) as React.ElementType; + content = ; + } else if (current.matches('detail.export')) { // TODO content = ( @@ -325,7 +331,7 @@ export class DataSourcePane extends PureComponent< className = '', helpLink = '', dataSourceTypes = [], - importPlugins, + importPlugins = [], } = this.props; const { current, listMode } = this.state; @@ -346,54 +352,52 @@ export class DataSourcePane extends PureComponent< const isEmpty = current.context.dataSourceList.length === 0; return ( - -
-
- 数据源 - {helpLink && } -
- - +
+ 数据源 + {helpLink && } +
+ + +
+ { + return ( + i.id.indexOf(current.context.dataSourceListFilter.keyword) !== + -1 && + (!current.context.dataSourceListFilter.dataSourceType || + current.context.dataSourceListFilter.dataSourceType === + i.type) + ); + })} + onOperationClick={this.handleOperationClick} /> -
- { - return ( - i.id.indexOf(current.context.dataSourceListFilter.keyword) !== - -1 && - (!current.context.dataSourceListFilter.dataSourceType || - current.context.dataSourceListFilter.dataSourceType === - i.type) - ); - })} - onOperationClick={this.handleOperationClick} - /> -
- {this.renderDetail()}
- + {this.renderDetail()} +
); } } diff --git a/packages/plugin-datasource-pane/src/pane/index.tsx b/packages/plugin-datasource-pane/src/pane/index.tsx index 096463e..1e5f4be 100644 --- a/packages/plugin-datasource-pane/src/pane/index.tsx +++ b/packages/plugin-datasource-pane/src/pane/index.tsx @@ -7,6 +7,8 @@ import _get from 'lodash/get'; import _set from 'lodash/set'; import _isEmpty from 'lodash/isEmpty'; import _isFunction from 'lodash/isFunction'; +import { HTML5Backend } from 'react-dnd-html5-backend'; +import { DndProvider } from 'react-dnd'; import { EditorContext } from '../utils/editor-context'; import { DataSourcePane } from './DataSourcePane'; import { DataSourceFilter } from '../components/DataSourceFilter'; @@ -32,8 +34,6 @@ export interface DataSource { list: InterpretDataSourceConfig[]; } -const stateService = createStateService(); - export { DataSourceForm } from '../components/DataSourceForm'; const PLUGIN_NAME = 'dataSourcePane'; @@ -83,6 +83,8 @@ export default class DataSourcePanePlugin extends PureComponent< exportPlugins: [], }; + stateService = createStateService(); + state = { active: false, panelKey: 1, @@ -110,11 +112,11 @@ export default class DataSourcePanePlugin extends PureComponent< } componentDidMount() { - stateService.start(); + this.stateService.start(); } componentWillUnmount() { - stateService.stop(); + this.stateService.stop(); } handleSchemaChange = (schema: DataSource) => { @@ -166,32 +168,34 @@ export default class DataSourcePanePlugin extends PureComponent< return ( - - { /* @ts-ignore */ } - >, - importPlugins as unknown as Array>, - 'name', - )} - exportPlugins={mergeTwoObjectListByKey( - BUILTIN_IMPORT_PLUGINS as unknown as Array>, - exportPlugins as unknown as Array>, - 'name', - )} - dataSourceTypes={dataSourceTypes} - initialSchema={schema} - onSchemaChange={this.handleSchemaChange} - /> - + + + { /* @ts-ignore */ } + >, + importPlugins as unknown as Array>, + 'name', + )} + exportPlugins={mergeTwoObjectListByKey( + BUILTIN_IMPORT_PLUGINS as unknown as Array>, + exportPlugins as unknown as Array>, + 'name', + )} + dataSourceTypes={dataSourceTypes} + initialSchema={schema} + onSchemaChange={this.handleSchemaChange} + /> + + ); diff --git a/packages/plugin-manual/.gitignore b/packages/plugin-manual/.gitignore deleted file mode 100644 index 7d916c2..0000000 --- a/packages/plugin-manual/.gitignore +++ /dev/null @@ -1,43 +0,0 @@ -node_modules/ -build/ -es/ -lib/ -.idea/ -.vscode/ -jsconfig.json -typings.json -typings/ -~* - -# Packages # -############ -# it's better to unpack these files and commit the raw source -# git has its own built in compression methods -*.7z -*.dmg -*.gz -*.iso -*.jar -*.rar -*.tar -*.zip - -# Logs and databases # -###################### -*.log -*.sql -*.sqlite - -# OS generated files # -###################### -.DS_Store -*.swp -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db -.lock -package-lock.json -.vdev diff --git a/packages/plugin-manual/build.json b/packages/plugin-manual/build.json index 1edfc2f..1767fef 100644 --- a/packages/plugin-manual/build.json +++ b/packages/plugin-manual/build.json @@ -3,7 +3,8 @@ [ "@alilc/build-plugin-alt", { - "type": "plugin" + "type": "plugin", + "inject": true } ], [ diff --git a/packages/plugin-manual/package.json b/packages/plugin-manual/package.json index 0442c29..700637d 100644 --- a/packages/plugin-manual/package.json +++ b/packages/plugin-manual/package.json @@ -1,7 +1,7 @@ { "name": "@alilc/lowcode-plugin-manual", "author": "humphry.huang9@gmail.com", - "version": "1.0.3", + "version": "1.0.4", "description": "低代码产品使用手册", "main": "lib/index.js", "module": "es/index.js", @@ -15,6 +15,7 @@ "pub": "npm publish" }, "publishConfig": { + "registry": "https://registry.npmjs.org/", "access": "public" }, "dependencies": {}, @@ -30,5 +31,10 @@ "build-plugin-fusion": "^0.1.19", "@alilc/build-plugin-alt": "^1.0.0" }, - "license": "MIT" + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/alibaba/lowcode-plugins.git", + "directory": "packages/plugin-manual" + } } diff --git a/packages/plugin-manual/src/index.tsx b/packages/plugin-manual/src/index.tsx index 2c90773..cf85189 100644 --- a/packages/plugin-manual/src/index.tsx +++ b/packages/plugin-manual/src/index.tsx @@ -1,20 +1,8 @@ -import * as React from 'react'; -import { ILowCodePluginContext } from '@alilc/lowcode-engine'; +import { IPublicModelPluginContext } from '@alilc/lowcode-types'; import { IconQuestion } from './icon'; -import { Dialog } from '@alifd/next'; -import { Documents } from './popup'; -const PluginManual = (ctx: ILowCodePluginContext) => { +const PluginManual = (ctx: IPublicModelPluginContext) => { return { - // 插件名,注册环境下唯一 - name: 'PluginManual', - // 依赖的插件(插件名数组) - dep: [], - // 插件对外暴露的数据和方法 - exports() { - return {}; - }, - // 插件的初始化函数,在引擎初始化之后会立刻调用 init() { // 往引擎增加面板 ctx.skeleton.add({ @@ -26,17 +14,7 @@ const PluginManual = (ctx: ILowCodePluginContext) => { icon: IconQuestion, description: '如何使用', onClick() { - Dialog.show({ - title: '低代码产品使用文档', - content: ( - - ), - height: window.innerHeight - 100 + 'px', - style: { - width: window.innerWidth - 300, - }, - footer: false, - }); + window.open('https://lowcode-engine.cn/site/docs/demoUsage/intro', '_blank').focus(); }, }, }); diff --git a/packages/plugin-manual/src/popup.tsx b/packages/plugin-manual/src/popup.tsx deleted file mode 100644 index 3710ddc..0000000 --- a/packages/plugin-manual/src/popup.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { material } from '@alilc/lowcode-engine'; -import { Tree, Tag, Loading } from '@alifd/next'; - -import { IconBug, IconLink } from './icon'; - -export function Documents() { - const [menu, setMenu] = useState([] as Array<{ title: string, url: string }>) - const [loading, setLoading] = useState(false) - const [selection, setSelection] = useState([] as string[]) - - useEffect(() => { - setLoading(true) - fetch('https://lowcode-engine.cn/api/get_usage') - .then((res) => res.json()) - .then((val) => { - const menu = val.data.filter((a: any) => !isNaN(parseInt(a.title))) - menu.sort((a: any, b: any) => parseInt(a.title) > parseInt(b.title) ? 1 : -1) - setMenu(menu) - setSelection(menu.length ? ['0'] : []) - }) - .catch(err => console.error(err)) - .finally(() => { - setLoading(false) - }) - }, []) - - return ( - -
-
- {!loading && ( - { - if (Array.isArray(newSelection) && newSelection.length > 0) { - setSelection(newSelection) - } - }} - isNodeBlock={{ - defaultPadingLeft: 1, - indent: 1, - }} - style={{ lineHeight: '26px' }} - > - {menu.map((item, index) => ( - - ))} - - - {IconLink} - 低代码引擎技术文档 - - )} - onClick={() => { - window.open('https://lowcode-engine.cn/doc') - }} - /> - - {IconLink} - engine - - {getVerionOf('ali-lowcode/ali-lowcode-engine') ?? (window as any).AliLowCodeEngine.version ?? '-'} - - - )} - onClick={() => { - window.open('https://lowcode-engine.cn/doc?url=engine-changelog') - }} - /> - - {IconLink} - ext - - {getVerionOf('ali-lowcode/lowcode-engine-ext') ?? (window as any).AliLowCodeEngineExt.version ?? '-'} - - - )} - onClick={() => { - window.open('https://lowcode-engine.cn/doc?url=engine-ext-changelog') - }} - /> - - {IconBug} - 提交 bug - - )} - onClick={() => { - const assets = material.getAssets() - const message = `## 复现截图 - -## 复现流程与链接 - -## 期望结果 - -## 环境信息 - -- 引擎版本 ${getVerionOf('ali-lowcode/ali-lowcode-engine') ?? (window as any).AliLowCodeEngine.version ?? '-'} -- ext 版本 ${getVerionOf('ali-lowcode/lowcode-engine-ext') ?? (window as any).AliLowCodeEngineExt.version ?? '-'} -- 物料 -${assets.packages - .filter((item: any) => !!item.package) - .map((item: any) => (` - ${item.package}${item.version ? '@' + item.version : ''}`.replace(/@/g, '﹫'))) - .join('\n') -}` - window.open(`https://github.com/alibaba/lowcode-engine/issues/new?body=${ - encodeURIComponent(message) - }`) - }} - /> - - - )} -
- {menu[+selection[0]]?.url && ( -