diff --git a/.umirc.ts b/.umirc.ts index de1437d9..03d7b666 100644 --- a/.umirc.ts +++ b/.umirc.ts @@ -28,19 +28,11 @@ export default defineConfig({ externals: { react: 'window.React', 'react-dom': 'window.ReactDOM', - codemirror: 'window.CodeMirror', darkreader: 'window.DarkReader', }, scripts: [ 'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js', 'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/lib/codemirror.min.js', - 'https://cdn.jsdelivr.net/npm/darkreader@4.9.27/darkreader.min.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/mode/shell/shell.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/mode/python/python.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/mode/javascript/javascript.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/addon/dialog/dialog.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/addon/search/search.js', - 'https://cdn.jsdelivr.net/npm/codemirror@5.62.0/addon/search/searchcursor.js', + 'https://cdn.jsdelivr.net/npm/darkreader@4.9.34/darkreader.min.js', ], }); diff --git a/package.json b/package.json index bcf18966..d6a04a0e 100644 --- a/package.json +++ b/package.json @@ -32,18 +32,19 @@ "express": "^4.17.1", "express-jwt": "^6.0.0", "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.21", "nedb": "^1.8.0", "node-fetch": "^2.6.1", "node-schedule": "^2.0.0", "p-queue": "6.6.2", "reflect-metadata": "^0.1.13", "typedi": "^0.8.0", - "lodash": "^4.17.21", "winston": "^3.3.3" }, "devDependencies": { "@ant-design/icons": "^4.6.2", "@ant-design/pro-layout": "^6.5.0", + "@monaco-editor/react": "^4.2.1", "@types/cors": "^2.8.10", "@types/express": "^4.17.8", "@types/express-jwt": "^6.0.1", @@ -57,7 +58,6 @@ "@types/react-dom": "^17.0.0", "@umijs/plugin-antd": "^0.9.1", "@umijs/test": "^3.3.9", - "codemirror": "^5.59.4", "compression-webpack-plugin": "6.1.1", "darkreader": "^4.9.27", "lint-staged": "^10.0.7", @@ -65,11 +65,11 @@ "prettier": "^2.2.0", "qrcode.react": "^1.0.1", "react": "17.x", - "react-codemirror2": "^7.2.1", "react-diff-viewer": "^3.1.1", "react-dnd": "^14.0.2", "react-dnd-html5-backend": "^14.0.0", "react-dom": "17.x", + "react-split-pane": "^0.1.92", "ts-node": "^9.0.0", "typescript": "^4.1.2", "umi": "^3.3.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 89bf8207..c3fdd954 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,6 +3,7 @@ lockfileVersion: 5.3 specifiers: '@ant-design/icons': ^4.6.2 '@ant-design/pro-layout': ^6.5.0 + '@monaco-editor/react': ^4.2.1 '@types/cors': ^2.8.10 '@types/express': ^4.17.8 '@types/express-jwt': ^6.0.1 @@ -18,7 +19,6 @@ specifiers: '@umijs/test': ^3.3.9 body-parser: ^1.19.0 celebrate: ^13.0.3 - codemirror: ^5.59.4 compression-webpack-plugin: 6.1.1 cors: ^2.8.5 cron-parser: ^3.5.0 @@ -37,11 +37,11 @@ specifiers: prettier: ^2.2.0 qrcode.react: ^1.0.1 react: 17.x - react-codemirror2: ^7.2.1 react-diff-viewer: ^3.1.1 react-dnd: ^14.0.2 react-dnd-html5-backend: ^14.0.0 react-dom: 17.x + react-split-pane: ^0.1.92 reflect-metadata: ^0.1.13 ts-node: ^9.0.0 typedi: ^0.8.0 @@ -74,6 +74,7 @@ dependencies: devDependencies: '@ant-design/icons': 4.6.2_react-dom@17.0.2+react@17.0.2 '@ant-design/pro-layout': 6.18.0_react-dom@17.0.2+react@17.0.2 + '@monaco-editor/react': 4.2.1_react-dom@17.0.2+react@17.0.2 '@types/cors': 2.8.10 '@types/express': 4.17.11 '@types/express-jwt': 6.0.1 @@ -87,7 +88,6 @@ devDependencies: '@types/react-dom': 17.0.5 '@umijs/plugin-antd': 0.9.1_5ccfec03b6e15849b3687a64fe975f75 '@umijs/test': 3.4.20_ts-node@9.1.1 - codemirror: 5.61.0 compression-webpack-plugin: 6.1.1_webpack@5.37.0 darkreader: 4.9.32 lint-staged: 10.5.4 @@ -95,11 +95,11 @@ devDependencies: prettier: 2.3.0 qrcode.react: 1.0.1_react@17.0.2 react: 17.0.2 - react-codemirror2: 7.2.1_codemirror@5.61.0+react@17.0.2 react-diff-viewer: 3.1.1_react-dom@17.0.2+react@17.0.2 react-dnd: 14.0.2_695545ed68ea337339babea285839fc0 react-dnd-html5-backend: 14.0.0 react-dom: 17.0.2_react@17.0.2 + react-split-pane: 0.1.92_react-dom@17.0.2+react@17.0.2 ts-node: 9.1.1_typescript@4.2.4 typescript: 4.2.4 umi: 3.4.20 @@ -866,6 +866,28 @@ packages: chalk: 4.1.1 dev: true + /@monaco-editor/loader/1.1.1: + resolution: {integrity: sha512-mkT4r4xDjIyOG9o9M6rJDSzEIeonwF80sYErxEvAAL4LncFVdcbNli8Qv6NDqF6nyv6sunuKkDzo4iFjxPL+uQ==} + peerDependencies: + monaco-editor: '>= 0.21.0 < 1' + dependencies: + state-local: 1.0.7 + dev: true + + /@monaco-editor/react/4.2.1_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-yN8qVY0PyFIbqPjfrZ5TbR/wrcfeiwoys8+0QkmyfiOzG74vXxSBOPIUxk7Ly+qCj7qWHPq1uDJskzFGaIqaPA==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + dependencies: + '@monaco-editor/loader': 1.1.1 + prop-types: 15.7.2 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + state-local: 1.0.7 + dev: true + /@npmcli/move-file/1.1.2: resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} engines: {node: '>=10'} @@ -2546,10 +2568,6 @@ packages: engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: true - /codemirror/5.61.0: - resolution: {integrity: sha512-D3wYH90tYY1BsKlUe0oNj2JAhQ9TepkD51auk3N7q+4uz7A/cgJ5JsWHreT0PqieW1QhOuqxQ2reCXV1YXzecg==} - dev: true - /collect-v8-coverage/1.0.1: resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} dev: true @@ -7592,16 +7610,6 @@ packages: strip-json-comments: 2.0.1 dev: true - /react-codemirror2/7.2.1_codemirror@5.61.0+react@17.0.2: - resolution: {integrity: sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==} - peerDependencies: - codemirror: 5.x - react: '>=15.5 <=16.x' - dependencies: - codemirror: 5.61.0 - react: 17.0.2 - dev: true - /react-diff-viewer/3.1.1_react-dom@17.0.2+react@17.0.2: resolution: {integrity: sha512-rmvwNdcClp6ZWdS11m1m01UnBA4OwYaLG/li0dB781e/bQEzsGyj+qewVd6W5ztBwseQ72pO7nwaCcq5jnlzcw==} engines: {node: '>= 8'} @@ -7743,6 +7751,25 @@ packages: tiny-warning: 1.0.3 dev: true + /react-split-pane/0.1.92_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-GfXP1xSzLMcLJI5BM36Vh7GgZBpy+U/X0no+VM3fxayv+p1Jly5HpMofZJraeaMl73b3hvlr+N9zJKvLB/uz9w==} + peerDependencies: + react: ^16.0.0-0 + react-dom: ^16.0.0-0 + dependencies: + prop-types: 15.7.2 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-lifecycles-compat: 3.0.4 + react-style-proptype: 3.2.2 + dev: true + + /react-style-proptype/3.2.2: + resolution: {integrity: sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ==} + dependencies: + prop-types: 15.7.2 + dev: true + /react-tween-state/0.1.5: resolution: {integrity: sha1-6YsGZVHvuTy5LdG+FJlcLj3q4zk=} dependencies: @@ -8595,6 +8622,10 @@ packages: escape-string-regexp: 2.0.0 dev: true + /state-local/1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + dev: true + /static-extend/0.1.2: resolution: {integrity: sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=} engines: {node: '>=0.10.0'} diff --git a/src/layouts/index.less b/src/layouts/index.less index fe57adbc..518db753 100644 --- a/src/layouts/index.less +++ b/src/layouts/index.less @@ -13,15 +13,32 @@ body { background-color: rgb(248, 248, 248); } -@import '~codemirror/lib/codemirror.css'; -@import '~codemirror/addon/dialog/dialog.css'; +.ant-modal { + padding-bottom: 0 !important; + width: 580px !important; +} -.ql-container-wrapper { - .CodeMirror { - position: absolute; - height: calc(100vh - 128px); - height: calc(100vh - var(--vh-offset, 0px) - 128px); - width: calc(100% - 32px); +.monaco-editor:not(.rename-box) { + height: calc(100vh - 128px) !important; + height: calc(100vh - var(--vh-offset, 0px) - 128px) !important; + .view-overlays .current-line{ + border-width: 0; + } +} + +.log-modal { + .monaco-editor:not(.rename-box) { + height: calc(100vh - 176px) !important; + height: calc(100vh - var(--vh-offset, 0px) - 176px) !important; + background-color: transparent !important; + } +} + +.rename-box { + height: 0; + .rename-input{ + height: 0; + padding: 0 !important; } } @@ -29,7 +46,7 @@ body { max-width: unset !important; overflow: auto; .ant-pro-page-container-children-content { - overflow: auto; + overflow: visible; height: calc(100vh - 96px); height: calc(100vh - var(--vh-offset, 0px) - 96px); background-color: #fff; @@ -127,15 +144,14 @@ input:-webkit-autofill:active { height: calc(100vh - 184px); height: calc(100vh - var(--vh-offset, 0px) - 184px); } - .CodeMirror { - height: calc(100vh - 216px); - height: calc(100vh - var(--vh-offset, 0px) - 216px); - width: calc(100vw - 80px); + .monaco-editor:not(.rename-box) { + height: calc(100vh - 216px) !important; + height: calc(100vh - var(--vh-offset, 0px) - 216px) !important; } } - .CodeMirror { - height: calc(100vh - 176px); - height: calc(100vh - var(--vh-offset, 0px) - 176px); + .monaco-editor:not(.rename-box) { + height: calc(100vh - 176px) !important; + height: calc(100vh - var(--vh-offset, 0px) - 176px) !important; } } diff --git a/src/pages/config/index.tsx b/src/pages/config/index.tsx index 34fb9215..bcfc70b2 100644 --- a/src/pages/config/index.tsx +++ b/src/pages/config/index.tsx @@ -2,8 +2,8 @@ import React, { PureComponent, Fragment, useState, useEffect } from 'react'; import { Button, message, Modal, TreeSelect } from 'antd'; import config from '@/utils/config'; import { PageContainer } from '@ant-design/pro-layout'; -import { Controlled as CodeMirror } from 'react-codemirror2'; import { request } from '@/utils/http'; +import Editor from "@monaco-editor/react"; const Config = () => { const [width, setWidth] = useState('100%'); @@ -14,6 +14,7 @@ const Config = () => { const [title, setTitle] = useState('config.sh'); const [select, setSelect] = useState('config.sh'); const [data, setData] = useState([]); + const [theme, setTheme] = useState(''); const getConfig = (name: string) => { request.get(`${config.apiPrefix}configs/${name}`).then((data: any) => { @@ -61,6 +62,22 @@ const Config = () => { getConfig('config.sh'); }, []); + useEffect(()=>{ + const media = window.matchMedia('(prefers-color-scheme: dark)'); + const storageTheme = localStorage.getItem('qinglong_dark_theme'); + const isDark = (media.matches && storageTheme !== 'light') || storageTheme === 'dark'; + setTheme(isDark?'vs-dark':'vs'); + media.addEventListener('change',(e)=>{ + if(storageTheme === 'auto' || !storageTheme){ + if(e.matches){ + setTheme('vs-dark') + }else{ + setTheme('vs'); + } + } + }) + },[]) + return ( { }, }} > - { - setValue(value); - }} - onChange={(editor, data, value) => {}} + onChange={(val) => {setValue(val as string)}} /> ); diff --git a/src/pages/crontab/logModal.tsx b/src/pages/crontab/logModal.tsx index 015a3e99..cc67d2e5 100644 --- a/src/pages/crontab/logModal.tsx +++ b/src/pages/crontab/logModal.tsx @@ -6,7 +6,7 @@ import { Loading3QuartersOutlined, CheckCircleOutlined, } from '@ant-design/icons'; -import { Controlled as CodeMirror } from 'react-codemirror2'; +import Editor from "@monaco-editor/react"; enum CrontabStatus { 'running', @@ -28,6 +28,7 @@ const CronLogModal = ({ const [loading, setLoading] = useState(true); const [excuting, setExcuting] = useState(true); const [isPhone, setIsPhone] = useState(false); + const [theme, setTheme] = useState(''); const getCronLog = (isFirst?: boolean) => { if (isFirst) { @@ -91,40 +92,50 @@ const CronLogModal = ({ setIsPhone(document.body.clientWidth < 768); }, []); + useEffect(()=>{ + const media = window.matchMedia('(prefers-color-scheme: dark)'); + const storageTheme = localStorage.getItem('qinglong_dark_theme'); + const isDark = (media.matches && storageTheme !== 'light') || storageTheme === 'dark'; + setTheme(isDark?'vs-dark':'vs'); + media.addEventListener('change',(e)=>{ + if(storageTheme === 'auto' || !storageTheme){ + if(e.matches){ + setTheme('vs-dark') + }else{ + setTheme('vs'); + } + } + }) + },[]) + return ( cancel()} onCancel={() => cancel()} > {!loading && value && ( -
-          {value}
-        
+ )}
); diff --git a/src/pages/diff/index.tsx b/src/pages/diff/index.tsx index f67ae103..db774adf 100644 --- a/src/pages/diff/index.tsx +++ b/src/pages/diff/index.tsx @@ -5,6 +5,7 @@ import { PageContainer } from '@ant-design/pro-layout'; import { request } from '@/utils/http'; import ReactDiffViewer from 'react-diff-viewer'; import './index.less'; +import { DiffEditor } from "@monaco-editor/react"; const Crontab = () => { const [width, setWidth] = useState('100%'); @@ -13,6 +14,7 @@ const Crontab = () => { const [value, setValue] = useState(''); const [sample, setSample] = useState(''); const [loading, setLoading] = useState(true); + const [theme, setTheme] = useState(''); const getConfig = () => { request.get(`${config.apiPrefix}configs/config.sh`).then((data) => { @@ -44,6 +46,22 @@ const Crontab = () => { getSample(); }, []); + useEffect(()=>{ + const media = window.matchMedia('(prefers-color-scheme: dark)'); + const storageTheme = localStorage.getItem('qinglong_dark_theme'); + const isDark = (media.matches && storageTheme !== 'light') || storageTheme === 'dark'; + setTheme(isDark?'vs-dark':'vs'); + media.addEventListener('change',(e)=>{ + if(storageTheme === 'auto' || !storageTheme){ + if(e.matches){ + setTheme('vs-dark') + }else{ + setTheme('vs'); + } + } + }) + },[]) + return ( { }, }} > - - {/* */} ); }; diff --git a/src/pages/log/index.module.less b/src/pages/log/index.module.less index d2dafec2..73ee7c51 100644 --- a/src/pages/log/index.module.less +++ b/src/pages/log/index.module.less @@ -14,9 +14,7 @@ &-scroller { flex: 1; overflow: auto; - } - &-search { - margin-bottom: 8px; + border-right: 1px dashed #f0f0f0; } } @@ -29,9 +27,5 @@ .ant-pro-grid-content.wide .ant-pro-page-container-children-content { background-color: #f8f8f8; } - - .CodeMirror { - width: calc(100% - 32px - @tree-width); - } } } diff --git a/src/pages/log/index.tsx b/src/pages/log/index.tsx index 1f86ab6e..133beb9e 100644 --- a/src/pages/log/index.tsx +++ b/src/pages/log/index.tsx @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, Key, useRef } from 'react'; import { TreeSelect, Tree, Input } from 'antd'; import config from '@/utils/config'; import { PageContainer } from '@ant-design/pro-layout'; -import { Controlled as CodeMirror } from 'react-codemirror2'; +import Editor from "@monaco-editor/react"; import { request } from '@/utils/http'; import styles from './index.module.less'; @@ -48,6 +48,7 @@ const Log = () => { const [isPhone, setIsPhone] = useState(false); const [height, setHeight] = useState(); const treeDom = useRef(); + const [theme, setTheme] = useState(''); const getLogs = () => { setLoading(true); @@ -119,6 +120,22 @@ const Log = () => { setHeight(treeDom.current.clientHeight); }, []); + useEffect(()=>{ + const media = window.matchMedia('(prefers-color-scheme: dark)'); + const storageTheme = localStorage.getItem('qinglong_dark_theme'); + const isDark = (media.matches && storageTheme !== 'light') || storageTheme === 'dark'; + setTheme(isDark?'vs-dark':'vs'); + media.addEventListener('change',(e)=>{ + if(storageTheme === 'auto' || !storageTheme){ + if(e.matches){ + setTheme('vs-dark') + }else{ + setTheme('vs'); + } + } + }) + },[]) + return ( { )} - { - setValue(value); - }} - onChange={(editor, data, value) => {}} + onChange={(val, ev) => {setValue(val as string)}} /> diff --git a/src/pages/script/index.module.less b/src/pages/script/index.module.less index d2dafec2..73ee7c51 100644 --- a/src/pages/script/index.module.less +++ b/src/pages/script/index.module.less @@ -14,9 +14,7 @@ &-scroller { flex: 1; overflow: auto; - } - &-search { - margin-bottom: 8px; + border-right: 1px dashed #f0f0f0; } } @@ -29,9 +27,5 @@ .ant-pro-grid-content.wide .ant-pro-page-container-children-content { background-color: #f8f8f8; } - - .CodeMirror { - width: calc(100% - 32px - @tree-width); - } } } diff --git a/src/pages/script/index.tsx b/src/pages/script/index.tsx index 1ac87134..6e2d6872 100644 --- a/src/pages/script/index.tsx +++ b/src/pages/script/index.tsx @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, Key, useRef } from 'react'; import { TreeSelect, Tree, Input } from 'antd'; import config from '@/utils/config'; import { PageContainer } from '@ant-design/pro-layout'; -import { Controlled as CodeMirror } from 'react-codemirror2'; +import Editor from "@monaco-editor/react"; import { request } from '@/utils/http'; import styles from './index.module.less'; @@ -39,6 +39,7 @@ const Script = () => { const [mode, setMode] = useState(''); const [height, setHeight] = useState(); const treeDom = useRef(); + const [theme, setTheme] = useState(''); const getScripts = () => { setLoading(true); @@ -94,6 +95,22 @@ const Script = () => { setHeight(treeDom.current.clientHeight); }, []); + useEffect(()=>{ + const media = window.matchMedia('(prefers-color-scheme: dark)'); + const storageTheme = localStorage.getItem('qinglong_dark_theme'); + const isDark = (media.matches && storageTheme !== 'light') || storageTheme === 'dark'; + setTheme(isDark?'vs-dark':'vs'); + media.addEventListener('change',(e)=>{ + if(storageTheme === 'auto' || !storageTheme){ + if(e.matches){ + setTheme('vs-dark') + }else{ + setTheme('vs'); + } + } + }) + },[]) + return ( { )} - { - setValue(value); - }} - onChange={(editor, data, value) => {}} + onChange={(val) => {setValue(val as string)}} />