mirror of
https://gitee.com/eolink_admin/postcat.git
synced 2024-12-02 03:38:03 +08:00
Share api document (#168)
This commit is contained in:
parent
2a64e7d3a2
commit
0746c235f5
21
.dockerignore
Normal file
21
.dockerignore
Normal file
@ -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
|
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@ -2,6 +2,7 @@ name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
# branches: [for debug]
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -54,3 +54,6 @@ Thumbs.db
|
||||
# *-lock.json
|
||||
-error.log
|
||||
.vercel
|
||||
nginx-test.conf
|
||||
docker-compose.dev.yml
|
||||
Dockerfile.dev
|
||||
|
23
CHANGELOG.md
23
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)
|
||||
|
||||
|
||||
|
26
Dockerfile
Normal file
26
Dockerfile
Normal file
@ -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
|
39
docker-compose.yml
Normal file
39
docker-compose.yml
Normal file
@ -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
|
86
nginx.conf
Normal file
86
nginx.conf
Normal file
@ -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;
|
||||
#}
|
||||
}
|
@ -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",
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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';
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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.getExtensionPagePathByName = (extName: string) => {
|
||||
return ipcRenderer.invoke('eo-sync', { action: 'getExtensionPagePathByName', data: { extName } });
|
||||
};
|
||||
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.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 }) => {
|
||||
|
@ -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 || '<core-module>';
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { ViewBounds } from 'eo/shared/common/bounds';
|
||||
|
||||
export interface BrowserViewOpts {
|
||||
bounds: ViewBounds;
|
||||
partition?: string;
|
||||
preloadPath?: string;
|
||||
viewPath: string;
|
||||
preload?: string;
|
||||
}
|
3
src/platform/electron-node/preload.ts
Normal file
3
src/platform/electron-node/preload.ts
Normal file
@ -0,0 +1,3 @@
|
||||
globalThis.eo = {
|
||||
getExtensionSetting() {},
|
||||
};
|
@ -88,7 +88,7 @@ export class Configuration implements ConfigurationInterface {
|
||||
* @param section
|
||||
* @returns
|
||||
*/
|
||||
getModuleSettings<T = any>(section?: string): T {
|
||||
getExtensionSettings<T = any>(section?: string): T {
|
||||
return this.getConfiguration(section);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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) => {
|
||||
|
@ -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<ModuleInfo>): 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列表
|
||||
}
|
||||
}
|
@ -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<string, ExtensionTabView>();
|
||||
const extSidebarViewServerMap = new Map<string, SidebarView>();
|
||||
|
||||
// * 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<string, Map<string, object>>;
|
||||
private readonly features: Map<string, Map<string, FeatureInfo>>;
|
||||
|
||||
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<ModuleInfo> {
|
||||
const output: Array<ModuleInfo> = [];
|
||||
const modules: Map<string, ModuleInfo> = 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<ModuleInfo> {
|
||||
const output: Array<ModuleInfo> = [];
|
||||
const modules: Map<string, ModuleInfo> = 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<string, ModuleInfo> {
|
||||
if (belongs) {
|
||||
return this.moduleBelongs();
|
||||
}
|
||||
getModules(): Map<string, ModuleInfo> {
|
||||
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<string, ModuleInfo> {
|
||||
const newModules: Map<string, ModuleInfo> = 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<SidebarView> {
|
||||
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<string>, 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<ExtensionTabView[]> {
|
||||
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<SidebarView[]> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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<ModuleHandlerResult>;
|
||||
uninstall: (module: ModuleManagerInfo) => Promise<ModuleHandlerResult>;
|
||||
refresh: (module: ModuleManagerInfo) => void;
|
||||
refreshAll: () => void;
|
||||
getModule: (id: string) => ModuleInfo;
|
||||
getModules: () => Map<string, ModuleInfo>;
|
||||
getFeature: (featureKey: string) => Map<string, object>;
|
||||
getFeatures: () => Map<string, Map<string, object>>;
|
||||
setupExtensionPageServer: (extName: string) => any;
|
||||
}
|
||||
|
@ -1,3 +1,2 @@
|
||||
export * from './handler';
|
||||
export * from './manager';
|
||||
export * from './loader';
|
||||
export * from './module';
|
||||
|
@ -1,18 +0,0 @@
|
||||
import {ModuleInfo} from './manager';
|
||||
|
||||
/**
|
||||
* 模块加载接口.
|
||||
*/
|
||||
export interface ModuleLoaderInterface {
|
||||
loadModules: (modules: Array<ModuleInfo>) => void;
|
||||
loadModule: (module: ModuleInfo) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模块运行环境
|
||||
*/
|
||||
export enum ModuleRuntime {
|
||||
main = 'main',
|
||||
render = 'render',
|
||||
web = 'web'
|
||||
}
|
@ -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<string>;
|
||||
// 下层关联模块ID集合
|
||||
//!TODO what usage?
|
||||
sideItems?: Array<string>;
|
||||
// 模块路径
|
||||
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<string>;
|
||||
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<ModuleHandlerResult>;
|
||||
uninstall: (module: ModuleManagerInfo) => Promise<ModuleHandlerResult>;
|
||||
refresh: (module: ModuleManagerInfo) => void;
|
||||
refreshAll: () => void;
|
||||
getModule: (moduleID: string, belongs?: boolean) => ModuleInfo;
|
||||
getModules: (belongs?: boolean) => Map<string, ModuleInfo>;
|
||||
getAppModuleList: () => Array<ModuleInfo>;
|
||||
getSideModuleList: (moduleID: string) => Array<ModuleInfo>;
|
||||
getFeature: (featureKey: string) => Map<string, object>;
|
||||
getFeatures: () => Map<string, Map<string, object>>;
|
||||
}
|
113
src/platform/node/extension-manager/types/module.ts
Normal file
113
src/platform/node/extension-manager/types/module.ts
Normal file
@ -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<string>;
|
||||
default: string | number | null;
|
||||
label: string;
|
||||
description?: string;
|
||||
required?: boolean;
|
||||
}
|
||||
export type ExtensionTabView = {
|
||||
name: string;
|
||||
url: string;
|
||||
debugUrl: string;
|
||||
server: HttpServer;
|
||||
};
|
||||
|
||||
type HttpServer = ReturnType<typeof createServer>;
|
||||
export type SidebarView = {
|
||||
icon: string;
|
||||
title: string;
|
||||
url: string;
|
||||
debugUrl: string;
|
||||
server: HttpServer;
|
||||
};
|
||||
|
||||
export interface I18nLocale {
|
||||
sourceLocale: string;
|
||||
locales: string[];
|
||||
}
|
@ -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];
|
||||
}
|
||||
|
@ -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<boolean>('eoapi-features.mock.matchType');
|
||||
const isMatchType = this.configuration.getExtensionSettings<boolean>('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<boolean>('eoapi-features.mock.matchType');
|
||||
const isMatchType = this.configuration.getExtensionSettings<boolean>('eoapi-features.mock.matchType');
|
||||
if (req.params.mockID || isMatchType !== false) {
|
||||
this.view.webContents.send('getMockApiList', JSON.parse(jsonStringify(req)));
|
||||
ipcMain.once('getMockApiList', (event, message) => {
|
||||
|
@ -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<ViewZone, ViewBounds> => {
|
||||
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]
|
||||
]);
|
||||
};
|
1
src/workbench/browser/.gitignore
vendored
1
src/workbench/browser/.gitignore
vendored
@ -12,6 +12,7 @@ src/**/*.js
|
||||
!src/ng1/**/*.js
|
||||
!src/assets/libs/*.js
|
||||
*.js.map
|
||||
proxy.conf.json
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
@ -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"}}}
|
@ -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',
|
||||
`<!DOCTYPE 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();
|
||||
|
21
src/workbench/browser/elements/apiContent.ts
Normal file
21
src/workbench/browser/elements/apiContent.ts
Normal file
@ -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: `<eo-api></eo-api>`,
|
||||
data: [],
|
||||
methods: [],
|
||||
};
|
||||
}
|
||||
}
|
@ -28,3 +28,4 @@ export { HTTPS } from './service/httpS';
|
||||
|
||||
// * 业务
|
||||
export { ManageAccess } from './manageAccess';
|
||||
export { ApiContent } from './apiContent';
|
||||
|
@ -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} })`;
|
||||
}
|
||||
}
|
||||
|
@ -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: `<nz-tree [nzData]="nodes" nzShowLine (nzClick)="nzEvent($event)"></nz-tree>`,
|
||||
data: [],
|
||||
methods: [],
|
||||
template: `<eo-api-group-tree ${this.showline ? 'nzShowLine' : ''}></eo-api-group-tree>`,
|
||||
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}`;
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"/api": {
|
||||
"target": "https://290135738u.oicp.vip/",
|
||||
"secure": false,
|
||||
"pathRewrite": {
|
||||
"^/api": ""
|
||||
},
|
||||
"logLevel": "debug"
|
||||
}
|
||||
}
|
@ -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 {}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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/`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
}
|
@ -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: `<h2 class="text-lg flex justify-between items-center">
|
||||
<span class="font-bold text-lg mb-2" i18n>Account</span>
|
||||
</h2>
|
||||
<h2
|
||||
class="text-lg flex justify-between items-center"
|
||||
id="eoapi-account-username"
|
||||
>
|
||||
<h2 class="text-lg flex justify-between items-center" id="eoapi-account-username">
|
||||
<span class="font-bold text-base mb-2" i18n>Username</span>
|
||||
</h2>
|
||||
<section class="w-1/2">
|
||||
<form nz-form [formGroup]="validateUsernameForm" nzLayout="vertical">
|
||||
<nz-form-item>
|
||||
<nz-form-control nzErrorTip="Please input your username;">
|
||||
<input
|
||||
type="text"
|
||||
nz-input
|
||||
formControlName="username"
|
||||
placeholder=""
|
||||
i18n-placeholder
|
||||
/>
|
||||
<input type="text" nz-input formControlName="username" placeholder="" i18n-placeholder />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
@ -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
|
||||
</form>
|
||||
<section class="h-4"></section>
|
||||
</section>
|
||||
<h2
|
||||
class="text-lg flex justify-between items-center"
|
||||
id="eoapi-account-password"
|
||||
>
|
||||
<h2 class="text-lg flex justify-between items-center" id="eoapi-account-password">
|
||||
<span class="font-bold text-base mb-2" i18n>Password</span>
|
||||
</h2>
|
||||
<section class="w-1/2">
|
||||
<form nz-form [formGroup]="validatePasswordForm" nzLayout="vertical">
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="24" nzRequired i18n
|
||||
>Current password</nz-form-label
|
||||
>
|
||||
<nz-form-label [nzSpan]="24" nzRequired i18n>Current password</nz-form-label>
|
||||
<nz-form-control nzErrorTip="Please input your current password;">
|
||||
<input
|
||||
type="password"
|
||||
nz-input
|
||||
formControlName="oldPassword"
|
||||
placeholder=""
|
||||
i18n-placeholder
|
||||
/>
|
||||
<input type="password" nz-input formControlName="oldPassword" placeholder="" i18n-placeholder />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="24" nzRequired i18n
|
||||
>New password</nz-form-label
|
||||
>
|
||||
<nz-form-label [nzSpan]="24" nzRequired i18n>New password</nz-form-label>
|
||||
<nz-form-control nzErrorTip="Please input your new password;">
|
||||
<input
|
||||
type="password"
|
||||
nz-input
|
||||
formControlName="newPassword"
|
||||
placeholder=""
|
||||
i18n-placeholder
|
||||
/>
|
||||
<input type="password" nz-input formControlName="newPassword" placeholder="" i18n-placeholder />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="24" nzRequired i18n
|
||||
>Confirm new password</nz-form-label
|
||||
>
|
||||
<nz-form-label [nzSpan]="24" nzRequired i18n>Confirm new password</nz-form-label>
|
||||
<nz-form-control [nzErrorTip]="confirmPasswordErrorTpl">
|
||||
<input
|
||||
type="password"
|
||||
nz-input
|
||||
formControlName="confirmPassword"
|
||||
placeholder=""
|
||||
i18n-placeholder
|
||||
/>
|
||||
<input type="password" nz-input formControlName="confirmPassword" placeholder="" i18n-placeholder />
|
||||
<ng-template #confirmPasswordErrorTpl let-control>
|
||||
<ng-container *ngIf="control.hasError('required')" i18n>
|
||||
Please input your confirm new password;
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="control.hasError('isEqual')" i18n>
|
||||
Please confirm your password;
|
||||
</ng-container>
|
||||
<ng-container *ngIf="control.hasError('isEqual')" i18n> Please confirm your password; </ng-container>
|
||||
|
||||
<ng-container *ngIf="control.hasError('minlength')" i18n>
|
||||
Min length is 6;
|
||||
</ng-container>
|
||||
<ng-container *ngIf="control.hasError('minlength')" i18n> Min length is 6; </ng-container>
|
||||
|
||||
<ng-container *ngIf="control.hasError('maxlength')" i18n>
|
||||
Max length is 11;
|
||||
</ng-container>
|
||||
<ng-container *ngIf="control.hasError('maxlength')" i18n> Max length is 11; </ng-container>
|
||||
</ng-template>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
@ -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
|
||||
</section>
|
||||
</form>
|
||||
</section>
|
||||
<section class="h-4"></section> `
|
||||
<section class="h-4"></section> `,
|
||||
})
|
||||
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<void> {
|
||||
// * 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<any> = new Subject();
|
||||
BASIC_TABS: Partial<TabItem>[] = [
|
||||
{
|
||||
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<TabItem>[] = 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
|
||||
|
@ -10,7 +10,12 @@
|
||||
>
|
||||
<!-- <div class="side-container"> -->
|
||||
<nz-content class="api-container-tabs">
|
||||
<nz-tabset nzCentered [nzAnimated]="false" [(nzSelectedIndex)]="tabsIndex">
|
||||
<nz-tabset
|
||||
[ngClass]="{ 'share-group-tabset': status.isShare }"
|
||||
nzCentered
|
||||
[nzAnimated]="false"
|
||||
[(nzSelectedIndex)]="tabsIndex"
|
||||
>
|
||||
<nz-tab [nzTitle]="apiTitle">
|
||||
<ng-template #apiTitle>
|
||||
<span
|
||||
@ -27,7 +32,7 @@
|
||||
<eo-api-group-tree></eo-api-group-tree>
|
||||
</div>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="historyTitle">
|
||||
<nz-tab [nzTitle]="historyTitle" *ngIf="!status.isShare">
|
||||
<ng-template #historyTitle>
|
||||
<span
|
||||
i18n-nzTooltipTitle
|
||||
@ -74,8 +79,14 @@
|
||||
<nz-option *ngFor="let item of envList" [nzValue]="item.uuid" [nzLabel]="item.name"></nz-option>
|
||||
</nz-select>
|
||||
<ng-template #renderTemplate>
|
||||
<nz-divider></nz-divider>
|
||||
<a class="text-sx manager-env" nz-button nzType="link" (click)="gotoEnvManager()" i18n
|
||||
<nz-divider *ngIf="!status.isShare"></nz-divider>
|
||||
<a
|
||||
*ngIf="!status.isShare"
|
||||
class="text-sx manager-env"
|
||||
nz-button
|
||||
nzType="link"
|
||||
(click)="gotoEnvManager()"
|
||||
i18n
|
||||
>Manage Environment</a
|
||||
>
|
||||
</ng-template>
|
||||
@ -106,23 +117,28 @@
|
||||
*ngIf="this.id"
|
||||
nzLinkRouter
|
||||
>
|
||||
<nz-tab *ngFor="let tab of TABS">
|
||||
<nz-tab *ngFor="let tab of renderTabs">
|
||||
<p *ngIf="web.isWeb && tab.onlyDestop">
|
||||
<span *nzTabLink nz-tab-link (click)="goDownload($event)">{{ tab.title }}</span>
|
||||
</p>
|
||||
<span *ngIf="!web.isWeb || !tab.onlyDestop">
|
||||
<div *ngIf="!web.isWeb || !tab.onlyDestop">
|
||||
<a *nzTabLink nz-tab-link [routerLink]="['http/' + tab.routerLink]" queryParamsHandling="merge">
|
||||
{{ tab.title }}</a
|
||||
>
|
||||
</span>
|
||||
{{ tab.title }} <nz-badge *ngIf="apiTabComponent.getCurrentTab()?.extends?.hasChanged?.[tab.routerLink]" nzStatus="success"></nz-badge
|
||||
></a>
|
||||
</div>
|
||||
</nz-tab>
|
||||
</nz-tabset>
|
||||
</div>
|
||||
<section class="relative" [ngStyle]="{ paddingRight: activeBar ? dyWidth + 'px' : '40px' }">
|
||||
<section class="relative" [ngStyle]="{ paddingRight: countPaddingRight() }">
|
||||
<!-- Get router child component by activate -->
|
||||
<router-outlet (activate)="onActivate($event)"></router-outlet>
|
||||
<eo-split-x *ngIf="activeBar" (x)="handleDrag($event)" [init]="[200, dyWidth, 400]"></eo-split-x>
|
||||
<eo-split-x
|
||||
*ngIf="activeBar && !status.isShare"
|
||||
(x)="handleDrag($event)"
|
||||
[init]="[200, dyWidth, 400]"
|
||||
></eo-split-x>
|
||||
<div
|
||||
*ngIf="!status.isShare"
|
||||
class="absolute top-0 bottom-0 right-0 flex right-bar"
|
||||
[ngClass]="{ 'left-line': !activeBar }"
|
||||
[ngStyle]="{ width: activeBar ? dyWidth + 'px' : '40px' }"
|
||||
@ -132,7 +148,6 @@
|
||||
[ngClass]="activeBar ? 'active' : ''"
|
||||
(click)="toggleRightBar()"
|
||||
nz-tooltip
|
||||
[nzTooltipMouseEnterDelay]="0.7"
|
||||
[nzTooltipMouseLeaveDelay]="0"
|
||||
i18n-nzTooltipTitle="@@Environment Setting"
|
||||
nzTooltipTitle="Environment Setting"
|
||||
|
@ -2,7 +2,6 @@ nz-content {
|
||||
width: 100%;
|
||||
background-color: var(--MAIN_BG);
|
||||
}
|
||||
|
||||
:lang(zh) {
|
||||
nz-select {
|
||||
width: 132px;
|
||||
@ -45,7 +44,6 @@ nz-divider {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep {
|
||||
eo-api {
|
||||
display: flex;
|
||||
@ -108,6 +106,11 @@ nz-divider {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.share-group-tabset{
|
||||
.ant-tabs-nav{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.content_container {
|
||||
border-top: 1px solid var(--BORDER);
|
||||
.inside_page_tabset {
|
||||
@ -206,12 +209,4 @@ nz-divider {
|
||||
}
|
||||
}
|
||||
}
|
||||
.eo-tab-theme-icon {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
background-color: var(--MAIN_THEME_COLOR);
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,10 @@ import { ApiTabComponent } from 'eo/workbench/browser/src/app/pages/api/tab/api-
|
||||
import { ApiTabService } from './api-tab.service';
|
||||
import { NzResizeEvent } from 'ng-zorro-antd/resizable';
|
||||
import { WebService } from 'eo/workbench/browser/src/app/core/services';
|
||||
import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service';
|
||||
import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/workspace/workspace.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';
|
||||
|
||||
const DY_WIDTH_KEY = 'DY_WIDTH';
|
||||
const LEFT_SIDER_WIDTH_KEY = 'LEFT_SIDER_WIDTH_KEY';
|
||||
@ -42,9 +46,11 @@ export class ApiComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
id: number;
|
||||
pageID: number;
|
||||
renderTabs = [];
|
||||
TABS = [
|
||||
{
|
||||
routerLink: 'detail',
|
||||
isShare: true,
|
||||
title: $localize`:@@API Detail:Preview`,
|
||||
},
|
||||
{
|
||||
@ -53,6 +59,7 @@ export class ApiComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
{
|
||||
routerLink: 'test',
|
||||
isShare: true,
|
||||
title: $localize`Test`,
|
||||
},
|
||||
{
|
||||
@ -79,7 +86,11 @@ export class ApiComponent implements OnInit, OnDestroy {
|
||||
private messageService: MessageService,
|
||||
private storage: StorageService,
|
||||
public web: WebService,
|
||||
private store: Store
|
||||
private store: Store,
|
||||
public status: StatusService,
|
||||
private workspace: WorkspaceService,
|
||||
private http: RemoteService,
|
||||
private share: ShareService
|
||||
) {}
|
||||
get envUuid(): number | null {
|
||||
return Number(localStorage.getItem('env:selected')) || 0;
|
||||
@ -109,6 +120,7 @@ export class ApiComponent implements OnInit, OnDestroy {
|
||||
this.watchDataSourceChange();
|
||||
this.initEnv();
|
||||
this.watchEnvChange();
|
||||
this.renderTabs = this.status.isShare ? this.TABS.filter((it) => 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 || []);
|
||||
|
@ -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 {}
|
||||
|
@ -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<ApiData> {
|
||||
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);
|
||||
|
@ -7,8 +7,7 @@
|
||||
</nz-form-item>
|
||||
</form>
|
||||
<p *ngIf="isDelete" i18n>
|
||||
Data from <strong title="{{ group.name }}">{{
|
||||
group.name.length > 50 ? group.name.slice(0, 50) + '...' : group.name
|
||||
}}</strong>
|
||||
Data from
|
||||
<strong title="{{ group.name }}">{{ group.name.length > 50 ? group.name.slice(0, 50) + '...' : group.name }}</strong>
|
||||
will be deleted. This cannot be undone. Are you sure you want to delete?
|
||||
</p>
|
||||
|
@ -1,9 +1,22 @@
|
||||
<header class="flex pt-2">
|
||||
<input nz-input type="text" class="flex-1 px-3 eo-search-input" i18n-placeholder="@@Search" placeholder="Search"
|
||||
[(ngModel)]="searchValue" />
|
||||
<button nzType="primary" nz-button class="flex w-[20px] items-center justify-center ml-3 text-base shrink-0"
|
||||
nz-dropdown [nzDropdownMenu]="menu" nzPlacement="bottomRight"
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'addAPI' })">
|
||||
<input
|
||||
nz-input
|
||||
type="text"
|
||||
class="flex-1 px-3 eo-search-input"
|
||||
i18n-placeholder="@@Search"
|
||||
placeholder="Search"
|
||||
[(ngModel)]="searchValue"
|
||||
/>
|
||||
<button
|
||||
*ngIf="!status.isShare"
|
||||
nzType="primary"
|
||||
nz-button
|
||||
class="flex w-[20px] items-center justify-center ml-3 text-base shrink-0"
|
||||
nz-dropdown
|
||||
[nzDropdownMenu]="menu"
|
||||
nzPlacement="bottomRight"
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'addAPI' })"
|
||||
>
|
||||
<eo-iconpark-icon name="plus" size="16px"></eo-iconpark-icon>
|
||||
</button>
|
||||
<nz-dropdown-menu #menu="nzDropdownMenu">
|
||||
@ -21,10 +34,21 @@
|
||||
|
||||
<!-- Custom Group -->
|
||||
<div class="group_container group_tree pt10">
|
||||
<nz-tree *ngIf="treeNodes.length" [nzData]="treeNodes" [nzSelectedKeys]="nzSelectedKeys" #apiGroup
|
||||
[nzSearchValue]="searchValue" [nzHideUnMatched]="true" [nzExpandedKeys]="expandKeys"
|
||||
(nzClick)="clickTreeItem($event)" (nzExpandChange)="toggleExpand()" nzDraggable nzBlockNode
|
||||
(nzOnDrop)="treeItemDrop($event)" [nzTreeTemplate]="nzTreeTemplate"></nz-tree>
|
||||
<nz-tree
|
||||
*ngIf="treeNodes.length"
|
||||
[nzData]="treeNodes"
|
||||
[nzSelectedKeys]="nzSelectedKeys"
|
||||
#apiGroup
|
||||
[nzSearchValue]="searchValue"
|
||||
[nzHideUnMatched]="true"
|
||||
[nzExpandedKeys]="expandKeys"
|
||||
(nzClick)="clickTreeItem($event)"
|
||||
(nzExpandChange)="toggleExpand()"
|
||||
[nzDraggable]="isEdit"
|
||||
nzBlockNode
|
||||
(nzOnDrop)="treeItemDrop($event)"
|
||||
[nzTreeTemplate]="nzTreeTemplate"
|
||||
></nz-tree>
|
||||
<nz-skeleton [nzLoading]="apiDataLoading && !treeNodes.length" [nzActive]="true">
|
||||
<ng-template #nzTreeTemplate let-node let-origin="origin">
|
||||
<div [style.--tree-level]="node.level">
|
||||
@ -33,7 +57,7 @@
|
||||
<div class="overflow-hidden f_row_ac text-ellipsis">
|
||||
<span class="text_omit node_title">{{ node.title }}</span>
|
||||
</div>
|
||||
<span class="flex tree_node_operate">
|
||||
<span class="flex tree_node_operate" *ngIf="isEdit">
|
||||
<button nz-dropdown [nzDropdownMenu]="groupMenu" class="flex items-center">
|
||||
<eo-iconpark-icon class="mr5" name="more" size="16px"></eo-iconpark-icon>
|
||||
</button>
|
||||
@ -60,15 +84,17 @@
|
||||
<div class="overflow-hidden f_row_ac text-ellipsis">
|
||||
<b class="method_text method_text_{{ node.origin.method }} mr5" *ngIf="node.origin.method">{{
|
||||
node.origin.method
|
||||
}}</b>
|
||||
}}</b>
|
||||
<span class="text_omit node_title">{{ node.title }}</span>
|
||||
</div>
|
||||
<div class="flex tree_node_operate">
|
||||
<button class="flex items-center"
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'testApi', node: node })">
|
||||
<button
|
||||
class="flex items-center"
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'testApi', node: node })"
|
||||
>
|
||||
<eo-iconpark-icon class="mr5" name="lightning" size="15px"></eo-iconpark-icon>
|
||||
</button>
|
||||
<button class="flex items-center" nz-dropdown [nzDropdownMenu]="apiDataMenu">
|
||||
<button class="flex items-center" nz-dropdown [nzDropdownMenu]="apiDataMenu" *ngIf="isEdit">
|
||||
<eo-iconpark-icon class="mr5" name="more" size="16px"></eo-iconpark-icon>
|
||||
</button>
|
||||
<nz-dropdown-menu #apiDataMenu="nzDropdownMenu">
|
||||
@ -76,12 +102,16 @@
|
||||
<li nz-menu-item (click)="operateApiEvent({ event: $event, eventName: 'editApi', node: node })">
|
||||
<a i18n>Edit</a>
|
||||
</li>
|
||||
<li nz-menu-item
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'copyApi', node: apiDataItems[node.key] })">
|
||||
<li
|
||||
nz-menu-item
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'copyApi', node: apiDataItems[node.key] })"
|
||||
>
|
||||
<a i18n="@@Copy">Copy</a>
|
||||
</li>
|
||||
<li nz-menu-item
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'deleteApi', node: apiDataItems[node.key] })">
|
||||
<li
|
||||
nz-menu-item
|
||||
(click)="operateApiEvent({ event: $event, eventName: 'deleteApi', node: apiDataItems[node.key] })"
|
||||
>
|
||||
<a i18n="@@Delete">Delete</a>
|
||||
</li>
|
||||
</ul>
|
||||
@ -91,8 +121,6 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<nz-empty *ngIf="!treeNodes.length" nzNotFoundImage="simple">
|
||||
</nz-empty>
|
||||
<nz-empty *ngIf="!treeNodes.length" nzNotFoundImage="simple"> </nz-empty>
|
||||
</nz-skeleton>
|
||||
|
||||
</div>
|
||||
|
@ -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;
|
||||
|
@ -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<void> = new Subject<void>();
|
||||
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;
|
||||
|
@ -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<any[]>((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);
|
||||
|
@ -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) => {
|
||||
|
@ -22,14 +22,25 @@
|
||||
<nz-input-group nzCompact>
|
||||
<nz-form-item nz-col>
|
||||
<nz-form-control class="w_250" i18n-nzErrorTip nzErrorTip="Please select an API group">
|
||||
<nz-tree-select nzAllowClear="false" [nzExpandedKeys]="expandKeys" [nzDropdownMatchSelectWidth]="false"
|
||||
[nzNodes]="groups" [(ngModel)]="model.groupID" [nzShowSearch]="true" #apiGroup formControlName="groupID">
|
||||
<nz-tree-select
|
||||
nzAllowClear="false"
|
||||
[nzExpandedKeys]="expandKeys"
|
||||
[nzDropdownMatchSelectWidth]="false"
|
||||
[nzNodes]="groups"
|
||||
[(ngModel)]="model.groupID"
|
||||
[nzShowSearch]="true"
|
||||
#apiGroup
|
||||
formControlName="groupID"
|
||||
>
|
||||
</nz-tree-select>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item nz-col class="fg1">
|
||||
<nz-form-control i18n-nzErrorTip nzErrorTip="Please enter API name"
|
||||
[nzValidateStatus]="this.validateForm.controls.name">
|
||||
<nz-form-control
|
||||
i18n-nzErrorTip
|
||||
nzErrorTip="Please enter API name"
|
||||
[nzValidateStatus]="this.validateForm.controls.name"
|
||||
>
|
||||
<input type="text" [(ngModel)]="model.name" name="name" id="name" nz-input formControlName="name" />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
@ -45,24 +56,36 @@
|
||||
<span i18n>Request Headers</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.requestHeaders)">{{
|
||||
model.requestHeaders | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-edit-header class="eo_theme_iblock bbd bld brd" (modelChange)="emitChangeFun()"
|
||||
[model]="model.requestHeaders"></eo-api-edit-header>
|
||||
<eo-api-edit-header
|
||||
class="eo_theme_iblock bbd bld brd"
|
||||
(modelChange)="emitChangeFun()"
|
||||
[model]="model.requestHeaders"
|
||||
></eo-api-edit-header>
|
||||
</nz-tab>
|
||||
<!-- Request Body -->
|
||||
<nz-tab [nzTitle]="bodyTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #bodyTitleTmp>
|
||||
<span i18n>Body</span>
|
||||
<span class="eo-tab-theme-icon" *ngIf="
|
||||
<nz-badge
|
||||
class="ml-1"
|
||||
*ngIf="
|
||||
['formData', 'json', 'xml'].includes(model.requestBodyType)
|
||||
? bindGetApiParamNum(model.requestBody)
|
||||
: model.requestBody?.length
|
||||
"></span>
|
||||
"
|
||||
nzStatus="success"
|
||||
></nz-badge>
|
||||
</ng-template>
|
||||
<eo-api-edit-body class="eo_theme_iblock bbd bld brd" [(bodyType)]="model.requestBodyType"
|
||||
[(model)]="model.requestBody" (modelChange)="emitChangeFun()"
|
||||
[supportType]="['formData', 'json', 'xml', 'raw', 'binary']" [(jsonRootType)]="model.requestBodyJsonType">
|
||||
<eo-api-edit-body
|
||||
class="eo_theme_iblock bbd bld brd"
|
||||
[(bodyType)]="model.requestBodyType"
|
||||
[(model)]="model.requestBody"
|
||||
(modelChange)="emitChangeFun()"
|
||||
[supportType]="['formData', 'json', 'xml', 'raw', 'binary']"
|
||||
[(jsonRootType)]="model.requestBodyJsonType"
|
||||
>
|
||||
</eo-api-edit-body>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="queryTitleTmp" [nzForceRender]="true">
|
||||
@ -70,20 +93,26 @@
|
||||
<span i18n>Query</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.queryParams)">{{
|
||||
model.queryParams | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-edit-query (modelChange)="emitChangeFun()" class="eo_theme_iblock bbd bld brd"
|
||||
[model]="model.queryParams"></eo-api-edit-query>
|
||||
<eo-api-edit-query
|
||||
(modelChange)="emitChangeFun()"
|
||||
class="eo_theme_iblock bbd bld brd"
|
||||
[model]="model.queryParams"
|
||||
></eo-api-edit-query>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="restTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #restTitleTmp>
|
||||
<span i18n>REST</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.restParams)">{{
|
||||
model.restParams | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-edit-rest class="eo_theme_iblock bbd bld brd" [model]="model.restParams"
|
||||
(modelChange)="emitChangeFun()"></eo-api-edit-rest>
|
||||
<eo-api-edit-rest
|
||||
class="eo_theme_iblock bbd bld brd"
|
||||
[model]="model.restParams"
|
||||
(modelChange)="emitChangeFun()"
|
||||
></eo-api-edit-rest>
|
||||
</nz-tab>
|
||||
</nz-tabset>
|
||||
</nz-collapse-panel>
|
||||
@ -97,24 +126,36 @@
|
||||
<span i18n>Response Headers</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.responseHeaders)">{{
|
||||
model.responseHeaders | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-edit-header class="eo_theme_iblock bbd bld brd" [model]="model.responseHeaders"
|
||||
(modelChange)="emitChangeFun()">
|
||||
<eo-api-edit-header
|
||||
class="eo_theme_iblock bbd bld brd"
|
||||
[model]="model.responseHeaders"
|
||||
(modelChange)="emitChangeFun()"
|
||||
>
|
||||
</eo-api-edit-header>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="responseTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #responseTitleTmp>
|
||||
<span i18n>Response</span>
|
||||
<span class="eo-tab-theme-icon" *ngIf="
|
||||
['formData', 'json', 'xml'].includes(model.responseBodyType)
|
||||
? bindGetApiParamNum(model.responseBody)
|
||||
: model.responseBody?.length
|
||||
"></span>
|
||||
<nz-badge
|
||||
class="ml-1"
|
||||
*ngIf="
|
||||
['formData', 'json', 'xml'].includes(model.responseBodyType)
|
||||
? bindGetApiParamNum(model.responseBody)
|
||||
: model.responseBody?.length
|
||||
"
|
||||
nzStatus="success"
|
||||
></nz-badge>
|
||||
</ng-template>
|
||||
<eo-api-edit-body class="eo_theme_iblock bbd bld brd" [(bodyType)]="model.responseBodyType"
|
||||
[(model)]="model.responseBody" (modelChange)="emitChangeFun()"
|
||||
[supportType]="['json', 'xml', 'raw', 'binary']" [(jsonRootType)]="model.responseBodyJsonType">
|
||||
<eo-api-edit-body
|
||||
class="eo_theme_iblock bbd bld brd"
|
||||
[(bodyType)]="model.responseBodyType"
|
||||
[(model)]="model.responseBody"
|
||||
(modelChange)="emitChangeFun()"
|
||||
[supportType]="['json', 'xml', 'raw', 'binary']"
|
||||
[(jsonRootType)]="model.responseBodyJsonType"
|
||||
>
|
||||
</eo-api-edit-body>
|
||||
</nz-tab>
|
||||
</nz-tabset>
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -6,11 +6,16 @@
|
||||
<div class="mt-[20px]">
|
||||
<eo-table [(model)]="mocklList" [columns]="mockListColumns" [hideEmptyLine]="true">
|
||||
<ng-template cell="name" let-scope="scope" let-index="index">
|
||||
<div class=" w-[120px]">{{ scope.name }}</div>
|
||||
<div class="w-[120px]">{{ scope.name }}</div>
|
||||
</ng-template>
|
||||
<ng-template cell="url" let-scope="scope" let-index="index">
|
||||
<span i18n-nzTooltipTitle nzTooltipTitle="Click to Copy" nzTooltipPlacement="top" nz-tooltip
|
||||
(click)="copyText(scope.url)">
|
||||
<span
|
||||
i18n-nzTooltipTitle
|
||||
nzTooltipTitle="Click to Copy"
|
||||
nzTooltipPlacement="top"
|
||||
nz-tooltip
|
||||
(click)="copyText(scope.url)"
|
||||
>
|
||||
<span nz-typography nzEllipsis [nzContent]="scope.url"> </span>
|
||||
</span>
|
||||
</ng-template>
|
||||
@ -19,14 +24,28 @@
|
||||
</ng-template>
|
||||
<ng-template cell="action" let-scope="scope" let-index="index">
|
||||
<div class="flex">
|
||||
<a nz-button nzType="link" *ngIf="scope.name || scope.url" [ngSwitch]="scope.createWay"
|
||||
(click)="addOrEditModal(index)">
|
||||
<a
|
||||
nz-button
|
||||
nzType="link"
|
||||
*ngIf="scope.name || scope.url"
|
||||
[ngSwitch]="scope.createWay"
|
||||
(click)="addOrEditModal(index)"
|
||||
>
|
||||
<span *ngSwitchCase="'system'" i18n>Preview</span>
|
||||
<span *ngSwitchDefault i18n>Edit</span>
|
||||
</a>
|
||||
<a nz-button nzType="link" *ngIf="(scope.name || scope.url) && scope.createWay !== 'system'" nz-popconfirm
|
||||
i18n-nzPopconfirmTitle nzPopconfirmTitle="Are you sure you want to delete this Mock?"
|
||||
nzPopconfirmPlacement="topRight" (nzOnConfirm)="handleDeleteMockItem(index)" i18n="@@Delete">Delete</a>
|
||||
<a
|
||||
nz-button
|
||||
nzType="link"
|
||||
*ngIf="(scope.name || scope.url) && scope.createWay !== 'system'"
|
||||
nz-popconfirm
|
||||
i18n-nzPopconfirmTitle
|
||||
nzPopconfirmTitle="Are you sure you want to delete this Mock?"
|
||||
nzPopconfirmPlacement="topRight"
|
||||
(nzOnConfirm)="handleDeleteMockItem(index)"
|
||||
i18n="@@Delete"
|
||||
>Delete</a
|
||||
>
|
||||
</div>
|
||||
</ng-template>
|
||||
</eo-table>
|
||||
@ -46,8 +65,14 @@
|
||||
<nz-form-item>
|
||||
<nz-form-label i18n nzFor="currentEditMock.response">Response</nz-form-label>
|
||||
<nz-form-control>
|
||||
<eo-monaco-editor [(code)]="responseStr" (codeChange)="rawDataChange()" [maxLine]="15" class="h-[200px]"
|
||||
[config]="{ readOnly: isSystemMock }" [eventList]="['type', 'format', 'copy', 'search', 'replace']">
|
||||
<eo-monaco-editor
|
||||
[(code)]="responseStr"
|
||||
(codeChange)="rawDataChange()"
|
||||
[maxLine]="15"
|
||||
class="h-[200px]"
|
||||
[config]="{ readOnly: isSystemMock }"
|
||||
[eventList]="['type', 'format', 'copy', 'search', 'replace']"
|
||||
>
|
||||
</eo-monaco-editor>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
@ -346,7 +346,7 @@ export class ApiTestUtilService {
|
||||
});
|
||||
return result;
|
||||
}
|
||||
private filterCommonHeader(headers) {
|
||||
private filterCommonHeader(headers=[]) {
|
||||
const commonHeader = [
|
||||
'content-type',
|
||||
'accept',
|
||||
|
@ -9,15 +9,33 @@
|
||||
<nz-select class="!w-[106px] flex-none" [(ngModel)]="model.request.method" formControlName="method">
|
||||
<nz-option *ngFor="let item of REQUEST_METHOD" [nzLabel]="item.key" [nzValue]="item.value"></nz-option>
|
||||
</nz-select>
|
||||
<div *ngIf="env.hostUri" nz-typography nzEllipsis class="env_front_uri" nzTooltipTitle="{{ env.hostUri }}"
|
||||
nzTooltipPlacement="bottom" nz-tooltip>
|
||||
<div
|
||||
*ngIf="env.hostUri"
|
||||
nz-typography
|
||||
nzEllipsis
|
||||
class="env_front_uri"
|
||||
nzTooltipTitle="{{ env.hostUri }}"
|
||||
nzTooltipPlacement="bottom"
|
||||
nz-tooltip
|
||||
>
|
||||
{{ env.hostUri }}
|
||||
</div>
|
||||
<nz-form-item nz-col class="fg1">
|
||||
<nz-form-control [nzValidateStatus]="this.validateForm.controls.uri" i18n-nzErrorTip
|
||||
nzErrorTip="Please enter URL">
|
||||
<input type="text" i18n-placeholder placeholder="Enter URL" name="uri" nz-input formControlName="uri"
|
||||
[(ngModel)]="model.request.uri" (change)="changeUri()" />
|
||||
<nz-form-control
|
||||
[nzValidateStatus]="this.validateForm.controls.uri"
|
||||
i18n-nzErrorTip
|
||||
nzErrorTip="Please enter URL"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
i18n-placeholder
|
||||
placeholder="Enter URL"
|
||||
name="uri"
|
||||
nz-input
|
||||
formControlName="uri"
|
||||
[(ngModel)]="model.request.uri"
|
||||
(change)="changeUri()"
|
||||
/>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<button type="submit" id="btn-test" nz-button nzType="primary" class="ml10 w_100" (click)="clickTest()">
|
||||
@ -25,41 +43,66 @@
|
||||
<span *ngIf="status === 'testing'" i18n>Abort</span>
|
||||
<span *ngIf="status === 'testing' && waitSeconds" class="ml-1">{{ waitSeconds }}</span>
|
||||
</button>
|
||||
<button type="button"
|
||||
*ngIf="!route.snapshot.queryParams.uuid || route.snapshot.queryParams.uuid.includes('history_')" nz-button
|
||||
nzType="default" (click)="saveApi()" class="ml10" i18n>
|
||||
<button
|
||||
type="button"
|
||||
*ngIf="
|
||||
!statusS.isShare &&
|
||||
(!route.snapshot.queryParams.uuid || route.snapshot.queryParams.uuid.includes('history_'))
|
||||
"
|
||||
nz-button
|
||||
nzType="default"
|
||||
(click)="saveApi()"
|
||||
class="ml10"
|
||||
i18n
|
||||
>
|
||||
Save as API
|
||||
</button>
|
||||
</nz-input-group>
|
||||
</form>
|
||||
<!-- Request Info -->
|
||||
<nz-tabset [nzTabBarStyle]="{ 'padding-left': '10px' }" [nzAnimated]="false"
|
||||
[(nzSelectedIndex)]="model.requestTabIndex">
|
||||
<nz-tabset
|
||||
[nzTabBarStyle]="{ 'padding-left': '10px' }"
|
||||
[nzAnimated]="false"
|
||||
[(nzSelectedIndex)]="model.requestTabIndex"
|
||||
>
|
||||
<!-- Request Headers -->
|
||||
<nz-tab [nzTitle]="headerTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #headerTitleTmp>
|
||||
<span i18n="@@RequestHeaders">Headers</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.request.requestHeaders)">{{
|
||||
model.request.requestHeaders | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-test-header class="eo_theme_iblock bbd" [(model)]="model.request.requestHeaders"
|
||||
(modelChange)="emitChangeFun('requestHeaders')"></eo-api-test-header>
|
||||
<eo-api-test-header
|
||||
class="eo_theme_iblock bbd"
|
||||
[(model)]="model.request.requestHeaders"
|
||||
(modelChange)="emitChangeFun('requestHeaders')"
|
||||
></eo-api-test-header>
|
||||
</nz-tab>
|
||||
<!--Request Info -->
|
||||
<nz-tab [nzTitle]="bodyTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #bodyTitleTmp>
|
||||
<span i18n>Body</span>
|
||||
<span class="eo-tab-theme-icon" *ngIf="
|
||||
<nz-badge
|
||||
class="ml-1"
|
||||
*ngIf="
|
||||
['formData', 'json', 'xml'].includes(model.request.requestBodyType)
|
||||
? bindGetApiParamNum(model.request.requestBody)
|
||||
: model.request.requestBody?.length
|
||||
"></span>
|
||||
"
|
||||
nzStatus="success"
|
||||
></nz-badge>
|
||||
</ng-template>
|
||||
<eo-api-test-body class="eo_theme_iblock bbd" [(contentType)]="model.contentType"
|
||||
(contentTypeChange)="changeContentType($event)" [(bodyType)]="model.request.requestBodyType"
|
||||
(bodyTypeChange)="changeBodyType($event)" [(model)]="model.request.requestBody"
|
||||
(modelChange)="emitChangeFun('requestBody')" [supportType]="['formData', 'raw', 'binary']">
|
||||
<eo-api-test-body
|
||||
class="eo_theme_iblock bbd"
|
||||
[(contentType)]="model.contentType"
|
||||
(contentTypeChange)="changeContentType($event)"
|
||||
[(bodyType)]="model.request.requestBodyType"
|
||||
(bodyTypeChange)="changeBodyType($event)"
|
||||
[(model)]="model.request.requestBody"
|
||||
(modelChange)="emitChangeFun('requestBody')"
|
||||
[supportType]="['formData', 'raw', 'binary']"
|
||||
>
|
||||
</eo-api-test-body>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="queryTitleTmp" [nzForceRender]="true">
|
||||
@ -67,46 +110,67 @@
|
||||
<span i18n>Query</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.request.queryParams)">{{
|
||||
model.request.queryParams | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-test-query class="eo_theme_iblock bbd" [model]="model.request.queryParams"
|
||||
(modelChange)="emitChangeFun('queryParams')"></eo-api-test-query>
|
||||
<eo-api-test-query
|
||||
class="eo_theme_iblock bbd"
|
||||
[model]="model.request.queryParams"
|
||||
(modelChange)="emitChangeFun('queryParams')"
|
||||
></eo-api-test-query>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="restTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #restTitleTmp>
|
||||
<span i18n>REST</span>
|
||||
<span class="eo-tab-icon ml-[4px]" *ngIf="bindGetApiParamNum(model.request.restParams)">{{
|
||||
model.request.restParams | apiParamsNum
|
||||
}}</span>
|
||||
}}</span>
|
||||
</ng-template>
|
||||
<eo-api-test-rest class="eo_theme_iblock bbd" [(model)]="model.request.restParams"
|
||||
(modelChange)="emitChangeFun('restParams')"></eo-api-test-rest>
|
||||
<eo-api-test-rest
|
||||
class="eo_theme_iblock bbd"
|
||||
[(model)]="model.request.restParams"
|
||||
(modelChange)="emitChangeFun('restParams')"
|
||||
></eo-api-test-rest>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="preScriptTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #preScriptTitleTmp>
|
||||
<span i18n>Pre-request Script</span>
|
||||
<span class="eo-tab-theme-icon" *ngIf="model.beforeScript?.trim()"></span>
|
||||
<nz-badge class="ml-1" *ngIf="model.beforeScript?.trim()" nzStatus="success"></nz-badge>
|
||||
</ng-template>
|
||||
<eo-api-script *ngIf="model.requestTabIndex === 4" [(code)]="model.beforeScript"
|
||||
(codeChange)="emitChangeFun('beforeScript')" [treeData]="BEFORE_DATA"
|
||||
[completions]="beforeScriptCompletions" class="eo_theme_iblock bbd"></eo-api-script>
|
||||
<eo-api-script
|
||||
*ngIf="model.requestTabIndex === 4"
|
||||
[(code)]="model.beforeScript"
|
||||
(codeChange)="emitChangeFun('beforeScript')"
|
||||
[treeData]="BEFORE_DATA"
|
||||
[completions]="beforeScriptCompletions"
|
||||
class="eo_theme_iblock bbd"
|
||||
></eo-api-script>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="suffixScriptTitleTmp" [nzForceRender]="true">
|
||||
<ng-template #suffixScriptTitleTmp>
|
||||
<span i18n>After-response Script</span>
|
||||
<span class="eo-tab-theme-icon" *ngIf="model.afterScript?.trim()"></span>
|
||||
<nz-badge class="ml-1" *ngIf="model.afterScript?.trim()" nzStatus="success"></nz-badge>
|
||||
</ng-template>
|
||||
<eo-api-script *ngIf="model.requestTabIndex === 5" [(code)]="model.afterScript"
|
||||
(codeChange)="emitChangeFun('afterScript')" [treeData]="AFTER_DATA" [completions]="afterScriptCompletions"
|
||||
class="eo_theme_iblock bbd"></eo-api-script>
|
||||
<eo-api-script
|
||||
*ngIf="model.requestTabIndex === 5"
|
||||
[(code)]="model.afterScript"
|
||||
(codeChange)="emitChangeFun('afterScript')"
|
||||
[treeData]="AFTER_DATA"
|
||||
[completions]="afterScriptCompletions"
|
||||
class="eo_theme_iblock bbd"
|
||||
></eo-api-script>
|
||||
</nz-tab>
|
||||
</nz-tabset>
|
||||
</div>
|
||||
<div class="bottom_container scroll_container" bottom>
|
||||
<!-- Response -->
|
||||
<nz-tabset [nzTabBarStyle]="{ 'padding-left': '10px' }" [(nzSelectedIndex)]="model.responseTabIndex"
|
||||
[nzTabBarExtraContent]="extraTemplate" [nzAnimated]="false" class="mt-2.5 response_container"
|
||||
(nzSelectChange)="handleBottomTabSelect($event)">
|
||||
<nz-tabset
|
||||
[nzTabBarStyle]="{ 'padding-left': '10px' }"
|
||||
[(nzSelectedIndex)]="model.responseTabIndex"
|
||||
[nzTabBarExtraContent]="extraTemplate"
|
||||
[nzAnimated]="false"
|
||||
class="response_container"
|
||||
(nzSelectChange)="handleBottomTabSelect($event)"
|
||||
>
|
||||
<nz-tab i18n-nzTitle nzTitle="Response">
|
||||
<eo-api-test-result-response [model]="model.testResult.response" [uri]="model.request.uri">
|
||||
</eo-api-test-result-response>
|
||||
@ -118,8 +182,10 @@
|
||||
</div>
|
||||
<nz-tab i18n-nzTitle nzTitle="Body" [nzForceRender]="true">
|
||||
<!-- TODO use isRequestBodyLoaded -->
|
||||
<eo-api-test-result-request-body *ngIf="model.responseTabIndex === 2"
|
||||
[model]="model.testResult.request.requestBody || ''">
|
||||
<eo-api-test-result-request-body
|
||||
*ngIf="model.responseTabIndex === 2"
|
||||
[model]="model.testResult.request.requestBody || ''"
|
||||
>
|
||||
</eo-api-test-result-request-body>
|
||||
</nz-tab>
|
||||
<nz-tab i18n-nzTitle nzTitle="Request Headers">
|
||||
@ -129,8 +195,15 @@
|
||||
<ng-template #extraTemplate>
|
||||
<div *ngIf="model.responseTabIndex === 0" class="py-[6px] px-[12px] flex items-center">
|
||||
<!-- <span nz-icon nzType="download" nzTheme="outline">下载</span> -->
|
||||
<eo-iconpark-icon name="download" *ngIf="!isEmpty(model.testResult?.response)" class="cursor-pointer"
|
||||
i18n-nzTooltipTitle nz-tooltip nzTooltipTitle="Save As File" (click)="downloadFile()">
|
||||
<eo-iconpark-icon
|
||||
name="download"
|
||||
*ngIf="!isEmpty(model.testResult?.response)"
|
||||
class="cursor-pointer"
|
||||
i18n-nzTooltipTitle
|
||||
nz-tooltip
|
||||
nzTooltipTitle="Save As File"
|
||||
(click)="downloadFile()"
|
||||
>
|
||||
</eo-iconpark-icon>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
],
|
||||
|
@ -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) {
|
||||
|
@ -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<TabItem>[];
|
||||
//* 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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -14,24 +14,23 @@
|
||||
[ngClass]="{ 'fixed-tab-item-container': tabStorage.tabsByID.get(uuid)?.isFixed }"
|
||||
>
|
||||
<!-- loading -->
|
||||
<nz-spin nzSimple class="mr10" [nzSize]="'small'" *ngIf="tabStorage.tabsByID.get(uuid).isLoading"></nz-spin>
|
||||
<nz-spin nzSimple class="mr10" [nzSize]="'small'" *ngIf="tabStorage.tabsByID.get(uuid)?.isLoading"></nz-spin>
|
||||
<eo-iconpark-icon
|
||||
class="mr5"
|
||||
name="{{ tabStorage.tabsByID.get(uuid).icon }}"
|
||||
name="{{ tabStorage.tabsByID.get(uuid)?.icon }}"
|
||||
size="14px"
|
||||
*ngIf="tabStorage.tabsByID.get(uuid).icon"
|
||||
*ngIf="tabStorage.tabsByID.get(uuid)?.icon"
|
||||
></eo-iconpark-icon>
|
||||
<span
|
||||
class="mr5 method-text method_text_{{ tabStorage.tabsByID.get(uuid).extends.method }}"
|
||||
*ngIf="tabStorage.tabsByID.get(uuid).extends?.method"
|
||||
>{{ tabStorage.tabsByID.get(uuid).extends.method }}</span
|
||||
>
|
||||
<span class="text_omit tab_text" [title]="tabStorage.tabsByID.get(uuid).title">
|
||||
{{ tabStorage.tabsByID.get(uuid).title }}</span
|
||||
<!-- {{ tabStorage.tabsByID.get(uuid) | json }} -->
|
||||
<span class="mr5 method-text method_text_{{ tabStorage.tabsByID.get(uuid)?.extends?.method || 'WS' }}">{{
|
||||
tabStorage.tabsByID.get(uuid)?.extends?.method || 'WS'
|
||||
}}</span>
|
||||
<span class="text_omit tab_text" [title]="tabStorage.tabsByID.get(uuid)?.title">
|
||||
{{ tabStorage.tabsByID.get(uuid)?.title }}</span
|
||||
>
|
||||
<!-- Close/HasEdit -->
|
||||
<div class="flex items-center tab-item-button-group">
|
||||
<span class="tab-has-edit-icon eo-tab-theme-icon" *ngIf="tabStorage.tabsByID.get(uuid).hasChanged"></span>
|
||||
<nz-badge class="tab-has-edit-icon" *ngIf="tabStorage.tabsByID.get(uuid)?.hasChanged" nzStatus="success"></nz-badge>
|
||||
<button
|
||||
aria-label="Close tab"
|
||||
(click)="closeTab({ $event: $event, index: i, tab: tabStorage.tabsByID.get(uuid) })"
|
||||
@ -56,7 +55,7 @@
|
||||
<nz-dropdown-menu #addMenu="nzDropdownMenu">
|
||||
<ul nz-menu>
|
||||
<li nz-menu-item (click)="newTab()">HTTP</li>
|
||||
<li nz-menu-item (click)="newTab('/home/api/ws/test')">Websocket</li>
|
||||
<li nz-menu-item (click)="newTab('ws')">Websocket</li>
|
||||
</ul>
|
||||
</nz-dropdown-menu>
|
||||
<a nz-dropdown [nzDropdownMenu]="menu">
|
||||
|
@ -76,8 +76,14 @@
|
||||
width: 100%;
|
||||
font-style: italic;
|
||||
.tab-has-edit-icon {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
.ant-badge-status-dot{
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
.ant-badge-status-text{
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
.tab-item-button-group {
|
||||
position: absolute;
|
||||
|
@ -7,6 +7,7 @@ import { TabItem, TabOperate } from 'eo/workbench/browser/src/app/pages/api/tab/
|
||||
import { ModalService } from '../../../shared/services/modal.service';
|
||||
import { KeyValue } from '@angular/common';
|
||||
import { NzTabsCanDeactivateFn } from 'ng-zorro-antd/tabs';
|
||||
import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service';
|
||||
@Component({
|
||||
selector: 'eo-api-tab',
|
||||
templateUrl: './api-tab.component.html',
|
||||
@ -23,7 +24,8 @@ export class ApiTabComponent implements OnInit, OnDestroy {
|
||||
public tabStorage: ApiTabStorageService,
|
||||
public tabOperate: ApiTabOperateService,
|
||||
private modal: ModalService,
|
||||
private router: Router
|
||||
private router: Router,
|
||||
public status: StatusService
|
||||
) {}
|
||||
ngOnInit(): void {
|
||||
this.tabOperate.init(this.list);
|
||||
@ -92,12 +94,12 @@ export class ApiTabComponent implements OnInit, OnDestroy {
|
||||
modal.destroy();
|
||||
this.tabOperate.closeTab(index);
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
//Quick see tabs change in templete,for debug,can be deleted
|
||||
//! just for debug
|
||||
// ! just for debug
|
||||
getConsoleTabs() {
|
||||
const tabs = [];
|
||||
this.tabStorage.tabOrder.forEach((uuid) => {
|
||||
|
@ -15,6 +15,7 @@ import { isEmptyObj } from 'eo/workbench/browser/src/app/utils/index.utils';
|
||||
import { ApiParamsNumPipe } from '../../../shared/pipes/api-param-num.pipe';
|
||||
|
||||
import { ApiTestHeaders, ApiTestQuery } from 'eo/workbench/browser/src/app/shared/services/api-test/api-test.model';
|
||||
import { StatusService } from 'eo/workbench/browser/src/app/shared/services/status.service';
|
||||
interface testViewModel {
|
||||
requestTabIndex: number;
|
||||
protocol: string;
|
||||
@ -60,7 +61,8 @@ export class WebsocketComponent implements OnInit, OnDestroy {
|
||||
private electron: ElectronService,
|
||||
private testService: ApiTestService,
|
||||
private modal: ModalService,
|
||||
private message: MessageService
|
||||
private message: MessageService,
|
||||
private status: StatusService
|
||||
) {
|
||||
this.initBasicForm();
|
||||
}
|
||||
@ -88,7 +90,7 @@ export class WebsocketComponent implements OnInit, OnDestroy {
|
||||
? APP_CONFIG.REMOTE_SOCKET_URL
|
||||
: `ws://localhost:${port || 13928}`
|
||||
}`,
|
||||
{ transports: ['websocket'] }
|
||||
{ path: '/socket.io', transports: ['websocket'] }
|
||||
);
|
||||
this.socket.on('connect_error', (error) => {
|
||||
// * conncet socketIO is failed
|
||||
@ -170,6 +172,9 @@ export class WebsocketComponent implements OnInit, OnDestroy {
|
||||
isExpand: false,
|
||||
});
|
||||
const { requestTabIndex, msg, ...data } = this.model;
|
||||
if (this.status.isShare) {
|
||||
return;
|
||||
}
|
||||
const res = await this.testService.addHistory({ protocol: 'websocket', ...data }, 0);
|
||||
if (res) {
|
||||
this.message.send({ type: 'updateHistory', data: {} });
|
||||
|
@ -0,0 +1,75 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { EventCenterForMicroApp } from '@micro-zoe/micro-app';
|
||||
import { StorageService } from 'eo/workbench/browser/src/app/shared/services/storage/storage.service';
|
||||
import microApp from '@micro-zoe/micro-app';
|
||||
|
||||
(window as any).eventCenterForAppNameVite = new EventCenterForMicroApp('appname-custom-tab');
|
||||
|
||||
@Component({
|
||||
selector: 'eo-custom-tab',
|
||||
template: `
|
||||
<div style="transform: translate(0)">
|
||||
<micro-app
|
||||
*ngIf="url"
|
||||
[attr.name]="name"
|
||||
[attr.url]="url"
|
||||
default-page="/"
|
||||
shadowDOM
|
||||
[data]="microAppData"
|
||||
(created)="handleCreate()"
|
||||
(beforemount)="handleBeforeMount()"
|
||||
(mounted)="handleMount()"
|
||||
(unmount)="handleUnmount()"
|
||||
(error)="handleError()"
|
||||
(datachange)="handleDataChange($event)"
|
||||
></micro-app>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class CustomTabComponent implements OnInit {
|
||||
@Input() name = ``;
|
||||
@Input() url = ``;
|
||||
microAppData = { msg: '来自基座的数据' };
|
||||
|
||||
constructor(private storage: StorageService) {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
/**
|
||||
* vite 子应用因为沙箱关闭,数据通信功能失效
|
||||
*/
|
||||
handleCreate(): void {
|
||||
console.log('child-vite 创建了');
|
||||
}
|
||||
|
||||
handleBeforeMount(): void {
|
||||
console.log('child-vite 即将被渲染');
|
||||
}
|
||||
|
||||
handleMount(): void {
|
||||
console.log('child-vite 已经渲染完成');
|
||||
this.storage.run('groupLoadAllByProjectID', [1], (result) => {
|
||||
if (result.status === 200) {
|
||||
this.microAppData = result.data;
|
||||
// 发送数据给子应用 my-app,setData第二个参数只接受对象类型
|
||||
microApp.setData(this.name, { data: this.microAppData });
|
||||
console.log('this.microAppData', this.microAppData);
|
||||
}
|
||||
});
|
||||
// setTimeout(() => {
|
||||
// this.microAppData = { msg: '来自基座的新数据' };
|
||||
// }, 2000);
|
||||
}
|
||||
|
||||
handleUnmount(): void {
|
||||
console.log('child-vite 卸载了');
|
||||
}
|
||||
|
||||
handleError(): void {
|
||||
console.log('child-vite 加载出错了');
|
||||
}
|
||||
|
||||
handleDataChange(e): void {
|
||||
console.log('来自子应用 child-vite 的数据:', e.detail.data);
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@ import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
|
||||
<form nz-form [nzLayout]="'vertical'" [formGroup]="validateForm" class="form">
|
||||
<nz-form-item nz-col class="fg1" *ngFor="let field of objectKeys(properties)">
|
||||
<ng-container *ngIf="properties[field]?.label">
|
||||
<ng-container *ngIf="properties[field]?.title || properties[field]?.label">
|
||||
<nz-form-label nzFor="{{ field }}" [nzRequired]="properties[field]?.required" class="label">
|
||||
{{ properties[field]?.label }}
|
||||
{{ properties[field]?.title || properties[field]?.label }}
|
||||
</nz-form-label>
|
||||
</ng-container>
|
||||
<!-- 二级说明 -->
|
||||
@ -28,7 +28,11 @@ import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
>
|
||||
{{ properties[field]?.description }}
|
||||
</div>
|
||||
<nz-form-control i18n-nzErrorTip nzErrorTip="Please Enter {{ properties[field]?.label }}" class="form-control">
|
||||
<nz-form-control
|
||||
i18n-nzErrorTip
|
||||
nzErrorTip="Please Enter {{ properties[field]?.title || properties[field]?.label }}"
|
||||
class="form-control"
|
||||
>
|
||||
<!-- 字符串类型 -->
|
||||
<!-- <ng-container *ngIf="properties[field]?.type === 'string'"> -->
|
||||
<input
|
||||
@ -37,7 +41,9 @@ import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
id="{{ field }}"
|
||||
[disabled]="properties[field]?.disabled"
|
||||
i18n-placeholder
|
||||
placeholder="{{ properties[field]?.placeholder ?? 'Please Enter ' + properties[field]?.label }}"
|
||||
placeholder="{{
|
||||
(properties[field]?.placeholder ?? 'Please Enter ' + properties[field]?.title) || properties[field]?.label
|
||||
}}"
|
||||
formControlName="{{ field }}"
|
||||
[(ngModel)]="localSettings[field]"
|
||||
/>
|
||||
@ -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<string, any>;
|
||||
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
|
||||
*
|
||||
|
@ -9,10 +9,14 @@
|
||||
<div class="mr-2">
|
||||
<nz-avatar nzSize="small" class="!w-[20px] !h-[20px]" nzSrc="{{ extensionDetail.logo }}"></nz-avatar>
|
||||
</div>
|
||||
<span class="font-bold text-[14px]">{{ extensionDetail.moduleName }}</span>
|
||||
<span class="font-bold text-[14px]">{{ extensionDetail.title || extensionDetail.moduleName }}</span>
|
||||
<ng-container *ngIf="extensionDetail?.installed">
|
||||
<nz-switch [(ngModel)]="isEnable" nzSize="small" class="ml-2.5"
|
||||
(ngModelChange)="handleEnableExtension($event)">
|
||||
<nz-switch
|
||||
[(ngModel)]="isEnable"
|
||||
nzSize="small"
|
||||
class="ml-2.5"
|
||||
(ngModelChange)="handleEnableExtension($event)"
|
||||
>
|
||||
</nz-switch>
|
||||
</ng-container>
|
||||
</div>
|
||||
@ -21,21 +25,33 @@
|
||||
<section class="h-full px-4 max-w-[80vw] mx-auto flex flex-col">
|
||||
<p class="w-full text-[#888] text-[12px]">{{ extensionDetail.description }}</p>
|
||||
<div>
|
||||
<button nz-button [nzSize]="extensionDetail?.installed ? 'small' : 'default'"
|
||||
[nzType]="extensionDetail?.installed ? 'default' : 'primary'" class="mt-[8px]" [nzLoading]="isOperating"
|
||||
(click)="handleInstall()">
|
||||
<button
|
||||
nz-button
|
||||
[nzSize]="extensionDetail?.installed ? 'small' : 'default'"
|
||||
[nzType]="extensionDetail?.installed ? 'default' : 'primary'"
|
||||
class="mt-[8px]"
|
||||
[nzLoading]="isOperating"
|
||||
(click)="handleInstall()"
|
||||
>
|
||||
<span *ngIf="extensionDetail?.installed" i18n>Uninstall</span>
|
||||
<span *ngIf="!extensionDetail?.installed" i18n>Install</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nz-tabset [(nzSelectedIndex)]="nzSelectedIndex" [nzAnimated]="false"
|
||||
<nz-tabset
|
||||
[(nzSelectedIndex)]="nzSelectedIndex"
|
||||
[nzAnimated]="false"
|
||||
[class]="{ settings: nzSelectedIndex === 0 && extensionDetail?.features?.configuration }"
|
||||
(nzSelectChange)="handleTabChange($event)">
|
||||
(nzSelectChange)="handleTabChange($event)"
|
||||
>
|
||||
<!-- <nz-tab *ngIf="pagePath" i18n-nzTitle nzTitle="CustomTab">
|
||||
<eo-custom-tab [url]="pagePath" [name]="extName"></eo-custom-tab>
|
||||
</nz-tab> -->
|
||||
<!-- Setting -->
|
||||
<nz-tab *ngIf="extensionDetail?.features?.configuration && extensionDetail?.installed" i18n-nzTitle
|
||||
nzTitle="Settings">
|
||||
<eo-extension-setting [configuration]="extensionDetail?.features?.configuration"></eo-extension-setting>
|
||||
<eo-extension-setting [configuration]="extensionDetail?.features?.configuration"
|
||||
[extName]="extensionDetail.name"></eo-extension-setting>
|
||||
</nz-tab>
|
||||
<!-- Details -->
|
||||
<nz-tab i18n-nzTitle="@@ExtensionDetail" nzTitle="Details">
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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) {
|
||||
|
@ -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',
|
||||
|
@ -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<string> = [];
|
||||
HOST = '';
|
||||
localExtensions: Map<string, ModuleInfo>;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -2,20 +2,16 @@
|
||||
<div class="grid grid-cols-2 gap-6 py-5 list-block">
|
||||
<div
|
||||
class="bd_all w-full min-h-[140px] p-5 flex flex-col flex-wrap plugin-block hover:border-green-700 hover:shadow-lg transition-shadow duration-300"
|
||||
*ngFor="let it of renderList"
|
||||
(click)="clickExtension($event, it)"
|
||||
>
|
||||
*ngFor="let it of renderList" (click)="clickExtension($event, it)">
|
||||
<nz-skeleton [nzLoading]="loading" [nzActive]="true" [nzAvatar]="true">
|
||||
<div class="flex justify-between w-full">
|
||||
<div class="flex">
|
||||
<div
|
||||
class="shrink-0 block w-[40px] h-[40px] rounded-lg bg-[length:90%] bg-center bg-no-repeat mr-[20px]"
|
||||
[ngClass]="{ 'bg-gray-100': it.logo }"
|
||||
[ngStyle]="{ 'background-image': 'url(' + (it.logo || '') + ')' }"
|
||||
></div>
|
||||
<div class="shrink-0 block w-[40px] h-[40px] rounded-lg bg-[length:90%] bg-center bg-no-repeat mr-[20px]"
|
||||
[ngClass]="{ 'bg-gray-100': it.logo }" [ngStyle]="{ 'background-image': 'url(' + (it.logo || '') + ')' }">
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col flex-auto">
|
||||
<span class="text-lg font-bold">{{ it.moduleName }}</span>
|
||||
<span class="text-lg font-bold">{{ it.title || it.moduleName }}</span>
|
||||
<span class="my-2 text-gray-400">{{ it.author }}</span>
|
||||
<span class="my-1 desc">{{ it.description }}</span>
|
||||
</div>
|
||||
@ -29,19 +25,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="type === 'installed'">
|
||||
<nz-switch
|
||||
click-stop-propagation
|
||||
[(ngModel)]="it.isEnable"
|
||||
(ngModelChange)="handleEnableExtension($event, it)"
|
||||
></nz-switch>
|
||||
<nz-switch click-stop-propagation [(ngModel)]="it.isEnable"
|
||||
(ngModelChange)="handleEnableExtension($event, it)"></nz-switch>
|
||||
</div>
|
||||
<div *ngIf="type !== 'installed'">
|
||||
<span
|
||||
*ngIf="electron.isElectron ? extensionService.localExtensions.has(it.moduleID) : it.installed"
|
||||
<span *ngIf="extensionService.localExtensions.has(it.moduleID)"
|
||||
class="p-1 text-xs text-green-700 border-green-700 rounded-sm bd_all whitespace-nowrap"
|
||||
i18n
|
||||
>Installed</span
|
||||
>
|
||||
i18n>Installed</span>
|
||||
</div>
|
||||
</div>
|
||||
</nz-skeleton>
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<input
|
||||
nz-input
|
||||
[(ngModel)]="inputPersonValue"
|
||||
i18n-placeholder
|
||||
placeholder="Search by username"
|
||||
/>
|
||||
<input nz-input [(ngModel)]="inputPersonValue" i18n-placeholder placeholder="Search by username" />
|
||||
<section class="h-4"></section>
|
||||
<button
|
||||
nz-button
|
||||
@ -33,8 +28,8 @@ import { Component, OnInit } from '@angular/core'
|
||||
class=""
|
||||
nzType="primary"
|
||||
nzBlock
|
||||
(click)="btn7ykkd6Callback()"
|
||||
[disabled]="btnrgj8s9Status()"
|
||||
(click)="btn0r9zcbCallback()"
|
||||
[disabled]="btnguixdgStatus()"
|
||||
i18n
|
||||
>
|
||||
Select a member above
|
||||
@ -49,27 +44,24 @@ import { Component, OnInit } from '@angular/core'
|
||||
[nzLoading]="isAddPeopleBtnLoading"
|
||||
class=""
|
||||
nzType="primary"
|
||||
(click)="btnuvurciCallback()"
|
||||
[disabled]="btnsqcmi2Status()"
|
||||
(click)="btnf5umnoCallback()"
|
||||
[disabled]="btny703n5Status()"
|
||||
i18n
|
||||
>
|
||||
Add people
|
||||
</button>
|
||||
</h2>
|
||||
<section class="py-5">
|
||||
<eo-manage-access
|
||||
[data]="memberList"
|
||||
(eoOnRemove)="ew833r8Callback($event)"
|
||||
></eo-manage-access>
|
||||
<eo-manage-access [data]="memberList" (eoOnRemove)="e97uoiuCallback($event)"></eo-manage-access>
|
||||
</section>
|
||||
</section>`
|
||||
</section>`,
|
||||
})
|
||||
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<void> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -6,7 +6,13 @@
|
||||
<img class="mx-4" src="https://img.shields.io/github/stars/eolinker/eoapi?style=social" alt="" />
|
||||
</a>
|
||||
<!-- Select workspace -->
|
||||
<div class="flex items-center can_be_click" nz-dropdown nzTrigger="click" [nzDropdownMenu]="workspaceMenu">
|
||||
<div
|
||||
*ngIf="!status.isShare"
|
||||
class="flex items-center can_be_click"
|
||||
nz-dropdown
|
||||
nzTrigger="click"
|
||||
[nzDropdownMenu]="workspaceMenu"
|
||||
>
|
||||
<eo-iconpark-icon
|
||||
class="mr-[5px]"
|
||||
name="link-cloud-{{ workspaceService.currentWorkspace?.id !== -1 ? 'sucess' : 'faild' }}"
|
||||
@ -54,9 +60,42 @@
|
||||
</ul>
|
||||
</nz-dropdown-menu>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center can_be_click">
|
||||
<button
|
||||
*ngIf="!workspaceService.isLocal && !status.isShare"
|
||||
nz-button
|
||||
nzType="default"
|
||||
class="mx-2 btn_scondary"
|
||||
nz-popover
|
||||
[nzPopoverContent]="contentTemplate"
|
||||
nzPopoverPlacement="bottomRight"
|
||||
nzPopoverTrigger="click"
|
||||
i18n
|
||||
>
|
||||
Share
|
||||
</button>
|
||||
<ng-template #contentTemplate>
|
||||
<div class="w-[360px] pb-4">
|
||||
<p i18n class="font-bold">Share via link</p>
|
||||
<p i18n class="pb-2 text-xs text-gray-400">
|
||||
This link will be updated with the API content. Everyone can access it without logging in
|
||||
</p>
|
||||
<nz-input-group nzSearch [nzAddOnAfter]="suffixIconButton">
|
||||
<input readonly type="text" nz-input [value]="shareLink" />
|
||||
</nz-input-group>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #suffixIconButton>
|
||||
<button nz-button nzType="primary" *ngIf="!isCopy" (click)="handleCopy()">Copy</button>
|
||||
<button nz-button nzType="default" *ngIf="isCopy" class="text-[#158565]">Copied</button>
|
||||
</ng-template>
|
||||
<nz-select *ngIf="status.isShare" [(ngModel)]="langValue" nzBorderless (ngModelChange)="handleSwitchLang($event)">
|
||||
<nz-option nzValue="en-US" nzLabel="English"></nz-option>
|
||||
<nz-option nzValue="zh-Hans" nzLabel="中文"></nz-option>
|
||||
</nz-select>
|
||||
<!-- setting -->
|
||||
<span
|
||||
*ngIf="!status.isShare"
|
||||
class="flex items-center justify-center mx-1 icon"
|
||||
i18n-nzTooltipTitle
|
||||
nz-tooltip
|
||||
@ -73,7 +112,6 @@
|
||||
<nz-dropdown-menu #helpMenu="nzDropdownMenu">
|
||||
<ul nz-menu>
|
||||
<a href="https://docs.eoapi.io" target="_blank" nz-menu-item i18n>Document</a>
|
||||
<a href="https://developer.eoapi.io" target="_blank" nz-menu-item i18n>Developer Support</a>
|
||||
<li nz-menu-divider></li>
|
||||
<a
|
||||
href="https://github.com/eolinker/eoapi/issues/new?assignees=&labels=&template=bug_report.yml&environment={{
|
||||
@ -87,7 +125,13 @@
|
||||
</ul>
|
||||
</nz-dropdown-menu>
|
||||
<!-- User -->
|
||||
<span class="flex items-center justify-center mx-1 icon" nz-dropdown [nzDropdownMenu]="UserMenu">
|
||||
|
||||
<span
|
||||
*ngIf="!status.isShare"
|
||||
class="flex items-center justify-center mx-1 icon"
|
||||
nz-dropdown
|
||||
[nzDropdownMenu]="UserMenu"
|
||||
>
|
||||
<eo-iconpark-icon name="me"> </eo-iconpark-icon>
|
||||
</span>
|
||||
<nz-dropdown-menu #UserMenu="nzDropdownMenu">
|
||||
@ -140,7 +184,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<!-- Web download client -->
|
||||
<div *ngIf="!electron.isElectron">
|
||||
<div *ngIf="!electron.isElectron && !status.isShare">
|
||||
<div class="btn py-1.5 px-2 mx-1 flex items-center" nz-dropdown i18n [nzDropdownMenu]="download">
|
||||
<span class="flex items-center delete-icon">
|
||||
<eo-iconpark-icon name="down-two" size="14px"></eo-iconpark-icon>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<string, ModuleInfo>;
|
||||
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<void> {
|
||||
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<ModuleInfo> {
|
||||
return Array.from(this.modules.values());
|
||||
}
|
||||
handleSwitchLang(event) {
|
||||
this.lang.changeLanguage(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开系统设置
|
||||
|
@ -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],
|
||||
})
|
||||
|
@ -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,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
@ -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],
|
||||
|
@ -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),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -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: `<div>share</div>`,
|
||||
template: `<section class="flex flex-col"><eo-api></eo-api></section>`,
|
||||
})
|
||||
export class ShareComponent implements OnInit {
|
||||
constructor() {}
|
||||
async ngOnInit(): Promise<void> {}
|
||||
constructor(private route: ActivatedRoute, private share: ShareService, private status: StatusService) {}
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.route.queryParams.subscribe(({ shareId }) => {
|
||||
this.share.setShareId(shareId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<span i18n>
|
||||
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.
|
||||
</span>
|
||||
<nz-alert
|
||||
nzType="warning"
|
||||
@ -44,7 +40,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w
|
||||
[nzLoading]="isSyncCancelBtnLoading"
|
||||
class=""
|
||||
nzType="default"
|
||||
(click)="btn4wxiipCallback()"
|
||||
(click)="btnsgs0ckCallback()"
|
||||
i18n
|
||||
>
|
||||
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
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<span i18n> Can't connect right now, click to retry or </span>
|
||||
<span
|
||||
style="color: #1890ff"
|
||||
class="cursor-pointer"
|
||||
(click)="texte83xg2Callback()"
|
||||
i18n
|
||||
>
|
||||
<span style="color: #1890ff" class="cursor-pointer" (click)="textiqd22iCallback()" i18n>
|
||||
config in the configuration
|
||||
</span>
|
||||
</ng-container>
|
||||
@ -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
|
||||
/>
|
||||
<ng-template #passwordErrorTpl let-control>
|
||||
<ng-container *ngIf="control.hasError('required')" i18n>
|
||||
Please input your password;
|
||||
</ng-container>
|
||||
<ng-container *ngIf="control.hasError('required')" i18n> Please input your password; </ng-container>
|
||||
|
||||
<ng-container *ngIf="control.hasError('minlength')" i18n>
|
||||
Min length is 6;
|
||||
</ng-container>
|
||||
<ng-container *ngIf="control.hasError('minlength')" i18n> Min length is 6; </ng-container>
|
||||
</ng-template>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
@ -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
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<span i18n> If you want to collaborate, please </span>
|
||||
<span
|
||||
style="color: #1890ff"
|
||||
class="cursor-pointer"
|
||||
(click)="textnrbqvsCallback()"
|
||||
i18n
|
||||
>
|
||||
<span style="color: #1890ff" class="cursor-pointer" (click)="textqdb64pCallback()" i18n>
|
||||
open the settings
|
||||
</span>
|
||||
<span i18n> and fill in the configuration </span>
|
||||
@ -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
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<form
|
||||
nz-form
|
||||
[formGroup]="validateWorkspaceNameForm"
|
||||
nzLayout="horizontal"
|
||||
>
|
||||
<form nz-form [formGroup]="validateWorkspaceNameForm" nzLayout="horizontal">
|
||||
<nz-form-item>
|
||||
<nz-form-control nzErrorTip="Please input your new work name;">
|
||||
<input
|
||||
@ -222,7 +200,7 @@ import { WorkspaceService } from 'eo/workbench/browser/src/app/shared/services/w
|
||||
type="button"
|
||||
class="mr-3"
|
||||
nzType="default"
|
||||
(click)="btnfjbf3iCallback()"
|
||||
(click)="btn66ztjiCallback()"
|
||||
i18n
|
||||
>
|
||||
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
|
||||
</section>
|
||||
</form>
|
||||
</ng-container>
|
||||
</nz-modal>`
|
||||
</nz-modal>`,
|
||||
})
|
||||
export class UserModalComponent implements OnInit {
|
||||
isSyncModalVisible
|
||||
isSyncCancelBtnLoading
|
||||
isSyncSyncBtnLoading
|
||||
isCheckConnectModalVisible
|
||||
isCheckConnectCancelBtnLoading
|
||||
isCheckConnectRetryBtnLoading
|
||||
isLoginModalVisible
|
||||
validateLoginForm
|
||||
@ViewChild('usernameLoginRef') usernameLoginRef: ElementRef<HTMLInputElement>
|
||||
isLoginBtnBtnLoading
|
||||
isOpenSettingModalVisible
|
||||
isAddWorkspaceModalVisible
|
||||
validateWorkspaceNameForm
|
||||
isSyncModalVisible;
|
||||
isSyncCancelBtnLoading;
|
||||
isSyncSyncBtnLoading;
|
||||
isCheckConnectModalVisible;
|
||||
isCheckConnectCancelBtnLoading;
|
||||
isCheckConnectRetryBtnLoading;
|
||||
isLoginModalVisible;
|
||||
validateLoginForm;
|
||||
@ViewChild('usernameLoginRef') usernameLoginRef: ElementRef<HTMLInputElement>;
|
||||
isLoginBtnBtnLoading;
|
||||
isOpenSettingModalVisible;
|
||||
isAddWorkspaceModalVisible;
|
||||
validateWorkspaceNameForm;
|
||||
@ViewChild('newWorkNameWorkspaceNameRef')
|
||||
newWorkNameWorkspaceNameRef: ElementRef<HTMLInputElement>
|
||||
isCancelBtnLoading
|
||||
isSaveBtnLoading
|
||||
newWorkNameWorkspaceNameRef: ElementRef<HTMLInputElement>;
|
||||
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<void> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
<div style="transform: translate(0)">
|
||||
<micro-app [attr.name]="name" [attr.url]='url' shadowDOM [data]='microAppData' (created)='handleCreate()'
|
||||
default-page='/' (beforemount)='handleBeforeMount()' (mounted)='handleMount()' (unmount)='handleUnmount()'
|
||||
(error)='handleError()' (datachange)='handleDataChange($event)'></micro-app>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Vue3Component } from './vue3.component';
|
||||
|
||||
describe('Vue3Component', () => {
|
||||
let component: Vue3Component;
|
||||
let fixture: ComponentFixture<Vue3Component>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ Vue3Component ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(Vue3Component);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
45
src/workbench/browser/src/app/pages/vue3/vue3.component.ts
Normal file
45
src/workbench/browser/src/app/pages/vue3/vue3.component.ts
Normal file
@ -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);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user