diff --git a/extensions/iceworks-app/src/locales/en-US.json b/extensions/iceworks-app/src/locales/en-US.json index ca2252941..8656442e3 100644 --- a/extensions/iceworks-app/src/locales/en-US.json +++ b/extensions/iceworks-app/src/locales/en-US.json @@ -30,5 +30,9 @@ "extension.iceworksApp.showDepsQuickPick.quickPickItem.detail": "Install <%= label %>", "extension.iceworksApp.openEntryFile.ErrorMessage": "Cannot find entry", "extension.iceworksApp.extension.title": "Iceworks Settings", - "extension.iceworksApp.extension.emptyWorkplace": "Current workspace is empty, please open or create an application." + "extension.iceworksApp.extension.emptyWorkplace": "Current workspace is empty, please open or create an application.", + "extension.iceworksApp.views.pageViews.createPage": "Create Page", + "extension.iceworksApp.views.pageViews.createPageDetail": "Create page through page templates", + "extension.iceworksApp.views.pageViews.generatePage": "Generate Page", + "extension.iceworksApp.views.pageViews.generatePageDetail": "Generate page through assmebling component materials" } diff --git a/extensions/iceworks-app/src/locales/zh-CN.json b/extensions/iceworks-app/src/locales/zh-CN.json index dd0cd8129..706c4a93b 100644 --- a/extensions/iceworks-app/src/locales/zh-CN.json +++ b/extensions/iceworks-app/src/locales/zh-CN.json @@ -30,5 +30,8 @@ "extension.iceworksApp.showDepsQuickPick.quickPickItem.detail": "安装 <%= label %>", "extension.iceworksApp.openEntryFile.ErrorMessage": "没有找到入口", "extension.iceworksApp.extension.title": "设置 - Iceworks", - "extension.iceworksApp.extension.emptyWorkplace": "当前工作区为空,请打开应用或新建应用。" + "extension.iceworksApp.views.pageViews.createPage": "创建页面", + "extension.iceworksApp.views.pageViews.createPageDetail": "通过配置模板的方式创建页面", + "extension.iceworksApp.views.pageViews.generatePage": "生成页面", + "extension.iceworksApp.views.pageViews.generatePageDetail": "通过区块组装的方式生成页面" } diff --git a/extensions/iceworks-app/src/views/pagesView.ts b/extensions/iceworks-app/src/views/pagesView.ts index d9ddd9011..152a0697a 100644 --- a/extensions/iceworks-app/src/views/pagesView.ts +++ b/extensions/iceworks-app/src/views/pagesView.ts @@ -4,6 +4,7 @@ import * as path from 'path'; import { checkPathExists, registerCommand } from '@iceworks/common-service'; import { pagesPath, projectPath } from '@iceworks/project-service'; import openEntryFile from '../openEntryFile'; +import i18n from '../i18n'; export class PagesProvider implements vscode.TreeDataProvider { private workspaceRoot: string; @@ -85,13 +86,36 @@ class PageTreeItem extends vscode.TreeItem { contextValue = 'page'; } +const addPageQuickPickItems: any[] = [ + { + label: i18n.format('extension.iceworksApp.views.pageViews.createPage'), + detail: i18n.format('extension.iceworksApp.views.pageViews.createPageDetail'), + command: 'iceworks-ui-builder.create-page', + }, + { + label: i18n.format('extension.iceworksApp.views.pageViews.generatePage'), + detail: i18n.format('extension.iceworksApp.views.pageViews.generatePageDetail'), + command: 'iceworks-ui-builder.generate-page', + }, +]; +function showAddPageQuickPicks() { + const quickPick = vscode.window.createQuickPick(); + quickPick.items = addPageQuickPickItems; + quickPick.onDidChangeSelection((change) => { + // @ts-ignore + vscode.commands.executeCommand(change[0].command); + }); + quickPick.onDidHide(() => quickPick.dispose()); + quickPick.show(); +} + export function createPagesTreeView(context: vscode.ExtensionContext) { const pagesProvider = new PagesProvider(context, projectPath); const treeView = vscode.window.createTreeView('pages', { treeDataProvider: pagesProvider }); registerCommand('iceworksApp.pages.add', () => { console.log('iceworksApp: activate iceworks-ui-builder.generate-page'); - vscode.commands.executeCommand('iceworks-ui-builder.generate-page'); + showAddPageQuickPicks(); }); registerCommand('iceworksApp.pages.refresh', () => pagesProvider.refresh()); registerCommand('iceworksApp.pages.openFile', (pagePath) => openEntryFile(pagePath)); diff --git a/extensions/iceworks-ui-builder/CHANGELOG.md b/extensions/iceworks-ui-builder/CHANGELOG.md index fda30cb27..80a719cd7 100644 --- a/extensions/iceworks-ui-builder/CHANGELOG.md +++ b/extensions/iceworks-ui-builder/CHANGELOG.md @@ -2,6 +2,7 @@ ## 0.1.8 +- feat: support create page - feat: support component-generator dark theme ## 0.1.7 diff --git a/extensions/iceworks-ui-builder/README.md b/extensions/iceworks-ui-builder/README.md index 5f66c8704..5249d512d 100644 --- a/extensions/iceworks-ui-builder/README.md +++ b/extensions/iceworks-ui-builder/README.md @@ -31,7 +31,7 @@ Through GUI, you can quickly assemble pages with materials. ### Activate 1. Open vscode command palette by `Ctrl+Shift+P` or `⇧⌘P` . -2. In the command palette, type 'Iceworks: Generate page' and click on the selected item or press enter on the keyboard to evoke page-builder extension. +2. In the command palette, type `Iceworks: Generate page` and click on the selected item or press enter on the keyboard to evoke page-builder extension. ### Usage @@ -41,6 +41,28 @@ Through GUI, you can quickly assemble pages with materials. ![generate-page](https://img.alicdn.com/tfs/TB1ErOEjnM11u4jSZPxXXahcXXa-1440-900.gif) +## Create Page + +Create the page by visual configuration + +### Activate + +![demo](https://user-images.githubusercontent.com/56879942/91519113-4a211d00-e924-11ea-8fbe-36170dedc765.gif) + +1. Open vscode command palette by `Ctrl+Shift+P` or `⇧⌘P` . +2. In the command palette, type `Iceworks: Create page` and click on the selected item or press enter on the keyboard to evoke page-builder extension. + +### Usage + +![demo](https://user-images.githubusercontent.com/56879942/91536884-03451e80-e948-11ea-98e6-6bf89b62e932.gif) + +1. Select a page template. +2. Click `NEXT` to enter the configuration page. +3. Configure page templates to generate a customized page. +4. Click the `CREATE PAGE` button to add the page information. +5. Enter the name of the page and route information. +6. Click `OK` button to generate page code, which will be generated under 'SRC/Pages/' directory. + ## Create Component Iceworks provides a huge amount of high quality materials for React and [Rax](https://rax.js.org/) apps. You can select materials to create components. diff --git a/extensions/iceworks-ui-builder/README.zh-CN.md b/extensions/iceworks-ui-builder/README.zh-CN.md index 5f76d954e..ae8d51266 100644 --- a/extensions/iceworks-ui-builder/README.zh-CN.md +++ b/extensions/iceworks-ui-builder/README.zh-CN.md @@ -41,6 +41,28 @@ ![拼接区块组装页面](https://img.alicdn.com/tfs/TB1ErOEjnM11u4jSZPxXXahcXXa-1440-900.gif) +## 通过模板配置生成页面 + +使用页面模板,可视化配置的方式生成页面。 + +### 激活 + +![使用示例](https://user-images.githubusercontent.com/56879942/91519104-442b3c00-e924-11ea-93a3-e52bbc83f05d.gif) + +1. 通过 `⇧⌘P` 或 `Ctrl+Shift+P` 快捷键唤醒命令面板 +2. 在命令面板中输入 `Iceworks: 创建页面` ,点击选中的项目或按下键盘回车键,激活页面生成插件 + +### 使用 + +![使用示例](https://user-images.githubusercontent.com/56879942/91536902-08a26900-e948-11ea-9c80-41fe4387b48f.gif) + +1. 选择一个页面模板 +2. 点击 `下一步` ,进入配置页面 +3. 进行页面模板的配置,通过使用这些配置生成个性化页面 +4. 点击 `创建页面` 按钮,添加页面信息表单 +5. 填入页面的名称,路由信息 +6. 点击 `确认` 按钮,生成页面代码,页面代码将生成到 `src/pages/` 目录下。 + ## 下载远程物料到本地 Iceworks 为 React 和 [Rax](https://rax.js.org/) 应用提供了海量的高质量物料,通过选择物料快速创建前端组件。 diff --git a/extensions/iceworks-ui-builder/package.json b/extensions/iceworks-ui-builder/package.json index fd516c6d4..f91bc38b1 100644 --- a/extensions/iceworks-ui-builder/package.json +++ b/extensions/iceworks-ui-builder/package.json @@ -22,7 +22,8 @@ "activationEvents": [ "onCommand:iceworks-ui-builder.generate-page", "onCommand:iceworks-ui-builder.create-component", - "onCommand:iceworks-ui-builder.generate-component" + "onCommand:iceworks-ui-builder.generate-component", + "onCommand:iceworks-ui-builder.create-page" ], "repository": { "type": "git", @@ -42,6 +43,10 @@ { "command": "iceworks-ui-builder.generate-page", "title": "%iceworksUIBuilder.commands.generatePage.title%" + }, + { + "command": "iceworks-ui-builder.create-page", + "title": "%iceworksUIBuilder.commands.createPage.title%" } ], "configuration": { @@ -107,6 +112,7 @@ "compile": "tsc -p ./tsconfig.json" }, "devDependencies": { + "@types/lodash": "^4.14.160", "@types/node": "^13.11.0", "@types/vscode": "^1.41.0", "ts-loader": "^7.0.5", diff --git a/extensions/iceworks-ui-builder/package.nls.json b/extensions/iceworks-ui-builder/package.nls.json index 3c1d8a878..0c8185a46 100644 --- a/extensions/iceworks-ui-builder/package.nls.json +++ b/extensions/iceworks-ui-builder/package.nls.json @@ -4,5 +4,6 @@ "iceworksUIBuilder.configuration.properties.iceworks.materialSources.description": "Iceworks material sources, decide which materials to use.", "iceworksUIBuilder.commands.generateComponent.title": "Iceworks: Generate Component", "iceworksUIBuilder.commands.createComponent.title": "Iceworks: Create Component", - "iceworksUIBuilder.commands.generatePage.title": "Iceworks: Generate Page" + "iceworksUIBuilder.commands.generatePage.title": "Iceworks: Generate Page", + "iceworksUIBuilder.commands.createPage.title": "Iceworks: Create Page" } diff --git a/extensions/iceworks-ui-builder/package.nls.zh-cn.json b/extensions/iceworks-ui-builder/package.nls.zh-cn.json index f640999da..dd2bcbfbb 100644 --- a/extensions/iceworks-ui-builder/package.nls.zh-cn.json +++ b/extensions/iceworks-ui-builder/package.nls.zh-cn.json @@ -4,5 +4,6 @@ "iceworksUIBuilder.configuration.properties.iceworks.materialSources.description": "Iceworks 物料源,决定使用哪些物料。", "iceworksUIBuilder.commands.generateComponent.title": "Iceworks: 生成组件", "iceworksUIBuilder.commands.createComponent.title": "Iceworks: 创建组件", - "iceworksUIBuilder.commands.generatePage.title": "Iceworks: 生成页面" + "iceworksUIBuilder.commands.generatePage.title": "Iceworks: 生成页面", + "iceworksUIBuilder.commands.createPage.title": "Iceworks: 创建页面" } diff --git a/extensions/iceworks-ui-builder/src/extension.ts b/extensions/iceworks-ui-builder/src/extension.ts index 6777c1ba7..77321a11c 100644 --- a/extensions/iceworks-ui-builder/src/extension.ts +++ b/extensions/iceworks-ui-builder/src/extension.ts @@ -89,6 +89,24 @@ export function activate(context: vscode.ExtensionContext) { activePageGeneraterWebview(); }) ); + function activePageCreatorWebview() { + const webviewPanel: vscode.WebviewPanel = window.createWebviewPanel( + 'iceworks', + i18n.format('extension.iceworksPageCreator.extensnion.webViewTitle'), + ViewColumn.One, + { + enableScripts: true, + retainContextWhenHidden: true, + } + ); + webviewPanel.webview.html = getHtmlForWebview(extensionPath, 'pagecreator', true); + connectService(webviewPanel, context, { services, recorder }); + } + subscriptions.push( + registerCommand('iceworks-ui-builder.create-page', function () { + activePageCreatorWebview(); + }) + ); } export function deactivate() {} diff --git a/extensions/iceworks-ui-builder/src/locales/en-US.json b/extensions/iceworks-ui-builder/src/locales/en-US.json index cdccdca82..bd72d7f41 100644 --- a/extensions/iceworks-ui-builder/src/locales/en-US.json +++ b/extensions/iceworks-ui-builder/src/locales/en-US.json @@ -1,5 +1,6 @@ { "extension.iceworksComponentGenerator.extension.webviewTitle": "Generate Component - Iceworks", "extension.iceworksComponentBuilder.extension.webviewTitle": "Create Component - Iceworks", - "extension.iceworksPageBuilder.extensnion.webViewTitle": "Generate Page - Iceworks" + "extension.iceworksPageBuilder.extensnion.webViewTitle": "Generate Page - Iceworks", + "extension.iceworksPageCreator.extensnion.webViewTitle": "Create Page - Iceworks" } diff --git a/extensions/iceworks-ui-builder/src/locales/zh-CN.json b/extensions/iceworks-ui-builder/src/locales/zh-CN.json index a1238a347..e27a7b0df 100644 --- a/extensions/iceworks-ui-builder/src/locales/zh-CN.json +++ b/extensions/iceworks-ui-builder/src/locales/zh-CN.json @@ -1,5 +1,6 @@ { "extension.iceworksComponentGenerator.extension.webviewTitle": "生成组件 - Iceworks", "extension.iceworksComponentBuilder.extension.webviewTitle": "创建组件 - Iceworks", - "extension.iceworksPageBuilder.extensnion.webViewTitle": "生成页面 - Iceworks" + "extension.iceworksPageBuilder.extensnion.webViewTitle": "生成页面 - Iceworks", + "extension.iceworksPageCreator.extensnion.webViewTitle": "创建页面 - Iceworks" } diff --git a/extensions/iceworks-ui-builder/web/mocks/material/getData.json b/extensions/iceworks-ui-builder/web/mocks/material/getData.json index 3ce2530c0..e867bdfd0 100644 --- a/extensions/iceworks-ui-builder/web/mocks/material/getData.json +++ b/extensions/iceworks-ui-builder/web/mocks/material/getData.json @@ -246,5 +246,127 @@ "publishTime": "2019-11-07T09:05:00.572Z", "updateTime": "2020-04-08T05:28:38.818Z" } + ], + "pages": [ + { + "name": "BasicPage", + "title": "BasicPage", + "category": "Basic", + "views": [ + { + "title": "", + "props": {}, + "screenshot": "build/views/block_view1.png", + "html": "build/views/block_view1.html" + } + ], + "screenshot": "https://unpkg.com/@alifd/fusion-advanced-detail/screenshot.png", + "description": "intro block", + "homepage": "https://unpkg.com/@alifd/fusion-advanced-detail@0.1.9/build/index.html", + "categories": ["Information"], + "repository": "https://github.com/alibaba-fusion/materials/tree/master/blocks/AdvancedDetail", + "source": { + "type": "npm", + "npm": "@alifd/fusion-advanced-detail", + "version": "0.1.9", + "registry": "https://registry.npmjs.org" + }, + "dependencies": { + "prop-types": "^15.5.8" + }, + "screenshots": ["https://unpkg.com/@alifd/fusion-advanced-detail/screenshot.png"], + "publishTime": "2019-11-28T11:30:32.213Z", + "updateTime": "2020-03-31T12:36:39.300Z" + }, + { + "name": "AdvancePage", + "title": "AdvancePage", + "category": "Other", + "views": [ + { + "title": "", + "props": {}, + "screenshot": "build/views/block_view1.png", + "html": "build/views/block_view1.html" + } + ], + "screenshot": "https://unpkg.com/@alifd/fusion-basic-detail/screenshot.png", + "description": "intro block", + "homepage": "https://unpkg.com/@alifd/fusion-basic-detail@0.1.7/build/index.html", + "categories": ["Information"], + "repository": "https://github.com/alibaba-fusion/materials/tree/master/blocks/BasicDetail", + "source": { + "type": "npm", + "npm": "@alifd/fusion-basic-detail", + "version": "0.1.7", + "registry": "https://registry.npmjs.org" + }, + "dependencies": { + "prop-types": "^15.5.8" + }, + "screenshots": ["https://unpkg.com/@alifd/fusion-basic-detail/screenshot.png"], + "publishTime": "2019-11-28T11:38:31.720Z", + "updateTime": "2020-03-31T12:52:50.478Z" + }, + { + "name": "BasicDetail", + "title": "BasicDetail", + "category": "Information", + "views": [ + { + "title": "", + "props": {}, + "screenshot": "build/views/block_view1.png", + "html": "build/views/block_view1.html" + } + ], + "screenshot": "https://unpkg.com/@alifd/fusion-basic-detail/screenshot.png", + "description": "intro block", + "homepage": "https://unpkg.com/@alifd/fusion-basic-detail@0.1.7/build/index.html", + "categories": ["Information"], + "repository": "https://github.com/alibaba-fusion/materials/tree/master/blocks/BasicDetail", + "source": { + "type": "npm", + "npm": "@alifd/fusion-basic-detail", + "version": "0.1.7", + "registry": "https://registry.npmjs.org" + }, + "dependencies": { + "prop-types": "^15.5.8" + }, + "screenshots": ["https://unpkg.com/@alifd/fusion-basic-detail/screenshot.png"], + "publishTime": "2019-11-28T11:38:31.720Z", + "updateTime": "2020-03-31T12:52:50.478Z" + }, + { + "name": "BasicDetail", + "title": "BasicDetail", + "category": "Information", + "views": [ + { + "title": "", + "props": {}, + "screenshot": "build/views/block_view1.png", + "html": "build/views/block_view1.html" + } + ], + "screenshot": "https://unpkg.com/@alifd/fusion-basic-detail/screenshot.png", + "description": "intro block", + "homepage": "https://unpkg.com/@alifd/fusion-basic-detail@0.1.7/build/index.html", + "categories": ["Information"], + "repository": "https://github.com/alibaba-fusion/materials/tree/master/blocks/BasicDetail", + "source": { + "type": "npm", + "npm": "@alifd/fusion-basic-detail", + "version": "0.1.7", + "registry": "https://registry.npmjs.org" + }, + "dependencies": { + "prop-types": "^15.5.8" + }, + "screenshots": ["https://unpkg.com/@alifd/fusion-basic-detail/screenshot.png"], + "publishTime": "2019-11-28T11:38:31.720Z", + "updateTime": "2020-03-31T12:52:50.478Z" + } ] } diff --git a/extensions/iceworks-ui-builder/web/mocks/page/checkRouteConfigPathExists.json b/extensions/iceworks-ui-builder/web/mocks/page/checkRouteConfigPathExists.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/extensions/iceworks-ui-builder/web/mocks/page/checkRouteConfigPathExists.json @@ -0,0 +1 @@ +{} diff --git a/extensions/iceworks-ui-builder/web/mocks/page/createPage.json b/extensions/iceworks-ui-builder/web/mocks/page/createPage.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/extensions/iceworks-ui-builder/web/mocks/page/createPage.json @@ -0,0 +1 @@ +{} diff --git a/extensions/iceworks-ui-builder/web/mocks/page/getAll.json b/extensions/iceworks-ui-builder/web/mocks/page/getAll.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/extensions/iceworks-ui-builder/web/mocks/page/getAll.json @@ -0,0 +1 @@ +{} diff --git a/extensions/iceworks-ui-builder/web/mocks/page/getTemplateSchema.json b/extensions/iceworks-ui-builder/web/mocks/page/getTemplateSchema.json new file mode 100644 index 000000000..f109ca13f --- /dev/null +++ b/extensions/iceworks-ui-builder/web/mocks/page/getTemplateSchema.json @@ -0,0 +1,104 @@ +{ + "schema": { + "title": "用户任务列表", + "description": "显示用户信息和用户持有的任务", + "type": "object", + "required": ["isShowUser"], + "properties": { + "isShowUser": { + "type": "boolean", + "title": "是否显示用户信息" + }, + "title": { + "type": "string", + "title": "标题", + "description": "我是一个 Description", + "x-component": "Input" + }, + "userTitle": { + "type": "number", + "title": "用户页面标题" + }, + "object": { + "type": "object", + "title": "object" + }, + "select": { + "type": "string", + "title": "select", + "enum": [1, 2, 3, 4] + }, + "datarange": { + "type": "daterange", + "title": "daterange" + }, + "Time": { + "type": "time", + "title": "time" + }, + "array": { + "type": "array", + "title": "array", + "items": { + "type": "object", + "properties": { + "NO_NAME_FIELD_$0": { + "key": "NO_NAME_FIELD_$0", + "type": "object", + "name": "NO_NAME_FIELD_$0", + "x-component-props": { + "labelCol": 6, + "wrapperCol": 8 + }, + "properties": { + "aa": { + "key": "aa", + "name": "aa", + "x-component": "input", + "description": "hello world", + "title": "字段1" + }, + "bb": { + "key": "bb", + "name": "bb", + "x-component": "input", + "title": "字段2" + }, + "cc": { + "key": "cc", + "name": "cc", + "x-component": "input", + "title": "字段3" + }, + "dd": { + "key": "dd", + "name": "dd", + "x-component": "input", + "title": "字段5" + }, + "ee": { + "key": "ee", + "name": "ee", + "x-component": "input", + "title": "字段6" + }, + "ff": { + "key": "ff", + "name": "ff", + "x-component": "input", + "title": "字段7" + }, + "gg": { + "key": "gg", + "name": "gg", + "x-component": "rangepicker", + "title": "字段8" + } + } + } + } + } + } + } + } +} diff --git a/extensions/iceworks-ui-builder/web/package.json b/extensions/iceworks-ui-builder/web/package.json index dcd3e583b..9c3bb88c9 100644 --- a/extensions/iceworks-ui-builder/web/package.json +++ b/extensions/iceworks-ui-builder/web/package.json @@ -1,12 +1,13 @@ { "name": "web-for-iceworks-component-builder", - "version": "0.1.3", + "version": "0.1.4", "description": "web for Iceworks component builder", "private": true, "devDependencies": { "@types/classnames": "^2.2.10", "@types/react": "^16.8.0", "@types/react-dom": "^16.8.0", + "@types/lodash": "^4.14.160", "build-plugin-css-assets-local": "^0.1.0", "build-plugin-fusion": "^0.1.3", "build-plugin-moment-locales": "^0.1.0", @@ -16,13 +17,17 @@ "dependencies": { "@alifd/next": "~1.19.2", "@alifd/theme-iceworks-dark": "^1.1.0", + "@formily/next": "^1.3.1", + "@formily/next-components": "^1.3.1", "@iceworks/material-ui": "^0.1.5", "@iceworks/vscode-webview": "^0.1.1", + "lodash.forin": "^4.4.0", "moment": "^2.24.0", "react": "^16.8.0", "react-dom": "^16.8.0", "react-intl": "^5.3.2", - "react-sortable-hoc": "^1.11.0" + "react-sortable-hoc": "^1.11.0", + "styled-components": "^5.1.1" }, "scripts": { "start": "icejs start --disable-reload", diff --git a/extensions/iceworks-ui-builder/web/public/pagecreator.html b/extensions/iceworks-ui-builder/web/public/pagecreator.html new file mode 100644 index 000000000..60681e97b --- /dev/null +++ b/extensions/iceworks-ui-builder/web/public/pagecreator.html @@ -0,0 +1,13 @@ + + + + + + + Page Creator + + + +
+ + diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageGenerater/components/RouterDetailForm/index.module.scss b/extensions/iceworks-ui-builder/web/src/components/RouterDetailForm/index.module.scss similarity index 100% rename from extensions/iceworks-ui-builder/web/src/pages/PageGenerater/components/RouterDetailForm/index.module.scss rename to extensions/iceworks-ui-builder/web/src/components/RouterDetailForm/index.module.scss diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageGenerater/components/RouterDetailForm/index.tsx b/extensions/iceworks-ui-builder/web/src/components/RouterDetailForm/index.tsx similarity index 100% rename from extensions/iceworks-ui-builder/web/src/pages/PageGenerater/components/RouterDetailForm/index.tsx rename to extensions/iceworks-ui-builder/web/src/components/RouterDetailForm/index.tsx diff --git a/extensions/iceworks-ui-builder/web/src/locales/en-US.json b/extensions/iceworks-ui-builder/web/src/locales/en-US.json index e0b562bb1..4dc9ed4e4 100644 --- a/extensions/iceworks-ui-builder/web/src/locales/en-US.json +++ b/extensions/iceworks-ui-builder/web/src/locales/en-US.json @@ -1,19 +1,26 @@ { - "web.iceworksUIBuilder.componentCreator.getMaterialError": "Fail to obtain materials. Please try again later.", - "web.iceworksUIBuilder.componentCreator.getDataError": "Fail to obtain material data. Please try again later.", + "web.iceworksUIBuilder.getDataError": "Fail to get material data. Please try agin later.", + "web.iceworksUIBuilder.getMaterialError": "Fail to obtain materials. Please try again later.", + "web.iceworksUIBuilder.inputComponentNamePlaceHolder": "Component name must start with [A-Z] and only contains letters and numbers. Special characters are not allowed.", "web.iceworksUIBuilder.componentCreator.noComponentName": "Please Enter Component Name.", "web.iceworksUIBuilder.componentCreator.didNotSeletBlock": "Please choose a block before generate.", "web.iceworksUIBuilder.componentCreator.generateSuccess": "Create component successfully.", "web.iceworksUIBuilder.componentCreator.inputComponentName": "1. Enter Component Name.", - "web.iceworksUIBuilder.componentCreator.inputComponentNamePlaceHolder": "Component name must start with [A-Z] and only contains letters and numbers. Special characters are not allowed.", "web.iceworksUIBuilder.componentCreator.selectBlock": "2. Choose A Block", - "web.iceworksUIBuilder.componentCreator.generate": "Create Component", - "web.iceworksUIBuilder.pageGenerater.failGetMaterial": "Fail to get materials. Please try agin later.", - "web.iceworksUIBuilder.pageGenerater.failGetData": "Fail to get material data. Please try agin later.", + "web.iceworksUIBuilder.componentCreator.generateComponent": "Create Component", + "web.iceworksUIBuilder.pageCreator.didNotSeletPage": "Please choose a page template。", + "web.iceworksUIBuilder.pageCreator.selectPage": "Choose A Page Template:", + "web.iceworksUIBuilder.pageCreator.noPageName": "Please enter a page name first。", + "web.iceworksUIBuilder.pageCreator.createPageSuccess": "Create Page Success!", + "web.iceworksUIBuilder.pageCreator.next": "NEXT", + "web.iceworksUIBuilder.pageCreator.previous": "PREVIOUS", + "web.iceworksUIBuilder.pageCreator.createPage": "CREATE PAGE", + "web.iceworksUIBuilder.pageCreator.reset": "RESET", + "web.iceworksUIBuilder.pageCreator.defaultTitle": "Page Template Setting", + "web.iceworksUIBuilder.pageCreator.defaultDescription": "Plase Complete This Form To Customize Page Material", "web.iceworksUIBuilder.pageGenerater.enterPageName": "Please enter page name.", "web.iceworksUIBuilder.pageGenerater.successCreatePage": "Page generated successfully.", "web.iceworksUIBuilder.pageGenerater.enterPageNameTitle": "Enter Page Name", - "web.iceworksUIBuilder.pageGenerater.pageNameFormat": "Page name must starts with [A-Z] and only contains letters and numbers. Special characters are not allowed.", "web.iceworksUIBuilder.pageGenerater.chooseBlock": "Choose Blocks", "web.iceworksUIBuilder.pageGenerater.createPage": "Generate Page", "web.iceworksUIBuilder.pageGenerater.PageSelect.SelectFromRight": "Please choose block from the right side." diff --git a/extensions/iceworks-ui-builder/web/src/locales/zh-CN.json b/extensions/iceworks-ui-builder/web/src/locales/zh-CN.json index 78aba10c8..dc8d8ceaa 100644 --- a/extensions/iceworks-ui-builder/web/src/locales/zh-CN.json +++ b/extensions/iceworks-ui-builder/web/src/locales/zh-CN.json @@ -1,18 +1,26 @@ { - "web.iceworksUIBuilder.componentCreator.getMaterialError": "获取物料源信息失败,请稍后再试。", - "web.iceworksUIBuilder.componentCreator.getDataError": "获取物料集合信息失败,请稍后再试。", + "web.iceworksUIBuilder.getDataError": "获取物料集合信息失败,请稍后再试。", + "web.iceworksUIBuilder.getMaterialError": "获取物料源信息失败,请稍后再试。", + "web.iceworksUIBuilder.inputComponentNamePlaceHolder": "名称必须英文字母 A-Z 开头,只包含英文和数字,不允许有特殊字符", "web.iceworksUIBuilder.componentCreator.noComponentName": "请填写组件名。", "web.iceworksUIBuilder.componentCreator.didNotSeletBlock": "请选择使用的区块。", "web.iceworksUIBuilder.componentCreator.generateSuccess": "组件生成成功!", "web.iceworksUIBuilder.componentCreator.inputComponentName": "1. 填写组件名:", - "web.iceworksUIBuilder.componentCreator.inputComponentNamePlaceHolder": "名称必须英文字母 A-Z 开头,只包含英文和数字,不允许有特殊字符", "web.iceworksUIBuilder.componentCreator.selectBlock": "2. 选择使用的区块:", - "web.iceworksUIBuilder.componentCreator.generate": "创建组件", - "web.iceworksUIBuilder.pageGenerater.failGetMaterial": "获取物料源失败,请稍后再试。", - "web.iceworksUIBuilder.pageGenerater.failGetData": "获取物料集合信息失败,请稍后再试。", + "web.iceworksUIBuilder.componentCreator.generateComponent": "创建组件", + "web.iceworksUIBuilder.pageCreator.didNotSeletPage": "请选择使用的页面模板。", + "web.iceworksUIBuilder.pageCreator.selectPage": "选择使用的页面模板:", + "web.iceworksUIBuilder.pageCreator.noPageName": "请填写页面名称。", + "web.iceworksUIBuilder.pageCreator.createPageSuccess": "创建页面成功!", + "web.iceworksUIBuilder.pageCreator.next": "下一步", + "web.iceworksUIBuilder.pageCreator.previous": "上一步", + "web.iceworksUIBuilder.pageCreator.createPage": "创建页面", + "web.iceworksUIBuilder.pageCreator.reset": "重置", + "web.iceworksUIBuilder.pageCreator.defaultTitle": "页面模板配置表单", + "web.iceworksUIBuilder.pageCreator.defaultDescription": "请进行配置以生成个性化表格", "web.iceworksUIBuilder.pageGenerater.enterPageName": "请填写页面名称。", "web.iceworksUIBuilder.pageGenerater.successCreatePage": "生成页面成功", - "web.iceworksUIBuilder.pageGenerater.pageNameFormat": "名称必须英文字母 A-Z 开头,只包含英文和数字,不允许有特殊字符", + "web.iceworksUIBuilder.pageGenerater.enterPageNameTitle": "填写页面名称", "web.iceworksUIBuilder.pageGenerater.chooseBlock": "选择区块", "web.iceworksUIBuilder.pageGenerater.createPage": "生成页面", "web.iceworksUIBuilder.pageGenerater.PageSelect.SelectFromRight": "请从右侧选择区块。" diff --git a/extensions/iceworks-ui-builder/web/src/pages/ComponentCreator/index.tsx b/extensions/iceworks-ui-builder/web/src/pages/ComponentCreator/index.tsx index 8a11d7594..193c17a7b 100644 --- a/extensions/iceworks-ui-builder/web/src/pages/ComponentCreator/index.tsx +++ b/extensions/iceworks-ui-builder/web/src/pages/ComponentCreator/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { Notification, Button, Input } from '@alifd/next'; import Material from '@iceworks/material-ui'; import { LocaleProvider } from '@/i18n'; @@ -26,7 +26,7 @@ const Home = () => { sources = await callService('material', 'getSourcesByProjectType'); } catch (e) { Notification.error({ - content: intl.formatMessage({ id: 'web.iceworksUIBuilder.componentCreator.getMaterialError' }), + content: intl.formatMessage({ id: 'web.iceworksUIBuilder.getMaterialError' }), }); } @@ -40,7 +40,7 @@ const Home = () => { data = await callService('material', 'getData', source); } catch (e) { Notification.error({ - content: intl.formatMessage({ id: 'web.iceworksUIBuilder.componentCreator.getDataError' }), + content: intl.formatMessage({ id: 'web.iceworksUIBuilder.getDataError' }), }); } console.log('getData', data); @@ -109,7 +109,7 @@ const Home = () => {
{
diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageCreator/app.ts b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/app.ts new file mode 100644 index 000000000..8dc4788a6 --- /dev/null +++ b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/app.ts @@ -0,0 +1,13 @@ +import { createApp } from 'ice'; +import Home from './index'; + +const appConfig = { + router: { + routes: [{ path: '/', component: Home }], + }, + app: { + rootId: 'ice-container', + }, +}; + +createApp(appConfig); diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageCreator/configForm.tsx b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/configForm.tsx new file mode 100644 index 000000000..9502eaeef --- /dev/null +++ b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/configForm.tsx @@ -0,0 +1,178 @@ +/* eslint-disable no-param-reassign */ +import React, { useState, useRef, useEffect } from 'react'; +import { SchemaForm, Submit, Reset } from '@formily/next'; +import { FormattedMessage, useIntl } from 'react-intl'; +import * as nextComponents from '@formily/next-components'; +import { Button, Notification, Loading } from '@alifd/next'; +import forIn from 'lodash.forin'; +import RouterDetailForm from '@/components/RouterDetailForm'; +import styles from './index.module.scss'; +import callService from '../../callService'; + +nextComponents.setup(); + +export default ({ + templateSchema, + originResetData, + setCurrentStep, + currentStep, + isCreating, + setIsCreating, + selectedPage, +}) => { + const intl = useIntl(); + const [loading, setLoading] = useState(true); + const formilySchema = useRef({ title: undefined, description: undefined }); + const [visible, setVisible] = useState(false); + const [routerConfig, setRouterConfig] = useState([]); + const [isConfigurableRouter, setIsConfigurableRouter] = useState(true); + const [templateData, setTemplateData] = useState({}); + const [components, setComponents] = useState({}); + + useEffect(() => { + const tmpComponents = {}; + forIn(nextComponents, (value, key) => { + if (key !== 'setup') { + tmpComponents[key] = value; + } + }); + setComponents(tmpComponents); + setLoading(false); + }, []); + + function getDefaultFromType(type) { + // TODO: 丰富所有类型的默认值。 + switch (type) { + case 'string': + return ''; + case 'boolean': + return false; + case 'number': + return 0; + case 'array': + return []; + case 'object': + return {}; + default: + return ''; + } + } + + function getDefaultData() { + const defaultSetting = {}; + forIn(templateSchema.properties, (prop, key) => { + defaultSetting[key] = prop.default !== undefined ? prop.default : getDefaultFromType(prop.type); + }); + return defaultSetting; + } + + function getTemplateData(userConfig) { + const templateData = getDefaultData(); + forIn(templateData, (val, key) => { + templateData[key] = userConfig[key] !== undefined ? userConfig[key] : val; + }); + return templateData; + } + + async function getRouterForm(setting) { + try { + const isRouteConfigPathExists = await callService('page', 'checkRouteConfigPathExists'); + setIsConfigurableRouter(isRouteConfigPathExists); + if (isRouteConfigPathExists) { + // configurable router + const config = await callService('page', 'getAll'); + setRouterConfig(config); + } + setTemplateData(getTemplateData(setting)); + setVisible(true); + } catch (err) { + Notification.error({ + className: err.message, + }); + } + } + + async function createPage(values) { + try { + setIsCreating(true); + await callService('page', 'createPage', { + ...selectedPage, + pageName: values.pageName, + templateData, + }); + + if (isConfigurableRouter) { + await callService('page', 'createRouter', values); + } + Notification.success({ + content: intl.formatMessage({ id: 'web.iceworksUIBuilder.pageCreator.createPageSuccess' }), + }); + } catch (e) { + Notification.error({ content: e.message }); + } finally { + setIsCreating(false); + setVisible(false); + resetData(); + } + } + + function resetData() { + originResetData(); + setRouterConfig([]); + } + function onClose() { + setVisible(false); + } + + return ( + <> + {loading ? ( + + ) : ( + <> +

+ {formilySchema.current.title || + intl.formatMessage({ id: 'web.iceworksUIBuilder.pageCreator.defaultTitle' })} +

+

+ {formilySchema.current.description || + intl.formatMessage({ id: 'web.iceworksUIBuilder.pageCreator.defaultDescription' })} +

+ { + getRouterForm(setting); + }} + > +
+ + + + + + + +
+ +
+ + )} + + ); +}; diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageCreator/index.module.scss b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/index.module.scss new file mode 100644 index 000000000..4f3553f4a --- /dev/null +++ b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/index.module.scss @@ -0,0 +1,61 @@ +.wrap { + overflow: hidden; + padding: 20px; + width: 640px; + margin-left: auto; + margin-right: auto; + + .list { + overflow: hidden; + + .item { + margin-bottom: 24px; + &:last-child { + margin-bottom: 0; + } + .label { + margin-bottom: 14px; + font-size: 14px; + } + .select { + height: 560px; + :global { + .next-tabs-nav-extra { + .next-icon { + color: $color-text1-4 !important; + } + } + } + + a[rel='noopener noreferrer'] { + color: $color-text1-4; + text-decoration: none; + } + } + .pageNameInput { + width: 100%; + } + } + } + + .opts { + margin-top: 24px; + display: flex; + justify-content: center; + align-items: center; + } +} + +.blockIsDraging { + z-index: 99999; + overflow: hidden; + border: 1px solid $color-line1-1; + + img { + width: 607px; + } +} +.btn { + margin: 10px; + min-width: 70px; +} diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageCreator/index.tsx b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/index.tsx new file mode 100644 index 000000000..ba1f0ca91 --- /dev/null +++ b/extensions/iceworks-ui-builder/web/src/pages/PageCreator/index.tsx @@ -0,0 +1,130 @@ +import React, { useState } from 'react'; +import { Notification, Button, Input } from '@alifd/next'; +import Material from '@iceworks/material-ui'; +import { LocaleProvider } from '@/i18n'; +import { useIntl, FormattedMessage } from 'react-intl'; +import callService from '../../callService'; +import styles from './index.module.scss'; +import ConfigForm from './configForm'; +import '@alifd/theme-iceworks-dark/dist/next.css'; + +const Home = () => { + const intl = useIntl(); + const [selectedPage, setSelectedPage] = useState([]); + const [downloading, setDownloading] = useState(false); + const [isCreating, setIsCreating] = useState(false); + const [currentStep, setCurrentStep] = useState(0); + const [schema, setSchema] = useState({}); + const pages = [ + <> +
+
+
+ +
+
+ +
+
+
+
+ +
+ , + , + ]; + + function resetData() { + setSelectedPage(undefined); + } + + async function onSettingsClick() { + try { + await callService('common', 'executeCommand', 'iceworksApp.configHelper.start'); + } catch (e) { + Notification.error({ content: e.message }); + } + } + + async function getSources() { + let sources = []; + try { + sources = await callService('material', 'getSourcesByProjectType'); + } catch (e) { + Notification.error({ + content: intl.formatMessage({ id: 'web.iceworksUIBuilder.getMaterialError' }), + }); + } + + console.log('getSources', sources); + return sources; + } + + async function getData(source: string) { + let data = {}; + try { + data = await callService('material', 'getData', source); + } catch (e) { + Notification.error({ + content: intl.formatMessage({ id: 'web.iceworksUIBuilder.getDataError' }), + }); + } + console.log('getData', data); + return data; + } + + function onSelect(page) { + console.log(page); + setSelectedPage(page); + } + + async function getConfigPage() { + console.log('selectedPage', selectedPage); + setDownloading(true); + try { + const data = { + page: selectedPage, + }; + + if (data.page.length < 1) { + throw new Error(intl.formatMessage({ id: 'web.iceworksUIBuilder.pageCreator.didNotSeletPage' })); + } + const templateConfig = await callService('page', 'getTemplateSchema', selectedPage); + setSchema(templateConfig.schema); + setCurrentStep(currentStep + 1); + } catch (error) { + Notification.error({ content: error.message }); + } + setDownloading(false); + } + + return
{pages[currentStep]}
; +}; + +const IntlHome = () => { + return ( + + + + ); +}; + +export default IntlHome; diff --git a/extensions/iceworks-ui-builder/web/src/pages/PageGenerater/index.tsx b/extensions/iceworks-ui-builder/web/src/pages/PageGenerater/index.tsx index a7ded9608..79eeeeaaf 100644 --- a/extensions/iceworks-ui-builder/web/src/pages/PageGenerater/index.tsx +++ b/extensions/iceworks-ui-builder/web/src/pages/PageGenerater/index.tsx @@ -5,8 +5,8 @@ import Material from '@iceworks/material-ui'; import { LocaleProvider } from '@/i18n'; import { useIntl, FormattedMessage } from 'react-intl'; import { IMaterialData } from '@iceworks/material-utils'; +import RouterDetailForm from '@/components/RouterDetailForm'; import PageSelected from './components/PageSelected'; -import RouterDetailForm from './components/RouterDetailForm'; import callService from '../../callService'; import styles from './index.module.scss'; @@ -27,7 +27,7 @@ const Home = () => { sources = await callService('material', 'getSourcesByProjectType'); } catch (e) { Notification.error({ - content: intl.formatMessage({ id: 'web.iceworksUIBuilder.pageGenerater.failGetMaterial' }), + content: intl.formatMessage({ id: 'web.iceworksUIBuilder.getMaterialError' }), }); } @@ -40,7 +40,7 @@ const Home = () => { try { data = await callService('material', 'getData', source); } catch (e) { - Notification.error({ content: intl.formatMessage({ id: 'web.iceworksUIBuilder.pageGenerater.failGetData' }) }); + Notification.error({ content: intl.formatMessage({ id: 'web.iceworksUIBuilder.getDataError' }) }); } console.log('getData', data); return data; diff --git a/packages/block-service/package.json b/packages/block-service/package.json index 97770ed89..a7aad0d8b 100644 --- a/packages/block-service/package.json +++ b/packages/block-service/package.json @@ -1,6 +1,6 @@ { "name": "@iceworks/block-service", - "version": "0.1.12", + "version": "0.1.13", "description": "Iceworks block service for VSCode extension.", "files": [ "lib" diff --git a/packages/block-service/src/index.ts b/packages/block-service/src/index.ts index a52d24257..32ac0bd78 100644 --- a/packages/block-service/src/index.ts +++ b/packages/block-service/src/index.ts @@ -2,24 +2,23 @@ import * as path from 'path'; import * as vscode from 'vscode'; import * as fsExtra from 'fs-extra'; import * as glob from 'glob'; -import * as readFiles from 'fs-readdir-recursive'; -import { getAndExtractTarball, readPackageJSON } from 'ice-npm-utils'; -import { getTarballURLByMaterielSource, IMaterialBlock } from '@iceworks/material-utils'; +import { IMaterialBlock } from '@iceworks/material-utils'; import { - projectPath, getProjectLanguageType, pagesPath, COMPONENT_DIR_NAME, jsxFileExtnames, checkIsTemplate, + projectPath, } from '@iceworks/project-service'; import { - createNpmCommand, getTagTemplate, getImportInfos, getLastAcitveTextEditor, getImportTemplate, - getIceworksTerminal, + getFolderLanguageType, + bulkInstallMaterialsDependencies, + bulkDownloadMaterials, } from '@iceworks/common-service'; import * as upperCamelCase from 'uppercamelcase'; import * as transfromTsToJs from 'transform-ts-to-js'; @@ -28,66 +27,36 @@ import { generateBlockName } from './utils/generateBlockName'; const { window, Position } = vscode; -function getBlockType(blockSourceSrcPath) { - const files = readFiles(blockSourceSrcPath); - - const index = files.findIndex((item) => { - return /\.ts(x)/.test(item); - }); - - return index >= 0 ? 'ts' : 'js'; -} - /** * Generate block code */ export const bulkGenerate = async function (blocks: IMaterialBlock[], localPath: string) { - await bulkDownload(blocks, localPath); - await bulkInstallDependencies(blocks); + const blocksTempDir = path.join(localPath, '.temp-block'); + await bulkDownloadMaterials(blocks, blocksTempDir); + await renderBlocks(blocks, blocksTempDir, localPath); + await fsExtra.remove(blocksTempDir); + await bulkInstallMaterialsDependencies(blocks, projectPath); }; /** - * Download blocks code to page + * Render blocks code to targetDir */ -export const bulkDownload = async function (blocks: IMaterialBlock[], localPath: string, log?: (text: string) => void) { +export const renderBlocks = async function ( + blocks: IMaterialBlock[], + blockTempDir: string, + targetDir: string, + log?: (text: string) => void +) { if (!log) { log = (text) => console.log(text); } return await Promise.all( blocks.map(async (block: any) => { - const blockSourceNpm = block.source.npm; - - await fsExtra.mkdirp(localPath); - const blockName: string = upperCamelCase(block.name); - - let tarballURL: string; - try { - log(i18n.format('package.block-service.downloadBlock.getDownloadUrl')); - tarballURL = await getTarballURLByMaterielSource(block.source); - } catch (error) { - error.message = i18n.format('package.block-service.downloadBlock.downloadError', { blockName, tarballURL }); - throw error; - } - log(i18n.format('package.block-service.downloadBlock.unzipCode')); - const blockDir = path.join(localPath, blockName); - const blockTempDir = path.join(localPath, `.${blockName}.temp`); - - try { - await getAndExtractTarball(blockTempDir, tarballURL, ({ percent }) => { - log(i18n.format('package.block-service.downloadBlock.process', { percent: (percent * 100).toFixed(2) })); - }); - } catch (error) { - error.message = i18n.format('package.block-service.uzipError', { blockName, tarballURL }); - if (error.code === 'ETIMEDOUT' || error.code === 'ESOCKETTIMEDOUT') { - error.message = i18n.format('package.block-service.uzipOutTime', { blockName, tarballURL }); - } - await fsExtra.remove(blockTempDir); - throw error; - } - - const blockSourceSrcPath = path.join(blockTempDir, 'src'); - const blockType = getBlockType(blockSourceSrcPath); + const blockName = upperCamelCase(block.name); + const blockSourceSrcPath = path.join(blockTempDir, blockName, 'src'); + const blockSrcPath = path.join(targetDir, blockName, 'src'); + const blockType = getFolderLanguageType(blockSourceSrcPath); const projectType = await getProjectLanguageType(); console.log('blockType: ', blockType, 'projectType: ', projectType); @@ -106,49 +75,12 @@ export const bulkDownload = async function (blocks: IMaterialBlock[], localPath: }); } - await fsExtra.move(blockSourceSrcPath, blockDir); - await fsExtra.remove(blockTempDir); - return blockDir; + await fsExtra.move(blockSourceSrcPath, blockSrcPath); + return targetDir; }) ); }; -/** - * Installation block dependencies - */ -export const bulkInstallDependencies = async function (blocks: IMaterialBlock[]) { - const projectPackageJSON = await readPackageJSON(projectPath); - const { terminals } = vscode.window; - - // get all dependencies from blocks - const blocksDependencies: { [packageName: string]: string } = {}; - blocks.forEach(({ dependencies }: any) => Object.assign(blocksDependencies, dependencies)); - - // filter existing dependencies of project - const filterDependencies: { [packageName: string]: string }[] = []; - Object.keys(blocksDependencies).forEach((packageName) => { - if (!projectPackageJSON.dependencies.hasOwnProperty(packageName)) { - filterDependencies.push({ - [packageName]: blocksDependencies[packageName], - }); - } - }); - - if (filterDependencies.length > 0) { - const deps = filterDependencies.map((dependency) => { - const [packageName, version]: [string, string] = Object.entries(dependency)[0]; - return `${packageName}@${version}`; - }); - - const terminal = getIceworksTerminal(); - terminal.show(); - terminal.sendText(`cd '${projectPath}'`, true); - terminal.sendText(createNpmCommand('install', deps.join(' '), '--save'), true); - } else { - return []; - } -}; - export async function addBlockCode(block: IMaterialBlock) { const templateError = i18n.format('package.block-service.templateError', { jsxFileExtnames: jsxFileExtnames.join(','), @@ -183,7 +115,7 @@ export async function addBlockCode(block: IMaterialBlock) { materialOutputChannel.show(); materialOutputChannel.appendLine(i18n.format('package.block-service.startObtainBlock')); try { - const blockDir = await bulkDownload([{ ...block, name: blockName }], componentsPath, (text) => { + const blockDir = await bulkDownloadMaterials([{ ...block, name: blockName }], componentsPath, (text) => { materialOutputChannel.appendLine(`> ${text}`); }); materialOutputChannel.appendLine(i18n.format('package.block-service.obtainDone', { blockDir })); @@ -195,7 +127,7 @@ export async function addBlockCode(block: IMaterialBlock) { } // install block dependencies - await bulkInstallDependencies([block]); + await bulkInstallMaterialsDependencies([block], projectPath); } export async function insertBlock(activeTextEditor: vscode.TextEditor, blockName: string) { diff --git a/packages/block-service/src/locales/en-US.json b/packages/block-service/src/locales/en-US.json index c655389cc..44fc97d92 100644 --- a/packages/block-service/src/locales/en-US.json +++ b/packages/block-service/src/locales/en-US.json @@ -1,13 +1,4 @@ { - "package.block-service.downloadBlock.getDownloadUrl": "Obtain Download URL...", - "package.block-service.downloadBlock.getDownloadUrlError": "Failed to obtain url, please copy and open <%= repository %> in browse.", - "package.block-service.downloadBlock.unzipCode": "Download and unzip code...", - "package.block-service.downloadBlock.unzipCodeError": "Error in unzipping <%= blockName %>,please copy and download from this url: :<%= tarballURL %>", - "package.block-service.downloadBlock.process": "===>>> Downloading:<%= percent %>%", - "package.block-service.downloadBlock.downloadError": "Block <%= blockName %> download timeout, please copy and download from this url: :<%= tarballURL %>", - "package.block-service.downloadError": "Failed to obtain zips from <%= blockSourceNpm %> ,try to clone the <%= repository %> repository manually.", - "package.block-service.uzipError": "Failed to unzip <%= blockName %>,download from:<%= tarballURL %>", - "package.block-service.uzipOutTime": "Uzip <%= blockName %> timeout,download from:<%= tarballURL %>", "package.block-service.templateError": "You can only add block codes to <%= jsxFileExtnames %> ", "package.block-service.notPageFileError": "You can only add block codes to files in <%= pagesPath %>", "package.block-service.startObtainBlock": "> Obtain block codes...", diff --git a/packages/block-service/src/locales/zh-CN.json b/packages/block-service/src/locales/zh-CN.json index 386939cf1..b70cbfe6a 100644 --- a/packages/block-service/src/locales/zh-CN.json +++ b/packages/block-service/src/locales/zh-CN.json @@ -1,13 +1,4 @@ { - "package.block-service.downloadBlock.getDownloadUrl": "获取区块代码包下载地址", - "package.block-service.downloadBlock.getDownloadUrlError": "获取区块代码包地址失败,请手动拷贝代码仓库:<%= repository %>", - "package.block-service.downloadBlock.unzipCode": "下载区块代码包并解压", - "package.block-service.downloadBlock.unzipCodeError": "解压区块<%= blockName %>出错,请手动下载区块:<%= tarballURL %>", - "package.block-service.downloadBlock.process": "===>>> 进度:<%= percent %>%", - "package.block-service.downloadBlock.downloadError": "区块<%= blockName %>下载超时,请手动下载区块:<%= tarballURL %>", - "package.block-service.downloadError": "从 <%= blockSourceNpm %> 获取压缩包链接失败,您可以尝试手动克隆 <%= repository %> 仓库", - "package.block-service.uzipError": "解压 <%= blockName %> 失败,压缩包链接地址是:<%= tarballURL %>", - "package.block-service.uzipOutTime": "解压 <%= blockName %> 超时,压缩包链接地址是:<%= tarballURL %>", "package.block-service.templateError": "只能向 <%= jsxFileExtnames %> 文件添加区块代码", "package.block-service.notPageFileError": "只能向 <%= pagesPath %> 下的页面文件添加区块代码", "package.block-service.startObtainBlock": "> 开始获取区块代码", diff --git a/packages/common-service/package.json b/packages/common-service/package.json index 213ae0ce3..37105e54d 100644 --- a/packages/common-service/package.json +++ b/packages/common-service/package.json @@ -1,6 +1,6 @@ { "name": "@iceworks/common-service", - "version": "0.1.15", + "version": "0.1.16", "description": "Iceworks common service for VSCode extension.", "files": [ "lib" @@ -12,11 +12,15 @@ "@babel/parser": "^7.10.4", "@babel/traverse": "^7.10.4", "@iceworks/constant": "^0.1.0", + "@iceworks/i18n": "^0.1.0", + "@iceworks/material-utils": "^0.1.5", "@iceworks/recorder": "^0.1.0", "axios": "^0.19.2", "co": "4.6.0", "fs-extra": "^9.0.0", - "ice-npm-utils": "^2.0.0" + "fs-readdir-recursive": "^1.1.0", + "ice-npm-utils": "^2.0.0", + "uppercamelcase": "^3.0.0" }, "devDependencies": { "@types/axios": "^0.14.0", diff --git a/packages/common-service/src/i18n.ts b/packages/common-service/src/i18n.ts new file mode 100644 index 000000000..c0c80a5f2 --- /dev/null +++ b/packages/common-service/src/i18n.ts @@ -0,0 +1,11 @@ +import * as vscode from 'vscode'; +import I18nService from '@iceworks/i18n'; +import * as zhCNTextMap from './locales/zh-CN.json'; +import * as enUSTextMap from './locales/en-US.json'; + +const i18n = new I18nService(); +i18n.registry('zh-cn', zhCNTextMap); +i18n.registry('en', enUSTextMap); +i18n.setLocal(vscode.env.language); + +export default i18n; diff --git a/packages/common-service/src/index.ts b/packages/common-service/src/index.ts index 0169960b6..417b1fb50 100644 --- a/packages/common-service/src/index.ts +++ b/packages/common-service/src/index.ts @@ -1,7 +1,8 @@ -import { checkAliInternal } from 'ice-npm-utils'; +import { checkAliInternal, getAndExtractTarball, readPackageJSON } from 'ice-npm-utils'; import * as fse from 'fs-extra'; import * as vscode from 'vscode'; import * as path from 'path'; +import * as readFiles from 'fs-readdir-recursive'; import axios from 'axios'; import { recordDAU, recordExecuteCommand } from '@iceworks/recorder'; import { @@ -10,7 +11,10 @@ import { ALI_FUSION_MATERIAL_URL, ALI_NPM_REGISTRY, } from '@iceworks/constant'; +import * as upperCamelCase from 'uppercamelcase'; +import { getTarballURLByMaterielSource, IMaterialPage, IMaterialBlock } from '@iceworks/material-utils'; import { IImportDeclarations, getImportDeclarations } from './utils/getImportDeclarations'; +import i18n from './i18n'; // eslint-disable-next-line const co = require('co'); @@ -304,6 +308,97 @@ export function getIceworksTerminal(terminalName = 'Iceworks') { return terminal; } +export const getFolderLanguageType = (templateSourceSrcPath) => { + const files = readFiles(templateSourceSrcPath); + + const index = files.findIndex((item) => { + return /\.ts(x)/.test(item); + }); + + return index >= 0 ? 'ts' : 'js'; +}; + +/** + * Install materials dependencies + */ +export const bulkInstallMaterialsDependencies = async function ( + materials: IMaterialPage[] | IMaterialBlock[], + projectPath: string +) { + const projectPackageJSON = await readPackageJSON(projectPath); + + // get all dependencies from templates + const pagesDependencies: { [packageName: string]: string } = {}; + materials.forEach(({ dependencies }: any) => Object.assign(pagesDependencies, dependencies)); + + // filter existing dependencies of project + const filterDependencies: { [packageName: string]: string }[] = []; + Object.keys(pagesDependencies).forEach((packageName) => { + if (!projectPackageJSON.dependencies.hasOwnProperty(packageName)) { + filterDependencies.push({ + [packageName]: pagesDependencies[packageName], + }); + } + }); + + if (filterDependencies.length > 0) { + const deps = filterDependencies.map((dependency) => { + const [packageName, version]: [string, string] = Object.entries(dependency)[0]; + return `${packageName}@${version}`; + }); + + const terminal = getIceworksTerminal(); + terminal.show(); + terminal.sendText(`cd '${projectPath}'`, true); + terminal.sendText(createNpmCommand('install', deps.join(' '), '--save'), true); + } else { + return []; + } +}; + +export const bulkDownloadMaterials = async function ( + materials: IMaterialPage[] | IMaterialBlock[], + tmpPath: string, + log?: (text: string) => void +) { + if (!log) { + log = (text) => console.log(text); + } + + return await Promise.all( + // @ts-ignore + materials.map(async (template: any) => { + await fse.mkdirp(tmpPath); + const materialName: string = upperCamelCase(template.name); + + let tarballURL: string; + try { + log(i18n.format('package.common-service.downloadMaterial.getDownloadUrl')); + tarballURL = await getTarballURLByMaterielSource(template.source); + } catch (error) { + error.message = i18n.format('package.common-service.downloadMaterial.downloadError', { + materialName, + tarballURL, + }); + throw error; + } + log(i18n.format('package.common-service.downloadMaterial.unzipCode')); + const downloadPath = path.join(tmpPath, materialName); + try { + await getAndExtractTarball(downloadPath, tarballURL, ({ percent }) => { + log(i18n.format('package.common-service.downloadMaterial.process', { percent: (percent * 100).toFixed(2) })); + }); + } catch (error) { + error.message = i18n.format('package.common-service.uzipError', { materialName, tarballURL }); + if (error.code === 'ETIMEDOUT' || error.code === 'ESOCKETTIMEDOUT') { + error.message = i18n.format('package.common-service.uzipOutTime', { materialName, tarballURL }); + } + await fse.remove(tmpPath); + throw error; + } + }) + ); +}; export function openMaterialsSettings() { if (vscode.extensions.getExtension('iceworks-team.iceworks-app')) { executeCommand('iceworksApp.configHelper.start', 'iceworks.materialSources'); diff --git a/packages/common-service/src/locales/en-US.json b/packages/common-service/src/locales/en-US.json new file mode 100644 index 000000000..b9d52f066 --- /dev/null +++ b/packages/common-service/src/locales/en-US.json @@ -0,0 +1,8 @@ +{ + "package.common-service.downloadMaterial.getDownloadUrl": "Obtain Download URL...", + "package.common-service.downloadMaterial.downloadError": "Material <%= materialName %> download timeout, please copy and download from this url: :<%= tarballURL %>", + "package.common-service.downloadMaterial.unzipCode": "Download and unzip code...", + "package.common-service.downloadMaterial.process": "===>>> Downloading:<%= percent %>%", + "package.common-service.uzipError": "Failed to unzip <%= materialName %>,download from:<%= tarballURL %>", + "package.common-service.uzipOutTime": "Uzip <%= materialName %> timeout,download from:<%= tarballURL %>" +} diff --git a/packages/common-service/src/locales/zh-CN.json b/packages/common-service/src/locales/zh-CN.json new file mode 100644 index 000000000..290663335 --- /dev/null +++ b/packages/common-service/src/locales/zh-CN.json @@ -0,0 +1,8 @@ +{ + "package.common-service.downloadMaterial.getDownloadUrl": "获取物料代码包下载地址", + "package.common-service.downloadMaterial.downloadError": "物料<%= materialName %>下载超时,请手动下载物料:<%= tarballURL %>", + "package.common-service.downloadMaterial.unzipCode": "下载物料代码包并解压", + "package.common-service.downloadMaterial.process": "===>>> 进度:<%= percent %>%", + "package.common-service.uzipError": "解压 <%= materialName %> 失败,压缩包链接地址是:<%= tarballURL %>", + "package.common-service.uzipOutTime": "解压 <%= materialName %> 超时,压缩包链接地址是:<%= tarballURL %>" +} diff --git a/packages/common-service/tsconfig.json b/packages/common-service/tsconfig.json index 56c61d223..2876f7153 100644 --- a/packages/common-service/tsconfig.json +++ b/packages/common-service/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "baseUrl": "./", "rootDir": "src", - "outDir": "lib" + "outDir": "lib", + "resolveJsonModule": true }, "exclude": ["src/__tests__", "lib", "scripts"] } diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 769f83523..ac72181bf 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@iceworks/i18n", - "version": "0.1.0", + "version": "0.1.1", "description": "I18nService for iceworks", "main": "lib/index.js", "scripts": { @@ -12,8 +12,7 @@ "author": "", "license": "MIT", "dependencies": { - "loadash": "^1.0.0", - "lodash": "^4.17.19" + "lodash.template": "^4.5.0" }, "publishConfig": { "access": "public" diff --git a/packages/i18n/src/index.ts b/packages/i18n/src/index.ts index 4612848a6..696a8f45d 100644 --- a/packages/i18n/src/index.ts +++ b/packages/i18n/src/index.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +import template from 'lodash.template'; export interface ITextMap { // "${namespace}.${extensionName}.${moudelName}.${fieldName}": "xxx" @@ -24,6 +24,6 @@ export default class I18n { return ''; } - return args ? _.template(i18nformatString)(args) : i18nformatString; + return args ? template(i18nformatString)(args) : i18nformatString; } } diff --git a/packages/material-ui/package.json b/packages/material-ui/package.json index 33b33e50d..cec139d0f 100644 --- a/packages/material-ui/package.json +++ b/packages/material-ui/package.json @@ -1,6 +1,6 @@ { "name": "@iceworks/material-ui", - "version": "0.1.9", + "version": "0.1.10", "description": "Material panel for display and select materials.", "files": [ "demo/", @@ -54,6 +54,6 @@ "access": "public" }, "license": "MIT", - "homepage": "https://unpkg.com/@iceworks/material-ui@0.1.9/build/index.html", + "homepage": "https://unpkg.com/@iceworks/material-ui@0.1.10/build/index.html", "gitHead": "fc5b35f95ab4cc24898845916acf598c2f34d576" } diff --git a/packages/material-ui/src/components/page.module.scss b/packages/material-ui/src/components/page.module.scss new file mode 100644 index 000000000..fa30fbebf --- /dev/null +++ b/packages/material-ui/src/components/page.module.scss @@ -0,0 +1,87 @@ +@import '~@alifd/next/lib/core/index.scss'; + +.container { + transition: transform 0.3s ease; + display: block; + cursor: pointer; + overflow: hidden; + position: relative; + height: 120px; + padding: 5px 20px; + margin-bottom: 24px; + background-color: #252422; + &:hover { + text-decoration: none; + transform: translateY(-6px); + .actions { + transform: translateY(0); + } + } + + &.selected { + border-color: $color-line1-3; + } +} + +.screenshot { + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 160px; + transition: all 0.3s ease; + + img { + max-width: 100%; + max-height: 100%; + display: block; + } +} + +.title { + margin: 0; + padding: 10px 0; +} + +.desc { + color: $color-text1-2; +} + +.actions { + position: absolute; + bottom: 0; + left: 0; + right: 0; + border-radius: 0 0 4px 4px; + display: flex; + align-items: center; + justify-content: space-around; + transition: transform 0.3s ease; + transform: translateY(100%); + z-index: 10; + + .button { + display: flex; + align-items: center; + justify-content: center; + width: 50%; + height: 35px; + line-height: 35px; + font-size: 14px; + font-weight: bold; + background: $color-fill1-3; + color: $color-text1-4; + cursor: pointer; + + &:hover { + background-color: $color-fill1-4; + } + + .githubImg, + .eyeImg, + .downloadImg { + width: 20px; + margin-right: 6px; + } + } +} diff --git a/packages/material-ui/src/components/page.tsx b/packages/material-ui/src/components/page.tsx new file mode 100644 index 000000000..73225a567 --- /dev/null +++ b/packages/material-ui/src/components/page.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import { IMaterialBlock, PLACEHOLDER_IMG } from '@iceworks/material-utils'; +import classnames from 'classnames'; +import { Icon } from '@alifd/next'; +import * as styles from './page.module.scss'; + +export const MaterialPage: React.FC<{ + dataSource: IMaterialBlock; + onClick?: (dataSource: IMaterialBlock) => void; + selected?: boolean; +}> = ({ dataSource, onClick, selected }) => { + function handleClick() { + onClick && onClick(dataSource); + } + return ( +
+ {selected && ( + + )} +
+ {dataSource.isNewly ?
NEW
: null} + {dataSource.title} +
+
{dataSource.title}
+ +
+ ); +}; diff --git a/packages/material-ui/src/components/type.tsx b/packages/material-ui/src/components/type.tsx index 56e938ee5..885eac8b4 100644 --- a/packages/material-ui/src/components/type.tsx +++ b/packages/material-ui/src/components/type.tsx @@ -8,11 +8,13 @@ import { IMaterialComponent, IMaterialBase, CUSTOM_CATEGORY, + IMaterialPage, } from '@iceworks/material-utils'; import { MaterialScaffold } from './scaffold'; import { MaterialBlock } from './block'; import { MaterialComponent } from './component'; import { MaterialBase } from './base'; +import { MaterialPage } from './page'; import * as styles from './type.module.scss'; const { Cell } = ResponsiveGrid; @@ -24,9 +26,11 @@ interface ContentProps extends IMaterialTypeDatum { selectedBlocks?: IMaterialBlock[]; selectedComponents?: IMaterialComponent[]; selectedBases?: IMaterialBase[]; + selectedPages?: IMaterialPage[]; onComponentClick?: (dataSource: IMaterialComponent) => void; onBaseClick?: (dataSource: IMaterialBase) => void; onBlockClick?: (dataSource: IMaterialBlock) => void; + onPageClick?: (dataSource: IMaterialPage) => void; onScaffoldClick?: (dataSource: IMaterialScaffold) => void; } @@ -36,10 +40,12 @@ const Content: React.FC = ({ typeId, colSpan, selectedBlocks, + selectedPages, selectedComponents, selectedBases, onComponentClick, onBaseClick, + onPageClick, onBlockClick, onScaffoldClick, }) => { @@ -106,6 +112,28 @@ const Content: React.FC = ({ } else { $ele = $block; } + } else if (typeId === 'pages') { + const $page = ( + sellectedPage.name === item.name) + : false + } + onClick={onPageClick} + /> + ); + if (cIndex === 0 && index > 3 && scrollId) { + $ele = ( + + {$page} + + ); + } else { + $ele = $page; + } } else if (typeId === 'components') { $ele = ( void; onComponentClick?: (dataSource: IMaterialComponent) => void; onBlockClick?: (dataSource: IMaterialBlock) => void; + onPageClick?: (dataSorce: IMaterialPage[]) => void; onScaffoldClick?: (dataSource: IMaterialScaffold) => void; }> = ({ sources, currentSource, onChangeSource, extra, isLoadingSources, ...others }) => { const sourceActiveKey = sources.length ? currentSource : EMPTY_TAB_KEY; diff --git a/packages/material-utils/package.json b/packages/material-utils/package.json index 401f0a1f0..fea620da1 100644 --- a/packages/material-utils/package.json +++ b/packages/material-utils/package.json @@ -1,6 +1,6 @@ { "name": "@iceworks/material-utils", - "version": "0.1.5", + "version": "0.1.6", "description": "General tool library for materials.", "files": [ "lib" diff --git a/packages/material-utils/src/methods.ts b/packages/material-utils/src/methods.ts index 1723e1c8c..b13a1271f 100644 --- a/packages/material-utils/src/methods.ts +++ b/packages/material-utils/src/methods.ts @@ -10,7 +10,7 @@ import { import { CUSTOM_CATEGORY } from './constant'; export function convertMaterialData(materialData: IMaterialData): IMaterialTypeDatum[] { - const { blocks, scaffolds, components, bases } = materialData; + const { blocks, scaffolds, components, bases, pages } = materialData; const hasBase = bases && bases.length > 0; const componentName = hasBase ? '业务组件' : '组件'; const materialGroup: IMaterialTypeDatum[] = []; @@ -31,6 +31,14 @@ export function convertMaterialData(materialData: IMaterialData): IMaterialTypeD }); } + if (pages) { + materialGroup.push({ + name: '页面', + id: 'pages', + categoryData: getMaterialCategoryData(pages), + }); + } + if (components) { materialGroup.push({ name: componentName, @@ -46,6 +54,7 @@ export function convertMaterialData(materialData: IMaterialData): IMaterialTypeD categoryData: getMaterialCategoryData(bases as IMaterialBase[]), }); } + console.log('materialGroup', materialGroup); return materialGroup; } diff --git a/packages/material-utils/src/types.ts b/packages/material-utils/src/types.ts index 65ac00e44..fef2111e3 100644 --- a/packages/material-utils/src/types.ts +++ b/packages/material-utils/src/types.ts @@ -86,10 +86,30 @@ export interface IMaterialBlock { isNewly: boolean; } +export interface IMaterialPage { + name: string; + title: string; + description: string; + homepage: string; + categories: string[]; + repository: string; + source: IMaterialNpmSource; + dependencies: INpmDependencies; + screenshot: string; + screenshots: string[]; + publishTime: string; + updateTime: string[]; + uid: string[]; + isNewly: boolean; + templateData?: any; + pageName: any; +} + export interface IMaterialData { type: string; name: string; blocks: IMaterialBlock[]; + pages: IMaterialPage[]; components: IMaterialComponent[]; scaffolds: IMaterialScaffold[]; bases?: IMaterialBase[]; diff --git a/packages/page-service/package.json b/packages/page-service/package.json index be33993f2..06a4bc8a9 100644 --- a/packages/page-service/package.json +++ b/packages/page-service/package.json @@ -1,6 +1,6 @@ { "name": "@iceworks/page-service", - "version": "0.1.11", + "version": "0.1.12", "description": "Iceworks page service for VSCode extension.", "files": [ "lib" @@ -13,12 +13,15 @@ "@babel/traverse": "^7.10.5", "@babel/types": "^7.10.5", "@iceworks/block-service": "^0.1.5", + "@iceworks/common-service": "^0.1.14", + "@iceworks/i18n": "^0.1.0", "@iceworks/material-utils": "^0.1.3", "@iceworks/project-service": "^0.1.4", - "@iceworks/i18n": "^0.1.0", "ejs": "^3.1.3", "fs-extra": "^9.0.0", + "glob": "^7.1.6", "prettier": "^2.0.5", + "transform-ts-to-js": "^0.1.0", "uppercamelcase": "^3.0.0" }, "devDependencies": { diff --git a/packages/page-service/src/index.ts b/packages/page-service/src/index.ts index 877d05fbe..e74b94c81 100644 --- a/packages/page-service/src/index.ts +++ b/packages/page-service/src/index.ts @@ -1,7 +1,8 @@ import * as path from 'path'; -import * as fsExtra from 'fs-extra'; +import * as fse from 'fs-extra'; import * as prettier from 'prettier'; -import { IMaterialBlock } from '@iceworks/material-utils'; +import * as glob from 'glob'; +import { IMaterialBlock, IMaterialPage } from '@iceworks/material-utils'; import { pagesPath, COMPONENT_DIR_NAME, @@ -10,12 +11,19 @@ import { projectPath, } from '@iceworks/project-service'; import { bulkGenerate } from '@iceworks/block-service'; +import { + bulkDownloadMaterials, + bulkInstallMaterialsDependencies, + getFolderLanguageType, +} from '@iceworks/common-service'; import * as upperCamelCase from 'uppercamelcase'; import * as ejs from 'ejs'; +import * as transfromTsToJs from 'transform-ts-to-js'; import reactPageTemplate from './templates/template.react'; import vuePageTemplate from './templates/template.vue'; import { bulkCreate } from './router'; import i18n from './i18n'; +import renderEjsTemplates from './utils/renderEjsTemplates'; export * from './router'; @@ -36,9 +44,9 @@ export const generate = async function ({ const pagePath = path.join(pagesPath, pageName); // ensure that the root directory of the page store exists - await fsExtra.mkdirp(pagePath); + await fse.mkdirp(pagePath); - const isPagePathExists = await fsExtra.pathExists(pagePath); + const isPagePathExists = await fse.pathExists(pagePath); if (!isPagePathExists) { throw new Error(i18n.format('package.pageService.index.pagePathExistError', { name })); } @@ -71,7 +79,7 @@ export const generate = async function ({ parser: prettierParserType, }); - await fsExtra.writeFile(dist, rendered, 'utf-8'); + await fse.writeFile(dist, rendered, 'utf-8'); } catch (error) { remove(pageName); throw error; @@ -94,9 +102,72 @@ export async function createRouter(data) { * @param name {string} Page folder name */ export const remove = async function (name: string) { - await fsExtra.remove(path.join(pagesPath, name)); + await fse.remove(path.join(pagesPath, name)); }; export const addBlocks = async function (blocks: IMaterialBlock[], pageName: string) { return await bulkGenerate(blocks, path.join(pagesPath, pageName, COMPONENT_DIR_NAME)); }; + +export const getTemplateSchema = async (selectPage: IMaterialPage) => { + const templateTempDir = path.join(pagesPath, '.template'); + try { + await bulkDownloadMaterials([selectPage], templateTempDir); + const templateSchema = await fse.readJSON( + path.join(pagesPath, '.template', selectPage.name, 'config', 'settings.json') + ); + await fse.remove(templateTempDir); + return templateSchema; + } catch (err) { + await fse.remove(templateTempDir); + throw err; + } +}; + +export const createPage = async (selectPage: IMaterialPage) => { + const templateTempDir: string = path.join(pagesPath, '.template'); + try { + await bulkDownloadMaterials([selectPage], templateTempDir); + await renderPage(selectPage); + await bulkInstallMaterialsDependencies([selectPage], projectPath); + await fse.remove(templateTempDir); + } catch (err) { + await fse.remove(templateTempDir); + throw err; + } +}; + +export const renderPage = async (page: IMaterialPage) => { + console.log('renderPage', page); + const templateName = page.name; + const pageName: string = upperCamelCase(page.pageName); + const templatePath: string = path.join(pagesPath, '.template', `${templateName}`); + const targetPath: string = path.join(pagesPath, `${pageName}`); + const templateData = page.templateData; + + if (fse.existsSync(targetPath)) { + throw new Error(i18n.format('package.pageService.index.pagePathExistError', { name: pageName })); + } + + await renderEjsTemplates(templateData, templatePath); + const pageSourceSrcPath = path.join(templatePath, 'src'); + const pageType = getFolderLanguageType(pageSourceSrcPath); + const projectType = await getProjectLanguageType(); + + if (pageType === 'ts' && projectType === 'js') { + const files = glob.sync('**/*.@(ts|tsx)', { + cwd: pageSourceSrcPath, + }); + + console.log('transfrom ts to js', files.join(',')); + + transfromTsToJs(files, { + cwd: pageSourceSrcPath, + outDir: pageSourceSrcPath, + action: 'overwrite', + }); + } + await fse.move(pageSourceSrcPath, targetPath); + + return targetPath; +}; diff --git a/packages/page-service/src/locales/en-US.json b/packages/page-service/src/locales/en-US.json index 7e417ab58..b1a1a5c9a 100644 --- a/packages/page-service/src/locales/en-US.json +++ b/packages/page-service/src/locales/en-US.json @@ -1,3 +1,3 @@ { - "package.pageService.index.pagePathExistError": "Page folder「<%= name %> exists,please enter a new page name。" + "package.pageService.index.pagePathExistError": "Page folder「<%= name %>」 exists,please enter a new page name。" } diff --git a/packages/page-service/src/utils/renderEjsTemplates.ts b/packages/page-service/src/utils/renderEjsTemplates.ts new file mode 100644 index 000000000..fa984dbfb --- /dev/null +++ b/packages/page-service/src/utils/renderEjsTemplates.ts @@ -0,0 +1,46 @@ +import * as _ from 'lodash'; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import * as glob from 'glob'; +import * as ejs from 'ejs'; +import * as util from 'util'; + +export default async function renderEjsTemplates(templateData: object, templateDir: string) { + return new Promise((resolve, reject) => { + glob( + '**', + { + cwd: templateDir, + ignore: ['node_modules/**'], + nodir: true, + dot: true, + }, + (err, files) => { + if (err) { + return reject(err); + } + + Promise.all( + files.map((file) => { + const filepath = path.join(templateDir, file); + return renderFile(filepath, templateData); + }) + ) + .then(() => resolve()) + .catch(reject); + } + ); + }); +} + +async function renderFile(templateFilepath: string, data: any) { + const asyncRenderFile = util.promisify(ejs.renderFile); + try { + const content = await asyncRenderFile(templateFilepath, data); + const targetFilePath = templateFilepath.replace(/\.ejs$/, ''); + await fse.rename(templateFilepath, targetFilePath); + await fse.writeFile(targetFilePath, content); + } catch (err) { + console.log('RenderErr', err); + } +} diff --git a/yarn.lock b/yarn.lock index e607b5427..028a217e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11105,11 +11105,6 @@ load-json-file@^5.3.0: strip-bom "^3.0.0" type-fest "^0.3.0" -loadash@^1.0.0: - version "1.0.0" - resolved "https://registry.npm.taobao.org/loadash/download/loadash-1.0.0.tgz#b92e54d809f3c225f4f9a9cfbaeae5b56de1ca9f" - integrity sha1-uS5U2AnzwiX0+anPuurltW3hyp8= - loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz?cache=0&sync_timestamp=1593786187106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-runner%2Fdownload%2Floader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"