From 9ec849b5ade86479936ce9b5f967035860f52181 Mon Sep 17 00:00:00 2001 From: Hans Chan Date: Thu, 20 May 2021 10:31:25 +0800 Subject: [PATCH 1/3] feat: add configuration button for npm registry --- packages/core/src/api/index.ts | 34 +++++++-- .../core/src/components/console/index.tsx | 2 +- .../editModal.tsx | 32 +++++--- .../header/configuration/index.module.less | 10 +++ .../src/mods/header/configuration/index.tsx | 35 +++++++++ .../header/connectStatus/index.module.less | 16 ---- .../src/mods/header/connectStatus/index.tsx | 74 +++---------------- packages/core/src/mods/header/index.tsx | 55 +++++++++++++- 8 files changed, 160 insertions(+), 98 deletions(-) rename packages/core/src/mods/header/{connectStatus => configuration}/editModal.tsx (68%) create mode 100644 packages/core/src/mods/header/configuration/index.module.less create mode 100644 packages/core/src/mods/header/configuration/index.tsx diff --git a/packages/core/src/api/index.ts b/packages/core/src/api/index.ts index be9dd98..df7abca 100644 --- a/packages/core/src/api/index.ts +++ b/packages/core/src/api/index.ts @@ -1,9 +1,11 @@ import axios from 'axios'; import { message } from 'antd'; +const LOCAL_CONFIG_KEY = 'IMOVE:LOCAL_CONFIG_KEY'; export interface ILocalConfig { ip: string; port: string; + npmRegistry: string; } export enum ActionType { @@ -52,17 +54,38 @@ const request = (function () { }; })(); -export const localConfig: ILocalConfig = { - ip: '127.0.0.1', - port: '3500', +/** + * get local config data (saved in localStorage) + * @returns local config + */ +export const getLocalConfig = (): ILocalConfig => { + const savedConfigString = localStorage.getItem(LOCAL_CONFIG_KEY) || ''; + let savedConfig = {} as ILocalConfig; + try { + savedConfig = JSON.parse(savedConfigString); + } catch (e) {} + return { + ip: savedConfig.ip || '127.0.0.1', + port: savedConfig.port || '3500', + npmRegistry: savedConfig.npmRegistry || 'https://registry.npm.taobao.org', + }; }; +// export const localConfig: ILocalConfig = getLocalConfig(); + +/** + * get local config data (saved in localStorage) + */ export const updateLocalConfig = (config: ILocalConfig) => { - localConfig.ip = config.ip || localConfig.ip; - localConfig.port = config.port || localConfig.port; + const savedConfig = getLocalConfig(); + savedConfig.ip = config.ip || savedConfig.ip; + savedConfig.port = config.port || savedConfig.port; + savedConfig.npmRegistry = config.npmRegistry || savedConfig.npmRegistry; + localStorage.setItem(LOCAL_CONFIG_KEY, JSON.stringify(savedConfig)); }; export const localConnect = () => { + const localConfig = getLocalConfig(); return fetch(`http://${localConfig.ip}:${localConfig.port}/api/connect`, { method: 'GET', headers: { 'content-type': 'application/json' }, @@ -70,6 +93,7 @@ export const localConnect = () => { }; export const localSave = (data: any) => { + const localConfig = getLocalConfig(); fetch(`http://${localConfig.ip}:${localConfig.port}/api/save`, { method: 'POST', headers: { 'content-type': 'application/json' }, diff --git a/packages/core/src/components/console/index.tsx b/packages/core/src/components/console/index.tsx index 7213583..4e65a94 100644 --- a/packages/core/src/components/console/index.tsx +++ b/packages/core/src/components/console/index.tsx @@ -93,7 +93,7 @@ const LogLine: React.FC = (props) => { const renderLink = (data: string) => { return ( - + {data} ); diff --git a/packages/core/src/mods/header/connectStatus/editModal.tsx b/packages/core/src/mods/header/configuration/editModal.tsx similarity index 68% rename from packages/core/src/mods/header/connectStatus/editModal.tsx rename to packages/core/src/mods/header/configuration/editModal.tsx index 8c9914e..2c9f8b0 100644 --- a/packages/core/src/mods/header/connectStatus/editModal.tsx +++ b/packages/core/src/mods/header/configuration/editModal.tsx @@ -1,5 +1,4 @@ import React, { useRef } from 'react'; - import 'antd/es/form/style'; import 'antd/es/modal/style'; import 'antd/es/input/style'; @@ -7,10 +6,12 @@ import styles from './index.module.less'; import { Input, Form, Modal } from 'antd'; import { FormInstance } from 'antd/lib/form'; -import { ILocalConfig, localConfig, updateLocalConfig } from '../../../api'; +import { ILocalConfig, getLocalConfig, updateLocalConfig } from '../../../api'; const PORT_REGEX = /^\d{1,5}$/; const IP_REGEX = /^(localhost)|(((2(5[0-5]|[0-4]\d))|[01]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[01]?\d{1,2})){3})$/; +const NPM_REGISTRY_REGEX = /^https?:\/\//; // 简单 URL 检查 + const makeRules = (regex: RegExp, errTip: string) => { return [ { required: true, message: '不能为空!' }, @@ -27,13 +28,13 @@ interface IEditorModalProps { onCancel: () => void; } -const EditModal: React.FC = (props) => { +const EditModal: React.FC = (props: IEditorModalProps) => { const { visible, onOk, onCancel } = props; const formRef = useRef(null); // events const onClickOk = (): void => { - formRef.current && + if (formRef.current) { formRef.current .validateFields() .then((formValues) => { @@ -43,6 +44,7 @@ const EditModal: React.FC = (props) => { .catch((error) => { console.log(error.message); }); + } }; return ( @@ -51,22 +53,34 @@ const EditModal: React.FC = (props) => { visible={visible} okText={'保存'} cancelText={'取消'} - title={'本地连接配置'} + title={'配置'} onOk={onClickOk} onCancel={onCancel} > -
+ + + + diff --git a/packages/core/src/mods/header/configuration/index.module.less b/packages/core/src/mods/header/configuration/index.module.less new file mode 100644 index 0000000..a248f10 --- /dev/null +++ b/packages/core/src/mods/header/configuration/index.module.less @@ -0,0 +1,10 @@ +.editModal { + + width: 450px; + + :global { + .ant-form-item:last-child { + margin-bottom: 0; + } + } +} diff --git a/packages/core/src/mods/header/configuration/index.tsx b/packages/core/src/mods/header/configuration/index.tsx new file mode 100644 index 0000000..96ed2b0 --- /dev/null +++ b/packages/core/src/mods/header/configuration/index.tsx @@ -0,0 +1,35 @@ +import React, { useState, useCallback } from 'react'; +import { Button } from 'antd'; +import { SettingOutlined } from '@ant-design/icons'; +import EditModal from './editModal'; + +interface IProps { + confirmToSync: () => Promise; +} + +const Configuration: React.FC = (props: IProps) => { + const [visible, setVisible] = useState(false); + + // events + const onOpenEditModal = useCallback(() => { + setVisible(true); + }, [setVisible]); + const onCloseEditModal = useCallback(() => { + setVisible(false); + }, []); + const onOk = useCallback(() => { + onCloseEditModal(); + props.confirmToSync(); + }, [onCloseEditModal]); + + return ( +
+ + +
+ ); +}; + +export default Configuration; diff --git a/packages/core/src/mods/header/connectStatus/index.module.less b/packages/core/src/mods/header/connectStatus/index.module.less index fa65300..33155d6 100644 --- a/packages/core/src/mods/header/connectStatus/index.module.less +++ b/packages/core/src/mods/header/connectStatus/index.module.less @@ -1,22 +1,6 @@ .container { - display: flex; flex-direction: row; align-items: center; margin-left: 20px; - - .tag { - cursor: pointer; - } } - -.editModal { - - width: 450px; - - :global { - .ant-form-item:last-child { - margin-bottom: 0; - } - } -} \ No newline at end of file diff --git a/packages/core/src/mods/header/connectStatus/index.tsx b/packages/core/src/mods/header/connectStatus/index.tsx index bb26ee2..4a72851 100644 --- a/packages/core/src/mods/header/connectStatus/index.tsx +++ b/packages/core/src/mods/header/connectStatus/index.tsx @@ -1,31 +1,26 @@ import React, { useState, useEffect } from 'react'; import 'antd/es/tag/style'; -import 'antd/es/modal/style'; -import 'antd/es/message/style'; +import { Tag } from 'antd'; import styles from './index.module.less'; -import { Graph } from '@antv/x6'; -import EditModal from './editModal'; -import { Tag, Modal, message } from 'antd'; -import { localConnect } from '../../../api'; - -enum Status { +export enum Status { connected = 'success', disconnected = 'error', } interface IProps { - flowChart: Graph; + // flowChart: Graph; + status: Status; + projectName: string; + syncLocal: () => Promise; + confirmToSync: () => Promise; } const PULSE_RATE = 10 * 1000; // try to connect to local servet per 10 seconds -const ConnectStatus: React.FC = (props) => { - const { flowChart } = props; - const [visible, setVisible] = useState(false); - const [projectName, setProjectName] = useState(''); - const [status, setStatus] = useState(Status.disconnected); +const ConnectStatus: React.FC = (props: IProps) => { + const { status, confirmToSync, syncLocal, projectName } = props; // life useEffect(() => { @@ -34,61 +29,14 @@ const ConnectStatus: React.FC = (props) => { return () => clearInterval(timer); }, []); - // network - const syncLocal = () => { - return localConnect() - .then((res) => res.json()) - .then((data = {}) => { - const { projectName } = data; - setStatus(Status.connected); - setProjectName(projectName); - return data; - }) - .catch((error) => { - setStatus(Status.disconnected); - console.log('connect local failed, the error is:', error.message); - }); - }; - const confirmToSync = () => { - syncLocal().then((data) => { - const { dsl } = data || {}; - dsl && - Modal.confirm({ - title: '本地连接成功,是否将数据同步至当前项目?', - onOk() { - try { - flowChart.fromJSON(dsl); - } catch (error) { - message.error('同步失败!'); - } - }, - }); - }); - }; - - // events - const onOpenEditModal = (): void => { - setVisible(true); - }; - const onCloseEditModal = (): void => { - setVisible(false); - }; - const onOk = (): void => { - onCloseEditModal(); - confirmToSync(); - }; - - let tagText = '本地连接失败 点击修改配置'; + let tagText = '本地连接失败'; if (status === Status.connected) { tagText = [projectName, '本地连接成功'].join(' '); } return (
- - {tagText} - - + {tagText}
); }; diff --git a/packages/core/src/mods/header/index.tsx b/packages/core/src/mods/header/index.tsx index 1d538f9..796331f 100644 --- a/packages/core/src/mods/header/index.tsx +++ b/packages/core/src/mods/header/index.tsx @@ -1,19 +1,60 @@ -import React from 'react'; +import React, { useState, useCallback } from 'react'; import styles from './index.module.less'; import { Graph } from '@antv/x6'; +import { Modal, message } from 'antd'; import Guide from './guide'; import Export from './export'; import ImportDSL from './importDSL'; -import ConnectStatus from './connectStatus'; +import ConnectStatus, { Status } from './connectStatus'; +import Configuration from './configuration'; +import { localConnect } from '../../api'; interface IProps { flowChart: Graph; } -const Header: React.FC = (props) => { +const Header: React.FC = (props: IProps) => { const { flowChart } = props; + const [projectName, setProjectName] = useState(''); + const [status, setStatus] = useState(Status.disconnected); + + // network + const syncLocal = useCallback(() => { + return localConnect() + .then((res) => res.json()) + .then((data = {}) => { + console.log(data); + setStatus(Status.connected); + setProjectName(data.projectName); + return data; + }) + .catch((error) => { + console.log(error); + setStatus(Status.disconnected); + console.log('connect local failed, the error is:', error.message); + }); + }, [setStatus, setProjectName]); + + const confirmToSync = useCallback(() => { + return syncLocal().then((data) => { + const { dsl } = data || {}; + if (dsl) { + Modal.confirm({ + title: '本地连接成功,是否将数据同步至当前项目?', + onOk() { + try { + flowChart.fromJSON(dsl); + } catch (error) { + message.error('同步失败!'); + } + }, + }); + } + }); + }, [syncLocal, flowChart]); + return ( ); From d40760839342a1d1044aac2697b8e85432ea8314 Mon Sep 17 00:00:00 2001 From: Hans Chan Date: Thu, 20 May 2021 10:45:49 +0800 Subject: [PATCH 2/3] feat: analyze dependences from custom config npm registry --- packages/core/src/api/index.ts | 6 +++--- packages/core/src/utils/analyzeDeps.ts | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/src/api/index.ts b/packages/core/src/api/index.ts index df7abca..6258ac9 100644 --- a/packages/core/src/api/index.ts +++ b/packages/core/src/api/index.ts @@ -71,8 +71,6 @@ export const getLocalConfig = (): ILocalConfig => { }; }; -// export const localConfig: ILocalConfig = getLocalConfig(); - /** * get local config data (saved in localStorage) */ @@ -80,7 +78,9 @@ export const updateLocalConfig = (config: ILocalConfig) => { const savedConfig = getLocalConfig(); savedConfig.ip = config.ip || savedConfig.ip; savedConfig.port = config.port || savedConfig.port; - savedConfig.npmRegistry = config.npmRegistry || savedConfig.npmRegistry; + savedConfig.npmRegistry = ( + config.npmRegistry || savedConfig.npmRegistry + ).replace(/\/$/, ''); localStorage.setItem(LOCAL_CONFIG_KEY, JSON.stringify(savedConfig)); }; diff --git a/packages/core/src/utils/analyzeDeps.ts b/packages/core/src/utils/analyzeDeps.ts index 019dd86..5309688 100644 --- a/packages/core/src/utils/analyzeDeps.ts +++ b/packages/core/src/utils/analyzeDeps.ts @@ -1,5 +1,6 @@ import axios from 'axios'; import { safeGet } from './index'; +import { getLocalConfig } from '../api'; const regex = /import\s([\s\S]*?)\sfrom\s(?:('[@\.\/\-\w]+')|("[@\.\/\-\w]+"))/gm; @@ -22,9 +23,10 @@ const extractPkgs = (code: string, excludePkgs?: string[]): string[] => { }; const getPkgLatestVersion = (pkg: string): Promise => { + const localConfig = getLocalConfig(); return axios - .get(`https://registry.npm.taobao.org/${pkg}`) - .then((res) => { + .get(`${localConfig.npmRegistry}/${pkg}`) + .then((res: any) => { return [pkg, safeGet(res, 'data.dist-tags.latest', '*')]; }) .catch((err) => { From ee384f1bd6e3d90915d7d3f6be55013871d22a46 Mon Sep 17 00:00:00 2001 From: "hanchai.chc" Date: Tue, 25 May 2021 20:49:25 +0800 Subject: [PATCH 3/3] chore: remove console.log --- packages/core/src/mods/header/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/mods/header/index.tsx b/packages/core/src/mods/header/index.tsx index 796331f..20dba7b 100644 --- a/packages/core/src/mods/header/index.tsx +++ b/packages/core/src/mods/header/index.tsx @@ -25,7 +25,6 @@ const Header: React.FC = (props: IProps) => { return localConnect() .then((res) => res.json()) .then((data = {}) => { - console.log(data); setStatus(Status.connected); setProjectName(data.projectName); return data;