From 0746c235f56c84098d646099aec84a937790e65e Mon Sep 17 00:00:00 2001 From: Scarqin Date: Tue, 1 Nov 2022 21:41:26 +0800 Subject: [PATCH] Share api document (#168) --- .dockerignore | 21 + .github/workflows/release.yml | 1 + .gitignore | 3 + CHANGELOG.md | 23 + Dockerfile | 26 + docker-compose.yml | 39 + nginx.conf | 86 + package.json | 6 +- src/app/electron-main/appView.ts | 91 - src/app/electron-main/main.ts | 65 +- src/app/electron-main/updater.ts | 2 +- src/platform/common/i18n.ts | 4 +- src/platform/electron-browser/preload.ts | 131 +- .../electron-main/browserView/browserView.ts | 41 - .../browserView/browserView.type.ts | 9 - src/platform/electron-node/preload.ts | 3 + src/platform/node/configuration/lib/index.ts | 2 +- .../node/configuration/types/index.ts | 2 +- .../node/extension-manager/lib/core.ts | 15 +- .../node/extension-manager/lib/handler.ts | 8 +- .../node/extension-manager/lib/loader.ts | 61 - .../node/extension-manager/lib/manager.ts | 196 +- .../node/extension-manager/types/handler.ts | 31 + .../node/extension-manager/types/index.ts | 3 +- .../node/extension-manager/types/loader.ts | 18 - .../node/extension-manager/types/manager.ts | 131 -- .../node/extension-manager/types/module.ts | 113 + src/platform/node/i18n.ts | 16 +- src/platform/node/mock-server/index.ts | 4 +- src/shared/common/bounds.ts | 93 - src/workbench/browser/.gitignore | 1 + src/workbench/browser/angular.json | 2 +- src/workbench/browser/build/build.js | 14 +- src/workbench/browser/elements/apiContent.ts | 21 + src/workbench/browser/elements/index.ts | 1 + .../browser/elements/service/eventS.ts | 5 +- src/workbench/browser/elements/tree.ts | 98 +- src/workbench/browser/package.json | 4 +- src/workbench/browser/proxy.conf.json | 10 - .../browser/src/app/app-routing.module.ts | 7 +- .../browser/src/app/app.component.ts | 15 +- src/workbench/browser/src/app/app.module.ts | 12 +- src/workbench/browser/src/app/app.service.ts | 5 +- .../services/language/language.service.ts | 6 +- .../browser/src/app/pages/.component.ts | 10 - .../src/app/pages/account.component.ts | 213 +- .../src/app/pages/api/api-tab.service.ts | 69 +- .../src/app/pages/api/api.component.html | 39 +- .../src/app/pages/api/api.component.scss | 15 +- .../src/app/pages/api/api.component.ts | 42 +- .../browser/src/app/pages/api/api.module.ts | 5 +- .../browser/src/app/pages/api/api.service.ts | 20 +- .../group/edit/api-group-edit.component.html | 5 +- .../group/tree/api-group-tree.component.html | 70 +- .../group/tree/api-group-tree.component.scss | 5 +- .../group/tree/api-group-tree.component.ts | 45 +- .../pages/api/history/eo-history.component.ts | 3 +- .../api/http/detail/api-detail.component.ts | 33 +- .../api/http/edit/api-edit.component.html | 99 +- .../pages/api/http/edit/api-edit.component.ts | 7 +- .../pages/api/http/edit/api-edit.module.ts | 2 + .../api/http/mock/api-mock.component.html | 45 +- .../api/http/test/api-test-util.service.ts | 2 +- .../api/http/test/api-test.component.html | 155 +- .../pages/api/http/test/api-test.component.ts | 7 +- .../pages/api/http/test/api-test.module.ts | 4 +- .../api-test-result-response.component.ts | 13 +- .../pages/api/tab/api-tab-operate.service.ts | 63 +- .../pages/api/tab/api-tab-storage.service.ts | 25 +- .../app/pages/api/tab/api-tab.component.html | 23 +- .../app/pages/api/tab/api-tab.component.scss | 10 +- .../app/pages/api/tab/api-tab.component.ts | 8 +- .../api/websocket/websocket.component.ts | 9 +- .../detail/components/custom-tab.component.ts | 75 + .../detail/components/extensions.component.ts | 31 +- .../detail/extension-detail.component.html | 34 +- .../detail/extension-detail.component.ts | 64 +- .../detail/extension-detail.module.ts | 6 +- .../pages/extension/extension.component.ts | 12 +- .../app/pages/extension/extension.model.ts | 2 +- .../app/pages/extension/extension.service.ts | 41 +- .../list/extension-list.component.html | 28 +- .../list/extension-list.component.ts | 6 +- .../browser/src/app/pages/member.component.ts | 243 +- .../browser/src/app/pages/member.module.ts | 41 +- .../app/pages/navbar/navbar.component.html | 54 +- .../app/pages/navbar/navbar.component.scss | 8 +- .../src/app/pages/navbar/navbar.component.ts | 82 +- .../src/app/pages/navbar/navbar.module.ts | 3 +- .../src/app/pages/pages-routing.module.ts | 10 + .../browser/src/app/pages/pages.component.ts | 9 +- .../browser/src/app/pages/pages.module.ts | 3 +- .../src/app/pages/share-routing.module.ts | 29 + .../browser/src/app/pages/share.component.ts | 13 +- .../browser/src/app/pages/share.module.ts | 13 +- .../src/app/pages/user-modal.component.ts | 519 +++-- .../src/app/pages/vue3/vue3.component.html | 5 + .../src/app/pages/vue3/vue3.component.scss | 0 .../src/app/pages/vue3/vue3.component.spec.ts | 25 + .../src/app/pages/vue3/vue3.component.ts | 45 + .../src/app/pages/workspace.component.ts | 128 +- .../browser/src/app/pages/workspace.module.ts | 36 +- .../shared/components/api-script/constant.ts | 35 - .../components/env-list/env-list.component.ts | 40 +- .../shared/components/env/env.component.html | 30 +- .../shared/components/env/env.component.ts | 12 +- .../export-api/export-api.component.ts | 43 +- .../extension-select.component.html | 4 +- .../import-api/import-api.component.ts | 16 +- .../local-workspace-tip.component.ts | 6 +- .../manage-access.component.html | 2 +- .../monaco-editor/monaco-editor.component.ts | 1 - .../setting/common/data-storage.component.ts | 48 +- .../setting/common/extensions.component.ts | 12 +- .../eoapi-settings/extensiton-settings.json | 12 - .../components/setting/setting.component.html | 26 +- .../components/setting/setting.component.ts | 21 +- .../components/sidebar/sidebar.component.html | 8 +- .../components/sidebar/sidebar.component.ts | 93 +- .../components/sidebar/sidebar.model.ts | 4 +- .../components/sidebar/sidebar.service.ts | 2 +- .../split-panel/split.panel.component.ts | 1 + .../components/sync-api/sync-api.component.ts | 22 +- .../remote-node/test-connect.service.ts | 13 +- .../data-source/data-source.service.ts | 105 +- .../shared/services/remote/remote.service.ts | 185 ++ .../src/app/shared/services/share.service.ts | 22 + .../src/app/shared/services/status.service.ts | 24 + .../services/storage/IndexedDB/lib/index.ts | 2 +- .../shared/services/storage/api.service.ts | 49 + .../src/app/shared/services/storage/api.ts | 20 + .../storage/http/lib/baseUrl.service.ts | 70 +- .../shared/services/storage/index.model.ts | 2 +- .../shared/services/storage/local.service.ts | 178 ++ .../shared/services/storage/remote.service.ts | 1361 ++++++----- .../services/storage/storage.service.ts | 4 +- .../web-extension/webExtension.service.ts | 106 + .../services/workspace/workspace.service.ts | 81 +- .../browser/src/app/shared/shared.module.ts | 5 +- src/workbench/browser/src/app/shared/types.ts | 8 - .../browser/src/app/utils/index.utils.ts | 24 +- .../src/app/utils/module-loader/type.ts | 66 - .../browser/src/app/utils/tree/tree.utils.ts | 1 - .../browser/src/assets/theme/antd.less | 1 + .../browser/src/environments/common.ts | 1 + .../src/environments/environment.docker.ts | 13 + .../browser/src/environments/environment.ts | 3 +- src/workbench/browser/src/locale/messages.xlf | 887 ++++---- .../browser/src/locale/messages.zh.xlf | 918 ++++---- src/workbench/browser/src/main.ts | 17 +- src/workbench/browser/src/ng1/index.css | 3 - src/workbench/browser/views/share.ts | 11 +- src/workbench/browser/views/user-modal.ts | 1 + src/workbench/node/{server => }/package.json | 18 +- src/workbench/node/request/libs/apiUtil.js | 30 +- src/workbench/node/server/main.js | 2 +- src/workbench/node/server/socketio.js | 8 +- src/workbench/node/server/yarn.lock | 537 ++--- src/workbench/node/yarn.lock | 1982 +++++++++++++++++ yarn.lock | 95 +- 160 files changed, 7175 insertions(+), 4172 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 nginx.conf delete mode 100644 src/app/electron-main/appView.ts delete mode 100644 src/platform/electron-main/browserView/browserView.ts delete mode 100644 src/platform/electron-main/browserView/browserView.type.ts create mode 100644 src/platform/electron-node/preload.ts delete mode 100644 src/platform/node/extension-manager/lib/loader.ts delete mode 100644 src/platform/node/extension-manager/types/loader.ts delete mode 100644 src/platform/node/extension-manager/types/manager.ts create mode 100644 src/platform/node/extension-manager/types/module.ts delete mode 100644 src/shared/common/bounds.ts create mode 100644 src/workbench/browser/elements/apiContent.ts delete mode 100644 src/workbench/browser/proxy.conf.json delete mode 100644 src/workbench/browser/src/app/pages/.component.ts create mode 100644 src/workbench/browser/src/app/pages/extension/detail/components/custom-tab.component.ts create mode 100644 src/workbench/browser/src/app/pages/vue3/vue3.component.html create mode 100644 src/workbench/browser/src/app/pages/vue3/vue3.component.scss create mode 100644 src/workbench/browser/src/app/pages/vue3/vue3.component.spec.ts create mode 100644 src/workbench/browser/src/app/pages/vue3/vue3.component.ts delete mode 100644 src/workbench/browser/src/app/shared/components/setting/eoapi-settings/extensiton-settings.json create mode 100644 src/workbench/browser/src/app/shared/services/remote/remote.service.ts create mode 100644 src/workbench/browser/src/app/shared/services/share.service.ts create mode 100644 src/workbench/browser/src/app/shared/services/status.service.ts create mode 100644 src/workbench/browser/src/app/shared/services/web-extension/webExtension.service.ts delete mode 100644 src/workbench/browser/src/app/shared/types.ts delete mode 100644 src/workbench/browser/src/app/utils/module-loader/type.ts create mode 100644 src/workbench/browser/src/environments/environment.docker.ts rename src/workbench/node/{server => }/package.json (51%) create mode 100644 src/workbench/node/yarn.lock diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..37c9ec686 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,21 @@ +.DS_Store +node_modules/ +dist/ +release/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json +tests/**/coverage/ + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln + +.vercel +docker-compose.dev.yml +Dockerfile.dev diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34f66cb96..6763d59cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,6 +2,7 @@ name: Release on: push: + # branches: [for debug] tags: - 'v*.*.*' diff --git a/.gitignore b/.gitignore index fa347fbb0..e4e35adee 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ Thumbs.db # *-lock.json -error.log .vercel +nginx-test.conf +docker-compose.dev.yml +Dockerfile.dev diff --git a/CHANGELOG.md b/CHANGELOG.md index ba88c231b..eac66bc3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +# [1.9.0](https://github.com/eolinker/eoapi/compare/v1.8.2...v1.9.0) (2022-10-19) + + +### Features + +* mock lead to download in web ([65c7ecf](https://github.com/eolinker/eoapi/commit/65c7ecffe795844fd24621c05e412a8af17eca09)) + + + +## [1.8.2](https://github.com/eolinker/eoapi/compare/v1.8.1...v1.8.2) (2022-10-18) + + +### Bug Fixes + +* xml2json parser bug ([e2459a2](https://github.com/eolinker/eoapi/commit/e2459a23fc74a7696f5b6f3296c512d28939f6c7)) + + +### Features + +* keep queryParams stay in page ([baad303](https://github.com/eolinker/eoapi/commit/baad3038cbffd38cfea128f92d3cc3073a786e5a)) + + + ## [1.8.1](https://github.com/eolinker/eoapi/compare/v1.8.0...v1.8.1) (2022-10-13) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..f334d2e40 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM node:lts-alpine as builder + +WORKDIR /test-server + +# api 测试服务端口 +ENV NODE_SERVER_PORT 4201 +# websocket 测试服务端口 +ENV EOAPI_WEBSOCKET_POST 4202 + +COPY /src/workbench/node /test-server + +RUN yarn install + +EXPOSE 4201 4202 + +CMD ["yarn", "start:all"] + + +FROM nginx:alpine as production + +ENV NODE_ENV production + +COPY ./src/workbench/browser/dist/ /usr/share/nginx/html +COPY ./nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..c6d5551a3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +version: '3' + +services: + eoapi: + # build: 从当前路径构建镜像 + build: + context: . + dockerfile: Dockerfile + target: production + image: eolinker/eoapi:1.9.0 + container_name: eoapi + restart: always + extra_hosts: + - 'host.docker.internal:host-gateway' + ports: + - '8000:80' + networks: + - eoapi_net + + eoapi-test-server: + # build: 从当前路径构建镜像 + build: + context: . + dockerfile: Dockerfile + target: builder + image: eolinker/eoapi-test-server:1.9.0 + container_name: eoapi-test-server + restart: always + extra_hosts: + - 'host.docker.internal:host-gateway' + ports: + - '4201:4201' + - '4202:4202' + networks: + - eoapi_net + +networks: + eoapi_net: + name: eoapi_net diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 000000000..0696ba28c --- /dev/null +++ b/nginx.conf @@ -0,0 +1,86 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + absolute_redirect off; #取消绝对路径的重定向 + sendfile on; + default_type application/octet-stream; + + gzip on; + gzip_http_version 1.1; + gzip_disable "MSIE [1-6]\."; + gzip_min_length 256; + gzip_vary on; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; + gzip_comp_level 9; + + root /usr/share/nginx/html; + + location / { + return 301 $scheme://$http_host/zh; + } + + location /zh { + alias /usr/share/nginx/html/zh; + index index.html index.htm; + try_files $uri $uri/ /zh/index.html; + } + + location /en { + alias /usr/share/nginx/html/en; + index index.html index.htm; + try_files $uri $uri/ /en/index.html; + } + + # api测试服务 + location /api/unit { + proxy_pass http://eoapi-test-server:4201; # 转发规则 + proxy_set_header Host $proxy_host; # 修改转发请求头,让3000端口的应用可以受到真实的请求 + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + # websocket测试服务 + location ~/socket.io/(.*) { + proxy_pass http://eoapi-test-server:4202; # 转发规则 + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + proxy_set_header X-NginX-Proxy true; + proxy_redirect off; + } + + # 后端服务 + location ^~ /api { + proxy_pass http://eoapi-remote-server:3000; # 转发规则 + proxy_set_header Host $proxy_host; # 修改转发请求头,让3000端口的应用可以受到真实的请求 + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + # 后端服务兼容旧客户端 + location ~ ^/(system|workspace|user|auth|[0-9]+/[0-9]+/api_data|[0-9]+/[0-9]+/group|[0-9]+/[0-9]+/group|[0-9]+/[0-9]+/environment|[0-9]+/[0-9]+/api_test_history|[0-9]+/[0-9]+/mock|[0-9]+/project) { + proxy_pass http://eoapi-remote-server:3000; # 转发规则 + proxy_set_header Host $proxy_host; # 修改转发请求头,让3000端口的应用可以受到真实的请求 + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + rewrite "^/(.*)$" /api/$1 break; + } + + # location ^~ /zh/(.*)/assets/(.*)$ { + # alias /usr/share/nginx/html/zh/assets/$2; + # return 501 /usr/share/nginx/html/zh/assets/$2; + #} + + # location ^~ /zh/\.(gif|jpg|jpeg|png|css|js|ico|svg|ttf|woff2|woff|txt)$ { + # alias /usr/share/nginx/html/zh/$1; + # return 502 /usr/share/nginx/html/zh/$1; + #} +} diff --git a/package.json b/package.json index 466f53b22..091cabb66 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,11 @@ "scripts": { "postinstall": "electron-builder install-app-deps && npx patch-package", "start": "npm-run-all -p start:workbench electron:serve", - "start:web": "cd src/workbench/browser && npm run ng:serve", - "start:testServer": "cd src/workbench/node/server && yarn dev", + "serve:web": "cd src/workbench/browser && npm run ng:serve", + "start:testServer": "cd src/workbench/node && yarn dev", "start:workbench": "cd src/workbench/browser && yarn start", "build:workbench": "cd src/workbench/browser && yarn build", + "docker:build:workbench": "cd src/workbench/browser && yarn build:docker:web", "test:workbench": "cd src/workbench/browser && yarn test", "electron:serve": "wait-on tcp:4200 && npm run electron:dev", "electron:static": "npm run electron:tsc && electron .", @@ -47,6 +48,7 @@ "express": "4.18.1", "fix-path": "3.0.0", "form-data": "^4.0.0", + "http-server": "14.1.1", "iconv-lite": "^0.6.3", "jquery": "^3.3.0", "jsdom": "^11.5.1", diff --git a/src/app/electron-main/appView.ts b/src/app/electron-main/appView.ts deleted file mode 100644 index e40f193d0..000000000 --- a/src/app/electron-main/appView.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { ModuleInfo, ModuleType } from 'eo/platform/node/extension-manager/types'; -import { getViewBounds, SidePosition, ViewBounds, ViewZone } from 'eo/shared/common/bounds'; -import { BrowserView, BrowserWindow } from 'electron'; -import * as path from 'path'; -import { BrowserViewInstance } from 'eo/platform/electron-main/browserView/browserView'; -import { processEnv } from 'eo/platform/node/constant'; -export class AppViews { - mainModuleID: string; - view: BrowserView; - sidePosition: SidePosition = SidePosition.left; - constructor(private win: BrowserWindow) {} - - /** - * 加载app模块 - * @param module - */ - create(module: ModuleInfo) { - if (module && module.moduleType === ModuleType.app) { - if (module.isApp && this.mainModuleID !== module.moduleID) { - this.mainModuleID = module.moduleID; - // this.sidePosition = module.sidePosition; - } - this.createAppView(module); - - if (module.main_node) { - const main_node = require(module.main_node); - if (main_node.module && typeof main_node.module === 'object') { - const _fun = main_node.module; - _fun.setup({ - appView: this.view, - }); - } - } - } - return this.view; - } - - /** - * 删除视图 - */ - remove() { - if (!this.view) { - return; - } - this.view.webContents.closeDevTools(); - this.win.removeBrowserView(this.view); - this.view = undefined; - this.mainModuleID = undefined; - } - - rebuildBounds(sideWidth?: number) { - if (!this.view) { - return; - } - const windBounds = this.win.getContentBounds(); - const _bounds: ViewBounds = getViewBounds( - ViewZone.main, - windBounds.width, - windBounds.height, - this.sidePosition, - sideWidth - ); - this.view.setBounds(_bounds); - } - - /** - * 创建主视图,主要从模块载入文件 - * @param module - */ - private createAppView(module: ModuleInfo) { - const windBounds = this.win.getContentBounds(); - const _bounds: ViewBounds = getViewBounds(ViewZone.main, windBounds.width, windBounds.height, this.sidePosition); - let _view = new BrowserViewInstance({ - bounds: _bounds, - partition: `<${module.moduleID}>`, - preloadPath: path.join(__dirname, '../../', 'platform', 'electron-browser', 'preload.js'), - preload: module.preload, - viewPath: processEnv === 'development' && module.main_debug ? module.main_debug : module.main, - }).init(this.win); - this.remove(); - this.view = _view; - this.view.webContents.openDevTools(); - this.view.webContents.once('did-finish-load', () => { - _view.setBackgroundColor('#FFF'); - }); - this.view.webContents.once('dom-ready', () => { - this.rebuildBounds(); - require('@electron/remote/main').enable(this.view.webContents); - }); - } -} diff --git a/src/app/electron-main/main.ts b/src/app/electron-main/main.ts index 8eb9f7a49..67b42beb3 100644 --- a/src/app/electron-main/main.ts +++ b/src/app/electron-main/main.ts @@ -187,64 +187,20 @@ try { } } }); - ipcMain.on('eo-storage', (event, args) => { - let returnValue: any; - if (args.type === 'default' || args.type === 'remote') { - eoBrowserWindow.win.webContents.send('eo-storage', args); - returnValue = null; - } else if (args.type === 'sync') { - deleteFile(storageTemp); - eoBrowserWindow.win.webContents.send('eo-storage', args); - let data = readJson(storageTemp); - let count: number = 0; - while (data === null) { - if (count > 1500) { - data = { - // status: StorageResStatus.error, - status: 500, - data: 'storage sync load error', - }; - break; - } - data = readJson(storageTemp); - ++count; - } - deleteFile(storageTemp); - returnValue = data; - } else if (args.type === 'result') { - let view = subView.appView ? subView.appView?.view.webContents : eoBrowserWindow.win.webContents; - view.send('storageCallback', args.result); - } - }); // 这里可以封装成类+方法匹配调用,不用多个if else ['on', 'handle'].forEach((eventName) => ipcMain[eventName]('eo-sync', async (event, arg) => { let returnValue: any; - if (arg.action === 'getApiAccessRules') { - // 后期加入权限生成,根据moduleID,上层moduleID,应用范围等 - // 或者是像Android, 跳出权限列表让用户自己选择确认放开的权限。 - const output: string[] = ['getModules', 'getAppModuleList', 'getSlideModuleList', 'hook']; - returnValue = output; - } else if (arg.action === 'getModules') { - returnValue = moduleManager.getModules(true); + if (arg.action === 'getModules') { + returnValue = moduleManager.getModules(); } else if (arg.action === 'getModule') { - returnValue = moduleManager.getModule(arg.data.moduleID); - } else if (arg.action === 'getAppModuleList') { - returnValue = moduleManager.getAppModuleList(); + returnValue = moduleManager.getModule(arg.data.id); } else if (arg.action === 'installModule') { const data = await moduleManager.installExt(arg.data); - if (data.code === 0) { - //subView.mainView.view.webContents.send('moduleUpdate'); - } returnValue = Object.assign(data, { modules: moduleManager.getModules() }); } else if (arg.action === 'uninstallModule') { const data = await moduleManager.uninstall(arg.data); - if (data.code === 0) { - // subView.mainView.view.webContents.send('moduleUpdate'); - } returnValue = Object.assign(data, { modules: moduleManager.getModules() }); - } else if (arg.action === 'getSideModuleList') { - returnValue = moduleManager.getSideModuleList(subView.appView?.mainModuleID || 'default'); } else if (arg.action === 'getFeatures') { returnValue = moduleManager.getFeatures(); } else if (arg.action === 'getFeature') { @@ -257,19 +213,16 @@ try { returnValue = configuration.deleteModuleSettings(arg.data.moduleID); } else if (arg.action === 'getSettings') { returnValue = configuration.getSettings(); - } else if (arg.action === 'getModuleSettings') { - returnValue = configuration.getModuleSettings(arg.data.moduleID); - } else if (arg.action === 'getSidePosition') { - returnValue = subView.appView?.sidePosition; - // 获取mock服务地址 + } else if (arg.action === 'getExtensionSettings') { + returnValue = configuration.getExtensionSettings(arg.data.moduleID); } else if (arg.action === 'getMockUrl') { + // 获取mock服务地址 returnValue = mockServer.getMockUrl(); - // 获取websocket服务端口 } else if (arg.action === 'getWebsocketPort') { + // 获取websocket服务端口 returnValue = websocketPort; - // 重置并初始化mock路由 - } else if (arg.action === 'hook') { - returnValue = 'hook返回'; + } else if (arg.action === 'getExtensionPagePathByName') { + returnValue = moduleManager.setupExtensionPageServer(arg.data.extName); } else { returnValue = 'Invalid data'; } diff --git a/src/app/electron-main/updater.ts b/src/app/electron-main/updater.ts index 9c7910fce..ffe13b10d 100644 --- a/src/app/electron-main/updater.ts +++ b/src/app/electron-main/updater.ts @@ -10,7 +10,7 @@ export class EoUpdater { // url: 'https://packages.eoapi.io', // }); // 是否自动更新 - // autoUpdater.autoDownload = window.eo.getModuleSettings('common.app.autoUpdate') !== false; + // autoUpdater.autoDownload = window.eo.getExtensionSettings('common.app.autoUpdate') !== false; if (appVersion.includes('beta')) autoUpdater.channel = 'beta'; console.log('appVersion', appVersion, autoUpdater.channel); } diff --git a/src/platform/common/i18n.ts b/src/platform/common/i18n.ts index ec1f4690d..e8d7eb8d1 100644 --- a/src/platform/common/i18n.ts +++ b/src/platform/common/i18n.ts @@ -1,10 +1,10 @@ -import { ModuleInfo } from 'eo/platform/node/extension-manager'; +import { ModuleInfo } from "eo/platform/node/extension-manager/types"; /** * Single extension i18 service,chain call */ export class TranslateService { // Default key in package.json translate replace directly - defaultKeys = ['moduleName', 'description', 'author', 'logo']; + defaultKeys = ['moduleName','title','description', 'author', 'logo']; constructor(private module: ModuleInfo, private locale) {} translate() { return this.translateDefaultKey().translateVariableKey().get(); diff --git a/src/platform/electron-browser/preload.ts b/src/platform/electron-browser/preload.ts index 62931c822..5cd016620 100644 --- a/src/platform/electron-browser/preload.ts +++ b/src/platform/electron-browser/preload.ts @@ -1,7 +1,5 @@ import { I18N } from './i18n'; const { ipcRenderer } = require('electron'); -// 可以加上条件判断,根据不同模块id哪些允许放出 -const apiAccessRules = ipcRenderer.sendSync('eo-sync', { action: 'getApiAccessRules' }) || []; // 正在安装中的插件任务列表 const installTask = new Map(); // 正在卸载中的插件任务列表 @@ -25,67 +23,38 @@ const featureModules = new Map(); window.eo = { name: 'Eoapi public api', version: '1.0.0', -}; -// 边栏显示 -// window.eo.sidePosition = ipcRenderer.sendSync('eo-sync', { action: 'getSidePosition' }) || 'left'; -// 获取模块列表 -window.eo.getModules = () => { - return ipcRenderer.sendSync('eo-sync', { action: 'getModules' }); -}; -// 获取某个模块 -window.eo.getModule = (moduleID) => { - return ipcRenderer.sendSync('eo-sync', { action: 'getModule', data: { moduleID: moduleID } }); -}; -// 获取App应用列表 -window.eo.getAppModuleList = () => { - return ipcRenderer.sendSync('eo-sync', { action: 'getAppModuleList' }); -}; -// 获取边栏应用列表 -window.eo.getSideModuleList = () => { - return ipcRenderer.sendSync('eo-sync', { action: 'getSideModuleList' }); -}; -// 获取所有功能点列表 -window.eo.getFeatures = () => { - return ipcRenderer.sendSync('eo-sync', { action: 'getFeatures' }); -}; -// 获取某个功能点 -window.eo.getFeature = (featureKey) => { - return ipcRenderer.sendSync('eo-sync', { action: 'getFeature', data: { featureKey: featureKey } }); -}; -// 加载feature模块 -window.eo.loadFeatureModule = async (moduleID) => { - if (!featureModules.has(moduleID)) { - try { - const module = window.eo.getModule(moduleID); - window.eo._currentExtensionID = moduleID; - const _module = await require(module.baseDir); - featureModules.set(moduleID, _module); - } catch (e) { - console.log(e); + // 获取模块列表 + getModules() { + return ipcRenderer.sendSync('eo-sync', { action: 'getModules' }); + }, + getModule (id) { + return ipcRenderer.sendSync('eo-sync', { action: 'getModule', data: { id: id } }); + }, + getFeatures(){ + return ipcRenderer.sendSync('eo-sync', { action: 'getFeatures' }); + }, + getFeature(featureKey) { + return ipcRenderer.sendSync('eo-sync', { action: 'getFeature', data: { featureKey: featureKey } }); + }, + loadFeatureModule(id){ + if (!featureModules.has(id)) { + try { + const module = window.eo.getModule(id); + window.eo._currentExtensionID = id; + const _module = require(module.baseDir); + featureModules.set(id, _module); + } catch (e) { + console.log(e); + } } - } - return featureModules.get(moduleID); + return featureModules.get(id); + }, }; // 卸载feature模块 -window.eo.unloadFeatureModule = (moduleID) => { - featureModules.delete(moduleID); -}; -// Hook请求返回 -if (apiAccessRules.includes('hook')) { - window.eo.hook = (data) => { - return ipcRenderer.sendSync('eo-sync', { action: 'hook', data }); - }; -} -// 临时测试用 -window.eo.tempApi = (params) => { - return ipcRenderer.sendSync('eo-sync', params); -}; -window.eo.autoResize = (sideWidth) => { - ipcRenderer.send('eo-sync', { action: 'autoResize', data: { sideWidth: sideWidth } }); -}; -window.eo.getModules = () => { - return ipcRenderer.sendSync('eo-sync', { action: 'getModules' }); +window.eo.unloadFeatureModule = (id) => { + featureModules.delete(id); }; + window.eo.installModule = (name, isLocal = false) => { installTask.set(name, []); const result = ipcRenderer.invoke('eo-sync', { action: 'installModule', data: { name, isLocal } }); @@ -145,9 +114,6 @@ window.eo.uninstallModule = (name, isLocal = false) => { }); return result; }; -window.eo.openApp = (inputArg) => { - return ipcRenderer.sendSync('eo-sync', { action: 'openApp', data: inputArg }); -}; window.eo.getInstallTask = () => installTask; window.eo.getUninstallTask = () => uninstallTask; window.eo.getExtIsInTask = (name, callback) => { @@ -166,40 +132,9 @@ window.eo.getExtIsInTask = (name, callback) => { return false; }; -window.eo.storage = (args, callback: any) => { - const key = `${args.action}_${Date.now()}`; - storageCallback.set(key, callback); - args.type = 'default'; - args.callback = key; - ipcRenderer.send('eo-storage', args); -}; -window.eo.storageSync = (args) => { - console.log('run preload storageSync'); - args.type = 'sync'; - return ipcRenderer.sendSync('eo-storage', args); -}; -// window.eo.storageRemote = (args) => { -// console.log('run preload storageRemote'); -// args.type = 'remote'; -// const shareObject = window.require('@electron/remote').getGlobal('shareObject'); -// shareObject.storageResult = null; -// ipcRenderer.send('eo-storage', args); -// let output: any = shareObject.storageResult; -// let count: number = 0; -// while (output === null) { -// if (count > 1500) { -// output = { -// status: 'error', -// data: 'storage remote load error', -// }; -// break; -// } -// output = shareObject.storageResult; -// ++count; -// } -// shareObject.storageResult = null; -// return output; -// }; +window.eo.getExtensionPagePathByName = (extName: string) => { + return ipcRenderer.invoke('eo-sync', { action: 'getExtensionPagePathByName', data: { extName } }); +}; window.eo.saveSettings = (settings) => { // console.log('window.eo.saveSettings', settings); @@ -226,8 +161,8 @@ window.eo.getSettings = () => { }; window.eo.i18n = new I18N(); -window.eo.getModuleSettings = (moduleID) => { - return ipcRenderer.sendSync('eo-sync', { action: 'getModuleSettings', data: { moduleID: moduleID } }); +window.eo.getExtensionSettings = (moduleID) => { + return ipcRenderer.sendSync('eo-sync', { action: 'getExtensionSettings', data: { moduleID: moduleID } }); }; // 注册单个mock路由 window.eo.registerMockRoute = ({ method, path, data }) => { diff --git a/src/platform/electron-main/browserView/browserView.ts b/src/platform/electron-main/browserView/browserView.ts deleted file mode 100644 index 3e7992c24..000000000 --- a/src/platform/electron-main/browserView/browserView.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { throws } from 'assert'; -import { BrowserWindow, BrowserView, session, BrowserViewConstructorOptions } from 'electron'; -import { ViewBounds } from 'eo/shared/common/bounds'; -import { proxyOpenExternal } from 'eo/shared/common/browserView'; -import { BrowserViewOpts } from './browserView.type'; -export class BrowserViewInstance { - bounds: ViewBounds; - constructor(private opts: BrowserViewOpts) { - this.bounds = this.opts.bounds; - } - init(win: BrowserWindow) { - let viewOps: BrowserViewConstructorOptions = { - webPreferences: { - webSecurity: false, - nodeIntegration: true, - contextIsolation: false, - devTools: true, - webviewTag: true, - }, - }; - if (this.opts.preloadPath) { - const partition = this.opts.partition || ''; - const ses = session.fromPartition(partition); - ses.setPreloads([this.opts.preloadPath]); - viewOps.webPreferences.session = ses; - } - if (this.opts.preload) { - viewOps.webPreferences.preload = this.opts.preload; - } - let view = new BrowserView(viewOps); - view.webContents.loadURL(this.opts.viewPath); - // view.webContents.on("console-message",(e,level,message)=>{ - // console.log(message) - // }) - // view.webContents.openDevTools(); - win.addBrowserView(view); - view.setBounds(this.bounds); - proxyOpenExternal(view); - return view; - } -} diff --git a/src/platform/electron-main/browserView/browserView.type.ts b/src/platform/electron-main/browserView/browserView.type.ts deleted file mode 100644 index 9bc377702..000000000 --- a/src/platform/electron-main/browserView/browserView.type.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ViewBounds } from 'eo/shared/common/bounds'; - -export interface BrowserViewOpts { - bounds: ViewBounds; - partition?: string; - preloadPath?: string; - viewPath: string; - preload?: string; -} diff --git a/src/platform/electron-node/preload.ts b/src/platform/electron-node/preload.ts new file mode 100644 index 000000000..6f10512e4 --- /dev/null +++ b/src/platform/electron-node/preload.ts @@ -0,0 +1,3 @@ +globalThis.eo = { + getExtensionSetting() {}, +}; diff --git a/src/platform/node/configuration/lib/index.ts b/src/platform/node/configuration/lib/index.ts index 7cbbf85c7..556f9fc3d 100644 --- a/src/platform/node/configuration/lib/index.ts +++ b/src/platform/node/configuration/lib/index.ts @@ -88,7 +88,7 @@ export class Configuration implements ConfigurationInterface { * @param section * @returns */ - getModuleSettings(section?: string): T { + getExtensionSettings(section?: string): T { return this.getConfiguration(section); } diff --git a/src/platform/node/configuration/types/index.ts b/src/platform/node/configuration/types/index.ts index 2b3f20379..18f8d3ba3 100644 --- a/src/platform/node/configuration/types/index.ts +++ b/src/platform/node/configuration/types/index.ts @@ -6,7 +6,7 @@ export interface ConfigurationInterface { saveModuleSettings: (moduleID: string, settings: ConfigurationValueInterface) => boolean; deleteModuleSettings: (moduleID: string) => boolean; getSettings: () => ConfigurationValueInterface; - getModuleSettings: (moduleID: string) => ConfigurationValueInterface; + getExtensionSettings: (moduleID: string) => ConfigurationValueInterface; } export interface ConfigurationValueInterface { diff --git a/src/platform/node/extension-manager/lib/core.ts b/src/platform/node/extension-manager/lib/core.ts index d738a03d2..bb9e85ed7 100644 --- a/src/platform/node/extension-manager/lib/core.ts +++ b/src/platform/node/extension-manager/lib/core.ts @@ -1,7 +1,6 @@ import * as path from 'path'; import { ModuleHandlerOptions, ModuleInfo } from '../types'; import { fileExists, readFile, readJson } from 'eo/shared/node/file'; -import { isNotEmpty } from 'eo/shared/common/common'; import { getLocaleData } from 'eo/platform/node/i18n'; import { LanguageService } from 'eo/app/electron-main/language.service'; import { TranslateService } from 'eo/platform/common/i18n'; @@ -53,24 +52,20 @@ export class CoreHandler { // Check that the file exists locally moduleInfo.introduction = readFile(path.join(baseDir, `README.${lang}.md`)) || readFile(path.join(baseDir, `README.md`)); - moduleInfo.main = 'file://' + path.join(moduleInfo.baseDir, moduleInfo.main); - if (moduleInfo.preload?.length > 0) { - moduleInfo.preload = path.join(moduleInfo.baseDir, moduleInfo.preload); + if(moduleInfo.main){ + moduleInfo.main = 'file://' + path.join(moduleInfo.baseDir, moduleInfo.main); } - if (moduleInfo.main_node?.length > 0) { - moduleInfo.main_node = path.join(moduleInfo.baseDir, moduleInfo.main_node); + if(moduleInfo.node){ + moduleInfo.node = 'file://' + path.join(moduleInfo.baseDir, moduleInfo.node); } if (moduleInfo.logo?.length > 0 && !moduleInfo.logo.startsWith('http') && !moduleInfo.logo.includes('icon-')) { moduleInfo.logo = 'file://' + path.join(moduleInfo.baseDir, moduleInfo.logo); } - if (!moduleInfo.belongs || !isNotEmpty(moduleInfo.belongs)) { - moduleInfo.belongs = ['default']; - } if (typeof moduleInfo.author === 'object') { moduleInfo.author = moduleInfo.author['name'] || ''; } } catch (e) { - console.log(`Get module ${moduleInfo?.moduleID} error:${e}`); + console.log(`Get module ${moduleInfo?.name} error:${e}`); moduleInfo = {} as ModuleInfo; } return moduleInfo; diff --git a/src/platform/node/extension-manager/lib/handler.ts b/src/platform/node/extension-manager/lib/handler.ts index da27f2c4d..3259c3dd7 100644 --- a/src/platform/node/extension-manager/lib/handler.ts +++ b/src/platform/node/extension-manager/lib/handler.ts @@ -86,11 +86,11 @@ export class ModuleHandler extends CoreHandler { */ private operatePackage(result: any[], moduleList: string[], action: Action) { if (Array.isArray(result)) { - const moduleNames = moduleList.map((n) => n.split('@')[0]); + const names = moduleList.map((n) => n.split('@')[0]); const packagePath = path.join(this.baseDir, 'package.json'); result.forEach(([name]) => { const [pkgName, pkgVersion] = name.split('@'); - if (moduleNames.includes(pkgName)) { + if (names.includes(pkgName)) { const packageJSON = fs.readFileSync(packagePath); const packageObj = JSON.parse(packageJSON.toString()); const dependencieKeys = Object.keys(packageObj.dependencies); @@ -115,7 +115,7 @@ export class ModuleHandler extends CoreHandler { return; } npmCli.commands[command](moduleList, (err, data) => { - console.log('command', command); + // console.log('command', command); process.chdir(this.baseDir); if (err) { return reject(err); @@ -135,9 +135,7 @@ export class ModuleHandler extends CoreHandler { args = args.concat(`--proxy=${this.proxy}`); } } - console.log(args); const npm = spawn('npm', args, { cwd: this.baseDir }); - // console.log('2==>', npm); let output = ''; npm.stdout .on('data', (data: string) => { diff --git a/src/platform/node/extension-manager/lib/loader.ts b/src/platform/node/extension-manager/lib/loader.ts deleted file mode 100644 index aecda76bc..000000000 --- a/src/platform/node/extension-manager/lib/loader.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ModuleRuntime, ModuleType, ModuleInfo, ModuleLoaderInterface } from '../types'; - -/** - * 模块加载类 - * 根据运行环境加载模块 - */ -export class ModuleLoader implements ModuleLoaderInterface { - /** - * 模块运行时环境 - */ - private readonly runtime: ModuleRuntime; - - /** - * 模块加载方法 - */ - private readonly moduleRequire: any; - - constructor(_runtime: ModuleRuntime, _moduleRequire?: any) { - this.runtime = _runtime; - this.moduleRequire = _moduleRequire || require; - } - - /** - * 批量加载模块 - * @param modules - */ - loadModules(modules: Array): void { - modules.forEach((module: ModuleInfo) => { - this.loadModule(module); - }) - } - - /** - * 实际加载模块并运行 - * 需要检查模块的类型与运行环境匹配 - * main运行环境只能加载system和app模块 - * render运行环境只能加载ui和feature模块 - * web运行环境只能加载web支持的模块 - * @param module ModuleInfo - */ - loadModule(module: ModuleInfo): void { - if ((this.runtime === ModuleRuntime.main && ![ModuleType.system, ModuleType.app].indexOf(module.moduleType)) - || (this.runtime === ModuleRuntime.render && ![ModuleType.feature].indexOf(module.moduleType))) { - console.log(`The [${module.moduleType}] module [${module.name}] can not run in runtime [${this.runtime}].`); - return; - } - if (this.runtime === ModuleRuntime.main) { - console.log('load from main'); - const _module = this.moduleRequire(module.baseDir)(); - console.log(_module); - } else if (this.runtime === ModuleRuntime.render) { - console.log('load from render'); - const _module = this.moduleRequire(module.baseDir)(); - console.log(_module); - } else if (this.runtime === ModuleRuntime.web) { - console.log('load from web'); - // todo with script src - } - // 加入hooks列表 - } -} diff --git a/src/platform/node/extension-manager/lib/manager.ts b/src/platform/node/extension-manager/lib/manager.ts index 1eb8f43d1..f691c8875 100644 --- a/src/platform/node/extension-manager/lib/manager.ts +++ b/src/platform/node/extension-manager/lib/manager.ts @@ -1,12 +1,26 @@ import { MODULE_DIR as baseDir } from 'eo/shared/electron-main/constant'; import { ModuleHandler } from './handler'; -import { ModuleHandlerResult, ModuleInfo, ModuleManagerInfo, ModuleManagerInterface, ModuleType } from '../types'; +import { + ModuleHandlerResult, + ModuleInfo, + ModuleManagerInfo, + ModuleManagerInterface, + ExtensionTabView, + SidebarView, + FeatureInfo, +} from '../types'; import { isNotEmpty } from 'eo/shared/common/common'; -import { processEnv } from '../../constant'; import http from 'axios'; import { DATA_DIR } from '../../../../shared/electron-main/constant'; import { promises, readFileSync } from 'fs'; import { ELETRON_APP_CONFIG } from '../../../../enviroment'; +import { createServer } from 'http-server/lib/http-server'; +import path from 'node:path'; +import portfinder from 'portfinder'; +import { lstat } from 'fs/promises'; + +const extTabViewServerMap = new Map(); +const extSidebarViewServerMap = new Map(); // * npm pkg name const defaultExtension = [{ name: 'eoapi-export-openapi' }, { name: 'eoapi-import-openapi' }]; @@ -24,7 +38,7 @@ export class ModuleManager implements ModuleManagerInterface { /** * extension list */ - private installExtension = []; + private installExtension: ModuleManagerInfo[] = []; /** * 模块集合 @@ -34,7 +48,7 @@ export class ModuleManager implements ModuleManagerInterface { /** * 功能点集合 */ - private readonly features: Map>; + private readonly features: Map>; constructor() { this.moduleHandler = new ModuleHandler({ baseDir: baseDir }); @@ -43,7 +57,6 @@ export class ModuleManager implements ModuleManagerInterface { this.init(); this.updateAll(); } - async getRemoteExtension() { const { data } = await http.get(`${ELETRON_APP_CONFIG.EXTENSION_URL}/list`); return data.data.map(({ name, version }) => ({ name, version })); @@ -76,6 +89,12 @@ export class ModuleManager implements ModuleManagerInterface { const result = await this.moduleHandler.uninstall([{ name: module.name }], module.isLocal || false); if (result.code === 0) { this.delete(moduleInfo); + [extTabViewServerMap, extSidebarViewServerMap].forEach((item) => { + if (item.has(module.name)) { + item.get(module.name).server.close(); + item.delete(module.name); + } + }); } return result; } @@ -121,44 +140,13 @@ export class ModuleManager implements ModuleManagerInterface { this.refresh(module); }); } - /** - * 获取应用级app列表 - */ - getAppModuleList(): Array { - const output: Array = []; - const modules: Map = this.moduleBelongs(); - modules?.forEach((module: ModuleInfo) => { - if (module.isApp) { - (module.main = processEnv === 'development' && module.main_debug ? module.main_debug : module.main), - output.push(module); - } - }); - return output; - } - - /** - * 获取边栏应用列表 - */ - getSideModuleList(moduleID: string): Array { - const output: Array = []; - const modules: Map = this.moduleBelongs(); - modules.get(moduleID)?.sideItems?.forEach((_moduleID: string) => { - if (modules.has(_moduleID)) { - output.push(modules.get(_moduleID)); - } - }); - return output; - } /** * 获取所有模块列表 * belongs为true,返回关联子模块集合 * @param belongs */ - getModules(belongs: boolean = false): Map { - if (belongs) { - return this.moduleBelongs(); - } + getModules(): Map { return this.modules; } @@ -175,11 +163,8 @@ export class ModuleManager implements ModuleManagerInterface { * belongs为true,返回关联子模块集合 * @param belongs */ - getModule(moduleID: string, belongs: boolean = false): ModuleInfo { - if (belongs) { - return this.moduleBelongs().get(moduleID); - } - return this.modules.get(moduleID); + getModule(id: string): ModuleInfo { + return this.modules.get(id); } /** @@ -197,7 +182,7 @@ export class ModuleManager implements ModuleManagerInterface { */ private set(moduleInfo: ModuleInfo) { // 避免重置 - this.modules.set(moduleInfo.moduleID, moduleInfo); + this.modules.set(moduleInfo.name, moduleInfo); this.setFeatures(moduleInfo); } @@ -211,7 +196,7 @@ export class ModuleManager implements ModuleManagerInterface { if (!this.features.has(key)) { this.features.set(key, new Map()); } - this.features.get(key).set(moduleInfo.moduleID, { name: moduleInfo.name, ...value }); + this.features.get(key).set(moduleInfo.name, { extensionID: moduleInfo.name, ...value }); }); } } @@ -222,7 +207,7 @@ export class ModuleManager implements ModuleManagerInterface { */ private delete(moduleInfo: ModuleInfo) { // 避免删除核心 - this.modules.delete(moduleInfo.moduleID); + this.modules.delete(moduleInfo.name); this.deleteFeatures(moduleInfo); } @@ -234,7 +219,7 @@ export class ModuleManager implements ModuleManagerInterface { if (moduleInfo.features && typeof moduleInfo.features === 'object' && isNotEmpty(moduleInfo.features)) { for (const key in moduleInfo.features) { if (this.features.has(key)) { - this.features.get(key).delete(moduleInfo.moduleID); + this.features.get(key).delete(moduleInfo.name); } } } @@ -245,7 +230,7 @@ export class ModuleManager implements ModuleManagerInterface { * @param moduleInfo */ private setup(moduleInfo: ModuleInfo) { - if (moduleInfo && isNotEmpty(moduleInfo.moduleID)) { + if (moduleInfo && isNotEmpty(moduleInfo.name)) { this.set(moduleInfo); } } @@ -254,55 +239,86 @@ export class ModuleManager implements ModuleManagerInterface { * 读取本地package.json文件得到本地安装的模块列表,依次获取模块信息加入模块列表 */ private init() { - const moduleNames: string[] = this.moduleHandler.list(); - moduleNames.forEach((moduleName: string) => { + const names: string[] = this.moduleHandler.list(); + names.forEach((name: string) => { // 这里要加上try catch,避免异常 - const moduleInfo: ModuleInfo = this.moduleHandler.info(moduleName); + const moduleInfo: ModuleInfo = this.moduleHandler.info(name); this.setup(moduleInfo); }); } - /** - * 获取模块到上层模块后的模块列表 - * @returns - */ - private moduleBelongs(): Map { - const newModules: Map = new Map(); - const sideItems = new Map(); - this.modules?.forEach((module: ModuleInfo) => { - // 如果包含自己则是主应用 - // 后期加入权限限制是否能成为顶层应用 - const belongs: string[] = module.belongs || ['default']; - module.isApp = belongs.includes(module.moduleID); - newModules.set(module.moduleID, module); - belongs.forEach((belong: string) => { - // let _modules: string[]; - if (module.moduleType === ModuleType.app) { - /* - if (!sideItems.has(belong)) { - _modules = []; - } else { - _modules = sideItems.get(belong); - } - */ - const _modules: string[] = sideItems.get(belong) || []; - // 如果指定上层是自己,自己放最前面 - if (module.moduleID === belong) { - _modules.unshift(module.moduleID); - } else { - _modules.push(module.moduleID); - } - sideItems.set(belong, _modules); + + getExtFeatures(extName: string) {} + + async getExtPageInfo( + extName: string, + featureName: string, + ServerMap: typeof extSidebarViewServerMap + ): Promise { + try { + const extPath = this.moduleHandler.getModuleDir(extName); + const stats = await lstat(extPath); + const feature = require(path.join(extPath, 'package.json')).features[featureName]; + // 是否为软连接,是则为本地开发,需要提供本地开发web服务地址 + if (stats.isSymbolicLink()) { + if (feature?.debugUrl) { + return { + url: feature?.debugUrl, + ...feature, + }; } - }); - }); - sideItems?.forEach((value: Array, key: string) => { - const _current: ModuleInfo = newModules.get(key); - if (_current && _current.isApp) { - _current.sideItems = value; - newModules.set(key, _current); } - }); - return newModules; + // 生产环境需要提供 html 入口文件地址(pageEntry字段) + if (feature?.url) { + if (ServerMap.has(extName)) { + return ServerMap.get(extName); + } + const port = await portfinder.getPortPromise(); + const pageDir = path.parse(path.join(extPath, feature?.url)).dir; + console.log('extension pageDir', pageDir); + const server = createServer({ root: pageDir }); + server.listen(port); + const url = `http://127.0.0.1:${port}`; + ServerMap.set(extName, { + ...feature, + url, + server, + }); + return ServerMap.get(extName); + } + return Promise.reject('该插件package.json缺少sidebarView字段'); + } catch (error) { + return Promise.reject(error); + } + } + setupExtensionPageServer() {} + async getExtTabs(extName: string): Promise { + const result = []; + for (let index = 0; index < this.installExtension.length; index++) { + try { + const sidebarView = await this.getExtPageInfo( + this.installExtension[index].name, + 'sidebarView', + extSidebarViewServerMap + ); + result.push(sidebarView); + } catch (error) {} + } + return result; + } + + async getSidebarViews(): Promise { + const result = []; + for (let index = 0; index < this.installExtension.length; index++) { + try { + const sidebarView = await this.getExtPageInfo( + this.installExtension[index].name, + 'sidebarView', + extSidebarViewServerMap + ); + result.push(sidebarView); + } catch (error) {} + } + return result; } } diff --git a/src/platform/node/extension-manager/types/handler.ts b/src/platform/node/extension-manager/types/handler.ts index 8b14d2c13..a6bf52083 100644 --- a/src/platform/node/extension-manager/types/handler.ts +++ b/src/platform/node/extension-manager/types/handler.ts @@ -1,3 +1,5 @@ +import { ModuleInfo } from "eo/platform/node/extension-manager/types"; + /** * 模块管理器配置 * baseDir 模块安装目录 @@ -17,3 +19,32 @@ export interface ModuleHandlerResult { code: number; data: string; } + +/** + * 模块管理信息 + * name 模块名称 + * isLocal 是否本地模块 (本地调用link, unlink安装与卸载) + */ +export interface ModuleManagerInfo { + name: string; + isLocal?: boolean; +} +/** + * 模块管理 + * install 安装模块 + * uninstall 卸载模块 + * refresh 重新从本地读取并更新模块信息 + * getModules 获取所有模块列表,或返回有模块关联子模块的信息 + */ +export interface ModuleManagerInterface { + installExt: any; + install: (module: ModuleManagerInfo) => Promise; + uninstall: (module: ModuleManagerInfo) => Promise; + refresh: (module: ModuleManagerInfo) => void; + refreshAll: () => void; + getModule: (id: string) => ModuleInfo; + getModules: () => Map; + getFeature: (featureKey: string) => Map; + getFeatures: () => Map>; + setupExtensionPageServer: (extName: string) => any; +} diff --git a/src/platform/node/extension-manager/types/index.ts b/src/platform/node/extension-manager/types/index.ts index c5055170a..bcd3f637e 100644 --- a/src/platform/node/extension-manager/types/index.ts +++ b/src/platform/node/extension-manager/types/index.ts @@ -1,3 +1,2 @@ export * from './handler'; -export * from './manager'; -export * from './loader'; +export * from './module'; diff --git a/src/platform/node/extension-manager/types/loader.ts b/src/platform/node/extension-manager/types/loader.ts deleted file mode 100644 index 440a7407f..000000000 --- a/src/platform/node/extension-manager/types/loader.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {ModuleInfo} from './manager'; - -/** - * 模块加载接口. - */ -export interface ModuleLoaderInterface { - loadModules: (modules: Array) => void; - loadModule: (module: ModuleInfo) => void; -} - -/** - * 模块运行环境 - */ -export enum ModuleRuntime { - main = 'main', - render = 'render', - web = 'web' -} diff --git a/src/platform/node/extension-manager/types/manager.ts b/src/platform/node/extension-manager/types/manager.ts deleted file mode 100644 index a689549e4..000000000 --- a/src/platform/node/extension-manager/types/manager.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { SidePosition } from 'eo/shared/common/bounds'; -import { ModuleHandlerResult } from './handler'; - -/** - * 模块类型 - * system 系统模块 - * app 应用模块 - * ui 页面模块 - * feature 功能模块 - */ -export enum ModuleType { - system = 'system', - app = 'app', - feature = 'feature', -} -export interface I18nLocale { - locale: string; - package: any; -} -/** - * 模块信息接口 - */ -export interface ModuleInfo { - // npm package name - name: string; - // author - author: string; - // extension version - version: string; - // extension description - description: string; - // extension intro,from README.md - introduction: string; - // extension ID - moduleID: string; - // extension name - moduleName: string; - // extension type - //!TODO what usage - moduleType: ModuleType; - // extension logo - logo: string; - // manifest code file - main: string; - // main node script - main_node?: string; - // 入口开发调试 - main_debug?: string; - // inject script before start app - preload?: string; - // 判断是不是顶层App - //!TODO use feature contribution to control page - isApp?: boolean; - - // 模块对应上层模块ID - //!TODO what usage? - belongs?: Array; - // 下层关联模块ID集合 - //!TODO what usage? - sideItems?: Array; - // 模块路径 - baseDir?: string; - // 配置项 - configuration?: ModuleConfiguration; - /** 贡献点 */ - contributes: ModuleContributes; - // 功能点配置 - features?: { - [index: string]: any; - }; - i18n?: I18nLocale[]; -} -/** - * 贡献点 - */ - -export type ModuleContributes = { - configuration: ModuleConfiguration; -}; - -/** - * 模块配置项接口 - */ -export interface ModuleConfiguration { - title: string; - properties: { - [index: string]: ModuleConfigurationField; - }; -} - -/** - * 模块配置项目字段接口 - */ -export interface ModuleConfigurationField { - type: string | Array; - default: string | number | null; - label: string; - description?: string; - required?: boolean; -} - -/** - * 模块管理信息 - * name 模块名称 - * isLocal 是否本地模块 (本地调用link, unlink安装与卸载) - */ -export interface ModuleManagerInfo { - name: string; - isLocal?: boolean; -} - -/** - * 模块管理 - * install 安装模块 - * uninstall 卸载模块 - * refresh 重新从本地读取并更新模块信息 - * getModules 获取所有模块列表,或返回有模块关联子模块的信息 - */ -export interface ModuleManagerInterface { - installExt: any; - install: (module: ModuleManagerInfo) => Promise; - uninstall: (module: ModuleManagerInfo) => Promise; - refresh: (module: ModuleManagerInfo) => void; - refreshAll: () => void; - getModule: (moduleID: string, belongs?: boolean) => ModuleInfo; - getModules: (belongs?: boolean) => Map; - getAppModuleList: () => Array; - getSideModuleList: (moduleID: string) => Array; - getFeature: (featureKey: string) => Map; - getFeatures: () => Map>; -} diff --git a/src/platform/node/extension-manager/types/module.ts b/src/platform/node/extension-manager/types/module.ts new file mode 100644 index 000000000..0342f744f --- /dev/null +++ b/src/platform/node/extension-manager/types/module.ts @@ -0,0 +1,113 @@ +import { createServer } from 'http-server/lib/http-server'; + +export type FeatureInfo = { + icon: string; + title: string; + description: string; + //Function name + action: string; + //ExportAPI.Filename + filename?: string; + + //*Field for browser generate by code,not actually in package.json + extensionID: string; + //!Will deprecated + label: string; +}; + +/** + * 模块信息接口 + */ +export interface ModuleInfo { + //Unique npm package name + name: string; + version: string; + author: string | { name: 'string' }; + //Entry js file,webRender enviroment + main: string; + // extension description + description: string; + + //* Eoapi extend + //Entry js file,node enviroment + node: string; + title: string; + // extension logo + logo: string; + //Contribution Feature + features?: { + configuration: ModuleConfiguration; + i18n?: I18nLocale; + extensionTabView: ExtensionTabView; + sidebarView: SidebarView; + importAPI: FeatureInfo; + exportAPI: FeatureInfo; + syncAPI: FeatureInfo; + + //Random feature + [index: string]: any; + + //!Will Deprecated + 'apimanage.export': FeatureInfo; + 'apimanage.import': FeatureInfo; + 'apimanage.sync': FeatureInfo; + }; + + //*Field for browser generate by code,not actually in package.json + //Extension intro,from README.md + introduction: string; + //file location + baseDir: string; + + //*Only exist in HTTP request(from extension server) moduleInfo + i18n: { + locale: string; + package: any | object; + }[]; + //!Will Deprecated + // 模块ID,用于关联 + moduleID: string; + // 模块名称,用于显示 + moduleName: string; +} + +/** + * 模块配置项接口 + */ +interface ModuleConfiguration { + title: string; + properties: { + [index: string]: ModuleConfigurationField; + }; +} + +/** + * 模块配置项目字段接口 + */ +interface ModuleConfigurationField { + type: string | Array; + default: string | number | null; + label: string; + description?: string; + required?: boolean; +} +export type ExtensionTabView = { + name: string; + url: string; + debugUrl: string; + server: HttpServer; +}; + +type HttpServer = ReturnType; +export type SidebarView = { + icon: string; + title: string; + url: string; + debugUrl: string; + server: HttpServer; +}; + +export interface I18nLocale { + sourceLocale: string; + locales: string[]; +} diff --git a/src/platform/node/i18n.ts b/src/platform/node/i18n.ts index 881058fe0..a010226a8 100644 --- a/src/platform/node/i18n.ts +++ b/src/platform/node/i18n.ts @@ -1,4 +1,4 @@ -import { I18nLocale, ModuleInfo } from 'eo/platform/node/extension-manager'; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types'; interface LooseObject { [key: string]: any; @@ -6,7 +6,7 @@ interface LooseObject { const localeStorage: LooseObject = {}; /** * Get locale file from extension i18 file dir - * @param moduleID + * @param module * @returns json */ function getLocaleFile(module: ModuleInfo, lang): Object { @@ -26,12 +26,14 @@ function getSupportLang(module: ModuleInfo) { export function getLocaleData(module: ModuleInfo, lang): Object | null { let supportLang = getSupportLang(module); if (!supportLang.includes(lang)) { - console.log(`Error: extenaion ${module.moduleID} can't find the i18n package ${lang}`); + console.error(`Error: extension ${module.title || module.moduleName} can't find the i18n package ${lang}`); return null; } - localeStorage[module.moduleID] = localeStorage[module.moduleID] || {}; - if (!localeStorage[module.moduleID][lang]) { - localeStorage[module.moduleID][lang] = getLocaleFile(module, lang); + //Get and storage locale data + localeStorage[module.name] = localeStorage[module.name] || {}; + if (!localeStorage[module.name][lang]) { + localeStorage[module.name][lang] = getLocaleFile(module, lang); } - return localeStorage[module.moduleID][lang]; + + return localeStorage[module.name][lang]; } diff --git a/src/platform/node/mock-server/index.ts b/src/platform/node/mock-server/index.ts index 7eef62279..7013a779a 100644 --- a/src/platform/node/mock-server/index.ts +++ b/src/platform/node/mock-server/index.ts @@ -69,7 +69,7 @@ export class MockServer { this.app.all('/mock/:mockID/*', (req, res, next) => { // if (!protocolReg.test(req.url)) { // match request type - const isMatchType = this.configuration.getModuleSettings('eoapi-features.mock.matchType'); + const isMatchType = this.configuration.getExtensionSettings('eoapi-features.mock.matchType'); if (req.params.mockID || isMatchType !== false) { this.view.webContents.send('getMockApiList', JSON.parse(jsonStringify(req))); ipcMain.once('getMockApiList', (event, message) => { @@ -93,7 +93,7 @@ export class MockServer { this.app.all('/:workspaceID/:projectID/mock/:mockID/*', (req, res, next) => { // if (!protocolReg.test(req.url)) { // match request type - const isMatchType = this.configuration.getModuleSettings('eoapi-features.mock.matchType'); + const isMatchType = this.configuration.getExtensionSettings('eoapi-features.mock.matchType'); if (req.params.mockID || isMatchType !== false) { this.view.webContents.send('getMockApiList', JSON.parse(jsonStringify(req))); ipcMain.once('getMockApiList', (event, message) => { diff --git a/src/shared/common/bounds.ts b/src/shared/common/bounds.ts deleted file mode 100644 index 3f5676876..000000000 --- a/src/shared/common/bounds.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * 边栏放置位置 - */ -export enum SidePosition { - left = 'left', - right = 'right', - top = 'top', - bottom = 'bottom' -}; - -/** - * 视图区域 - */ -export enum ViewZone { - top = 'top', - bottom = 'bottom', - side = 'side', - main = 'main' -} - -/** - * 视图尺寸、位置 - */ -export interface ViewBounds { - x: number; - y: number; - width: number; - height: number; -} - -/** - * 获取某个显示区域的bounds - * @param zone - * @param width - * @param height - * @param sidePosition - */ -export const getViewBounds = (zone: ViewZone, width: number, height: number, sidePosition?: SidePosition, sideWidth?: number): ViewBounds => { - return calculateViewBounds(width, height, sidePosition, sideWidth).get(zone); -}; - -/** - * 根据容器的尺寸计算所有显示区域的尺寸与位置 - * TODO:需要加上隐藏边栏的属性参数判断 - * @param width - * @param height - * @param sidePosition - */ -export const calculateViewBounds = (width: number, height: number, sidePosition?: SidePosition, sideWidth?: number): Map => { - const position: SidePosition = sidePosition || SidePosition.left; - const _topHeight: number = 50; - const _bottomHeight: number = 0; - const _sideWidth: number = sideWidth || 50; - const _mainHeight: number = height - _topHeight - _bottomHeight; - let topBounds: ViewBounds = {x: 0, y: 0, width: width, height: _topHeight}; - let bottomBounds: ViewBounds = {x: 0, y: (height - _bottomHeight), width: width, height: _bottomHeight}; - let sideBounds: ViewBounds = {x: 0, y: 0, width: _sideWidth, height: _mainHeight }; - let mainBounds: ViewBounds = {x: 0, y: 0, width: width, height: _mainHeight}; - switch (position) { - case SidePosition.left: - sideBounds.y = topBounds.height; - mainBounds.x = sideBounds.width; - mainBounds.y = topBounds.height; - mainBounds.width -= mainBounds.x; - break; - case SidePosition.right: - sideBounds.y = topBounds.height; - sideBounds.x = width - sideBounds.width; - mainBounds.y = topBounds.height; - mainBounds.width = sideBounds.x; - break; - case SidePosition.top: - sideBounds.height = sideBounds.width; - sideBounds.width = width; - sideBounds.y = topBounds.height; - mainBounds.height = height - topBounds.height - sideBounds.height - bottomBounds.height; - mainBounds.y = topBounds.height + sideBounds.height; - break; - case SidePosition.bottom: - sideBounds.height = sideBounds.width; - sideBounds.width = width; - mainBounds.y = topBounds.height; - mainBounds.height -= sideBounds.height; - sideBounds.y = topBounds.height + mainBounds.height; - break; - } - return new Map([ - [ViewZone.top, topBounds], - [ViewZone.bottom, bottomBounds], - [ViewZone.side, sideBounds], - [ViewZone.main, mainBounds] - ]); -}; diff --git a/src/workbench/browser/.gitignore b/src/workbench/browser/.gitignore index fdb3a6a24..ff71a5ad7 100644 --- a/src/workbench/browser/.gitignore +++ b/src/workbench/browser/.gitignore @@ -12,6 +12,7 @@ src/**/*.js !src/ng1/**/*.js !src/assets/libs/*.js *.js.map +proxy.conf.json # dependencies node_modules diff --git a/src/workbench/browser/angular.json b/src/workbench/browser/angular.json index 3db91b5a3..023ba775b 100644 --- a/src/workbench/browser/angular.json +++ b/src/workbench/browser/angular.json @@ -1 +1 @@ -{"$schema":"./node_modules/@angular/cli/lib/config/schema.json","cli":{"analytics":false,"defaultCollection":"@angular-eslint/schematics"},"version":1,"newProjectRoot":"projects","projects":{"eoapi":{"root":"","i18n":{"sourceLocale":{"code":"en","baseHref":""},"locales":{"zh":{"translation":"src/locale/messages.zh.xlf","baseHref":""}}},"sourceRoot":"src","projectType":"application","schematics":{"@schematics/angular:application":{"strict":true}},"architect":{"build":{"builder":"@angular-builders/custom-webpack:browser","options":{"localize":true,"aot":true,"outputPath":"dist","index":"src/index.html","main":"src/main.ts","tsConfig":"src/tsconfig.app.json","polyfills":"src/polyfills.ts","assets":["src/icon.ico","src/assets",{"glob":"**/*","input":"../../../node_modules/monaco-editor/min/vs","output":"/assets/vs/"}],"styles":[{"input":"src/assets/theme/classic_forest.scss","bundleName":"classic_forest","inject":false},"src/assets/theme/antd.less","src/styles.scss","src/assets/font/iconfont.css","src/ng1/index.css"],"scripts":["src/ng1/lib/angular/angular.js","src/ng1/app.module.js","src/ng1/component/select-default.js","src/ng1/component/sort-and-filter.js","src/ng1/component/auto-complete.js","src/ng1/component/list-block.js","src/ng1/directive/get-dom-length.directive.js","src/ng1/directive/drop-down-menu.directive.js","src/ng1/directive/sort.directive.js","src/ng1/directive/drop-change-space.directive.js","src/ng1/directive/inner-html.directive.js","src/ng1/directive/insert-html.directive.js","src/ng1/directive/copy-common.directive.js","src/assets/libs/protocolcheck.js"],"customWebpackConfig":{"path":"./angular.webpack.js","replaceDuplicatePlugins":true},"allowedCommonJsDependencies":["brace","qs","rxjs"]},"configurations":{"dev":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"localize":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.dev.ts"}]},"devCn":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"localize":["zh"],"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.dev.ts"}]},"production":{"optimization":true,"outputHashing":"all","sourceMap":false,"namedChunks":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":true,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.prod.ts"}]}}},"serve":{"builder":"@angular-builders/custom-webpack:dev-server","options":{"browserTarget":"eoapi:build"},"configurations":{"dev":{"browserTarget":"eoapi:build:dev"},"devCn":{"browserTarget":"eoapi:build:devCn"},"production":{"browserTarget":"eoapi:build:production"}}},"extract-i18n":{"builder":"@angular-devkit/build-angular:extract-i18n","options":{"browserTarget":"eoapi:build"}},"test":{"builder":"@angular-builders/custom-webpack:karma","options":{"main":"src/test.ts","polyfills":"src/polyfills-test.ts","tsConfig":"src/tsconfig.spec.json","karmaConfig":"src/karma.conf.js","scripts":[],"styles":["src/styles.scss"],"assets":["src/assets"],"customWebpackConfig":{"path":"./angular.webpack.js","replaceDuplicatePlugins":true}}},"lint":{"builder":"@angular-eslint/builder:lint","options":{"lintFilePatterns":["src/**/*.ts","src/**/*.html"]}}}},"eoapi-e2e":{"root":"e2e","projectType":"application","architect":{"lint":{"builder":"@angular-eslint/builder:lint","options":{"lintFilePatterns":["e2e/**/*.ts"]}}}}},"defaultProject":"eoapi","schematics":{"@schematics/angular:component":{"prefix":"eo","style":"scss"},"@schematics/angular:directive":{"prefix":"eo"}}} +{"$schema":"./node_modules/@angular/cli/lib/config/schema.json","cli":{"analytics":false,"defaultCollection":"@angular-eslint/schematics"},"version":1,"newProjectRoot":"projects","projects":{"eoapi":{"root":"","i18n":{"sourceLocale":{"code":"en","baseHref":""},"locales":{"zh":{"translation":"src/locale/messages.zh.xlf","baseHref":""}}},"sourceRoot":"src","projectType":"application","schematics":{"@schematics/angular:application":{"strict":true}},"architect":{"build":{"builder":"@angular-builders/custom-webpack:browser","options":{"localize":true,"aot":true,"outputPath":"dist","index":"src/index.html","main":"src/main.ts","tsConfig":"src/tsconfig.app.json","polyfills":"src/polyfills.ts","assets":["src/icon.ico","src/assets",{"glob":"**/*","input":"../../../node_modules/monaco-editor/min/vs","output":"/assets/vs/"}],"styles":[{"input":"src/assets/theme/classic_forest.scss","bundleName":"classic_forest","inject":false},"src/assets/theme/antd.less","src/styles.scss","src/assets/font/iconfont.css","src/ng1/index.css"],"scripts":["src/ng1/lib/angular/angular.js","src/ng1/app.module.js","src/ng1/component/select-default.js","src/ng1/component/sort-and-filter.js","src/ng1/component/auto-complete.js","src/ng1/component/list-block.js","src/ng1/directive/get-dom-length.directive.js","src/ng1/directive/drop-down-menu.directive.js","src/ng1/directive/sort.directive.js","src/ng1/directive/drop-change-space.directive.js","src/ng1/directive/inner-html.directive.js","src/ng1/directive/insert-html.directive.js","src/ng1/directive/copy-common.directive.js","src/assets/libs/protocolcheck.js"],"customWebpackConfig":{"path":"./angular.webpack.js","replaceDuplicatePlugins":true},"allowedCommonJsDependencies":["brace","qs","rxjs"]},"configurations":{"dev":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"localize":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.dev.ts"}]},"devCn":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"localize":["zh"],"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.dev.ts"}]},"production":{"optimization":true,"outputHashing":"all","sourceMap":false,"namedChunks":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":true,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.prod.ts"}]},"docker":{"optimization":true,"outputHashing":"all","sourceMap":false,"namedChunks":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":true,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.docker.ts"}]}}},"serve":{"builder":"@angular-builders/custom-webpack:dev-server","options":{"browserTarget":"eoapi:build"},"configurations":{"dev":{"browserTarget":"eoapi:build:dev"},"devCn":{"browserTarget":"eoapi:build:devCn"},"production":{"browserTarget":"eoapi:build:production"}}},"extract-i18n":{"builder":"@angular-devkit/build-angular:extract-i18n","options":{"browserTarget":"eoapi:build"}},"test":{"builder":"@angular-builders/custom-webpack:karma","options":{"main":"src/test.ts","polyfills":"src/polyfills-test.ts","tsConfig":"src/tsconfig.spec.json","karmaConfig":"src/karma.conf.js","scripts":[],"styles":["src/styles.scss"],"assets":["src/assets"],"customWebpackConfig":{"path":"./angular.webpack.js","replaceDuplicatePlugins":true}}},"lint":{"builder":"@angular-eslint/builder:lint","options":{"lintFilePatterns":["src/**/*.ts","src/**/*.html"]}}}},"eoapi-e2e":{"root":"e2e","projectType":"application","architect":{"lint":{"builder":"@angular-eslint/builder:lint","options":{"lintFilePatterns":["e2e/**/*.ts"]}}}}},"defaultProject":"eoapi","schematics":{"@schematics/angular:component":{"prefix":"eo","style":"scss"},"@schematics/angular:directive":{"prefix":"eo"}}} \ No newline at end of file diff --git a/src/workbench/browser/build/build.js b/src/workbench/browser/build/build.js index 52b259613..a608d74eb 100644 --- a/src/workbench/browser/build/build.js +++ b/src/workbench/browser/build/build.js @@ -1,6 +1,9 @@ const fs = require('fs'); const { execSync } = require('child_process'); class webPlatformBuilder { + constructor(environment) { + this.environment = environment; + } resetBuildConfig(json) { delete json.projects.eoapi.i18n.sourceLocale.baseHref; Object.keys(json.projects.eoapi.i18n.locales).forEach((val) => { @@ -9,7 +12,7 @@ class webPlatformBuilder { return json; } executeBuild() { - execSync('ng build -c production', { stdio: 'inherit' }); + execSync(`ng build -c ${this.environment}`, { stdio: 'inherit' }); fs.writeFile( './dist/index.html', ` @@ -22,7 +25,7 @@ class webPlatformBuilder { try{ lang=JSON.parse(window.localStorage.getItem("LOCAL_SETTINGS_KEY"))["eoapi-language"]=='en-US'?'en':'zh'; }catch(e){ - + } let baseDir="/"+lang+'/' let search={}; @@ -53,10 +56,10 @@ class appPlatformBuilder { } } class PlatformBuilder { - constructor(platForm) { + constructor(platForm, environment) { switch (platForm) { case 'web': { - this.instance = new webPlatformBuilder(); + this.instance = new webPlatformBuilder(environment); break; } case 'app': { @@ -79,5 +82,6 @@ class PlatformBuilder { } } let platform = process.argv[2] || 'app'; -let platformBuilder = new PlatformBuilder(platform); +let environment = process.argv[3] || 'production'; +let platformBuilder = new PlatformBuilder(platform, environment); platformBuilder.build(); diff --git a/src/workbench/browser/elements/apiContent.ts b/src/workbench/browser/elements/apiContent.ts new file mode 100644 index 000000000..c56000198 --- /dev/null +++ b/src/workbench/browser/elements/apiContent.ts @@ -0,0 +1,21 @@ +import { Render } from 'ecode/dist/render'; + +export class ApiContent extends Render { + constructor() { + super({ children: [] }); + } + render() { + return { + type: 'element', + imports: [ + { + target: [{ name: 'ApiModule', type: 'module' }], + from: 'eo/workbench/browser/src/app/pages/api/api.module', + }, + ], + template: ``, + data: [], + methods: [], + }; + } +} diff --git a/src/workbench/browser/elements/index.ts b/src/workbench/browser/elements/index.ts index 1ac137b30..9d53f95a4 100644 --- a/src/workbench/browser/elements/index.ts +++ b/src/workbench/browser/elements/index.ts @@ -28,3 +28,4 @@ export { HTTPS } from './service/httpS'; // * 业务 export { ManageAccess } from './manageAccess'; +export { ApiContent } from './apiContent'; diff --git a/src/workbench/browser/elements/service/eventS.ts b/src/workbench/browser/elements/service/eventS.ts index 60741c893..5134cafe8 100644 --- a/src/workbench/browser/elements/service/eventS.ts +++ b/src/workbench/browser/elements/service/eventS.ts @@ -22,7 +22,7 @@ export class EventS extends Render { `; } send(name, data = '{}') { - return `this.message.send({type: '${name}', data: ${data}})`; + return EventS.send(name, (data = '{}')); } render() { return { @@ -47,4 +47,7 @@ export class EventS extends Render { methods: [], }; } + static send(name, data = '{}') { + return `this.message.send({ type: '${name}', data: ${data} })`; + } } diff --git a/src/workbench/browser/elements/tree.ts b/src/workbench/browser/elements/tree.ts index a69019fbd..0f0bcae85 100644 --- a/src/workbench/browser/elements/tree.ts +++ b/src/workbench/browser/elements/tree.ts @@ -1,21 +1,107 @@ import { Render } from 'ecode/dist/render'; export class Tree extends Render { - constructor({ data }) { + id; + showline; + clickMethod; + constructor({ id, showline = false, click = [] }) { super({ children: [] }); + this.id = Render.toCamel(id); + this.showline = showline; + this.clickMethod = Render.callbackRender(click); + } + setData(data) { + return Tree.setData(this.id, data); } render() { + const mainMethods = [ + `async handleClickTree${this.id}Data($event) { + ${this.clickMethod} + }`, + ]; return { type: 'element', imports: [ { - target: [{ name: 'NzTreeModule', type: 'module' }], - from: 'ng-zorro-antd/tree', + target: [{ name: 'ApiModule', type: 'module' }], + from: 'eo/workbench/browser/src/app/pages/api/api.module', }, ], - template: ``, - data: [], - methods: [], + template: ``, + data: [ + // { + // name: `tree${this.id}Data`, + // init: `[ + // { + // title: '0-0', + // key: '00', + // expanded: true, + // children: [ + // { + // title: '0-0-0', + // key: '000', + // expanded: true, + // children: [ + // { title: '0-0-0-0', key: '0000', isLeaf: true }, + // { title: '0-0-0-1', key: '0001', isLeaf: true }, + // { title: '0-0-0-2', key: '0002', isLeaf: true } + // ] + // }, + // { + // title: '0-0-1', + // key: '001', + // children: [ + // { title: '0-0-1-0', key: '0010', isLeaf: true }, + // { title: '0-0-1-1', key: '0011', isLeaf: true }, + // { title: '0-0-1-2', key: '0012', isLeaf: true } + // ] + // }, + // { + // title: '0-0-2', + // key: '002' + // } + // ] + // }, + // { + // title: '0-1', + // key: '01', + // children: [ + // { + // title: '0-1-0', + // key: '010', + // children: [ + // { title: '0-1-0-0', key: '0100', isLeaf: true }, + // { title: '0-1-0-1', key: '0101', isLeaf: true }, + // { title: '0-1-0-2', key: '0102', isLeaf: true } + // ] + // }, + // { + // title: '0-1-1', + // key: '011', + // children: [ + // { title: '0-1-1-0', key: '0110', isLeaf: true }, + // { title: '0-1-1-1', key: '0111', isLeaf: true }, + // { title: '0-1-1-2', key: '0112', isLeaf: true } + // ] + // } + // ] + // }, + // { + // title: '0-2', + // key: '02', + // isLeaf: true + // } + // ]`, + // type: ['any[]'], + // }, + ], + init: [], + methods: [...mainMethods], }; } + static setData(id, data) { + return ` + \/\/ * set tree data + this.tree${Render.toCamel(id)}Data = ${data}`; + } } diff --git a/src/workbench/browser/package.json b/src/workbench/browser/package.json index 844e366ac..c5b16f416 100644 --- a/src/workbench/browser/package.json +++ b/src/workbench/browser/package.json @@ -8,7 +8,8 @@ "start:zh": "ng serve -c devCn -o", "build": "node ./build/build.js", "build:web": "node ./build/build.js web", - "ng:serve": "ng serve -c dev -o", + "build:docker:web": "node ./build/build.js web docker", + "ng:serve": "ng serve -c dev -o --proxy-config=proxy.conf.json", "lang:gen": "ng extract-i18n --output-path src/locale", "test": "ng test --watch=false", "test:watch": "ng test", @@ -32,6 +33,7 @@ "@angular/upgrade": "^14.0.3", "@ant-design/icons-angular": "14.1.0", "@babel/runtime": "7.18.3", + "@micro-zoe/micro-app": "1.0.0-alpha.9", "@ngxs/store": "3.7.4", "ajv": "8.11.0", "js-beautify": "1.14.4", diff --git a/src/workbench/browser/proxy.conf.json b/src/workbench/browser/proxy.conf.json deleted file mode 100644 index 18b2d1c11..000000000 --- a/src/workbench/browser/proxy.conf.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "/api": { - "target": "https://290135738u.oicp.vip/", - "secure": false, - "pathRewrite": { - "^/api": "" - }, - "logLevel": "debug" - } -} diff --git a/src/workbench/browser/src/app/app-routing.module.ts b/src/workbench/browser/src/app/app-routing.module.ts index 01b0a5d08..16515b4d6 100644 --- a/src/workbench/browser/src/app/app-routing.module.ts +++ b/src/workbench/browser/src/app/app-routing.module.ts @@ -1,6 +1,7 @@ -import { NgModule } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { PageNotFoundComponent } from './shared/components'; +import { APP_BASE_HREF } from '@angular/common'; const routes: Routes = [ { @@ -23,5 +24,9 @@ const routes: Routes = [ RouterModule.forRoot(routes, { useHash: !!(window && window.process && window.process.type) ? true : false }), ], exports: [RouterModule], + // 👇 设置基础路由 + providers: [ + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }) export class AppRoutingModule {} diff --git a/src/workbench/browser/src/app/app.component.ts b/src/workbench/browser/src/app/app.component.ts index 301a34e6a..68e070249 100644 --- a/src/workbench/browser/src/app/app.component.ts +++ b/src/workbench/browser/src/app/app.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; -import { ElectronService, ThemeService } from './core/services'; -import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service'; +import { ThemeService } from './core/services'; +import { WebExtensionService } from 'eo/workbench/browser/src/app/shared/services/web-extension/webExtension.service'; @Component({ selector: 'eo-root', @@ -10,12 +10,11 @@ import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/ `, }) export class AppComponent { - constructor(private theme: ThemeService, private dataSource: DataSourceService, private electron: ElectronService) { + constructor( + private theme: ThemeService, + private webExtensionService: WebExtensionService + ) { + this.webExtensionService.init(); this.theme.changeTheme(); - //Check Connection at fisrt - if (!this.dataSource.isRemote || !this.electron.isElectron) { - return; - } - this.dataSource.checkRemoteAndTipModal(); } } diff --git a/src/workbench/browser/src/app/app.module.ts b/src/workbench/browser/src/app/app.module.ts index 08f2fca47..5d2deec61 100644 --- a/src/workbench/browser/src/app/app.module.ts +++ b/src/workbench/browser/src/app/app.module.ts @@ -1,9 +1,10 @@ import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { NgModule, LOCALE_ID } from '@angular/core'; +import { NgModule, LOCALE_ID, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { EouiModule } from 'eo/workbench/browser/src/app/eoui/eoui.module'; import { CommonModule } from '@angular/common'; import { HttpClientModule } from '@angular/common/http'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; //Other module import { CoreModule } from './core/core.module'; @@ -17,7 +18,6 @@ import { UpgradeModule } from '@angular/upgrade/static'; import { IndexedDBStorage } from 'eo/workbench/browser/src/app/shared/services/storage/IndexedDB/lib/'; import { HttpStorage } from 'eo/workbench/browser/src/app/shared/services/storage/http/lib'; import { StorageService } from 'eo/workbench/browser/src/app/shared/services/storage'; -import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service'; import { SettingService } from 'eo/workbench/browser/src/app/core/services/settings/settings.service'; import { NzMessageService } from 'ng-zorro-antd/message'; import { NzModalService } from 'ng-zorro-antd/modal'; @@ -33,13 +33,16 @@ import { registerLocaleData } from '@angular/common'; import { en_US, NZ_I18N, zh_CN } from 'ng-zorro-antd/i18n'; import en from '@angular/common/locales/en'; import zh from '@angular/common/locales/zh'; +import { Vue3Component } from 'eo/workbench/browser/src/app/pages/vue3/vue3.component'; registerLocaleData(en); registerLocaleData(zh); @NgModule({ - declarations: [AppComponent], + declarations: [AppComponent, Vue3Component], imports: [ CommonModule, + FormsModule, + ReactiveFormsModule, BrowserModule, BrowserAnimationsModule, CoreModule, @@ -54,7 +57,6 @@ registerLocaleData(zh); SettingService, ExtensionService, StorageService, - DataSourceService, IndexedDBStorage, HttpStorage, NzMessageService, @@ -65,7 +67,6 @@ registerLocaleData(zh); deps: ['$injector'], }, { provide: HTTP_INTERCEPTORS, useClass: BaseUrlInterceptor, multi: true }, - // { provide: HTTP_INTERCEPTORS, useClass: RemoteUrlInterceptor, multi: true }, { provide: NZ_I18N, useFactory: (localId: string) => { @@ -80,6 +81,7 @@ registerLocaleData(zh); }, ], bootstrap: [AppComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }) export class AppModule { constructor(private upgrade: UpgradeModule, private lang: LanguageService, private appService: AppService) { diff --git a/src/workbench/browser/src/app/app.service.ts b/src/workbench/browser/src/app/app.service.ts index 49c1fdbf9..0217a7144 100644 --- a/src/workbench/browser/src/app/app.service.ts +++ b/src/workbench/browser/src/app/app.service.ts @@ -8,19 +8,18 @@ import { StorageResStatus, } from 'eo/workbench/browser/src/app/shared/services/storage/index.model'; import { StorageService } from 'eo/workbench/browser/src/app/shared/services/storage/storage.service'; -import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service'; @Injectable() export class AppService { private ipcRenderer: IpcRenderer = window.require?.('electron')?.ipcRenderer; - constructor(private storageService: StorageService, private dataSource: DataSourceService) {} + constructor(private storageService: StorageService) {} init() { if (this.ipcRenderer) { this.ipcRenderer.on('getMockApiList', async (event, req = {}) => { const sender = event.sender; - const isEnabledMatchType = window.eo?.getModuleSettings?.('eoapi-features.mock.matchType') !== false; + const isEnabledMatchType = window.eo?.getExtensionSettings?.('eoapi-features.mock.matchType') !== false; const { mockID } = req.params; if (Number.isInteger(Number(mockID))) { try { diff --git a/src/workbench/browser/src/app/core/services/language/language.service.ts b/src/workbench/browser/src/app/core/services/language/language.service.ts index 49ce14420..12a3a57a7 100644 --- a/src/workbench/browser/src/app/core/services/language/language.service.ts +++ b/src/workbench/browser/src/app/core/services/language/language.service.ts @@ -26,14 +26,16 @@ export class LanguageService { return; } this.systemLanguage = localeID; - const localePath = (this.languages.find((val) => val.value === localeID) || this.languages[0]).path; + // const localePath = (this.languages.find((val) => val.value === localeID) || this.languages[0]).path; if (this.electron.isElectron) { this.electron.ipcRenderer.send('message', { action: 'changeLanguage', data: this.systemLanguage, }); } else { - window.location.href = `/${localePath}`; + const url = window.location.href; + const langHash = new Map().set('zh-Hans', 'zh').set('en-US', 'en'); + window.location.replace(url.replace(/\/(zh|en)\/home\//, `/${langHash.get(localeID)}/home/`)); } } } diff --git a/src/workbench/browser/src/app/pages/.component.ts b/src/workbench/browser/src/app/pages/.component.ts deleted file mode 100644 index 527bfbb42..000000000 --- a/src/workbench/browser/src/app/pages/.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' - -@Component({ - selector: 'eo-', - template: `` -}) -export class undefinedComponent implements OnInit { - constructor(public api: RemoteService) {} - async ngOnInit(): void {} -} diff --git a/src/workbench/browser/src/app/pages/account.component.ts b/src/workbench/browser/src/app/pages/account.component.ts index 641f25386..a6d546e1d 100644 --- a/src/workbench/browser/src/app/pages/account.component.ts +++ b/src/workbench/browser/src/app/pages/account.component.ts @@ -1,37 +1,23 @@ -import { - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, - Validators -} from '@angular/forms' -import { ViewChild, ElementRef, Component, OnInit } from '@angular/core' -import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service' -import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service' -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' -import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service' +import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; +import { ViewChild, ElementRef, Component, OnInit } from '@angular/core'; +import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service'; +import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; +import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; @Component({ selector: 'eo-account', template: `

Account

-

+

Username

- + @@ -42,7 +28,7 @@ import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-m type="submit" class="w-[84px]" nzType="primary" - (click)="btnxxkunjCallback()" + (click)="btnw9ec5mCallback()" i18n > Save @@ -51,72 +37,39 @@ import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-m
-

+

Password

- Current password + Current password - + - New password + New password - + - Confirm new password + Confirm new password - + Please input your confirm new password; - - Please confirm your password; - + Please confirm your password; - - Min length is 6; - + Min length is 6; - - Max length is 11; - + Max length is 11; @@ -128,7 +81,7 @@ import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-m type="submit" class="w-[84px]" nzType="primary" - (click)="btncf3rvjCallback()" + (click)="btnn016ppCallback()" i18n > Reset @@ -136,13 +89,13 @@ import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-m
-
` +
`, }) export class AccountComponent implements OnInit { - validateUsernameForm - isSaveUsernameBtnLoading - validatePasswordForm - isResetBtnBtnLoading + validateUsernameForm; + isSaveUsernameBtnLoading; + validatePasswordForm; + isResetBtnBtnLoading; constructor( public fb: UntypedFormBuilder, public user: UserService, @@ -150,16 +103,16 @@ export class AccountComponent implements OnInit { public api: RemoteService, public eMessage: EoMessageService ) { - this.validateUsernameForm = UntypedFormGroup - this.isSaveUsernameBtnLoading = false - this.validatePasswordForm = UntypedFormGroup - this.isResetBtnBtnLoading = false + this.validateUsernameForm = UntypedFormGroup; + this.isSaveUsernameBtnLoading = false; + this.validatePasswordForm = UntypedFormGroup; + this.isResetBtnBtnLoading = false; } async ngOnInit(): Promise { // * Init Username form this.validateUsernameForm = this.fb.group({ - username: [null, [Validators.required]] - }) + username: [null, [Validators.required]], + }); // * Init Password form this.validatePasswordForm = this.fb.group({ @@ -167,96 +120,86 @@ export class AccountComponent implements OnInit { newPassword: [null, [Validators.required]], confirmPassword: [ null, - [ - Validators.required, - Validators.minLength(6), - Validators.maxLength(11), - this.dynamicPasswordValidator - ] - ] - }) + [Validators.required, Validators.minLength(6), Validators.maxLength(11), this.dynamicPasswordValidator], + ], + }); // * get Username form values this.validateUsernameForm.patchValue({ - username: this.user.userProfile?.username - }) + username: this.user.userProfile?.username, + }); } - async btnxxkunjCallback() { + async btnw9ec5mCallback() { // * click event callback - this.isSaveUsernameBtnLoading = true + this.isSaveUsernameBtnLoading = true; const btnSaveUsernameRunning = async () => { - const { username: user } = this.validateUsernameForm.value + const { username: user } = this.validateUsernameForm.value; const [data, err]: any = await this.api.api_userUpdateUserProfile({ - username: user - }) + username: user, + }); if (err) { - this.eMessage.error($localize`Sorry, username is be used`) + this.eMessage.error($localize`Sorry, username is already in use`); if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - const [pData, pErr]: any = await this.api.api_userReadProfile(null) + const [pData, pErr]: any = await this.api.api_userReadProfile(null); if (pErr) { if (pErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.user.setUserProfile(pData) - this.eMessage.success($localize`Username update success !`) - } - await btnSaveUsernameRunning() - this.isSaveUsernameBtnLoading = false + this.user.setUserProfile(pData); + this.eMessage.success($localize`Username update success !`); + }; + await btnSaveUsernameRunning(); + this.isSaveUsernameBtnLoading = false; } - dynamicPasswordValidator = ( - control: UntypedFormControl - ): { [s: string]: boolean } => { - if ( - control.value && - control.value !== this.validatePasswordForm.controls.newPassword.value - ) { - return { isEqual: true, error: true } + dynamicPasswordValidator = (control: UntypedFormControl): { [s: string]: boolean } => { + if (control.value && control.value !== this.validatePasswordForm.controls.newPassword.value) { + return { isEqual: true, error: true }; } - return {} - } - async btncf3rvjCallback() { + return {}; + }; + async btnn016ppCallback() { // * click event callback - this.isResetBtnBtnLoading = true + this.isResetBtnBtnLoading = true; const btnResetBtnRunning = async () => { - const { oldPassword: oldPassword } = this.validatePasswordForm.value - const { newPassword: newPassword } = this.validatePasswordForm.value + const { oldPassword: oldPassword } = this.validatePasswordForm.value; + const { newPassword: newPassword } = this.validatePasswordForm.value; const [data, err]: any = await this.api.api_userUpdatePsd({ oldPassword, - newPassword - }) + newPassword, + }); if (err) { - this.eMessage.error($localize`Validation failed`) + this.eMessage.error($localize`Validation failed`); if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.user.setLoginInfo(data) - this.eMessage.success($localize`Password reset success !`) + this.user.setLoginInfo(data); + this.eMessage.success($localize`Password reset success !`); // * Clear password form - this.validatePasswordForm.reset() - } - await btnResetBtnRunning() - this.isResetBtnBtnLoading = false + this.validatePasswordForm.reset(); + }; + await btnResetBtnRunning(); + this.isResetBtnBtnLoading = false; } } diff --git a/src/workbench/browser/src/app/pages/api/api-tab.service.ts b/src/workbench/browser/src/app/pages/api/api-tab.service.ts index 79efa87b8..0e78812e1 100644 --- a/src/workbench/browser/src/app/pages/api/api-tab.service.ts +++ b/src/workbench/browser/src/app/pages/api/api-tab.service.ts @@ -6,6 +6,7 @@ import { TabItem } from 'eo/workbench/browser/src/app/pages/api/tab/tab.model'; import { isEmptyObj } from '../../utils/index.utils'; import { MessageService } from '../../shared/services/message'; import { Router } from '@angular/router'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; @Injectable() export class ApiTabService { componentRef; @@ -15,27 +16,47 @@ export class ApiTabService { return this.BASIC_TABS.find((val) => this.router.url.includes(val.pathname)); } private changeContent$: Subject = new Subject(); - BASIC_TABS: Partial[] = [ - { - pathname: '/home/api/http/test', - module: 'test', - type: 'edit', - title: $localize`New Request`, - extends: { method: 'POST' }, - }, - { pathname: '/home/api/http/edit', module: 'edit', isFixed: true, type: 'edit', title: $localize`New API` }, - { pathname: '/home/api/http/detail', module: 'detail', type: 'preview', title: $localize`Preview` }, - { - pathname: '/home/api/ws/test', - module: 'test', - isFixed: true, - type: 'edit', - extends: { method: 'WS' }, - title: $localize`New Websocket`, - }, - { pathname: '/home/api/http/mock', module: 'mock', type: 'preview', title: 'Mock' }, - ]; - constructor(private messageService: MessageService, private router: Router) { + BASIC_TABS: Partial[] = this.status.isShare + ? [ + { + pathname: '/home/share/http/test', + module: 'test', + type: 'edit', + title: $localize`New Request`, + extends: { method: 'POST' }, + }, + { pathname: '/home/share/http/detail', module: 'detail', type: 'preview', title: $localize`Preview` }, + { + pathname: '/home/share/ws/test', + module: 'test', + isFixed: true, + type: 'preview', + extends: { method: 'WS' }, + title: $localize`New Websocket`, + }, + ] + : [ + { + pathname: '/home/api/http/test', + module: 'test', + type: 'edit', + title: $localize`New Request`, + extends: { method: 'POST' }, + }, + { pathname: '/home/api/http/edit', module: 'edit', isFixed: true, type: 'edit', title: $localize`New API` }, + { pathname: '/home/api/http/detail', module: 'detail', type: 'preview', title: $localize`Preview` }, + { + pathname: '/home/api/ws/test', + module: 'test', + isFixed: true, + type: 'edit', + extends: { method: 'WS' }, + title: $localize`New Websocket`, + }, + { pathname: '/home/api/http/mock', module: 'mock', type: 'preview', title: 'Mock' }, + ]; + + constructor(private messageService: MessageService, private router: Router, private status: StatusService) { this.changeContent$.pipe(debounceTime(150)).subscribe((inData) => { this.afterContentChanged(inData); }); @@ -124,9 +145,9 @@ export class ApiTabService { } this.bindChildComponentChangeEvent(); - if (!this.componentRef.init) { + if (!this.componentRef?.init) { this.changeContent$.next({ when: 'init', url }); - console.warn('EO_ERROR:Child componentRef need has init function for reflesh data when router change'); + console.error('EO_ERROR:Child componentRef need has init function for reflesh data when router change'); return; } //?Why should use getCurrentTab()? @@ -183,7 +204,7 @@ export class ApiTabService { `EO_ERROR:Child componentRef[${this.componentRef.constructor.name}] need has isFormChange function check model change` ); } - let currentHasChanged = currentTab.hasChanged; + let currentHasChanged = currentTab.extends?.hasChanged?.[contentID] || false; switch (inData.when) { case 'editing': { // Saved APIs do not need to verify changes diff --git a/src/workbench/browser/src/app/pages/api/api.component.html b/src/workbench/browser/src/app/pages/api/api.component.html index 9a68ab0d0..19c8527f9 100644 --- a/src/workbench/browser/src/app/pages/api/api.component.html +++ b/src/workbench/browser/src/app/pages/api/api.component.html @@ -10,7 +10,12 @@ > - + - + - - + Manage Environment @@ -106,23 +117,28 @@ *ngIf="this.id" nzLinkRouter > - +

{{ tab.title }}

- +
- {{ tab.title }} - + {{ tab.title }} +
-
+
- +
it.isShare) : this.TABS; } ngOnDestroy() { this.destroy$.next(); @@ -154,6 +166,12 @@ export class ApiComponent implements OnInit, OnDestroy { // }); } + countPaddingRight() { + if (this.status.isShare) { + return '0px'; + } + return this.activeBar ? this.dyWidth + 'px' : '40px'; + } onResizeEnd() { this.isDragging = false; } @@ -178,11 +196,20 @@ export class ApiComponent implements OnInit, OnDestroy { localStorage.setItem(DY_WIDTH_KEY, String(this.dyWidth)); } handleEnvSelectStatus(event: boolean) {} - private changeStoreEnv(uuid) { + private async changeStoreEnv(uuid) { if (uuid == null) { this.store.dispatch(new Change(null)); return; } + if (this.status.isShare) { + const [data, err]: any = await this.http.api_shareDocGetEnv({ + uniqueID: this.share.shareId, + }); + if (err) { + return; + } + return this.store.dispatch(new Change(data)); + } this.storage.run('environmentLoadAllByProjectID', [1], (result: StorageRes) => { if (result.status === StorageResStatus.success) { const data = result.data.find((val) => val.uuid === Number(uuid)); @@ -226,7 +253,16 @@ export class ApiComponent implements OnInit, OnDestroy { } private getAllEnv(uuid?: number) { const projectID = 1; - return new Promise((resolve) => { + return new Promise(async (resolve) => { + if (this.status.isShare) { + const [data, err]: any = await this.http.api_shareDocGetEnv({ + uniqueID: this.share.shareId, + }); + if (err) { + return resolve([]); + } + return resolve(data || []); + } this.storage.run('environmentLoadAllByProjectID', [projectID], async (result: StorageRes) => { if (result.status === StorageResStatus.success) { return resolve(result.data || []); diff --git a/src/workbench/browser/src/app/pages/api/api.module.ts b/src/workbench/browser/src/app/pages/api/api.module.ts index 961616bb6..aa649b8d9 100644 --- a/src/workbench/browser/src/app/pages/api/api.module.ts +++ b/src/workbench/browser/src/app/pages/api/api.module.ts @@ -29,6 +29,8 @@ import { NzSelectModule } from 'ng-zorro-antd/select'; import { NzModalModule } from 'ng-zorro-antd/modal'; import { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm'; import { NzUploadModule } from 'ng-zorro-antd/upload'; +import { NzBadgeModule } from 'ng-zorro-antd/badge'; + import { ApiGroupTreeComponent } from './group/tree/api-group-tree.component'; import { ApiTabComponent } from './tab/api-tab.component'; @@ -74,6 +76,7 @@ const COMPONENTS = [ NzSpinModule, EouiModule, EnvModule, + NzBadgeModule, NzCardModule, NzModalModule, NzSelectModule, @@ -81,7 +84,7 @@ const COMPONENTS = [ SharedModule, ], declarations: [...COMPONENTS], - exports: [], + exports: [ApiComponent], providers: [ElectronService, ApiService, ApiTabService, ApiTabOperateService, ApiTabStorageService, IndexedDBStorage], }) export class ApiModule {} diff --git a/src/workbench/browser/src/app/pages/api/api.service.ts b/src/workbench/browser/src/app/pages/api/api.service.ts index 3261bb513..6842603e5 100644 --- a/src/workbench/browser/src/app/pages/api/api.service.ts +++ b/src/workbench/browser/src/app/pages/api/api.service.ts @@ -4,6 +4,9 @@ import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-m import { MessageService } from '../../shared/services/message'; import { StorageService } from '../../shared/services/storage'; import { Router } from '@angular/router'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; +import { ShareService } from 'eo/workbench/browser/src/app/shared/services/share.service'; @Injectable({ providedIn: 'root', }) @@ -12,10 +15,23 @@ export class ApiService { private messageService: MessageService, private message: EoMessageService, private router: Router, - private storage: StorageService + private storage: StorageService, + private status: StatusService, + private http: RemoteService, + private share: ShareService ) {} get(uuid): Promise { - return new Promise((resolve) => { + return new Promise(async (resolve) => { + if (this.status.isShare) { + const [data, err]: any = await this.http.api_shareDocGetApiDetail({ + uniqueID: this.share.shareId, + apiDataUUID: uuid, + }); + if (err) { + return; + } + return resolve(data); + } this.storage.run('apiDataLoad', [uuid], (result: StorageRes) => { if (result.status === StorageResStatus.success) { resolve(result.data); diff --git a/src/workbench/browser/src/app/pages/api/group/edit/api-group-edit.component.html b/src/workbench/browser/src/app/pages/api/group/edit/api-group-edit.component.html index 9c43f2337..41b8ac38e 100644 --- a/src/workbench/browser/src/app/pages/api/group/edit/api-group-edit.component.html +++ b/src/workbench/browser/src/app/pages/api/group/edit/api-group-edit.component.html @@ -7,8 +7,7 @@

- Data from {{ - group.name.length > 50 ? group.name.slice(0, 50) + '...' : group.name - }} + Data from + {{ group.name.length > 50 ? group.name.slice(0, 50) + '...' : group.name }} will be deleted. This cannot be undone. Are you sure you want to delete?

diff --git a/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.html b/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.html index 91b7bedd3..95504d8db 100644 --- a/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.html +++ b/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.html @@ -1,9 +1,22 @@
- - @@ -21,10 +34,21 @@
- +
@@ -33,7 +57,7 @@
{{ node.title }}
- + @@ -60,15 +84,17 @@
{{ node.origin.method - }} + }} {{ node.title }}
- - @@ -76,12 +102,16 @@
  • Edit
  • -
  • +
  • Copy
  • -
  • +
  • Delete
  • @@ -91,8 +121,6 @@
    - - + -
    diff --git a/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.scss b/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.scss index ed296ad86..48b01da62 100644 --- a/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.scss +++ b/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.scss @@ -37,7 +37,7 @@ ::ng-deep { .group_tree { overflow: hidden auto; - height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - 80px); + height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - 120px); .ant-tree-indent-unit { width: 8px; } @@ -48,9 +48,6 @@ } } } - .web-page-body .group_tree { - height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - 87px); - } } .ant-dropdown-menu { min-width: 100px; diff --git a/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.ts b/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.ts index 530be7832..bd7e60a4d 100644 --- a/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.ts +++ b/src/workbench/browser/src/app/pages/api/group/tree/api-group-tree.component.ts @@ -18,6 +18,9 @@ import { ApiService } from 'eo/workbench/browser/src/app/pages/api/api.service'; import { ImportApiComponent } from 'eo/workbench/browser/src/app/shared/components/import-api/import-api.component'; import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; import { ProjectService } from 'eo/workbench/browser/src/app/shared/services/project/project.service'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; +import { ShareService } from 'eo/workbench/browser/src/app/shared/services/share.service'; @Component({ selector: 'eo-api-group-tree', templateUrl: './api-group-tree.component.html', @@ -64,20 +67,25 @@ export class ApiGroupTreeComponent implements OnInit, OnDestroy { }, ]; nzSelectedKeys: number[] = []; + isEdit: boolean; private destroy$: Subject = new Subject(); constructor( + public electron: ElectronService, private router: Router, private route: ActivatedRoute, private modalService: ModalService, private message: EoMessageService, private messageService: MessageService, private storage: StorageService, - public electron: ElectronService, private apiService: ApiService, private projectService: ProjectService, - private nzModalService: NzModalService + private nzModalService: NzModalService, + public status: StatusService, + private http: RemoteService, + private share: ShareService ) {} ngOnInit(): void { + this.isEdit = !this.status.isShare; this.buildGroupTreeData(); this.watchApiAction(); this.watchRouterChange(); @@ -107,9 +115,27 @@ export class ApiGroupTreeComponent implements OnInit, OnDestroy { callback?.(); }); - getProjectCollections() { + async getProjectCollections() { this.apiDataLoading = true; - return new Promise((resolve) => { + return new Promise(async (resolve) => { + if (this.status.isShare) { + const [res, err]: any = await this.http.api_shareDocGetAllApi( + { + uniqueID: this.share.shareId, + }, + '/api' + ); + if (err) { + resolve(false); + return; + } + const { groups, apis } = res; + this.getGroups(groups); + this.getApis(apis); + this.apiDataLoading = false; + resolve(true); + return; + } this.storage.run('projectCollections', [this.projectService.currentProjectID], (result: StorageRes) => { if (result.status === StorageResStatus.success) { const { groups, apis } = result.data; @@ -190,7 +216,6 @@ export class ApiGroupTreeComponent implements OnInit, OnDestroy { case 'deleteApiSuccess': case 'updateGroupSuccess': { const group = inArg.data?.group; - if ( inArg.type === 'updateGroupSuccess' && group?.parentID && @@ -198,7 +223,6 @@ export class ApiGroupTreeComponent implements OnInit, OnDestroy { ) { this.expandKeys.push(`group-${group?.parentID}`); } - this.buildGroupTreeData(); break; } @@ -212,24 +236,25 @@ export class ApiGroupTreeComponent implements OnInit, OnDestroy { * @param inArg NzFormatEmitEvent */ operateApiEvent(inArg: NzFormatEmitEvent | any): void { + const prefix = this.status.isShare ? 'home/share' : '/home/api'; inArg.event.stopPropagation(); switch (inArg.eventName) { case 'testApi': case 'editApi': case 'detailApi': { - this.router.navigate([`/home/api/http/${inArg.eventName.replace('Api', '')}`], { - queryParams: { uuid: inArg.node.key }, + this.router.navigate([`${prefix}/http/${inArg.eventName.replace('Api', '')}`], { + queryParams: { uuid: inArg.node.key,shareId: this.share.shareId}, }); break; } case 'jumpOverview': { - this.router.navigate(['/home/api/overview'], { + this.router.navigate([`${prefix}/overview`], { queryParams: { uuid: 'overview' }, }); break; } case 'addAPI': { - this.router.navigate(['/home/api/http/edit'], { + this.router.navigate([`${prefix}/http/edit`], { queryParams: { groupID: inArg.node?.origin.key.replace('group-', '') }, }); break; diff --git a/src/workbench/browser/src/app/pages/api/history/eo-history.component.ts b/src/workbench/browser/src/app/pages/api/history/eo-history.component.ts index 3ca594d8d..70e5cc1c6 100644 --- a/src/workbench/browser/src/app/pages/api/history/eo-history.component.ts +++ b/src/workbench/browser/src/app/pages/api/history/eo-history.component.ts @@ -22,7 +22,7 @@ export class HistoryComponent implements OnInit { constructor(private storage: StorageService, private router: Router, private message: MessageService) {} async ngOnInit() { const result = await this.loadAllTest(); - this.historyList = result.reverse(); + this.historyList = (result||[]).reverse(); this.message .get() .pipe(takeUntil(this.destroy$)) @@ -39,7 +39,6 @@ export class HistoryComponent implements OnInit { return new Promise((resolve) => { this.storage.run('apiTestHistoryLoadAllByProjectID', [1], (result: StorageRes) => { if (result.status === StorageResStatus.success) { - console.log(result.data); resolve(result.data); } else { console.error(result.data); diff --git a/src/workbench/browser/src/app/pages/api/http/detail/api-detail.component.ts b/src/workbench/browser/src/app/pages/api/http/detail/api-detail.component.ts index ac5d8fe4a..843e15e59 100644 --- a/src/workbench/browser/src/app/pages/api/http/detail/api-detail.component.ts +++ b/src/workbench/browser/src/app/pages/api/http/detail/api-detail.component.ts @@ -11,6 +11,9 @@ import { treeToListHasLevel } from '../../../../utils/tree/tree.utils'; import { reverseObj } from '../../../../utils/index.utils'; import { StorageService } from '../../../../shared/services/storage'; import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; +import { ShareService } from 'eo/workbench/browser/src/app/shared/services/share.service'; @Component({ selector: 'api-detail', templateUrl: './api-detail.component.html', @@ -28,7 +31,14 @@ export class ApiDetailComponent implements OnInit { { title: $localize`Created Type`, slot: 'createWay', width: '18%' }, { title: 'URL', slot: 'url', width: '42%' }, ]; - constructor(private route: ActivatedRoute, private storage: StorageService, public electron: ElectronService) {} + constructor( + private route: ActivatedRoute, + private storage: StorageService, + private status: StatusService, + public electron: ElectronService, + private http: RemoteService, + private share: ShareService + ) {} ngOnInit(): void { this.init(); } @@ -39,13 +49,30 @@ export class ApiDetailComponent implements OnInit { if (id) { this.model = (await this.getApiByUuid(Number(id))) as ApiData; } else { - console.error("Can't no find api"); + console.error(`Can't no find api`); } } this.eoOnInit.emit(this.model); } getApiByUuid(id: number) { - return new Promise((resolve) => { + return new Promise(async (resolve) => { + if (this.status.isShare) { + const [data, err]: any = await this.http.api_shareDocGetApiDetail({ + apiDataUUID: id, + uniqueID: this.share.shareId, + }); + if (err) { + return; + } + ['requestBody', 'responseBody'].forEach((tableName) => { + if (['xml', 'json'].includes(data[`${tableName}Type`])) { + data[tableName] = treeToListHasLevel(data[tableName]); + } + }); + this.model = data; + resolve(this.model); + return; + } this.storage.run('apiDataLoad', [id], (result: StorageRes) => { if (result.status === StorageResStatus.success) { ['requestBody', 'responseBody'].forEach((tableName) => { diff --git a/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.html b/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.html index 975e8529e..d46a375b3 100644 --- a/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.html +++ b/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.html @@ -22,14 +22,25 @@ - + - + @@ -45,24 +56,36 @@ Request Headers {{ model.requestHeaders | apiParamsNum - }} + }}
    - + Body - + " + nzStatus="success" + > - + @@ -70,20 +93,26 @@ Query {{ model.queryParams | apiParamsNum - }} + }} - + REST {{ model.restParams | apiParamsNum - }} + }} - + @@ -97,24 +126,36 @@ Response Headers {{ model.responseHeaders | apiParamsNum - }} + }} - + Response - + - + diff --git a/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.ts b/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.ts index e1a3b8e29..92b6d65ca 100644 --- a/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.ts +++ b/src/workbench/browser/src/app/pages/api/http/edit/api-edit.component.ts @@ -24,6 +24,7 @@ import { ApiParamsNumPipe } from '../../../../shared/pipes/api-param-num.pipe'; import { ApiEditService } from 'eo/workbench/browser/src/app/pages/api/http/edit/api-edit.service'; import { ApiEditUtilService } from './api-edit-util.service'; import { EoMessageService } from '../../../../eoui/message/eo-message.service'; +import { after } from 'lodash-es'; @Component({ selector: 'eo-api-edit-edit', templateUrl: './api-edit.component.html', @@ -83,6 +84,8 @@ export class ApiEditComponent implements OnInit, OnDestroy { this.model = result; } } + //! Rest may generate from url + this.watchUri(); //Storage origin api data if (!this.initialModel) { if (!id) { @@ -92,9 +95,9 @@ export class ApiEditComponent implements OnInit, OnDestroy { this.initialModel = eoDeepCopy(this.model); } } + this.initBasicForm(); this.watchBasicForm(); - this.watchUri(); this.changeGroupID$.next(this.model.groupID); this.validateForm.patchValue(this.model); this.eoOnInit.emit(this.model); @@ -130,7 +133,7 @@ export class ApiEditComponent implements OnInit, OnDestroy { if (result.status === StorageResStatus.success) { this.message.success(title); this.initialModel = this.apiEditUtil.getFormdataFromApiData(eoDeepCopy(result.data)); - if(busEvent==='addApi'){ + if (busEvent === 'addApi') { this.router.navigate(['/home/api/http/detail'], { queryParams: { pageID: Number(this.route.snapshot.queryParams.pageID), diff --git a/src/workbench/browser/src/app/pages/api/http/edit/api-edit.module.ts b/src/workbench/browser/src/app/pages/api/http/edit/api-edit.module.ts index 066b6e59e..efe22dfcf 100644 --- a/src/workbench/browser/src/app/pages/api/http/edit/api-edit.module.ts +++ b/src/workbench/browser/src/app/pages/api/http/edit/api-edit.module.ts @@ -31,6 +31,7 @@ import { ApiParamsExtraSettingComponent } from './extra-setting/api-params-extra import { ApiEditUtilService } from './api-edit-util.service'; import { ApiEditService } from 'eo/workbench/browser/src/app/pages/api/http/edit/api-edit.service'; import { RouterModule } from '@angular/router'; +import { NzBadgeModule } from 'ng-zorro-antd/badge'; const NZ_COMPONETS = [ NzDropDownModule, @@ -46,6 +47,7 @@ const NZ_COMPONETS = [ NzDividerModule, NzAffixModule, NzPopconfirmModule, + NzBadgeModule ]; const COMPONENTS = [ ApiEditComponent, diff --git a/src/workbench/browser/src/app/pages/api/http/mock/api-mock.component.html b/src/workbench/browser/src/app/pages/api/http/mock/api-mock.component.html index 5ab6d1494..b6c092f2e 100644 --- a/src/workbench/browser/src/app/pages/api/http/mock/api-mock.component.html +++ b/src/workbench/browser/src/app/pages/api/http/mock/api-mock.component.html @@ -6,11 +6,16 @@
    -
    {{ scope.name }}
    +
    {{ scope.name }}
    - + @@ -19,14 +24,28 @@
    @@ -46,8 +65,14 @@ Response - + diff --git a/src/workbench/browser/src/app/pages/api/http/test/api-test-util.service.ts b/src/workbench/browser/src/app/pages/api/http/test/api-test-util.service.ts index 95a62df2a..92214fdf9 100644 --- a/src/workbench/browser/src/app/pages/api/http/test/api-test-util.service.ts +++ b/src/workbench/browser/src/app/pages/api/http/test/api-test-util.service.ts @@ -346,7 +346,7 @@ export class ApiTestUtilService { }); return result; } - private filterCommonHeader(headers) { + private filterCommonHeader(headers=[]) { const commonHeader = [ 'content-type', 'accept', diff --git a/src/workbench/browser/src/app/pages/api/http/test/api-test.component.html b/src/workbench/browser/src/app/pages/api/http/test/api-test.component.html index 8dcd5b9f7..0950c552a 100644 --- a/src/workbench/browser/src/app/pages/api/http/test/api-test.component.html +++ b/src/workbench/browser/src/app/pages/api/http/test/api-test.component.html @@ -9,15 +9,33 @@ -
    +
    {{ env.hostUri }}
    - - + + - - + Headers {{ model.request.requestHeaders | apiParamsNum - }} + }} - + Body - + " + nzStatus="success" + > - + @@ -67,46 +110,67 @@ Query {{ model.request.queryParams | apiParamsNum - }} + }} - + REST {{ model.request.restParams | apiParamsNum - }} + }} - + Pre-request Script - + - + After-response Script - + - +
    - + @@ -118,8 +182,10 @@
    - + @@ -129,8 +195,15 @@
    - +
    diff --git a/src/workbench/browser/src/app/pages/api/http/test/api-test.component.ts b/src/workbench/browser/src/app/pages/api/http/test/api-test.component.ts index 8987db6f2..1ed996d9d 100644 --- a/src/workbench/browser/src/app/pages/api/http/test/api-test.component.ts +++ b/src/workbench/browser/src/app/pages/api/http/test/api-test.component.ts @@ -35,6 +35,7 @@ import { transferUrlAndQuery } from 'eo/workbench/browser/src/app/utils/api'; import { getGlobals, setGlobals } from 'eo/workbench/browser/src/app/shared/services/api-test/api-test.utils'; import { ApiTestResultResponseComponent } from 'eo/workbench/browser/src/app/pages/api/http/test/result-response/api-test-result-response.component'; import { isEmpty } from 'lodash-es'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; const API_TEST_DRAG_TOP_HEIGHT_KEY = 'API_TEST_DRAG_TOP_HEIGHT'; interface testViewModel { @@ -102,6 +103,7 @@ export class ApiTestComponent implements OnInit, OnDestroy { private apiTestUtil: ApiTestUtilService, private testServer: TestServerService, private messageService: MessageService, + public statusS: StatusService, private lang: LanguageService ) { // TODO Select demo api when first open Eoapi @@ -115,7 +117,6 @@ export class ApiTestComponent implements OnInit, OnDestroy { // testBtn && testBtn.click(); // }, 600); // } - this.initBasicForm(); this.testServer.init((message) => { this.receiveMessage(message); @@ -183,8 +184,8 @@ export class ApiTestComponent implements OnInit, OnDestroy { if (!this.initialModel) { this.initialModel = eoDeepCopy(this.model); } - this.cdRef.detectChanges(); this.eoOnInit.emit(this.model); + this.cdRef.detectChanges(); } clickTest() { if (!this.checkForm()) { @@ -377,7 +378,7 @@ export class ApiTestComponent implements OnInit, OnDestroy { //If test sucess,addHistory //Only has statusCode need save report - if (!message.response.statusCode) { + if (!message.response.statusCode || this.statusS.isShare) { return; } this.addHistory(message.history, Number(queryParams.uuid)); diff --git a/src/workbench/browser/src/app/pages/api/http/test/api-test.module.ts b/src/workbench/browser/src/app/pages/api/http/test/api-test.module.ts index 21d485e02..7818a36ee 100644 --- a/src/workbench/browser/src/app/pages/api/http/test/api-test.module.ts +++ b/src/workbench/browser/src/app/pages/api/http/test/api-test.module.ts @@ -44,6 +44,7 @@ import { TestServerRemoteService } from 'eo/workbench/browser/src/app/shared/ser import { NzUploadModule } from 'ng-zorro-antd/upload'; import { RouterModule } from '@angular/router'; import { ApiSharedModule } from 'eo/workbench/browser/src/app/pages/api/api-shared.module'; +import { NzBadgeModule } from 'ng-zorro-antd/badge'; const NZ_COMPONETS = [ NzDropDownModule, @@ -63,7 +64,7 @@ const NZ_COMPONETS = [ NzAlertModule, NzTypographyModule, NzUploadModule, - ApiSharedModule, + NzBadgeModule ]; const COMPONENTS = [ ApiTestComponent, @@ -89,6 +90,7 @@ const COMPONENTS = [ CommonModule, ...NZ_COMPONETS, EouiModule, + ApiSharedModule, SharedModule, ParamsImportModule, ], diff --git a/src/workbench/browser/src/app/pages/api/http/test/result-response/api-test-result-response.component.ts b/src/workbench/browser/src/app/pages/api/http/test/result-response/api-test-result-response.component.ts index 1fa6c949d..5967701a8 100644 --- a/src/workbench/browser/src/app/pages/api/http/test/result-response/api-test-result-response.component.ts +++ b/src/workbench/browser/src/app/pages/api/http/test/result-response/api-test-result-response.component.ts @@ -29,7 +29,6 @@ export class ApiTestResultResponseComponent implements OnInit, OnChanges { ) {} ngOnChanges(changes) { - console.log('this.model', this.model); if (changes.model && this.model) { this.codeStatus = this.apiTest.getHTTPStatus(this.model?.statusCode); if (!this.responseIsImg) { @@ -46,7 +45,17 @@ export class ApiTestResultResponseComponent implements OnInit, OnChanges { } downloadResponseText() { - this.blobUrl = this.responseIsImg ? this.uri : getBlobUrl(this.model.body, this.model.contentType); + let code = this.model.body; + try { + if (['longText', 'stream'].includes(this.model.responseType)) { + code = window.atob(code); + } else { + code = JSON.stringify(typeof code === 'string' ? JSON.parse(code) : code, null, 4); + } + } catch { + code = String(code); + } + this.blobUrl = this.responseIsImg ? this.uri : getBlobUrl(code, this.model.contentType); const blobFileName = decodeURI(this.model.blobFileName || 'test_response'); const tmpAElem = document.createElement('a'); if ('download' in tmpAElem) { diff --git a/src/workbench/browser/src/app/pages/api/tab/api-tab-operate.service.ts b/src/workbench/browser/src/app/pages/api/tab/api-tab-operate.service.ts index 71fe17f98..7a56172e2 100644 --- a/src/workbench/browser/src/app/pages/api/tab/api-tab-operate.service.ts +++ b/src/workbench/browser/src/app/pages/api/tab/api-tab-operate.service.ts @@ -1,10 +1,13 @@ import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { ApiTabStorageService } from 'eo/workbench/browser/src/app/pages/api/tab/api-tab-storage.service'; -import { TabItem, TabOperate } from 'eo/workbench/browser/src/app/pages/api/tab/tab.model'; +import { storageTab, TabItem, TabOperate } from 'eo/workbench/browser/src/app/pages/api/tab/tab.model'; import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message'; import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; import { eoDeepCopy } from 'eo/workbench/browser/src/app/utils/index.utils'; +import { APP_CONFIG } from 'eo/workbench/browser/src/environments/environment'; +import { ShareService } from 'eo/workbench/browser/src/app/shared/services/share.service'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; /** * Api tab service operate tabs array add/replace/close... * Tab change by url change(router event) @@ -20,18 +23,22 @@ export class ApiTabOperateService { * Tab basic info */ BASIC_TABS: Partial[]; + //* Allow development mode debug not exist router + private allowNotExistRouter = !APP_CONFIG.production; constructor( private tabStorage: ApiTabStorageService, private messageService: MessageService, private router: Router, - private message: EoMessageService + private message: EoMessageService, + private share: ShareService, + private status: StatusService ) {} //Init tab info //Maybe from tab cache info or router url init(BASIC_TABS) { this.BASIC_TABS = BASIC_TABS; this.tabStorage.init(); - const tabCache = this.tabStorage.getPersistenceStorage(); + const tabCache = this.parseChangeRouter(this.tabStorage.getPersistenceStorage()); //No cache if (!tabCache || !tabCache.tabOrder?.length) { this.operateTabAfterRouteChange({ @@ -62,18 +69,21 @@ export class ApiTabOperateService { }); return; } + //Tab from url try { //If current url did't match exist tab,throw error - const existTab = this.getSameContentTab(this.generateTabFromUrl(this.router.url)); - if (existTab) { - this.operateTabAfterRouteChange({ - url: this.router.url, - }); - return; - } + this.getSameContentTab(this.generateTabFromUrl(this.router.url)); + //If current url is valid tab url,select it + this.operateTabAfterRouteChange({ + url: this.router.url, + }); + return; } catch (e) { console.error(e); + if (this.allowNotExistRouter) { + return; + } } //Tab from last choose const targetTab = this.getTabByIndex(tabCache.selectedIndex || 0); @@ -85,10 +95,10 @@ export class ApiTabOperateService { * * @returns tabItem */ - newDefaultTab(path?) { + newDefaultTab(routerStr?) { const tabItem = Object.assign( {}, - eoDeepCopy(this.BASIC_TABS.find((val) => val.pathname === path) || this.BASIC_TABS[0]) + eoDeepCopy(this.BASIC_TABS.find((val) => val.pathname.includes(routerStr)) || this.BASIC_TABS[0]) ); tabItem.params = {}; tabItem.uuid = tabItem.params.pageID = Date.now(); @@ -126,6 +136,12 @@ export class ApiTabOperateService { if (!tab) { return; } + if (this.status.isShare) { + this.router.navigate([tab.pathname], { + queryParams: { pageID: tab.uuid, ...tab.params, shareId: this.share.shareId }, + }); + return; + } this.router.navigate([tab.pathname], { queryParams: { pageID: tab.uuid, ...tab.params }, }); @@ -170,7 +186,7 @@ export class ApiTabOperateService { const params: any = {}; const basicTab = this.BASIC_TABS.find((val) => urlArr[0].includes(val.pathname)); if (!basicTab) { - throw new Error(`EO_ERROR: Please check this router has added in BASIC_TABS,current route:${url}`); + throw new Error(`EO_ERROR: Please check this router has added in BASIC_TABS,current route: ${url}`); } // Parse query params new URLSearchParams(urlArr[1]).forEach((value, key) => { @@ -215,8 +231,9 @@ export class ApiTabOperateService { */ operateTabAfterRouteChange(res: { url: string }) { const pureTab = this.getBasicInfoFromUrl(res.url); - const nextTab = this.generateTabFromUrl(res.url); const existTab = this.getSameContentTab(pureTab); + + const nextTab = this.generateTabFromUrl(res.url); //!Every tab must has pageID //If lack pageID,Jump to exist tab item to keep same pageID and so on if (!pureTab.uuid) { @@ -403,4 +420,22 @@ export class ApiTabOperateService { private updateChildView() { this.messageService.send({ type: 'tabContentInit', data: {} }); } + private parseChangeRouter(cache: storageTab) { + if (!cache) { + return; + } + //If router not exist basic tab,filter it + cache.tabOrder = cache.tabOrder.filter((id) => { + const tabItem = cache.tabsByID[id]; + if (!tabItem) { + return false; + } + const hasExist = this.BASIC_TABS.find((val) => val.pathname === tabItem.pathname); + if (!hasExist) { + delete cache.tabsByID[id]; + } + return hasExist; + }); + return cache; + } } diff --git a/src/workbench/browser/src/app/pages/api/tab/api-tab-storage.service.ts b/src/workbench/browser/src/app/pages/api/tab/api-tab-storage.service.ts index f69b79a91..b16d3449e 100644 --- a/src/workbench/browser/src/app/pages/api/tab/api-tab-storage.service.ts +++ b/src/workbench/browser/src/app/pages/api/tab/api-tab-storage.service.ts @@ -16,9 +16,7 @@ export class ApiTabStorageService { init() { this.tabOrder = []; this.tabsByID = new Map(); - this.cacheName = `${ - this.workspace.isLocal? 'local' : this.workspace.currentWorkspaceID - }_TabCache`; + this.cacheName = `${this.workspace.isLocal ? 'local' : this.workspace.currentWorkspaceID}_TabCache`; } addTab(tabItem) { if (this.tabsByID.has(tabItem.uuid)) { @@ -55,8 +53,10 @@ export class ApiTabStorageService { * @param data */ setPersistenceStorage(selectedIndex, opts) { - //! remote datasource may change - // if (this.dataSource.dataSourceType === 'http') {return;} + //TODO remote datasource may change + if (this.dataSource.dataSourceType === 'http') { + } + let tabsByID = Object.fromEntries(this.tabsByID); Object.values(tabsByID).forEach((val) => { if (val.type === 'preview') { @@ -77,24 +77,11 @@ export class ApiTabStorageService { }) ); } - parseChangeRouter(cache: storageTab) { - const map = { - '/home/api/edit': '/home/api/http/edit', - '/home/api/test': '/home/api/http/test', - '/home/api/detail': '/home/api/http/detail', - '/home/api/mock': '/home/api/http/mock', - }; - cache.tabOrder.forEach((id) => { - const tabItem = cache.tabsByID[id]; - tabItem.pathname = map[tabItem.pathname] || tabItem.pathname; - }); - return cache; - } + getPersistenceStorage(): storageTab { let result: any = null; try { result = JSON.parse(window.localStorage.getItem(this.cacheName) as string); - result = this.parseChangeRouter(result); } catch (e) {} return result; } diff --git a/src/workbench/browser/src/app/pages/api/tab/api-tab.component.html b/src/workbench/browser/src/app/pages/api/tab/api-tab.component.html index 58c9e122e..5e92aa616 100644 --- a/src/workbench/browser/src/app/pages/api/tab/api-tab.component.html +++ b/src/workbench/browser/src/app/pages/api/tab/api-tab.component.html @@ -14,24 +14,23 @@ [ngClass]="{ 'fixed-tab-item-container': tabStorage.tabsByID.get(uuid)?.isFixed }" > - + - {{ tabStorage.tabsByID.get(uuid).extends.method }} - - {{ tabStorage.tabsByID.get(uuid).title }} + {{ + tabStorage.tabsByID.get(uuid)?.extends?.method || 'WS' + }} + + {{ tabStorage.tabsByID.get(uuid)?.title }}
    - +
    - + @@ -73,12 +79,11 @@ import { NzMessageService } from 'ng-zorro-antd/message'; }) export class ExtensionSettingComponent implements OnInit { @Input() configuration = {} as any; + @Input() extName: string; localSettings = {} as Record; validateForm!: FormGroup; objectKeys = Object.keys; - get properties() { - return this.configuration?.properties || {}; - } + properties = {}; constructor( public languageService: LanguageService, @@ -92,14 +97,24 @@ export class ExtensionSettingComponent implements OnInit { } private init() { + this.formatProperties(); this.localSettings = this.settingService.getSettings(); const controls = {}; - this.setSettingsModel(this.configuration.properties, controls); + this.setSettingsModel(this.properties, controls); this.validateForm = this.fb.group(controls); } + formatProperties() { + const prefix = `${this.extName}.`; + this.properties = Object.entries(this.configuration?.properties).reduce((prev, [key, value]) => { + const newKey = key.startsWith(prefix) ? key : `${prefix}${key}`; + prev[newKey] = value; + return prev; + }, {}); + } + /** * set data * diff --git a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html index 066c6b986..5b6a30829 100644 --- a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html +++ b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html @@ -9,10 +9,14 @@
    - {{ extensionDetail.moduleName }} + {{ extensionDetail.title || extensionDetail.moduleName }} - +
    @@ -21,21 +25,33 @@

    {{ extensionDetail.description }}

    -
    - + (nzSelectChange)="handleTabChange($event)" + > + - + diff --git a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.ts b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.ts index 21c690318..3f1659540 100644 --- a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.ts +++ b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.ts @@ -6,6 +6,7 @@ import { ExtensionService } from '../extension.service'; import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service'; import { WebService } from '../../../core/services/web/web.service'; import { PROTOCOL } from 'eo/workbench/browser/src/app/shared/constants/protocol'; +import { WebExtensionService } from 'eo/workbench/browser/src/app/shared/services/web-extension/webExtension.service'; @Component({ selector: 'eo-extension-detail', @@ -20,6 +21,8 @@ export class ExtensionDetailComponent implements OnInit { isNotLoaded = true; extensionDetail: EoExtensionInfo; nzSelectedIndex = 0; + pagePath = ''; + extName = ''; changeLog = ''; changeLogNotFound = false; @@ -29,7 +32,8 @@ export class ExtensionDetailComponent implements OnInit { private router: Router, private webService: WebService, public electron: ElectronService, - private language: LanguageService + private language: LanguageService, + private webExtensionService: WebExtensionService ) { this.getDetail(); } @@ -37,16 +41,14 @@ export class ExtensionDetailComponent implements OnInit { ngOnInit(): void {} async handleInstall() { - if (this.electron.isElectron) { - this.manageExtension(this.extensionDetail?.installed ? 'uninstall' : 'install', this.extensionDetail?.name); - } else { - this.webService.jumpToClient($localize`Eoapi Client is required to install this extension.`); - } + this.manageExtension(this.extensionDetail?.installed ? 'uninstall' : 'install', this.extensionDetail?.name); } async getDetail() { - const extName = this.route.snapshot.queryParams.name; - this.isOperating = window.eo?.getExtIsInTask(extName, ({ type, status }) => { + this.extName = this.route.snapshot.queryParams.name; + + this.fetchExtensionPage(this.extName); + this.isOperating = window.eo?.getExtIsInTask(this.extName, ({ type, status }) => { if (type === 'install' && status === 'success') { this.extensionDetail.installed = true; } @@ -55,11 +57,11 @@ export class ExtensionDetailComponent implements OnInit { } this.isOperating = false; }); - this.extensionDetail = await this.extensionService.getDetail(this.route.snapshot.queryParams.id, extName); + this.extensionDetail = await this.extensionService.getDetail(this.route.snapshot.queryParams.id, this.extName); this.isEnable = this.extensionService.isEnable(this.extensionDetail.name); - if (!this.extensionDetail?.installed) { + if (!this.extensionDetail?.installed || this.webService.isWeb) { await this.fetchReadme(this.language.systemLanguage); } this.isNotLoaded = false; @@ -71,6 +73,22 @@ export class ExtensionDetailComponent implements OnInit { this.fetchChangelog(this.language.systemLanguage); } + fetchExtensionPage = async (extName: string) => { + this.pagePath='http://127.0.0.1:8080'; + // try { + // const res = await window.eo.getExtensionPagePathByName(extName); + // console.log('extName res', res); + // this.pagePath = res; + // } catch (e) { + // console.error('getExtensionPagePathByName err', e); + // fetch(`https://unpkg.com/${extName}/page/index.html`).then((res) => { + // if (res.status === 200) { + // this.pagePath = res.url + '/child/react17/'; + // } + // }); + // } + }; + async fetchChangelog(locale = '') { //Default locale en-US if (locale === 'en-US') { @@ -147,23 +165,27 @@ ${log} manageExtension(operate: string, id) { this.isOperating = true; - /** - * * WARNING:Sending a synchronous message will block the whole - * renderer process until the reply is received, so use this method only as a last - * resort. It's much better to use the asynchronous version, `invoke()`. - */ setTimeout(async () => { switch (operate) { case 'install': { - this.extensionDetail.installed = await this.extensionService.install(id); - this.handleEnableExtension(true); - this.getDetail(); + if (this.electron.isElectron) { + this.extensionDetail.installed = await this.extensionService.install(id); + this.handleEnableExtension(true); + this.getDetail(); + } else { + this.extensionDetail.installed = await this.webExtensionService.installExtension(this.extensionDetail.name); + } break; } case 'uninstall': { - this.extensionDetail.installed = !(await this.extensionService.uninstall(id)); - this.handleEnableExtension(false); - this.fetchReadme(this.language.systemLanguage); + if (this.electron.isElectron) { + this.extensionDetail.installed = !(await this.extensionService.uninstall(id)); + this.handleEnableExtension(false); + this.fetchReadme(this.language.systemLanguage); + } else { + this.webExtensionService.unInstallExtension(this.extensionDetail.name); + this.extensionDetail.installed = false; + } break; } } diff --git a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.module.ts b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.module.ts index 7539eb64a..7760b8370 100644 --- a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.module.ts +++ b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.module.ts @@ -1,13 +1,15 @@ -import { NgModule } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { ExtensionSettingComponent } from './components/extensions.component'; +import { CustomTabComponent } from './components/custom-tab.component'; import { ExtensionDetailComponent } from './extension-detail.component'; import { SharedModule } from 'eo/workbench/browser/src/app/shared/shared.module'; @NgModule({ imports: [SharedModule, FormsModule, CommonModule], - declarations: [ExtensionSettingComponent, ExtensionDetailComponent], + declarations: [ExtensionSettingComponent, ExtensionDetailComponent, CustomTabComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }) export class ExtensionDetailModule {} diff --git a/src/workbench/browser/src/app/pages/extension/extension.component.ts b/src/workbench/browser/src/app/pages/extension/extension.component.ts index ee5cd50cc..d87428dbc 100644 --- a/src/workbench/browser/src/app/pages/extension/extension.component.ts +++ b/src/workbench/browser/src/app/pages/extension/extension.component.ts @@ -53,13 +53,11 @@ export class ExtensionComponent implements OnInit { ngOnInit(): void { this.watchRouterChange(); this.setSelectedKeys(); - if (this.electron.isElectron) { - this.treeNodes.push({ - key: 'installed', - title: $localize`Installed`, - isLeaf: true, - }); - } + this.treeNodes.push({ + key: 'installed', + title: $localize`Installed`, + isLeaf: true, + }); } onSeachChange(keyword) { diff --git a/src/workbench/browser/src/app/pages/extension/extension.model.ts b/src/workbench/browser/src/app/pages/extension/extension.model.ts index e9a8cfb8f..ebdabc572 100644 --- a/src/workbench/browser/src/app/pages/extension/extension.model.ts +++ b/src/workbench/browser/src/app/pages/extension/extension.model.ts @@ -1,4 +1,4 @@ -import { ModuleInfo } from 'eo/platform/node/extension-manager/types/index'; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types'; export enum ExtensionGroupType { all = 'all', diff --git a/src/workbench/browser/src/app/pages/extension/extension.service.ts b/src/workbench/browser/src/app/pages/extension/extension.service.ts index 38729932e..b2a70dfe1 100644 --- a/src/workbench/browser/src/app/pages/extension/extension.service.ts +++ b/src/workbench/browser/src/app/pages/extension/extension.service.ts @@ -2,11 +2,12 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; import { lastValueFrom } from 'rxjs'; -import { ModuleInfo } from 'eo/platform/node/extension-manager/types/index'; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types'; import { TranslateService } from 'eo/platform/common/i18n'; import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service'; import { APP_CONFIG } from 'eo/workbench/browser/src/environments/environment'; import { DISABLE_EXTENSION_NAMES } from 'eo/workbench/browser/src/app/shared/constants/storageKeys'; +import { WebExtensionService } from 'eo/workbench/browser/src/app/shared/services/web-extension/webExtension.service'; @Injectable({ providedIn: 'root', @@ -17,32 +18,32 @@ export class ExtensionService { extensionIDs: Array = []; HOST = ''; localExtensions: Map; - constructor(private http: HttpClient, private electron: ElectronService, private language: LanguageService) { + constructor( + private http: HttpClient, + private electron: ElectronService, + private language: LanguageService, + private webExtensionService: WebExtensionService + ) { this.localExtensions = this.getExtensions(); this.extensionIDs = this.updateExtensionIDs(); this.HOST = this.electron.isElectron ? APP_CONFIG.EXTENSION_URL : APP_CONFIG.MOCK_URL; } private getExtensions() { - // Local extension - return window.eo?.getModules() || new Map(); + if (this.electron.isElectron) { + return window.eo?.getModules() || new Map(); + } else { + const webeExts = this.webExtensionService.installedList.map((n) => [n.name, n.pkgInfo]); + return new Map(webeExts as any); + } } getInstalledList() { // Local extension exception for ignore list - return Array.from(this.localExtensions.values()).filter((it) => this.extensionIDs.includes(it.moduleID)); + return Array.from(this.localExtensions.values()).filter((it) => this.extensionIDs.includes(it.name)); } isInstalled(name) { const installList = this.getInstalledList(); return installList.includes(name); } - private translateModule(module: ModuleInfo) { - const lang = this.language.systemLanguage; - const locale = module.i18n?.find((val) => val.locale === lang)?.package; - if (!locale) { - return module; - } - module = new TranslateService(module, locale).translate(); - return module; - } public async requestList() { const result: any = await lastValueFrom(this.http.get(`${this.HOST}/list?locale=${this.language.systemLanguage}`)); const installList = this.getInstalledList(); @@ -129,4 +130,16 @@ export class ExtensionService { .filter((it) => it) .filter((it) => !this.ignoreList.includes(it)); } + private translateModule(module: ModuleInfo) { + const lang = this.language.systemLanguage; + + //If extension from web,transalte package content from http moduleInfo + //Locale extension will translate from local i18n file + const locale = module.i18n?.find((val) => val.locale === lang)?.package; + if (!locale) { + return module; + } + module = new TranslateService(module, locale).translate(); + return module; + } } diff --git a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html index f727326c6..034310f46 100644 --- a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html +++ b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html @@ -2,20 +2,16 @@
    + *ngFor="let it of renderList" (click)="clickExtension($event, it)">
    -
    +
    +
    - {{ it.moduleName }} + {{ it.title || it.moduleName }} {{ it.author }} {{ it.description }}
    @@ -29,19 +25,13 @@
    - +
    - Installed + i18n>Installed
    diff --git a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts index ba33dfa3c..4347c9f52 100644 --- a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts +++ b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts @@ -13,9 +13,7 @@ class ExtensionList { this.list = list; } search(keyword: string) { - return this.list.filter( - (it) => it.moduleID.includes(keyword) || it.name.includes(keyword) || it.keywords?.includes(keyword) - ); + return this.list.filter((it) => it.name.includes(keyword) || it.keywords?.includes(keyword)); } } @Component({ @@ -87,7 +85,7 @@ export class ExtensionListComponent implements OnInit { .navigate(['home/extension/detail'], { queryParams: { type: this.route.snapshot.queryParams.type, - id: item.moduleID, + id: item.name, name: item.name, tab: event?.target?.dataset?.id === 'details' ? 1 : 0, }, diff --git a/src/workbench/browser/src/app/pages/member.component.ts b/src/workbench/browser/src/app/pages/member.component.ts index 774ad46d9..bc52dba0a 100644 --- a/src/workbench/browser/src/app/pages/member.component.ts +++ b/src/workbench/browser/src/app/pages/member.component.ts @@ -1,13 +1,13 @@ -import { NzModalService } from 'ng-zorro-antd/modal' -import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service' -import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service' -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' -import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service' -import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service' -import { distinct } from 'rxjs/operators' -import { interval } from 'rxjs' -import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service' -import { Component, OnInit } from '@angular/core' +import { NzModalService } from 'ng-zorro-antd/modal'; +import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service'; +import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; +import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; +import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service'; +import { distinct } from 'rxjs/operators'; +import { interval } from 'rxjs'; +import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service'; +import { Component, OnInit } from '@angular/core'; @Component({ selector: 'eo-member', @@ -15,17 +15,12 @@ import { Component, OnInit } from '@angular/core' [nzFooter]="null" [(nzVisible)]="isInvateModalVisible" (nzOnCancel)="handleInvateModalCancel()" - (nzAfterClose)="etmsgjfCallback()" + (nzAfterClose)="ehe4islCallback()" nzTitle="Add people to the workspace" i18n-nzTitle > - +
    - +
    -
    ` +
    `, }) export class MemberComponent implements OnInit { - isInvateModalVisible - inputPersonValue - isSelectBtnLoading - isAddPeopleBtnLoading - memberList + isInvateModalVisible; + inputPersonValue; + isSelectBtnLoading; + isAddPeopleBtnLoading; + memberList; constructor( public modal: NzModalService, public user: UserService, @@ -79,154 +71,149 @@ export class MemberComponent implements OnInit { public workspace: WorkspaceService, public dataSource: DataSourceService ) { - this.isInvateModalVisible = false - this.inputPersonValue = '' - this.isSelectBtnLoading = false - this.isAddPeopleBtnLoading = false - this.memberList = [] + this.isInvateModalVisible = false; + this.inputPersonValue = ''; + this.isSelectBtnLoading = false; + this.isAddPeopleBtnLoading = false; + this.memberList = []; } async ngOnInit(): Promise { this.message .get() .pipe(distinct(({ type }) => type, interval(400))) - .subscribe(async ({ type, data }) => {}) + .subscribe(async ({ type, data }) => {}); - const url = this.dataSource.mockUrl + const url = this.dataSource.remoteServerUrl; if (url === '') { - this.message.send({ type: 'need-config-remote', data: {} }) - return + this.message.send({ type: 'need-config-remote', data: {} }); + return; } - const { id: currentWorkspaceID } = this.workspace.currentWorkspace + const { id: currentWorkspaceID } = this.workspace.currentWorkspace; const [wData, wErr]: any = await this.api.api_workspaceMember({ - workspaceID: currentWorkspaceID - }) + workspaceID: currentWorkspaceID, + }); if (wErr) { if (wErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } // * 对成员列表进行排序 - const Owner = wData.filter((it) => it.roleName === 'Owner') - const Member = wData.filter((it) => it.roleName !== 'Owner') - this.memberList = Owner.concat(Member) + const Owner = wData.filter((it) => it.roleName === 'Owner'); + const Member = wData.filter((it) => it.roleName !== 'Owner'); + this.memberList = Owner.concat(Member); } handleInvateModalCancel(): void { // * 关闭弹窗 - this.isInvateModalVisible = false + this.isInvateModalVisible = false; } - async etmsgjfCallback() { + async ehe4islCallback() { // * nzAfterClose event callback { // * auto clear form - this.inputPersonValue = '' + this.inputPersonValue = ''; } - this.inputPersonValue = '' + this.inputPersonValue = ''; } - async btn7ykkd6Callback() { + async btn0r9zcbCallback() { // * click event callback - this.isSelectBtnLoading = true + this.isSelectBtnLoading = true; const btnSelectRunning = async () => { - const username = this.inputPersonValue - const [uData, uErr]: any = await this.api.api_userSearch({ username }) + const username = this.inputPersonValue; + const [uData, uErr]: any = await this.api.api_userSearch({ username }); if (uErr) { if (uErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } if (uData.length === 0) { - this.eMessage.error( - $localize`Could not find a user matching ${username}` - ) - return + this.eMessage.error($localize`Could not find a user matching ${username}`); + return; } - const [user] = uData - const { id } = user + const [user] = uData; + const { id } = user; - const { id: workspaceID } = this.workspace.currentWorkspace + const { id: workspaceID } = this.workspace.currentWorkspace; const [aData, aErr]: any = await this.api.api_workspaceAddMember({ workspaceID, - userIDs: [id] - }) + userIDs: [id], + }); if (aErr) { if (aErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.eMessage.success($localize`Add new member success`) + this.eMessage.success($localize`Add new member success`); // * 关闭弹窗 - this.isInvateModalVisible = false + this.isInvateModalVisible = false; - const { id: currentWorkspaceID } = this.workspace.currentWorkspace + const { id: currentWorkspaceID } = this.workspace.currentWorkspace; const [wData, wErr]: any = await this.api.api_workspaceMember({ - workspaceID: currentWorkspaceID - }) + workspaceID: currentWorkspaceID, + }); if (wErr) { if (wErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } // * 对成员列表进行排序 - const Owner = wData.filter((it) => it.roleName === 'Owner') - const Member = wData.filter((it) => it.roleName !== 'Owner') - this.memberList = Owner.concat(Member) - } - await btnSelectRunning() - this.isSelectBtnLoading = false + const Owner = wData.filter((it) => it.roleName === 'Owner'); + const Member = wData.filter((it) => it.roleName !== 'Owner'); + this.memberList = Owner.concat(Member); + }; + await btnSelectRunning(); + this.isSelectBtnLoading = false; } - btnrgj8s9Status() { + btnguixdgStatus() { // * disabled status status - return this.inputPersonValue === '' + return this.inputPersonValue === ''; } - async btnuvurciCallback() { + async btnf5umnoCallback() { // * click event callback - this.isAddPeopleBtnLoading = true + this.isAddPeopleBtnLoading = true; const btnAddPeopleRunning = async () => { // * 唤起弹窗 - this.isInvateModalVisible = true + this.isInvateModalVisible = true; { { } { } } - } - await btnAddPeopleRunning() - this.isAddPeopleBtnLoading = false + }; + await btnAddPeopleRunning(); + this.isAddPeopleBtnLoading = false; } - btnsqcmi2Status() { + btny703n5Status() { // * disabled status status - return - return ( - this.workspace.currentWorkspaceID !== -1 && - this.workspace.authEnum.canEdit - ) + return; + return this.workspace.currentWorkspaceID !== -1 && this.workspace.authEnum.canEdit; } - async ew833r8Callback($event) { + async e97uoiuCallback($event) { // * eoOnRemove event callback const confirm = () => @@ -237,50 +224,50 @@ export class MemberComponent implements OnInit { nzOkDanger: true, nzOkText: $localize`Delete`, nzOnOk: () => resolve(true), - nzOnCancel: () => resolve(false) - }) - }) - const isOk = await confirm() + nzOnCancel: () => resolve(false), + }); + }); + const isOk = await confirm(); if (!isOk) { - return + return; } - const { id: workspaceID } = this.workspace.currentWorkspace + const { id: workspaceID } = this.workspace.currentWorkspace; - const { id } = $event + const { id } = $event; const [data, err]: any = await this.api.api_workspaceRemoveMember({ workspaceID, - userIDs: [id] - }) + userIDs: [id], + }); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - const { id: currentWorkspaceID } = this.workspace.currentWorkspace + const { id: currentWorkspaceID } = this.workspace.currentWorkspace; const [wData, wErr]: any = await this.api.api_workspaceMember({ - workspaceID: currentWorkspaceID - }) + workspaceID: currentWorkspaceID, + }); if (wErr) { if (wErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } // * 对成员列表进行排序 - const Owner = wData.filter((it) => it.roleName === 'Owner') - const Member = wData.filter((it) => it.roleName !== 'Owner') - this.memberList = Owner.concat(Member) + const Owner = wData.filter((it) => it.roleName === 'Owner'); + const Member = wData.filter((it) => it.roleName !== 'Owner'); + this.memberList = Owner.concat(Member); } } diff --git a/src/workbench/browser/src/app/pages/member.module.ts b/src/workbench/browser/src/app/pages/member.module.ts index 3095737dd..957ab6ae3 100644 --- a/src/workbench/browser/src/app/pages/member.module.ts +++ b/src/workbench/browser/src/app/pages/member.module.ts @@ -1,35 +1,20 @@ -import { NgModule } from '@angular/core' -import { CommonModule } from '@angular/common' -import { NzModalService, NzModalModule } from 'ng-zorro-antd/modal' -import { NzInputModule } from 'ng-zorro-antd/input' -import { FormsModule } from '@angular/forms' -import { NzButtonModule } from 'ng-zorro-antd/button' -import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service' -import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service' -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' -import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service' -import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service' -import { distinct } from 'rxjs/operators' -import { interval } from 'rxjs' -import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service' -import { ManageAccessComponent } from 'eo/workbench/browser/src/app/shared/components/manage-access/manage-access.component' -import { SharedModule } from 'eo/workbench/browser/src/app/shared/shared.module' +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NzModalService, NzModalModule } from 'ng-zorro-antd/modal'; +import { NzInputModule } from 'ng-zorro-antd/input'; +import { FormsModule } from '@angular/forms'; +import { NzButtonModule } from 'ng-zorro-antd/button'; +import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; +import { ManageAccessComponent } from 'eo/workbench/browser/src/app/shared/components/manage-access/manage-access.component'; +import { SharedModule } from 'eo/workbench/browser/src/app/shared/shared.module'; -import { MemberRoutingModule } from './member-routing.module' -import { MemberComponent } from './member.component' +import { MemberRoutingModule } from './member-routing.module'; +import { MemberComponent } from './member.component'; @NgModule({ - imports: [ - MemberRoutingModule, - CommonModule, - NzModalModule, - NzInputModule, - FormsModule, - NzButtonModule, - SharedModule - ], + imports: [MemberRoutingModule, CommonModule, NzModalModule, NzInputModule, FormsModule, NzButtonModule, SharedModule], declarations: [MemberComponent, ManageAccessComponent], exports: [], - providers: [NzModalService, MessageService, RemoteService] + providers: [NzModalService, MessageService], }) export class MemberModule {} diff --git a/src/workbench/browser/src/app/pages/navbar/navbar.component.html b/src/workbench/browser/src/app/pages/navbar/navbar.component.html index 7208acff3..5456af300 100644 --- a/src/workbench/browser/src/app/pages/navbar/navbar.component.html +++ b/src/workbench/browser/src/app/pages/navbar/navbar.component.html @@ -6,7 +6,13 @@ -
    +
    -
    +
    + + +
    +

    Share via link

    +

    + This link will be updated with the API content. Everyone can access it without logging in +

    + + + +
    +
    + + + + + + + +
    -
    +
    diff --git a/src/workbench/browser/src/app/pages/navbar/navbar.component.scss b/src/workbench/browser/src/app/pages/navbar/navbar.component.scss index b743d7bce..3de50d1d9 100644 --- a/src/workbench/browser/src/app/pages/navbar/navbar.component.scss +++ b/src/workbench/browser/src/app/pages/navbar/navbar.component.scss @@ -34,9 +34,6 @@ left: 0; top: 0; padding: 0 8px; - // background-color: var(--NAVBAR_BG); - // color: var(--NAVBAR_TEXT); - // border-bottom: 1px solid var(--NAVBAR_BORDER_BOTTOM); border-bottom: 1px solid var(--BORDER); height: var(--NAVBAR_HEIGHT); .logo { @@ -72,3 +69,8 @@ font-size: 12px; } } +.btn_scondary{ + color:var(--BTN_PRIMARY_BG); + border-color:var(--BTN_PRIMARY_BG); +} + diff --git a/src/workbench/browser/src/app/pages/navbar/navbar.component.ts b/src/workbench/browser/src/app/pages/navbar/navbar.component.ts index 325fa551f..cee096021 100644 --- a/src/workbench/browser/src/app/pages/navbar/navbar.component.ts +++ b/src/workbench/browser/src/app/pages/navbar/navbar.component.ts @@ -1,14 +1,19 @@ import { Component, OnInit } from '@angular/core'; import { ElectronService, WebService } from '../../core/services'; -import { ModuleInfo } from 'eo/platform/node/extension-manager'; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types'; import { NzModalService } from 'ng-zorro-antd/modal'; import { SettingComponent } from '../../shared/components/setting/setting.component'; import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message'; import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service'; import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service'; import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; import { distinct } from 'rxjs/operators'; import { interval } from 'rxjs'; +import { copy } from 'eo/workbench/browser/src/app/utils/index.utils'; +import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; +import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service'; @Component({ selector: 'eo-navbar', templateUrl: './navbar.component.html', @@ -23,6 +28,9 @@ export class NavbarComponent implements OnInit { modules: Map; resourceInfo = this.web.resourceInfo; issueEnvironment; + shareLink = ''; + langValue; + isCopy = false; constructor( public electron: ElectronService, private web: WebService, @@ -30,9 +38,14 @@ export class NavbarComponent implements OnInit { private message: MessageService, public workspaceService: WorkspaceService, public userService: UserService, - public dataSourceService: DataSourceService + public dataSourceService: DataSourceService, + public status: StatusService, + private http: RemoteService, + private eoMessage: EoMessageService, + private lang: LanguageService ) { this.issueEnvironment = this.getEnviroment(); + this.langValue = this.lang.systemLanguage; if (this.workspaceService.currentWorkspace?.id !== -1) { this.workspaceService.getWorkspaceInfo(this.workspaceService.currentWorkspace.id); } @@ -63,44 +76,75 @@ export class NavbarComponent implements OnInit { action: 'close', }); } - ngOnInit(): void { - if (this.electron.isElectron) { - this.modules = window.eo.getAppModuleList(); - } else { - this.modules = new Map(); + handleCopy() { + if (this.isCopy) { + return; } + const isOk = copy(this.shareLink); + if (isOk) { + this.isCopy = true; + interval(700).subscribe(() => { + this.isCopy = false; + }); + } + } + async ngOnInit(): Promise { + this.modules = new Map(); + this.shareLink = await this.getShareLink(); this.message .get() .pipe(distinct(({ type }) => type, interval(400))) - .subscribe(({ type }) => { + .subscribe(async ({ type }) => { if (type === 'open-setting') { this.openSettingModal(); + return; + } + if (type === 'update-share-link') { + // * request share link + this.shareLink = await this.getShareLink(); } }); } - loginOrSign() { - if (this.web.isWeb) { - return this.web.jumpToClient($localize`Eoapi Client is required to sign in`); + async getShareLink() { + if (this.workspaceService.isLocal) { + return ''; + } + if (!this.userService.isLogin) { + return ''; + } + if (this.status.isShare) { + return ''; } + const [res, err]: any = await this.http.api_shareCreateShare({}); + if (err) { + return ''; + } + const langHash = new Map().set('zh-Hans', 'zh').set('en-US', 'en'); + return `${this.dataSourceService?.remoteServerUrl || window.location.host}/${langHash.get( + this.lang.systemLanguage + )}/home/share/http/test?shareId=${res.uniqueID}`.replace( + /\/{2,}(zh|en)\/home\/share/, + `/${langHash.get(this.lang.systemLanguage)}/home/share` + ); + } + loginOrSign() { this.dataSourceService.checkRemoteCanOperate(); } loginOut() { this.message.send({ type: 'logOut', data: {} }); } async addWorkspace() { - if (this.web.isWeb) { - return this.web.jumpToClient($localize`Eoapi Client is required to add workspace`); - // 1. 如果配置了远程地址 - } else { - this.dataSourceService.checkRemoteCanOperate(() => { - this.message.send({ type: 'addWorkspace', data: {} }); - }); - } + this.dataSourceService.checkRemoteCanOperate(() => { + this.message.send({ type: 'addWorkspace', data: {} }); + }); } getModules(): Array { return Array.from(this.modules.values()); } + handleSwitchLang(event) { + this.lang.changeLanguage(event); + } /** * 打开系统设置 diff --git a/src/workbench/browser/src/app/pages/navbar/navbar.module.ts b/src/workbench/browser/src/app/pages/navbar/navbar.module.ts index b393fff45..e263c2a21 100644 --- a/src/workbench/browser/src/app/pages/navbar/navbar.module.ts +++ b/src/workbench/browser/src/app/pages/navbar/navbar.module.ts @@ -4,10 +4,11 @@ import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; import { NavbarComponent } from 'eo/workbench/browser/src/app/pages/navbar/navbar.component'; import { SettingModule } from 'eo/workbench/browser/src/app/shared/components/setting/setting.module'; import { CommonModule } from '@angular/common'; +import { NzSelectModule } from 'ng-zorro-antd/select'; import { SharedModule } from 'eo/workbench/browser/src/app/shared/shared.module'; @NgModule({ - imports: [CommonModule, NzDropDownModule, NzToolTipModule, SettingModule, SharedModule], + imports: [CommonModule, NzDropDownModule, NzSelectModule, NzToolTipModule, SettingModule, SharedModule], declarations: [NavbarComponent], exports: [NavbarComponent], }) diff --git a/src/workbench/browser/src/app/pages/pages-routing.module.ts b/src/workbench/browser/src/app/pages/pages-routing.module.ts index 42142330a..ae49775e9 100644 --- a/src/workbench/browser/src/app/pages/pages-routing.module.ts +++ b/src/workbench/browser/src/app/pages/pages-routing.module.ts @@ -3,6 +3,7 @@ import { NgModule } from '@angular/core'; import { PagesComponent } from './pages.component'; import { PageBlankComponent } from '../shared/components/page-blank/page-blank.component'; +import { Vue3Component } from 'eo/workbench/browser/src/app/pages/vue3/vue3.component'; const routes: Routes = [ { path: '', @@ -37,6 +38,15 @@ const routes: Routes = [ path: 'extension', loadChildren: () => import('./extension/extension.module').then((m) => m.ExtensionModule), }, + // { + // path: 'app-vue3', + // children: [ + // { + // path: '**', + // component: Vue3Component, + // }, + // ], + // }, ], }, ]; diff --git a/src/workbench/browser/src/app/pages/pages.component.ts b/src/workbench/browser/src/app/pages/pages.component.ts index 4245b3fe9..1d2277a79 100644 --- a/src/workbench/browser/src/app/pages/pages.component.ts +++ b/src/workbench/browser/src/app/pages/pages.component.ts @@ -7,7 +7,10 @@ import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; styleUrls: ['./pages.component.scss'], }) export class PagesComponent implements OnInit { - isShowNotification = false; - constructor(public electron: ElectronService) {} - ngOnInit(): void {} + isShowNotification; + constructor(public electron: ElectronService) { + this.isShowNotification = false; + } + ngOnInit(): void { + } } diff --git a/src/workbench/browser/src/app/pages/pages.module.ts b/src/workbench/browser/src/app/pages/pages.module.ts index 3170c310a..6373ea902 100644 --- a/src/workbench/browser/src/app/pages/pages.module.ts +++ b/src/workbench/browser/src/app/pages/pages.module.ts @@ -1,5 +1,5 @@ import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { CommonModule, LocationStrategy } from '@angular/common'; import { PagesRoutingModule } from './pages-routing.module'; import { SettingModule } from '../shared/components/setting/setting.module'; import { PagesComponent } from './pages.component'; @@ -10,6 +10,7 @@ import { UserModalComponent } from './user-modal.component'; import { NzModalService } from 'ng-zorro-antd/modal'; import { NzAlertModule } from 'ng-zorro-antd/alert'; + @NgModule({ imports: [PagesRoutingModule, SettingModule, EouiModule, CommonModule, NzAlertModule, SharedModule, NavbarModule], declarations: [PagesComponent, UserModalComponent], diff --git a/src/workbench/browser/src/app/pages/share-routing.module.ts b/src/workbench/browser/src/app/pages/share-routing.module.ts index bce30c42b..3248569c9 100644 --- a/src/workbench/browser/src/app/pages/share-routing.module.ts +++ b/src/workbench/browser/src/app/pages/share-routing.module.ts @@ -7,6 +7,35 @@ const routes: Routes = [ { path: '', component: ShareComponent, + children: [ + { + path: '', + redirectTo: 'http', + pathMatch: 'full', + }, + { + path: 'http', + children: [ + { + path: 'detail', + loadChildren: () => import('../pages/api/http/detail/api-detail.module').then((m) => m.ApiDetailModule), + }, + { + path: 'test', + loadChildren: () => import('../pages/api/http/test/api-test.module').then((m) => m.ApiTestModule), + }, + ], + }, + { + path: 'ws', + children: [ + { + path: 'test', + loadChildren: () => import('../pages/api/websocket/websocket.module').then((m) => m.WebsocketModule), + }, + ], + }, + ], }, ]; diff --git a/src/workbench/browser/src/app/pages/share.component.ts b/src/workbench/browser/src/app/pages/share.component.ts index 33e78bb30..f76014b11 100644 --- a/src/workbench/browser/src/app/pages/share.component.ts +++ b/src/workbench/browser/src/app/pages/share.component.ts @@ -1,10 +1,17 @@ import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { ShareService } from 'eo/workbench/browser/src/app/shared/services/share.service'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; @Component({ selector: 'eo-share', - template: `
    share
    `, + template: `
    `, }) export class ShareComponent implements OnInit { - constructor() {} - async ngOnInit(): Promise {} + constructor(private route: ActivatedRoute, private share: ShareService, private status: StatusService) {} + async ngOnInit(): Promise { + this.route.queryParams.subscribe(({ shareId }) => { + this.share.setShareId(shareId); + }); + } } diff --git a/src/workbench/browser/src/app/pages/share.module.ts b/src/workbench/browser/src/app/pages/share.module.ts index 77e4dc071..a98456818 100644 --- a/src/workbench/browser/src/app/pages/share.module.ts +++ b/src/workbench/browser/src/app/pages/share.module.ts @@ -1,13 +1,14 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { ApiModule } from 'eo/workbench/browser/src/app/pages/api/api.module' -import { ShareRoutingModule } from './share-routing.module'; -import { ShareComponent } from './share.component'; +import { ShareRoutingModule } from './share-routing.module' +import { ShareComponent } from './share.component' @NgModule({ - imports: [ShareRoutingModule, CommonModule], + imports: [ShareRoutingModule, CommonModule, ApiModule], declarations: [ShareComponent], exports: [], - providers: [], + providers: [] }) export class ShareModule {} diff --git a/src/workbench/browser/src/app/pages/user-modal.component.ts b/src/workbench/browser/src/app/pages/user-modal.component.ts index 0a6eeb5fe..da879d0a4 100644 --- a/src/workbench/browser/src/app/pages/user-modal.component.ts +++ b/src/workbench/browser/src/app/pages/user-modal.component.ts @@ -1,20 +1,17 @@ -import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service' -import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service' -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' -import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service' -import { ProjectService } from 'eo/workbench/browser/src/app/shared/services/project/project.service' -import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service' -import { distinct } from 'rxjs/operators' -import { interval } from 'rxjs' -import { NzModalService } from 'ng-zorro-antd/modal' -import { - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, - Validators -} from '@angular/forms' -import { ViewChild, ElementRef, Component, OnInit } from '@angular/core' -import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service' +import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service'; +import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; +import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; +import { ProjectService } from 'eo/workbench/browser/src/app/shared/services/project/project.service'; +import { DataSourceService } from 'eo/workbench/browser/src/app/shared/services/data-source/data-source.service'; +import { distinct } from 'rxjs/operators'; +import { interval } from 'rxjs'; +import { NzModalService } from 'ng-zorro-antd/modal'; +import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; +import { ViewChild, ElementRef, Component, OnInit } from '@angular/core'; +import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service'; +import { WebService } from 'eo/workbench/browser/src/app/core/services'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; @Component({ selector: 'eo-user-modal', @@ -22,14 +19,13 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzFooter]="modalSyncFooter" [(nzVisible)]="isSyncModalVisible" (nzOnCancel)="handleSyncModalCancel()" - (nzAfterClose)="ek3bbgpCallback()" + (nzAfterClose)="e7odmm4Callback()" nzTitle="Do you want to upload local data to the cloud ?" i18n-nzTitle > - After confirmation, the system will create a cloud space to upload the - local data to the cloud. + After confirmation, the system will create a cloud space to upload the local data to the cloud. Cancel @@ -54,7 +50,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzLoading]="isSyncSyncBtnLoading" class="" nzType="primary" - (click)="btnddl2g5Callback()" + (click)="btnsf8zsrCallback()" i18n > Sync @@ -65,18 +61,13 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzFooter]="modalCheckConnectFooter" [(nzVisible)]="isCheckConnectModalVisible" (nzOnCancel)="handleCheckConnectModalCancel()" - (nzAfterClose)="e3xpndmCallback()" + (nzAfterClose)="e4pgjfkCallback()" nzTitle="Check your connection" i18n-nzTitle > Can't connect right now, click to retry or - + config in the configuration @@ -86,7 +77,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzLoading]="isCheckConnectCancelBtnLoading" class="" nzType="default" - (click)="btn85p48gCallback()" + (click)="btnzls4ymCallback()" i18n > Cancel @@ -96,7 +87,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzLoading]="isCheckConnectRetryBtnLoading" class="" nzType="primary" - (click)="btnb778v9Callback()" + (click)="btn0mu0b2Callback()" i18n > Retry @@ -108,7 +99,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzWidth]="400" [(nzVisible)]="isLoginModalVisible" (nzOnCancel)="handleLoginModalCancel()" - (nzAfterClose)="e31iieeCallback()" + (nzAfterClose)="euu4ezrCallback()" nzTitle="Sign In/Up" i18n-nzTitle > @@ -138,13 +129,9 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w i18n-placeholder /> - - Please input your password; - + Please input your password; - - Min length is 6; - + Min length is 6; @@ -157,7 +144,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w class="h-10 mt-2" nzType="primary" nzBlock - (click)="btnwvmlg8Callback()" + (click)="btnvz94ljCallback()" i18n > Sign In/Up @@ -171,18 +158,13 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzFooter]="null" [(nzVisible)]="isOpenSettingModalVisible" (nzOnCancel)="handleOpenSettingModalCancel()" - (nzAfterClose)="ejr6w2fCallback()" + (nzAfterClose)="e95oi5lCallback()" nzTitle="Open setting" i18n-nzTitle > If you want to collaborate, please - + open the settings and fill in the configuration @@ -192,16 +174,12 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w [nzFooter]="null" [(nzVisible)]="isAddWorkspaceModalVisible" (nzOnCancel)="handleAddWorkspaceModalCancel()" - (nzAfterClose)="epruwutCallback()" + (nzAfterClose)="ebdsz2aCallback()" nzTitle="Add Workspace" i18n-nzTitle > - + Cancel @@ -233,7 +211,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w type="submit" class="" nzType="primary" - (click)="btnkh8m1jCallback()" + (click)="btnd4wbcjCallback()" i18n > Save @@ -241,26 +219,26 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w
    - ` + `, }) export class UserModalComponent implements OnInit { - isSyncModalVisible - isSyncCancelBtnLoading - isSyncSyncBtnLoading - isCheckConnectModalVisible - isCheckConnectCancelBtnLoading - isCheckConnectRetryBtnLoading - isLoginModalVisible - validateLoginForm - @ViewChild('usernameLoginRef') usernameLoginRef: ElementRef - isLoginBtnBtnLoading - isOpenSettingModalVisible - isAddWorkspaceModalVisible - validateWorkspaceNameForm + isSyncModalVisible; + isSyncCancelBtnLoading; + isSyncSyncBtnLoading; + isCheckConnectModalVisible; + isCheckConnectCancelBtnLoading; + isCheckConnectRetryBtnLoading; + isLoginModalVisible; + validateLoginForm; + @ViewChild('usernameLoginRef') usernameLoginRef: ElementRef; + isLoginBtnBtnLoading; + isOpenSettingModalVisible; + isAddWorkspaceModalVisible; + validateWorkspaceNameForm; @ViewChild('newWorkNameWorkspaceNameRef') - newWorkNameWorkspaceNameRef: ElementRef - isCancelBtnLoading - isSaveBtnLoading + newWorkNameWorkspaceNameRef: ElementRef; + isCancelBtnLoading; + isSaveBtnLoading; constructor( public user: UserService, public message: MessageService, @@ -270,22 +248,24 @@ export class UserModalComponent implements OnInit { public dataSource: DataSourceService, public modal: NzModalService, public fb: UntypedFormBuilder, - public workspace: WorkspaceService + public workspace: WorkspaceService, + private web: WebService, + private status: StatusService ) { - this.isSyncModalVisible = false - this.isSyncCancelBtnLoading = false - this.isSyncSyncBtnLoading = false - this.isCheckConnectModalVisible = false - this.isCheckConnectCancelBtnLoading = false - this.isCheckConnectRetryBtnLoading = false - this.isLoginModalVisible = false - this.validateLoginForm = UntypedFormGroup - this.isLoginBtnBtnLoading = false - this.isOpenSettingModalVisible = false - this.isAddWorkspaceModalVisible = false - this.validateWorkspaceNameForm = UntypedFormGroup - this.isCancelBtnLoading = false - this.isSaveBtnLoading = false + this.isSyncModalVisible = false; + this.isSyncCancelBtnLoading = false; + this.isSyncSyncBtnLoading = false; + this.isCheckConnectModalVisible = false; + this.isCheckConnectCancelBtnLoading = false; + this.isCheckConnectRetryBtnLoading = false; + this.isLoginModalVisible = false; + this.validateLoginForm = UntypedFormGroup; + this.isLoginBtnBtnLoading = false; + this.isOpenSettingModalVisible = false; + this.isAddWorkspaceModalVisible = false; + this.validateWorkspaceNameForm = UntypedFormGroup; + this.isCancelBtnLoading = false; + this.isSaveBtnLoading = false; } async ngOnInit(): Promise { this.message @@ -294,438 +274,443 @@ export class UserModalComponent implements OnInit { .subscribe(async ({ type, data }) => { if (type === 'login') { // * 唤起弹窗 - this.isLoginModalVisible = true + this.isLoginModalVisible = true; { { { // * auto focus setTimeout(() => { - this.usernameLoginRef?.nativeElement.focus() - }, 300) + this.usernameLoginRef?.nativeElement.focus(); + }, 300); } } } - return + return; } if (type === 'clear-user') { - this.user.clearAuth() + this.user.clearAuth(); this.user.setUserProfile({ id: -1, password: '', username: '', - workspaces: [] - }) - return + workspaces: [], + }); + return; } if (type === 'http-401') { - const { id } = this.workspace.currentWorkspace + const { id } = this.workspace.currentWorkspace; if (id === -1) { - return + return; } // * 唤起弹窗 - this.isLoginModalVisible = true + this.isLoginModalVisible = true; { { { // * auto focus setTimeout(() => { - this.usernameLoginRef?.nativeElement.focus() - }, 300) + this.usernameLoginRef?.nativeElement.focus(); + }, 300); } } } - return + return; } if (type === 'logOut') { - this.workspace.setCurrentWorkspaceID(-1) + this.workspace.setCurrentWorkspaceID(-1); this.user.setUserProfile({ id: -1, password: '', username: '', - workspaces: [] - }) + workspaces: [], + }); { - this.workspace.setWorkspaceList([]) + this.workspace.setWorkspaceList([]); } - this.workspace.setCurrentWorkspace( - this.workspace.getLocalWorkspaceInfo() - ) - this.eMessage.success($localize`Successfully logged out !`) - const refreshToken = this.user.refreshToken - this.user.clearAuth() + this.workspace.setCurrentWorkspace(this.workspace.getLocalWorkspaceInfo()); + this.eMessage.success($localize`Successfully logged out !`); + const refreshToken = this.user.refreshToken; + this.user.clearAuth(); { const [data, err]: any = await this.api.api_authLogout({ - refreshToken - }) + refreshToken, + }); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } } - return + return; } if (type === 'ping-fail') { - this.eMessage.error($localize`Connect failed`) + this.eMessage.error($localize`Connect failed`); // * 唤起弹窗 - this.isCheckConnectModalVisible = true + this.isCheckConnectModalVisible = true; { } - return + return; } if (type === 'ping-success') { - this.eMessage.success($localize`Connect success`) - return + this.eMessage.success($localize`Connect success`); + return; } if (type === 'need-config-remote') { // * 唤起弹窗 - this.isOpenSettingModalVisible = true + this.isOpenSettingModalVisible = true; - return + return; } if (type === 'addWorkspace') { // * 唤起弹窗 - this.isAddWorkspaceModalVisible = true + this.isAddWorkspaceModalVisible = true; { { // * auto focus setTimeout(() => { - this.newWorkNameWorkspaceNameRef?.nativeElement.focus() - }, 300) + this.newWorkNameWorkspaceNameRef?.nativeElement.focus(); + }, 300); } } - return + return; } if (type === 'retry') { // * 唤起弹窗 - this.isCheckConnectModalVisible = true + this.isCheckConnectModalVisible = true; { } - return + return; } - }) + }); // * Init Login form this.validateLoginForm = this.fb.group({ username: [null, [Validators.required]], - password: [null, [Validators.required, Validators.minLength(6)]] - }) + password: [null, [Validators.required, Validators.minLength(6)]], + }); // * Init WorkspaceName form this.validateWorkspaceNameForm = this.fb.group({ - newWorkName: [null, [Validators.required]] - }) + newWorkName: [null, [Validators.required]], + }); - const { id: workspaceID } = this.workspace.currentWorkspace - const [data, err]: any = await this.api.api_workspaceList({}) + const { id: workspaceID } = this.workspace.currentWorkspace; + if (this.status.isShare) { + return; + } + const [data, err]: any = await this.api.api_workspaceList({}); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.workspace.setWorkspaceList(data) + this.workspace.setWorkspaceList(data); if (workspaceID !== -1) { - const { projects } = await this.workspace.getWorkspaceInfo(workspaceID) - this.project.setCurrentProjectID(projects.at(0).uuid) + const { projects } = await this.workspace.getWorkspaceInfo(workspaceID); + this.project.setCurrentProjectID(projects.at(0).uuid); } - const url = this.dataSource.mockUrl + const url = this.dataSource.remoteServerUrl; if (url === '') { // * 唤起弹窗 - this.isOpenSettingModalVisible = true + // this.isOpenSettingModalVisible = true; { } - return + return; } - const { id: currentWorkspaceID } = this.workspace.currentWorkspace + const { id: currentWorkspaceID } = this.workspace.currentWorkspace; if (currentWorkspaceID === -1) { - return + return; } - const status = this.dataSource.isConnectRemote + const status = this.dataSource.isConnectRemote; if (!status) { // * 唤起弹窗 - this.isCheckConnectModalVisible = true + if (this.web.isWeb) { + return; + } + this.isCheckConnectModalVisible = true; { } - return + return; } } handleSyncModalCancel(): void { // * 关闭弹窗 - this.isSyncModalVisible = false + this.isSyncModalVisible = false; } - async ek3bbgpCallback() { + async e7odmm4Callback() { // * nzAfterClose event callback { } } - async btn4wxiipCallback() { + async btnsgs0ckCallback() { // * click event callback - this.isSyncCancelBtnLoading = true + this.isSyncCancelBtnLoading = true; const btnSyncCancelRunning = async () => { // * 关闭弹窗 - this.isSyncModalVisible = false - } - await btnSyncCancelRunning() - this.isSyncCancelBtnLoading = false + this.isSyncModalVisible = false; + }; + await btnSyncCancelRunning(); + this.isSyncCancelBtnLoading = false; } - async btnddl2g5Callback() { + async btnsf8zsrCallback() { // * click event callback - this.isSyncSyncBtnLoading = true + this.isSyncSyncBtnLoading = true; const btnSyncSyncRunning = async () => { - const eData = await this.project.exportLocalProjectData() + const eData = await this.project.exportLocalProjectData(); - const [data, err]: any = await this.api.api_workspaceUpload(eData) + const [data, err]: any = await this.api.api_workspaceUpload(eData); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - const { workspace } = data - const list = this.workspace - .getWorkspaceList() - .filter((it) => it.id !== -1) - this.workspace.setWorkspaceList([...list, workspace]) - this.workspace.setCurrentWorkspaceID(workspace) + const { workspace } = data; + const list = this.workspace.getWorkspaceList().filter((it) => it.id !== -1); + this.workspace.setWorkspaceList([...list, workspace]); + this.workspace.setCurrentWorkspaceID(workspace); // * 关闭弹窗 - this.isSyncModalVisible = false - } - await btnSyncSyncRunning() - this.isSyncSyncBtnLoading = false + this.isSyncModalVisible = false; + }; + await btnSyncSyncRunning(); + this.isSyncSyncBtnLoading = false; } handleCheckConnectModalCancel(): void { // * 关闭弹窗 - this.isCheckConnectModalVisible = false + this.isCheckConnectModalVisible = false; } - async e3xpndmCallback() { + async e4pgjfkCallback() { // * nzAfterClose event callback { } } - async btn85p48gCallback() { + async btnzls4ymCallback() { // * click event callback - this.isCheckConnectCancelBtnLoading = true + this.isCheckConnectCancelBtnLoading = true; const btnCheckConnectCancelRunning = async () => { // * 关闭弹窗 - this.isCheckConnectModalVisible = false - } - await btnCheckConnectCancelRunning() - this.isCheckConnectCancelBtnLoading = false + this.isCheckConnectModalVisible = false; + }; + await btnCheckConnectCancelRunning(); + this.isCheckConnectCancelBtnLoading = false; } - async btnb778v9Callback() { + async btn0mu0b2Callback() { // * click event callback - this.isCheckConnectRetryBtnLoading = true + this.isCheckConnectRetryBtnLoading = true; const btnCheckConnectRetryRunning = async () => { - this.dataSource.checkRemoteAndTipModal() + this.dataSource.checkRemoteAndTipModal(); // * 关闭弹窗 - this.isCheckConnectModalVisible = false - } - await btnCheckConnectRetryRunning() - this.isCheckConnectRetryBtnLoading = false + this.isCheckConnectModalVisible = false; + }; + await btnCheckConnectRetryRunning(); + this.isCheckConnectRetryBtnLoading = false; } - async texte83xg2Callback() { + async textiqd22iCallback() { // * click event callback + this.message.send({ type: 'open-setting', data: {} }); // * 关闭弹窗 - this.isOpenSettingModalVisible = false + this.isCheckConnectModalVisible = false; + this.isOpenSettingModalVisible = false; } handleLoginModalCancel(): void { // * 关闭弹窗 - this.isLoginModalVisible = false + this.isLoginModalVisible = false; } - async e31iieeCallback() { + async euu4ezrCallback() { // * nzAfterClose event callback { // * auto clear form - this.validateLoginForm.reset() + this.validateLoginForm.reset(); } } - async btnwvmlg8Callback() { + async btnvz94ljCallback() { // * click event callback - this.isLoginBtnBtnLoading = true + this.isLoginBtnBtnLoading = true; const btnLoginBtnRunning = async () => { - const isOk = this.validateLoginForm.valid + const isOk = this.validateLoginForm.valid; if (!isOk) { - this.eMessage.error($localize`Please check you username or password`) - return + this.eMessage.error($localize`Please check you username or password`); + return; } - // * get login form values - const formData = this.validateLoginForm.value - const [data, err]: any = await this.api.api_authLogin(formData) + const formData = this.validateLoginForm.value; + const [data, err]: any = await this.api.api_authLogin(formData); if (err) { this.eMessage.error( $localize`Please check the account/password, the account must be a mobile phone number or email !` - ) - if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + ); + if ([401, 403].includes(err.status)) { + this.isLoginBtnBtnLoading = false; + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.user.setLoginInfo(data) + this.user.setLoginInfo(data); // * 关闭弹窗 - this.isLoginModalVisible = false + this.isLoginModalVisible = false; + this.message.send({ type: 'update-share-link', data: {} }); { - const [data, err]: any = await this.api.api_userReadProfile(null) + const [data, err]: any = await this.api.api_userReadProfile(null); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.user.setUserProfile(data) + this.user.setUserProfile(data); } { - const [data, err]: any = await this.api.api_workspaceList({}) + const [data, err]: any = await this.api.api_workspaceList({}); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.workspace.setWorkspaceList(data) + this.workspace.setWorkspaceList(data); } if (!data.isFirstLogin) { - return + return; } // * 唤起弹窗 - this.isSyncModalVisible = true + this.isSyncModalVisible = true; { } - } - await btnLoginBtnRunning() - this.isLoginBtnBtnLoading = false + }; + await btnLoginBtnRunning(); + this.isLoginBtnBtnLoading = false; } handleOpenSettingModalCancel(): void { // * 关闭弹窗 - this.isOpenSettingModalVisible = false + this.isOpenSettingModalVisible = false; } - async ejr6w2fCallback() { + async e95oi5lCallback() { // * nzAfterClose event callback { } } - async textnrbqvsCallback() { + async textqdb64pCallback() { // * click event callback - this.message.send({ type: 'open-setting', data: {} }) + this.message.send({ type: 'open-setting', data: {} }); // * 关闭弹窗 - this.isOpenSettingModalVisible = false + this.isOpenSettingModalVisible = false; } handleAddWorkspaceModalCancel(): void { // * 关闭弹窗 - this.isAddWorkspaceModalVisible = false + this.isAddWorkspaceModalVisible = false; } - async epruwutCallback() { + async ebdsz2aCallback() { // * nzAfterClose event callback { // * auto clear form - this.validateWorkspaceNameForm.reset() + this.validateWorkspaceNameForm.reset(); } } - async btnfjbf3iCallback() { + async btn66ztjiCallback() { // * click event callback - this.isCancelBtnLoading = true + this.isCancelBtnLoading = true; const btnCancelRunning = async () => { // * 关闭弹窗 - this.isAddWorkspaceModalVisible = false - } - await btnCancelRunning() - this.isCancelBtnLoading = false + this.isAddWorkspaceModalVisible = false; + }; + await btnCancelRunning(); + this.isCancelBtnLoading = false; } - async btnkh8m1jCallback() { + async btnd4wbcjCallback() { // * click event callback - this.isSaveBtnLoading = true + this.isSaveBtnLoading = true; const btnSaveRunning = async () => { - const { newWorkName: title } = this.validateWorkspaceNameForm.value - const [data, err]: any = await this.api.api_workspaceCreate({ title }) + const { newWorkName: title } = this.validateWorkspaceNameForm.value; + const [data, err]: any = await this.api.api_workspaceCreate({ title }); if (err) { - this.eMessage.error($localize`Add workspace Failed !`) + this.eMessage.error($localize`Add workspace Failed !`); if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.eMessage.success($localize`Create new workspace successfully !`) + this.eMessage.success($localize`Create new workspace successfully !`); // * 关闭弹窗 - this.isAddWorkspaceModalVisible = false - + this.isAddWorkspaceModalVisible = false; + this.message.send({ type: 'update-share-link', data: {} }); { - const [lData, err]: any = await this.api.api_workspaceList({}) + const [lData, err]: any = await this.api.api_workspaceList({}); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.workspace.setWorkspaceList(lData) - this.workspace.setCurrentWorkspace(data) + this.workspace.setWorkspaceList(lData); + this.workspace.setCurrentWorkspace(data); } - } - await btnSaveRunning() - this.isSaveBtnLoading = false + }; + await btnSaveRunning(); + this.isSaveBtnLoading = false; } } diff --git a/src/workbench/browser/src/app/pages/vue3/vue3.component.html b/src/workbench/browser/src/app/pages/vue3/vue3.component.html new file mode 100644 index 000000000..90859cda6 --- /dev/null +++ b/src/workbench/browser/src/app/pages/vue3/vue3.component.html @@ -0,0 +1,5 @@ +
    + +
    diff --git a/src/workbench/browser/src/app/pages/vue3/vue3.component.scss b/src/workbench/browser/src/app/pages/vue3/vue3.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/workbench/browser/src/app/pages/vue3/vue3.component.spec.ts b/src/workbench/browser/src/app/pages/vue3/vue3.component.spec.ts new file mode 100644 index 000000000..d05273c6c --- /dev/null +++ b/src/workbench/browser/src/app/pages/vue3/vue3.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { Vue3Component } from './vue3.component'; + +describe('Vue3Component', () => { + let component: Vue3Component; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ Vue3Component ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(Vue3Component); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/workbench/browser/src/app/pages/vue3/vue3.component.ts b/src/workbench/browser/src/app/pages/vue3/vue3.component.ts new file mode 100644 index 000000000..b5701bd98 --- /dev/null +++ b/src/workbench/browser/src/app/pages/vue3/vue3.component.ts @@ -0,0 +1,45 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-vue3', + templateUrl: './vue3.component.html', + styleUrls: ['./vue3.component.scss'], +}) +export class Vue3Component implements OnInit { + url = `https://www.npmjs.com/`; + name = 'app-vue3'; + + constructor() {} + + microAppData = { msg: '来自基座的数据' }; + + ngOnInit(): void {} + + handleCreate(): void { + console.log('child-vue3 创建了'); + } + + handleBeforeMount(): void { + console.log('child-vue3 即将被渲染'); + } + + handleMount(): void { + console.log('child-vue3 已经渲染完成'); + + setTimeout(() => { + this.microAppData = { msg: '来自基座的新数据' }; + }, 2000); + } + + handleUnmount(): void { + console.log('child-vue3 卸载了'); + } + + handleError(): void { + console.log('child-vue3 加载出错了'); + } + + handleDataChange(e): void { + console.log('来自子应用 child-vue3 的数据:', e.detail.data); + } +} diff --git a/src/workbench/browser/src/app/pages/workspace.component.ts b/src/workbench/browser/src/app/pages/workspace.component.ts index 9e218c531..2025ad950 100644 --- a/src/workbench/browser/src/app/pages/workspace.component.ts +++ b/src/workbench/browser/src/app/pages/workspace.component.ts @@ -1,16 +1,16 @@ -import { NzModalService } from 'ng-zorro-antd/modal' -import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service' -import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service' -import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service' -import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service' -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' +import { NzModalService } from 'ng-zorro-antd/modal'; +import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service'; +import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service'; +import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service'; +import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators -} from '@angular/forms' -import { ViewChild, ElementRef, Component, OnInit } from '@angular/core' +} from '@angular/forms'; +import { ViewChild, ElementRef, Component, OnInit } from '@angular/core'; @Component({ selector: 'eo-workspace', @@ -50,7 +50,7 @@ import { ViewChild, ElementRef, Component, OnInit } from '@angular/core' [nzLoading]="isSaveBtnBtnLoading" class="" nzType="primary" - (click)="btnkklkd9Callback()" + (click)="btnogunjqCallback()" i18n > Save @@ -73,7 +73,7 @@ import { ViewChild, ElementRef, Component, OnInit } from '@angular/core' class="" nzType="primary" nzDanger - (click)="btnbtfiktCallback()" + (click)="btn5y8eslCallback()" i18n > Delete @@ -82,9 +82,9 @@ import { ViewChild, ElementRef, Component, OnInit } from '@angular/core' ` }) export class WorkspaceComponent implements OnInit { - validateWspNameForm - isSaveBtnBtnLoading - isDelWspBtnLoading + validateWspNameForm; + isSaveBtnBtnLoading; + isDelWspBtnLoading; constructor( public modal: NzModalService, public workspace: WorkspaceService, @@ -94,66 +94,66 @@ export class WorkspaceComponent implements OnInit { public api: RemoteService, public fb: UntypedFormBuilder ) { - this.validateWspNameForm = UntypedFormGroup - this.isSaveBtnBtnLoading = false - this.isDelWspBtnLoading = false + this.validateWspNameForm = UntypedFormGroup; + this.isSaveBtnBtnLoading = false; + this.isDelWspBtnLoading = false; } async ngOnInit(): Promise { // * Init WspName form this.validateWspNameForm = this.fb.group({ workspace: [null, [Validators.required]] - }) + }); - const { title: currentWsp } = this.workspace.currentWorkspace + const { title: currentWsp } = this.workspace.currentWorkspace; // * get WspName form values this.validateWspNameForm.patchValue({ workspace: currentWsp - }) + }); } - async btnkklkd9Callback() { + async btnogunjqCallback() { // * click event callback - this.isSaveBtnBtnLoading = true + this.isSaveBtnBtnLoading = true; const btnSaveBtnRunning = async () => { - const { id: currentWsp } = this.workspace.currentWorkspace - const { workspace: title } = this.validateWspNameForm.value + const { id: currentWsp } = this.workspace.currentWorkspace; + const { workspace: title } = this.validateWspNameForm.value; const [data, err]: any = await this.api.api_workspaceEdit({ workspaceID: currentWsp, title - }) + }); if (err) { - this.eMessage.error($localize`Edit workspace failed`) + this.eMessage.error($localize`Edit workspace failed`); if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.eMessage.success($localize`Edit workspace successfully !`) - const [list, wErr]: any = await this.api.api_workspaceList({}) + this.eMessage.success($localize`Edit workspace successfully !`); + const [list, wErr]: any = await this.api.api_workspaceList({}); if (wErr) { if (wErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.workspace.setWorkspaceList(list) - } - await btnSaveBtnRunning() - this.isSaveBtnBtnLoading = false + this.workspace.setWorkspaceList(list); + }; + await btnSaveBtnRunning(); + this.isSaveBtnBtnLoading = false; } - async btnbtfiktCallback() { + async btn5y8eslCallback() { // * click event callback - this.isDelWspBtnLoading = true + this.isDelWspBtnLoading = true; const btnDelWspRunning = async () => { - this.isDelWspBtnLoading = false + this.isDelWspBtnLoading = false; const confirm = () => new Promise((resolve) => { @@ -162,46 +162,46 @@ export class WorkspaceComponent implements OnInit { nzContent: $localize`Are you sure you want to delete the workspace ? You cannot restore it once deleted!`, nzOkDanger: true, - nzOkText: $localize`Remove`, + nzOkText: $localize`Delete`, nzOnOk: () => resolve(true), nzOnCancel: () => resolve(false) - }) - }) - const isOk = await confirm() + }); + }); + const isOk = await confirm(); if (!isOk) { - return + return; } - const { id: currentWsp } = this.workspace.currentWorkspace + const { id: currentWsp } = this.workspace.currentWorkspace; const [data, err]: any = await this.api.api_workspaceDelete({ workspaceID: currentWsp - }) + }); if (err) { if (err.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.eMessage.success($localize`Delete success !`) - await this.workspace.setLocalSpace() - const [list, wErr]: any = await this.api.api_workspaceList({}) + this.eMessage.success($localize`Delete success !`); + await this.workspace.setLocalSpace(); + const [list, wErr]: any = await this.api.api_workspaceList({}); if (wErr) { if (wErr.status === 401) { - this.message.send({ type: 'clear-user', data: {} }) + this.message.send({ type: 'clear-user', data: {} }); if (this.user.isLogin) { - return + return; } - this.message.send({ type: 'http-401', data: {} }) + this.message.send({ type: 'http-401', data: {} }); } - return + return; } - this.workspace.setWorkspaceList(list) - } - await btnDelWspRunning() - this.isDelWspBtnLoading = false + this.workspace.setWorkspaceList(list); + }; + await btnDelWspRunning(); + this.isDelWspBtnLoading = false; } } diff --git a/src/workbench/browser/src/app/pages/workspace.module.ts b/src/workbench/browser/src/app/pages/workspace.module.ts index 3fc0f07cb..a2932a84f 100644 --- a/src/workbench/browser/src/app/pages/workspace.module.ts +++ b/src/workbench/browser/src/app/pages/workspace.module.ts @@ -1,22 +1,18 @@ -import { NgModule } from '@angular/core' -import { CommonModule } from '@angular/common' -import { NzModalService, NzModalModule } from 'ng-zorro-antd/modal' -import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.service' -import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service' -import { UserService } from 'eo/workbench/browser/src/app/shared/services/user/user.service' -import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service' -import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service' -import { ApiOverviewComponent } from 'eo/workbench/browser/src/app/pages/api/overview/api-overview.component' -import { EoIconparkIconModule } from 'eo/workbench/browser/src/app/eoui/iconpark-icon/eo-iconpark-icon.module' -import { NzDividerModule } from 'ng-zorro-antd/divider' -import { NzCardModule } from 'ng-zorro-antd/card' -import { ReactiveFormsModule } from '@angular/forms' -import { NzFormModule } from 'ng-zorro-antd/form' -import { NzInputModule } from 'ng-zorro-antd/input' -import { NzButtonModule } from 'ng-zorro-antd/button' +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NzModalService, NzModalModule } from 'ng-zorro-antd/modal'; +import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; +import { ApiOverviewComponent } from 'eo/workbench/browser/src/app/pages/api/overview/api-overview.component'; +import { EoIconparkIconModule } from 'eo/workbench/browser/src/app/eoui/iconpark-icon/eo-iconpark-icon.module'; +import { NzDividerModule } from 'ng-zorro-antd/divider'; +import { NzCardModule } from 'ng-zorro-antd/card'; +import { ReactiveFormsModule } from '@angular/forms'; +import { NzFormModule } from 'ng-zorro-antd/form'; +import { NzInputModule } from 'ng-zorro-antd/input'; +import { NzButtonModule } from 'ng-zorro-antd/button'; -import { WorkspaceRoutingModule } from './workspace-routing.module' -import { WorkspaceComponent } from './workspace.component' +import { WorkspaceRoutingModule } from './workspace-routing.module'; +import { WorkspaceComponent } from './workspace.component'; @NgModule({ imports: [ @@ -29,10 +25,10 @@ import { WorkspaceComponent } from './workspace.component' ReactiveFormsModule, NzFormModule, NzInputModule, - NzButtonModule + NzButtonModule, ], declarations: [WorkspaceComponent, ApiOverviewComponent], exports: [], - providers: [NzModalService, MessageService, RemoteService] + providers: [NzModalService, MessageService], }) export class WorkspaceModule {} diff --git a/src/workbench/browser/src/app/shared/components/api-script/constant.ts b/src/workbench/browser/src/app/shared/components/api-script/constant.ts index d69b8e78f..f94b3a8ed 100644 --- a/src/workbench/browser/src/app/shared/components/api-script/constant.ts +++ b/src/workbench/browser/src/app/shared/components/api-script/constant.ts @@ -160,41 +160,6 @@ const COMMON_DATA: TreeNode[] = [ }, ], }, - { - name: $localize`Environment Management`, - children: [ - { - name: $localize`Get enviroment host`, - caption: 'eo.env.http.baseUrl.get', - value: 'eo.env.http.baseUrl.get()', - note: { - code: 'eo.env.http.baseUrl.get()', - desc: $localize`Get enviroment host`, - output: $localize`The host prefix set in the environment`, - }, - }, - { - name: $localize`Get an environment variables`, - caption: 'eo.env.param.get', - value: 'eo.env.param.get("param_key")', - note: { - code: 'eo.env.param.get("param_key")', - desc: $localize`Get an environment variables`, - input: [commonInputs[0]], - }, - }, - { - name: $localize`Set an environment variables`, - caption: 'eo.env.param.set', - value: 'eo.env.param.set("param_key","param_value")', - note: { - code: 'eo.env.param.set("param_key","param_value")', - desc: $localize`Set an environment variables`, - input: [...commonInputs], - }, - }, - ], - }, { name: $localize`Encode and Decode`, children: [ diff --git a/src/workbench/browser/src/app/shared/components/env-list/env-list.component.ts b/src/workbench/browser/src/app/shared/components/env-list/env-list.component.ts index aac304b0c..d3c087be9 100644 --- a/src/workbench/browser/src/app/shared/components/env-list/env-list.component.ts +++ b/src/workbench/browser/src/app/shared/components/env-list/env-list.component.ts @@ -1,5 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { getGlobals } from 'eo/workbench/browser/src/app/shared/services/api-test/api-test.utils'; +import { ShareService } from 'eo/workbench/browser/src/app/shared/services/share.service'; +import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/storage/remote.service'; import { Environment, StorageRes, StorageResStatus } from '../../../shared/services/storage/index.model'; import { StorageService } from '../../services/storage'; @@ -12,12 +15,14 @@ import { StorageService } from '../../services/storage'; {{ it.value }}

    No Global variables

    -
    - Environment Host -
    -

    {{ env.hostUri }}

    +
    +
    + Environment Host +
    +

    {{ env.hostUri }}

    +
    - Environment variable + Environment Global variable
    {{ it.name }} {{ it.value }} @@ -29,7 +34,12 @@ import { StorageService } from '../../services/storage'; export class EnvListComponent implements OnInit { env: Environment | any = {}; gloablParams: any = []; - constructor(private storage: StorageService) {} + constructor( + private storage: StorageService, + private share: ShareService, + private status: StatusService, + private http: RemoteService + ) {} async ngOnInit() { this.gloablParams = this.getGlobalParams(); const uuid = Number(localStorage.getItem('env:selected')) || null; @@ -37,11 +47,25 @@ export class EnvListComponent implements OnInit { return; } const envList: any = await this.getAllEnv(); - this.env = envList.find((it: any) => it.uuid === uuid); + this.env = envList + .map((it) => ({ + ...it, + parameters: it.parameters.filter((item) => item.name || item.value), + })) + .find((it: any) => it.uuid === uuid); } getAllEnv(uuid?: number) { const projectID = 1; - return new Promise((resolve) => { + return new Promise(async (resolve) => { + if (this.status.isShare) { + const [data, err]: any = await this.http.api_shareDocGetEnv({ + uniqueID: this.share.shareId, + }); + if (err) { + return resolve([]); + } + return resolve(data || []); + } this.storage.run('environmentLoadAllByProjectID', [projectID], async (result: StorageRes) => { if (result.status === StorageResStatus.success) { return resolve(result.data || []); diff --git a/src/workbench/browser/src/app/shared/components/env/env.component.html b/src/workbench/browser/src/app/shared/components/env/env.component.html index e2e356594..569c1e6eb 100644 --- a/src/workbench/browser/src/app/shared/components/env/env.component.html +++ b/src/workbench/browser/src/app/shared/components/env/env.component.html @@ -9,10 +9,20 @@ New
    -
    + @@ -33,10 +43,14 @@ -

    Environment variable: API Documentation/Test can use {{ varName }} to refer to the - environment variable

    - +

    + Global variable: API Documentation/Test can use {{ varName }} to refer to the global variable +

    + @@ -45,7 +59,7 @@
    -