diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f1d8296a1aa..6ec7cc29ee82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2782,6 +2782,9 @@ importers: rc-virtual-list: specifier: ^3.4.13 version: 3.4.13(react-dom@18.1.0)(react@18.1.0) + react-json-view: + specifier: ^1.21.3 + version: 1.21.3(@types/react@18.0.26)(react-dom@18.1.0)(react@18.1.0) typescript: specifier: ^4 version: 4.9.4 @@ -17403,6 +17406,10 @@ packages: /balanced-match@2.0.0: resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + /base16@1.0.0: + resolution: {integrity: sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==} + dev: true + /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -19060,6 +19067,14 @@ packages: cross-spawn: 7.0.3 dev: true + /cross-fetch@3.1.5: + resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} + dependencies: + node-fetch: 2.6.7 + transitivePeerDependencies: + - encoding + dev: true + /cross-port-killer@1.4.0: resolution: {integrity: sha512-ujqfftKsSeorFMVI6JP25xMBixHEaDWVK+NarRZAGnJjR5AhebRQU+g+k/Lj8OHwM6f+wrrs8u5kkCdI7RLtxQ==} dev: true @@ -22565,6 +22580,32 @@ packages: dependencies: bser: 2.1.1 + /fbemitter@3.0.0: + resolution: {integrity: sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==} + dependencies: + fbjs: 3.0.4 + transitivePeerDependencies: + - encoding + dev: true + + /fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + dev: true + + /fbjs@3.0.4: + resolution: {integrity: sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==} + dependencies: + cross-fetch: 3.1.5 + fbjs-css-vars: 1.0.2 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 0.7.31 + transitivePeerDependencies: + - encoding + dev: true + /fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} dependencies: @@ -22812,6 +22853,21 @@ packages: /flatten@1.0.3: resolution: {integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==} + /flux@4.0.4(react@18.1.0): + resolution: {integrity: sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==} + peerDependencies: + react: ^15.0.2 || ^16.0.0 || ^17.0.0 + peerDependenciesMeta: + react: + optional: true + dependencies: + fbemitter: 3.0.0 + fbjs: 3.0.4 + react: 18.1.0 + transitivePeerDependencies: + - encoding + dev: true + /fmin@0.0.2: resolution: {integrity: sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==} dependencies: @@ -26639,6 +26695,10 @@ packages: resolution: {integrity: sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==} dev: false + /lodash.curry@4.1.1: + resolution: {integrity: sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==} + dev: true + /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -26646,6 +26706,10 @@ packages: resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} dev: true + /lodash.flow@3.5.0: + resolution: {integrity: sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==} + dev: true + /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: true @@ -31055,6 +31119,12 @@ packages: asap: 1.0.0 dev: true + /promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + dependencies: + asap: 2.0.6 + dev: true + /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -31181,6 +31251,10 @@ packages: - utf-8-validate dev: true + /pure-color@1.3.0: + resolution: {integrity: sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==} + dev: true + /purgecss-webpack-plugin@4.1.3(webpack@5.76.1): resolution: {integrity: sha512-1OHS0WE935w66FjaFSlV06ycmn3/A8a6Q+iVUmmCYAujQ1HPdX+psMXUhASEW0uF1PYEpOlhMc5ApigVqYK08g==} peerDependencies: @@ -34346,6 +34420,15 @@ packages: strip-json-comments: 2.0.1 dev: true + /react-base16-styling@0.6.0: + resolution: {integrity: sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==} + dependencies: + base16: 1.0.0 + lodash.curry: 4.1.1 + lodash.flow: 3.5.0 + pure-color: 1.3.0 + dev: true + /react-color@2.17.1(react@18.1.0): resolution: {integrity: sha512-S+I6TkUKJaqfALLkAIfiCZ/MANQyy7dKkf7g9ZU5GTUy2rf8c2Rx62otyvADAviWR+6HRkzdf2vL1Qvz9goCLQ==} peerDependencies: @@ -34653,6 +34736,28 @@ packages: /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + /react-json-view@1.21.3(@types/react@18.0.26)(react-dom@18.1.0)(react@18.1.0): + resolution: {integrity: sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==} + peerDependencies: + react: ^17.0.0 || ^16.3.0 || ^15.5.4 + react-dom: ^17.0.0 || ^16.3.0 || ^15.5.4 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + flux: 4.0.4(react@18.1.0) + react: 18.1.0 + react-base16-styling: 0.6.0 + react-dom: 18.1.0(react@18.1.0) + react-lifecycles-compat: 3.0.4 + react-textarea-autosize: 8.4.1(@types/react@18.0.26)(react@18.1.0) + transitivePeerDependencies: + - '@types/react' + - encoding + dev: true + /react-lifecycles-compat@3.0.4: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} @@ -34972,6 +35077,23 @@ packages: react-motion: 0.5.2(react@18.1.0) dev: true + /react-textarea-autosize@8.4.1(@types/react@18.0.26)(react@18.1.0): + resolution: {integrity: sha512-aD2C+qK6QypknC+lCMzteOdIjoMbNlgSFmJjCV+DrfTPwp59i/it9mMNf2HDzvRjQgKAyBDPyLJhcrzElf2U4Q==} + engines: {node: '>=10'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react: + optional: true + dependencies: + '@babel/runtime': 7.21.0 + react: 18.1.0 + use-composed-ref: 1.3.0(react@18.1.0) + use-latest: 1.2.1(@types/react@18.0.26)(react@18.1.0) + transitivePeerDependencies: + - '@types/react' + dev: true + /react-universal-interface@0.6.2(react@18.1.0)(tslib@2.5.0): resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} peerDependencies: @@ -38427,7 +38549,6 @@ packages: /ua-parser-js@0.7.31: resolution: {integrity: sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==} - dev: false /ufo@0.8.5: resolution: {integrity: sha512-e4+UtA5IRO+ha6hYklwj6r7BjiGMxS0O+UaSg9HbaTefg4kMkzj4tXzEBajRR+wkxf+golgAWKzLbytCUDMJAA==} @@ -39016,6 +39137,17 @@ packages: punycode: 1.3.2 querystring: 0.2.0 + /use-composed-ref@1.3.0(react@18.1.0): + resolution: {integrity: sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react: + optional: true + dependencies: + react: 18.1.0 + dev: true + /use-isomorphic-layout-effect@1.1.2(@types/react@18.0.26)(react@18.1.0): resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: @@ -39051,6 +39183,22 @@ packages: react: 18.1.0 dev: false + /use-latest@1.2.1(@types/react@18.0.26)(react@18.1.0): + resolution: {integrity: sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + dependencies: + '@types/react': 18.0.26 + react: 18.1.0 + use-isomorphic-layout-effect: 1.1.2(@types/react@18.0.26)(react@18.1.0) + dev: true + /use-media-antd-query@1.1.0(react@17.0.2): resolution: {integrity: sha512-B6kKZwNV4R+l4Rl11sWO7HqOay9alzs1Vp1b4YJqjz33YxbltBCZtt/yxXxkXN9rc1S7OeEL/GbwC30Wmqhw6Q==} peerDependencies: diff --git a/ui/.umirc.ts b/ui/.umirc.ts index 8d98fccaac97..5ff0bbf98de7 100644 --- a/ui/.umirc.ts +++ b/ui/.umirc.ts @@ -23,6 +23,7 @@ export default { 'ant-design:bug-outlined', 'ant-design:bulb-outlined', 'ant-design:star-outlined', + 'ant-design:info-circle-outlined', 'local:sun', 'local:moon', ], diff --git a/ui/app.tsx b/ui/app.tsx index 85a083e46c0a..0ea6f2d55db9 100644 --- a/ui/app.tsx +++ b/ui/app.tsx @@ -12,7 +12,9 @@ ${globalCSS} &.dark { --bg-color: #151515; - --bg-hover-color: #1c1c1d; + --bg-hover-color: #333; + --bg-active-color: #117cf3; + --bg-active-text-color: #fff; --highlight-color: #117cf3; --text-color: #9a9a9a; --accent-color: #ffffff; @@ -23,7 +25,9 @@ ${globalCSS} } --bg-color: #fff; - --bg-hover-color: #fefefe; + --bg-hover-color: #f4f4f4; + --bg-active-color: #e6f4ff; + --bg-active-text-color: #117cf3; --highlight-color: #117cf3; --text-color: #333; --accent-color: #000; diff --git a/ui/components/Logo.tsx b/ui/components/Logo.tsx index 5bd6333dc1f1..a7d79f6301c2 100644 --- a/ui/components/Logo.tsx +++ b/ui/components/Logo.tsx @@ -6,7 +6,7 @@ const Wrapper = styled.div` align-items: center; justify-content: space-between; padding: 1.25rem 1rem; - border-bottom: 1px solid var(--subtle-color); + // border-bottom: 1px solid var(--subtle-color); .logo-left { display: flex; diff --git a/ui/components/Menu.tsx b/ui/components/Menu.tsx index f704acef4c6d..810597f16288 100644 --- a/ui/components/Menu.tsx +++ b/ui/components/Menu.tsx @@ -4,11 +4,14 @@ import { Icon, NavLink, styled, useSnapshot } from 'umi'; const Wrapper = styled.div` & > div { + padding: 0.25rem; + a { display: flex; align-items: center; - padding: 0.75rem 1.25rem; - border-bottom: 1px solid var(--subtle-color); + padding: 0.5rem 1.25rem; + border-radius: 5px; + // border-bottom: 1px solid var(--subtle-color); span { margin-right: 0.5rem; @@ -17,8 +20,9 @@ const Wrapper = styled.div` a:hover { background: var(--bg-hover-color); } - .active { - color: var(--highlight-color); + a.active { + background: var(--bg-active-color); + color: var(--bg-active-text-color); } } `; diff --git a/ui/components/imports/ViewButton.tsx b/ui/components/imports/ViewButton.tsx index ef08f2b76740..a5eb02c98eb4 100644 --- a/ui/components/imports/ViewButton.tsx +++ b/ui/components/imports/ViewButton.tsx @@ -2,7 +2,7 @@ import { FC } from 'react'; import { Icon, styled } from 'umi'; interface IProps { - options: { icon: string; value: string }[]; + options: { icon?: string; value: string; str?: string }[]; onChange: (v: string) => void; value: string; } @@ -48,7 +48,11 @@ export const ViewButton: FC = ({ value, options = [], onChange }) => { className={value === opt.value ? 'view active' : 'view'} onClick={() => onChange(opt.value)} > - + {opt.icon ? ( + + ) : ( + opt.str + )} ); })} diff --git a/ui/components/plugin/PluginList.tsx b/ui/components/plugin/PluginList.tsx index 8fb1b4bf8e95..643d07b5b70d 100644 --- a/ui/components/plugin/PluginList.tsx +++ b/ui/components/plugin/PluginList.tsx @@ -1,7 +1,7 @@ import { innerPluginList } from '@/contants'; import type { IAppData } from '@/hooks/useAppData'; import { getRegisterTime } from '@/utils/getPluginRegisterTime'; -import { Input, List, Switch, Tag } from 'antd'; +import { Input, List, Popover, Switch, Tag } from 'antd'; import { FC, useMemo, useState } from 'react'; import { Icon, styled } from 'umi'; @@ -102,10 +102,16 @@ export const PluginList: FC = ({ plugins }) => { }) .map((k) => { const plugin = plugins[k]; - const totalTime = getRegisterTime(plugin); + const { totalTime, detail } = getRegisterTime(plugin); + const detailTxt = Object.keys(detail).map((k) => ( +
+ {k}: {detail[k]}ms +
+ )); return { name: k, totalTime, + detailTxt, ...plugin, }; }) @@ -146,7 +152,27 @@ export const PluginList: FC = ({ plugins }) => { {item.name} {item.key} {item.totalTime ? ( - {item.totalTime}ms + + +
+ {item.totalTime}ms + +
+
+
) : null} {item.path ? ( diff --git a/ui/layouts/index.tsx b/ui/layouts/index.tsx index edea9a2c950a..32f50088f49d 100644 --- a/ui/layouts/index.tsx +++ b/ui/layouts/index.tsx @@ -9,7 +9,7 @@ const Wrapper = styled.div` height: 100%; aside { min-width: 200px; - border-right: 1px solid var(--subtle-color); + // border-right: 1px solid var(--subtle-color); } main { flex: 1; diff --git a/ui/package.json b/ui/package.json index 7679fdf3285f..630542cca9f8 100644 --- a/ui/package.json +++ b/ui/package.json @@ -29,6 +29,7 @@ "@types/react-dom": "^18", "antd": "^5.2.3", "rc-virtual-list": "^3.4.13", + "react-json-view": "^1.21.3", "typescript": "^4" }, "packageManager": "pnpm@7.3.0", diff --git a/ui/pages/config.tsx b/ui/pages/config.tsx index fe4d2fab0145..6156124b149b 100644 --- a/ui/pages/config.tsx +++ b/ui/pages/config.tsx @@ -1,16 +1,61 @@ -import { CodeBlock } from '@/components/CodeBlock'; +import { ViewButton } from '@/components/imports/ViewButton'; import { useAppData } from '@/hooks/useAppData'; -import { styled } from 'umi'; +import { state as globalState } from '@/models/global'; +import { useState } from 'react'; +import ReactJson, { ThemeKeys } from 'react-json-view'; +import { styled, useSnapshot } from 'umi'; + +type ConfigType = 'userConfig' | 'config'; + +const options = [ + { + value: 'userConfig', + str: 'UserConfig', + }, + { + value: 'config', + str: 'FinalConfig', + }, +]; const Wrapper = styled.div``; +const JSONTheme: Record = { + dark: 'threezerotwofour', + light: 'shapeshifter:inverted', +}; + export default function Page() { + const [viewType, setViewType] = useState('userConfig'); const { data } = useAppData(); + const { mode } = useSnapshot(globalState); + if (!data) return
Loading...
; return ( - +
+ setViewType(v as ConfigType)} + /> +
+
+ +
); } diff --git a/ui/pages/index.tsx b/ui/pages/index.tsx index c48cf25d05f4..471055aa3136 100644 --- a/ui/pages/index.tsx +++ b/ui/pages/index.tsx @@ -7,19 +7,22 @@ const cardList = [ name: 'Routes', path: '/routes', icon: 'cluster-outlined', - color: '#91caff', + textColor: '#4096ff', + color: 'rgba(64, 150, 255, .2)', }, { name: 'Plugins', path: '/plugins', icon: 'api-outlined', - color: '#b7eb8f', + textColor: '#73d13d', + color: 'rgba(115, 209, 61, .2)', }, { name: 'Imports', path: '/imports', icon: 'right-square-outlined', - color: '#fffb8f', + textColor: '#f759ab', + color: 'rgba(247, 89, 171, .2)', }, ]; @@ -27,7 +30,10 @@ const cardColorStr = cardList .map((item) => { return ` .card-item-${item.name}:hover { - color: ${item.color} + color: ${item.textColor}; + .card-content { + background: ${item.color}; + } } `; }) diff --git a/ui/utils/getPluginRegisterTime.ts b/ui/utils/getPluginRegisterTime.ts index 6a1db442537a..0b5577e0ac48 100644 --- a/ui/utils/getPluginRegisterTime.ts +++ b/ui/utils/getPluginRegisterTime.ts @@ -4,10 +4,20 @@ export const getRegisterTime = (plugin: IPlugin) => { const { time: { hooks, register }, } = plugin; + const hooksTimeMap: Record = { + register, + }; const hooksTime = Object.keys(hooks).reduce((acc, k) => { const timeList = hooks[k]; - return acc + timeList.reduce((total, t) => total + t); + const t = timeList.reduce((total, t) => total + t); + if (t > 0) { + hooksTimeMap[k] = t; + } + return acc + t; }, 0); - return hooksTime + register; + return { + totalTime: hooksTime + register, + detail: hooksTimeMap, + }; };