新增cloudIDE

This commit is contained in:
何童崇 2022-05-25 15:26:19 +08:00
parent c170a5e6fe
commit a621d10d9d
13 changed files with 28757 additions and 35 deletions

View File

@ -83,6 +83,11 @@ module.exports = {
devtoolModuleFilenameTemplate: (info) =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, "/"),
},
externals: {
"react": "React",
"react-dom": "ReactDOM",
'alex': 'Alex',
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"

View File

@ -71,6 +71,11 @@ module.exports = {
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, "/"),
},
externals: {
'alex': 'Alex',
"react": "React",
"react-dom": "ReactDOM",
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"

View File

@ -2,13 +2,13 @@
<html lang="zh-CN" class="notranslate translated-ltr" translate="no">
<head>
<meta charset="utf-8">
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>
<meta name="Keywords" Content="gitLink,GitLink,gitlink,trustie,trustieforge,forge,确实让创建更美好,协同开发平台">
<meta name=”Keywords” Content=”TrustieOpenSourceProject″>
<meta name=”Keywords” Content=”issue,bug,tracker,软件工程,课程实践″>
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link href="https://gw.alipayobjects.com/os/lib/alipay/alex/1.9.10/bundle/alex.editor.all.global.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/editormd.min.css">
@ -20,11 +20,17 @@
<div id="md_div" style="display: none;"></div>
<div id="root" class="page -layout-v -fit widthunit"></div>
<div id="picture_display" style="display: none;"></div>
<script src="%PUBLIC_URL%js/react.development.js"></script>
<script src="%PUBLIC_URL%js/react-dom.development.js"></script>
<script src="%PUBLIC_URL%js/jquery-1.8.3.min.js"></script>
<script src="%PUBLIC_URL%js/js_min_all.js"></script>
<script src="%PUBLIC_URL%js/codemirror/codemirror.js"></script>
<script src="%PUBLIC_URL%js/editormd/editormd.min.js"></script>
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
<script src="%PUBLIC_URL%js/alex/alex.editor.all.global.min.js" defer ></script>
<script src="%PUBLIC_URL%js/alex/languages.global.min.js" defer ></script>
<!-- <script src="https://gw.alipayobjects.com/os/lib/alipay/alex/1.9.12/bundle/alex.editor.all.global.min.js" defer ></script>
<script src="https://gw.alipayobjects.com/os/lib/alipay/alex/1.9.12/languages/languages.global.min.js" defer ></script> -->
<%= htmlWebpackPlugin.tags.bodyTags %>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ if (isDev) {
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'student'
}
window._debugType = debugType;
export function initAxiosInterceptors(props) {

View File

@ -14,12 +14,12 @@ function CoderDepotPath({treeValuePath , returnUlr , returnMain , getPathUrl , i
</a>
{treeValuePath.map((item, key) => {
return (
<React.Fragment>
<React.Fragment key={key}>
{
key === treeValuePath.length-1 ?
<span className="color-grey-6 subFileName" key={key}>{item}</span>
<span className="color-grey-6 subFileName">{item}</span>
:
<a onClick={()=>returnUlr(`${getPathUrl(treeValuePath,key+1)}`)} className="color-blue subFileName">{item}</a>
<a onClick={()=>returnUlr(`${getPathUrl(treeValuePath,key+1)}`)} className="color-blue subFileName">{item}</a>
}
</React.Fragment>
);

View File

@ -0,0 +1,31 @@
const IPluginAPI = {
commands: {}
}
export class Plugin {
PLUGIN_ID = 'ChangeThemePlugin';
_commands = IPluginAPI['commands'] || null;
get commands() {
return this._commands;
}
activate({ context, commands }) {
this._commands = commands;
context.subscriptions.push(
commands.registerCommand(
'ChangeThemePlugin.changeTheme',
(value) => {
commands.executeCommand(
'alex.setDefaultPreference',
'general.theme',
value
);
}
)
);
}
}
export default new Plugin();

View File

@ -0,0 +1,82 @@
import React from 'react';
import { EditorRenderer } from 'alex';
function CloudIDE() {
const group = 'Gitlink';
const repo = 'forgeplus';
return (
<div className="welcome-main">
<EditorRenderer
appConfig={{
//
workspaceDir: `${group}/${repo}`,
defaultPreferences: {
// ide-dark
'general.theme': 'ide-light',
// 'general.theme': 'ide-dark',
//
'editor.forceReadOnly': false,
//
'editor.scrollBeyondLastLine': false,
}
}}
runtimeConfig={{
//
biz: 'gitlink',
// editor null
scenario: null,
// editor none
startupEditor: 'none',
// editor tab
hideEditorTab: true,
}}
editorConfig={{
stretchHeight: true,
disableEditorSearch: true,
}}
//
documentModel={{
// code code
type: 'code',
// tag
ref: 'master',
//
owner: group,
//
name: repo,
//
filepath: 'robots.ts',
//
readFile: async (filepath) => {
if (!filepath) {
return;
}
//
const res = await fetch('https://gist.githubusercontent.com/gaearon/0b180827c190fe4fd98b4c7f570ea4a8/raw/b9157ce933c79a4559d2aa9ff3372668cce48de7/LikeButton.js');
return res.arrayBuffer();
},
// utf8 gbk
encoding: 'utf8',
onFilepathChange: (changedFilepath) => {
if (changedFilepath) {
console.log(`路由跳转到 ${changedFilepath}`)
}
},
//
// lineNumber: [0, 1],
onLineNumberChange: line => {
if (typeof line === 'number') {
console.log(`#L${line}`)
} else {
console.log(`#L${line[0]}-${line[1]}`)
}
},
}}
/>
</div>
)
}
export default CloudIDE;

View File

@ -1,8 +1,22 @@
.monaco-editor .view-overlays .current-line{
.monaco-editor .view-overlays .current-line {
border: none !important;
background-color: rgba(48,232,132,0.15);
background-color: rgba(48, 232, 132, 0.15);
}
.monaco-editor .margin-view-overlays .current-line{
background-color: rgba(48,232,132,0.15);
.monaco-editor .margin-view-overlays .current-line {
background-color: rgba(48, 232, 132, 0.15);
}
.branchTable .margin-view-overlays{border-right: none !important; background-color: #fcfcfc !important;}
.branchTable .margin-view-overlays {
border-right: none !important;
background-color: #fcfcfc !important;
}
.editorBorderBox {
position: relative;
}
.ideStyle {
position: absolute;
z-index: 10;
right: 0;
}
.ant-switch-checked{
background-color: #466AFF;
}

View File

@ -1,10 +1,13 @@
import React, { Component } from "react";
import {UnControlled as CodeMirror} from 'react-codemirror2';
import React, { Component, Fragment } from "react";
import { Switch } from 'antd';
import { UnControlled as CodeMirror } from 'react-codemirror2';
import { EditorRenderer } from 'alex';
import { getUrl } from 'educoder';
import 'codemirror/addon/selection/active-line.js';
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/clike/clike';
import 'codemirror/mode/css/css';
import changeThemePlugin from './changeTheme';
import UserSubmitComponent from "./UserSubmitComponent";
import "./index.css";
@ -15,26 +18,53 @@ class m_editor extends Component {
super(props);
this.state = {
editorValue: this.props.content,
changeValue:this.props.content,
prevHeight:0
changeValue: this.props.content,
prevHeight: 0,
ideStyle: 'ide-light',
};
}
componentDidUpdate=(prevProps)=>{
if(prevProps && this.props && this.props.content !== prevProps.content){
componentDidUpdate = (prevProps) => {
if (prevProps && this.props && this.props.content !== prevProps.content) {
this.setState({
editorValue:this.props.content
editorValue: this.props.content
})
}
}
changeEditor = (editorValue,data) => {
changeEditor = (editorValue, data) => {
this.setState({
changeValue:editorValue.getValue(),
changeValue: editorValue.getValue(),
});
};
changeStyle = async(v) => {
// this.setState({
// ideStyle: v ? 'ide-light' : 'ide-dark'
// });
const commands = changeThemePlugin.commands;
if (commands) {
await commands.executeCommand(
'ChangeThemePlugin.changeTheme',
v ? 'ide-light' : 'ide-dark'
);
// await commands.executeCommand('theme.toggle');
}
}
changeTheme= async() =>{
const commands = changeThemePlugin.commands;
if (commands) {
await commands.executeCommand(
'ChangeThemePlugin.changeTheme',
'ide-dark'
);
// await commands.executeCommand('theme.toggle');
}
}
render() {
const { editorValue , changeValue } = this.state;
const { readOnly, editorType, currentBranch , descName , checkName } = this.props;
const { editorValue, changeValue, ideStyle } = this.state;
const { readOnly, editorType, currentBranch, descName, checkName, detail } = this.props;
console.log(ideStyle);
const editor_options = {
lineNumbers: "on",
lineWrapping: true, //强制换行
@ -42,7 +72,7 @@ class m_editor extends Component {
lineHeight: 24,
renderLineHighlight: "line",
revealHorizontalRightPadding: 5,
placeholder:"请输入内容",
placeholder: "请输入内容",
readOnly: readOnly,
cursorStyle: readOnly ? "underline-thin" : "line",
folding: true,
@ -50,24 +80,105 @@ class m_editor extends Component {
automaticLayout: true, // 自适应布局
overviewRulerBorder: false, // 不要滚动条的边框
scrollBeyondLastLine: false, // 取消代码后面一大段空白
styleActiveLine:true,//光标代码高亮
styleActiveLine: true,//光标代码高亮
minimap: {
// 不要小地图
enabled: false,
},
};
const group = 'Gitlink';
const repo = 'forgeplus';
let download_url = detail && detail.download_url;
return (
<React.Fragment>
<Fragment>
<div className="editorBorderBox">
<CodeMirror
placeholder="请输入内容"
value={editorValue}
options={editor_options}
onChange={this.changeEditor}
/>
{!readOnly ?
<CodeMirror
placeholder="请输入内容"
value={editorValue}
options={editor_options}
onChange={this.changeEditor}
/> :
<Fragment>
<div className="ideStyle">
<Switch checkedChildren="light" unCheckedChildren="dark" defaultChecked onChange={this.changeStyle}></Switch>
</div>
<EditorRenderer
appConfig={{
// 工作空间目录
plugins: [changeThemePlugin],
workspaceDir: `${group}/${repo}`,
defaultPreferences: {
// 默认主题,如果暗色为 ide-dark
// 'general.theme': 'ide-light',
'general.theme': ideStyle,
// 编辑器只读
'editor.forceReadOnly': true,
// 最后一行禁止继续滚动
'editor.scrollBeyondLastLine': false,
}
}}
runtimeConfig={{
// 业务标识
biz: 'gitlink',
// 在 editor 下推荐传 null此时不会持久化缓存工作空间数据
scenario: null,
// 启动时显示的编辑器editor 下传 none 即可
startupEditor: 'none',
// 隐藏 editor tab
hideEditorTab: true,
}}
editorConfig={{
stretchHeight: true,
disableEditorSearch: true,
}}
// 文档模型,以下数据变更时会更新打开的编辑器
documentModel={{
// 类型code 下为 code保持不变
type: 'code',
// 分支或 tag
ref: 'master',
// 仓库群组和用户
owner: group,
// 仓库名
name: repo,
// 仓库文件路径
filepath: 'robots.ts',
// 读取文件接口
readFile: async (filepath) => {
if (!filepath) {
return;
}
// 请求接口
// const res = await fetch('https://gist.githubusercontent.com/gaearon/0b180827c190fe4fd98b4c7f570ea4a8/raw/b9157ce933c79a4559d2aa9ff3372668cce48de7/LikeButton.js');
const res = await fetch(`${getUrl()}/attachments/entries/get_file?download_url=${download_url}`);
return res.arrayBuffer();
},
// 文件编码,和标准工作空间支持编码类型一致,简单场景只传 utf8 或 gbk 即可
encoding: 'utf8',
onFilepathChange: (changedFilepath) => {
if (changedFilepath) {
console.log(`路由跳转到 ${changedFilepath}`)
}
},
// 指定当前选中多少行
// lineNumber: [0, 1],
onLineNumberChange: line => {
if (typeof line === 'number') {
console.log(`#L${line}`)
} else {
console.log(`#L${line[0]}-${line[1]}`)
}
},
}}
/>
</Fragment>
}
</div>
{!readOnly && (
<div className="editorBorderSubmitBox" style={{padding:"20px"}}>
<div className="editorBorderSubmitBox" style={{ padding: "20px" }}>
<UserSubmitComponent
{...this.props}
{...this.state}
@ -78,9 +189,9 @@ class m_editor extends Component {
descName={descName}
checkName={checkName}
></UserSubmitComponent>
</div>
</div>
)}
</React.Fragment>
</Fragment>
);
}
}