Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

chromesetting
daiao 5 years ago
commit 6d4572a2f3

@ -41,8 +41,6 @@ class Users::ShixunService
def user_policy_filter(relations) def user_policy_filter(relations)
# 只有自己或者管理员才有过滤筛选及查看全部状态下实训功能 # 只有自己或者管理员才有过滤筛选及查看全部状态下实训功能
Rails.logger.info("self_or_admin?: #{self_or_admin?}")
Rails.logger.info("user: #{user.id}")
if self_or_admin? if self_or_admin?
relations = relations.where.not(status: -1) relations = relations.where.not(status: -1)
status_filter(relations) status_filter(relations)

@ -15,6 +15,7 @@ import actions from '../../redux/actions';
import MultipTags from './components/multiptags'; import MultipTags from './components/multiptags';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import CONST from '../../constants'; import CONST from '../../constants';
import { withRouter } from 'react-router';
const {tagBackground, diffText} = CONST; const {tagBackground, diffText} = CONST;
const { Search } = Input; const { Search } = Input;
@ -96,66 +97,67 @@ const testMaps = {
} }
} }
/** class DeveloperHome extends React.PureComponent {
* 表格列 /**
*/ * 表格列
const options = { */
title: '操作', options = {
key: 'action', title: '操作',
fixed: 'right', key: 'action',
width: 100, fixed: 'right',
render: (text, record) => ( width: 100,
<span> render: (text, record) => (
<Button type="primary"> <span>
<Link to={`/problems/${record.identifier}/edit`}>编辑</Link> <Button type="primary">
</Button> <Link to={`/problems/${record.identifier}/edit`}>编辑</Link>
</span> </Button>
), </span>
} ),
const columns = [ }
{
title: '标题', columns = [
dataIndex: 'name', {
render: (name, record) => <Link style={{ color: '#459be5' }} to={`/myproblems/${record.identifier}`}>{name}</Link> title: '标题',
}, dataIndex: 'name',
{ render: (name, record) => <Button type="link" onClick={() => this.handleNameClick(record)} className={'oj_item_name'}>{name}</Button>
title: '分类', },
dataIndex: 'category', {
width: '20%', title: '分类',
align: 'center', dataIndex: 'category',
render: (category) => <span>{category ? testMaps['category'][+category] : '-'}</span> width: '20%',
}, align: 'center',
{ render: (category) => <span>{category ? testMaps['category'][+category] : '-'}</span>
title: '难度', },
dataIndex: 'difficult', {
align: 'center', title: '难度',
width: '15%', dataIndex: 'difficult',
render: (difficult) => { align: 'center',
if (difficult) { width: '15%',
return <Tag color={tagBackground[+difficult]}>{diffText[+difficult]}</Tag> render: (difficult) => {
} else { if (difficult) {
return '-'; return <Tag color={tagBackground[+difficult]}>{diffText[+difficult]}</Tag>
} else {
return '-';
}
} }
} },
}, {
{ title: '热度',
title: '热度', dataIndex: 'hack_user_lastest_codes_count',
dataIndex: 'hack_user_lastest_codes_count', sorter: true,
sorter: true, align: 'center',
align: 'center', width: '10%'
width: '10%' },
}, {
{ title: '通过率',
title: '通过率', dataIndex: 'passed_rate',
dataIndex: 'passed_rate', sorter: true,
sorter: true, align:'right',
align:'right', width: '10%',
width: '10%', render: val => <span>{`${val}%`}</span>
render: val => <span>{`${val}%`}</span> },
}, ];
];
class DeveloperHome extends React.PureComponent {
state = { state = {
data: [], data: [],
loading: false, loading: false,
@ -170,7 +172,7 @@ class DeveloperHome extends React.PureComponent {
page: 1, // 当前页数 page: 1, // 当前页数
limit: 10 // 每页显示条件 limit: 10 // 每页显示条件
}, },
columns: columns, columns: this.columns,
searchInfo: [] searchInfo: []
}; };
@ -179,7 +181,7 @@ class DeveloperHome extends React.PureComponent {
const { isMySource } = this.props; const { isMySource } = this.props;
if (isMySource) { if (isMySource) {
this.handleFilterSearch({come_from: 'mine'}); this.handleFilterSearch({come_from: 'mine'});
let _columns = columns.concat([options]); let _columns = this.columns.concat([this.options]);
this.setState({ this.setState({
columns: _columns columns: _columns
}); });
@ -309,13 +311,13 @@ class DeveloperHome extends React.PureComponent {
this.handleFilterSearch({come_from: item.key === 'all' ? '' : item.key}); this.handleFilterSearch({come_from: item.key === 'all' ? '' : item.key});
if (item.key !== 'all') { if (item.key !== 'all') {
let _columns = columns.concat([options]); let _columns = this.columns.concat([this.options]);
this.setState({ this.setState({
columns: _columns columns: _columns
}); });
} else { } else {
this.setState({ this.setState({
columns: columns columns: this.columns
}) })
} }
} }
@ -333,10 +335,19 @@ class DeveloperHome extends React.PureComponent {
}); });
if (info.type === 'come_from' && info.key === 'mine') { if (info.type === 'come_from' && info.key === 'mine') {
this.setState({ this.setState({
columns: columns columns: this.columns
}); });
} }
} }
// 点击name
handleNameClick = (record) => {
console.log('name has click', record);
// 先调用start接口获取返回的 identifier, 再跳转到开启编辑
this.props.startProgramQuestion(record.identifier, this.props);
}
render () { render () {
// const { testReducer, handleClick } = this.props; // const { testReducer, handleClick } = this.props;
const { const {
@ -453,10 +464,11 @@ const mapDispatchToProps = (dispatch) => ({
handleClick: () => dispatch(actions.toggleTodo()), handleClick: () => dispatch(actions.toggleTodo()),
fetchOJList: (params) => dispatch(actions.getOJList(params)), fetchOJList: (params) => dispatch(actions.getOJList(params)),
changePaginationInfo: (obj) => dispatch(actions.changePaginationInfo(obj)), changePaginationInfo: (obj) => dispatch(actions.changePaginationInfo(obj)),
startProgramQuestion: (id, props) => dispatch(actions.startProgramQuestion(id, props))
}); });
export default connect( export default withRouter(connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(DeveloperHome); )(DeveloperHome));
// export default DeveloperHome; // export default DeveloperHome;

@ -72,4 +72,8 @@
color: #fff; color: #fff;
} }
} }
.oj_item_name{
color: #459be5;
cursor: pointer;
}
} }

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2019-11-25 09:46:03 * @Date: 2019-11-25 09:46:03
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-11-29 14:45:27 * @LastEditTime: 2019-11-29 15:04:12
*/ */
import 'quill/dist/quill.core.css'; import 'quill/dist/quill.core.css';
import 'quill/dist/quill.bubble.css'; import 'quill/dist/quill.bubble.css';

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2019-11-23 10:53:19 * @Date: 2019-11-23 10:53:19
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-11-29 08:56:18 * @LastEditTime: 2019-11-29 20:00:34
*/ */
import './index.scss'; import './index.scss';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
@ -20,9 +20,10 @@ import actions from '../../../redux/actions';
const StudentStudy = (props) => { const StudentStudy = (props) => {
useEffect(() => { useEffect(() => {
const { match: { params }, startProgramQuestion } = props; const { match: { params }, getUserProgramDetail } = props;
let { id } = params; let { id } = params;
startProgramQuestion(id); // startProgramQuestion(id);
getUserProgramDetail(id);
}, []); }, []);
return ( return (
<div className={'student_study_warp'}> <div className={'student_study_warp'}>
@ -61,7 +62,9 @@ const mapStateToProps = (state) => ({});
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
// 调用开启编辑 // 调用开启编辑
startProgramQuestion: (id) => dispatch(actions.startProgramQuestion(id)) // startProgramQuestion: (id) => dispatch(actions.startProgramQuestion(id))
// 调用编程题详情
getUserProgramDetail: (id) => dispatch(actions.getUserProgramDetail(id))
}); });
export default connect( export default connect(

@ -33,13 +33,15 @@ function getModeByMirrorName(mirror_name) {
return mode; return mode;
} }
const _extraKeys = {"Alt-/": "autocomplete"}; const _extraKeys = {"Alt-/": "autocomplete"};
function createCMOptions(mirror_name) { function createCMOptions(mirror_name, theme) {
let mode = getModeByMirrorName(mirror_name) let mode = getModeByMirrorName(mirror_name)
let cmOptions = { let cmOptions = {
lineNumbers: true, lineNumbers: true,
mode: mode, mode: mode,
theme: "railscasts", // theme: "railscasts",
// theme: "vs-dark",
theme: theme,
indentUnit:4, indentUnit:4,
matchBrackets: true, matchBrackets: true,
autoRefresh: true, autoRefresh: true,
@ -97,6 +99,7 @@ class TPICodeMirror extends Component {
super(props) super(props)
this.state = { this.state = {
cmFontSize: fromStore('cmFontSize', 16), cmFontSize: fromStore('cmFontSize', 16),
cmCodeMode: fromStore('cmCodeMode', 'vs-dark'),
autoCompleteSwitch: fromStore('autoCompleteSwitch', true), autoCompleteSwitch: fromStore('autoCompleteSwitch', true),
} }
} }
@ -114,7 +117,7 @@ class TPICodeMirror extends Component {
} }
} }
componentDidMount() { componentDidMount() {
let cmOptions = createCMOptions(this.props.mirror_name) let cmOptions = createCMOptions(this.props.mirror_name, this.state.cmCodeMode)
extend_editor = window.CodeMirror.fromTextArea(window.$('#extend-challenge-file-edit')[0] extend_editor = window.CodeMirror.fromTextArea(window.$('#extend-challenge-file-edit')[0]
, cmOptions); , cmOptions);
@ -241,6 +244,12 @@ class TPICodeMirror extends Component {
this.setState({ cmFontSize: value }); this.setState({ cmFontSize: value });
} }
onCodeModeChange = (value) => {
toStore('cmCodeMode', value);
this.setState({ cmCodeMode: value });
window.monaco.editor.setTheme(value);
}
render() { render() {
const { repositoryCode, showSettingDrawer, settingDrawerOpen } = this.props; const { repositoryCode, showSettingDrawer, settingDrawerOpen } = this.props;
const { cmFontSize } = this.state; const { cmFontSize } = this.state;
@ -259,6 +268,7 @@ class TPICodeMirror extends Component {
> >
<TPICodeSetting {...this.props} {...this.state} <TPICodeSetting {...this.props} {...this.state}
onFontSizeChange={this.onFontSizeChange} onFontSizeChange={this.onFontSizeChange}
onCodeModeChange={this.onCodeModeChange}
onAutoCompleteSwitchChange={this.onAutoCompleteSwitchChange} onAutoCompleteSwitchChange={this.onAutoCompleteSwitchChange}
></TPICodeSetting> ></TPICodeSetting>
</Drawer> </Drawer>

@ -18,12 +18,12 @@ class TPICodeSetting extends Component {
render() { render() {
const { autoCompleteSwitch, onAutoCompleteSwitchChange, onFontSizeChange const { autoCompleteSwitch, onAutoCompleteSwitchChange, onFontSizeChange
, cmFontSize, , cmFontSize, cmCodeMode,
onCodeModeChange,
shixun } = this.props; shixun } = this.props;
const task_pass = shixun.task_pass const task_pass = shixun.task_pass
const forbid_copy = shixun.forbid_copy const forbid_copy = shixun.forbid_copy
const test_set_permission = shixun.test_set_permission const test_set_permission = shixun.test_set_permission
return ( return (
<div className="ide-settings--content"> <div className="ide-settings--content">
<style>{` <style>{`
@ -54,6 +54,25 @@ class TPICodeSetting extends Component {
</div> </div>
</div> </div>
</div>*/} </div>*/}
<div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">显示模式</div>
<div className="ide-settings--item-value">
<div className="select -view-flat -value">
<div className="-layout-v -start">
<div className="select--wrapper -layout-h -center -justify" >
<Select
style={{ width: '120px' }}
value={cmCodeMode}
onChange={onCodeModeChange}
>
<Option value={'vs'}>白色背景</Option>
<Option value={'vs-dark'}>黑色背景</Option>
</Select>
</div>
</div>
</div>
</div>
</div>
<div className="-layout-h -center -justify-between"> <div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">字体大小</div> <div className="ide-settings--item-key">字体大小</div>
<div className="ide-settings--item-value"> <div className="ide-settings--item-value">
@ -61,6 +80,7 @@ class TPICodeSetting extends Component {
<div className="-layout-v -start"> <div className="-layout-v -start">
<div className="select--wrapper -layout-h -center -justify" > <div className="select--wrapper -layout-h -center -justify" >
<Select <Select
style={{ width: '120px' }}
value={cmFontSize} value={cmFontSize}
onChange={onFontSizeChange}> onChange={onFontSizeChange}>
<Option value={12}>12px</Option> <Option value={12}>12px</Option>

@ -93,7 +93,7 @@
.monaco-editor .monaco-editor-hover code { background-color: rgba(10, 10, 10, 0.4); } .monaco-editor .monaco-editor-hover code { background-color: rgba(10, 10, 10, 0.4); }
.monaco-editor .goto-definition-link { color: #4e94ce !important; } .monaco-editor .goto-definition-link { color: #4e94ce !important; }
.mtk1 { color: #d4d4d4 !important; } /* .mtk1 { color: #d4d4d4 !important; }
.mtk2 { color: #1e1e1e !important; } .mtk2 { color: #1e1e1e !important; }
.mtk3 { color: #cc6666 !important; } .mtk3 { color: #cc6666 !important; }
.mtk4 { color: #9cdcfe !important; } .mtk4 { color: #9cdcfe !important; }
@ -116,7 +116,7 @@
.mtk21 { color: #4f76ac !important; } .mtk21 { color: #4f76ac !important; }
.mtk22 { color: #3dc9b0 !important; } .mtk22 { color: #3dc9b0 !important; }
.mtk23 { color: #74b0df !important; } .mtk23 { color: #74b0df !important; }
.mtk24 { color: #4864aa !important; } .mtk24 { color: #4864aa !important; } */
.mtki { font-style: italic; } .mtki { font-style: italic; }
.mtkb { font-weight: bold; } .mtkb { font-weight: bold; }
.mtku { text-decoration: underline; text-underline-position: under; } .mtku { text-decoration: underline; text-underline-position: under; }

@ -17,10 +17,11 @@ import * as monaco from 'monaco-editor'
import { fromStore, toStore } from 'educoder' import { fromStore, toStore } from 'educoder'
import './TPIMonacoConfig' import './TPIMonacoConfig'
import { isThisSecond } from 'date-fns';
// https://microsoft.github.io/monaco-editor/playground.html#customizing-the-appearence-exposed-colors // https://microsoft.github.io/monaco-editor/playground.html#customizing-the-appearence-exposed-colors
monaco.editor.defineTheme('myCoolTheme', { monaco.editor.defineTheme('myCoolTheme', {
base: 'vs-dark', base: 'vs', // vs、vs-dark、hc-black
inherit: true, inherit: true,
rules: [ rules: [
{ token: 'green', background: 'FF0000', foreground: '00FF00', fontStyle: 'italic'}, { token: 'green', background: 'FF0000', foreground: '00FF00', fontStyle: 'italic'},
@ -213,8 +214,9 @@ class TPIMonaco extends Component {
loadMonacoResouce(); loadMonacoResouce();
this.state = { this.state = {
cmFontSize: fromStore('cmFontSize', 16), cmFontSize: fromStore('cmFontSize', 16),
cmCodeMode: fromStore('cmCodeMode', 'vs-dark'),
autoCompleteSwitch: fromStore('autoCompleteSwitch', true), autoCompleteSwitch: fromStore('autoCompleteSwitch', true),
} }
} }
componentDidUpdate(prevProps, prevState, snapshot) { componentDidUpdate(prevProps, prevState, snapshot) {
@ -243,7 +245,6 @@ class TPIMonaco extends Component {
editor_monaco.setValue(this.props.repositoryCode) editor_monaco.setValue(this.props.repositoryCode)
} }
// 代码没变也需要layout可能从命令行自动切回了代码tab // 代码没变也需要layout可能从命令行自动切回了代码tab
editor_monaco.layout();
// Clears the editor's undo history. // Clears the editor's undo history.
// TODO // TODO
@ -290,11 +291,12 @@ class TPIMonaco extends Component {
language: lang, language: lang,
// language: 'css', // language: 'css',
// theme: "vs-dark", // theme: "vs",
theme: "myCoolTheme", theme: this.state.cmCodeMode,
// theme: 'myCoolTheme',
insertSpaces: false, insertSpaces: false,
fontSize: this.state.cmFontSize fontSize: this.state.cmFontSize,
// theme: this.state.cdCodeMode
}); });
window.editor_monaco = editor; window.editor_monaco = editor;
@ -368,10 +370,17 @@ class TPIMonaco extends Component {
} }
onFontSizeChange = (value) => { onFontSizeChange = (value) => {
toStore('cmFontSize', value) toStore('cmFontSize', value)
this.setState({ cmFontSize: value });
this.editor_monaco.updateOptions({fontSize: value}) this.editor_monaco.updateOptions({fontSize: value})
}
this.setState({ cmFontSize: value }); onCodeModeChange = (value) => {
toStore('cmCodeMode', value);
this.setState({ cmCodeMode: value });
window.monaco.editor.setTheme(value);
} }
onAutoCompleteSwitchChange = () => { onAutoCompleteSwitchChange = () => {
} }
@ -393,6 +402,7 @@ class TPIMonaco extends Component {
> >
<TPICodeSetting {...this.props} {...this.state} <TPICodeSetting {...this.props} {...this.state}
onFontSizeChange={this.onFontSizeChange} onFontSizeChange={this.onFontSizeChange}
onCodeModeChange={this.onCodeModeChange}
onAutoCompleteSwitchChange={this.onAutoCompleteSwitchChange} onAutoCompleteSwitchChange={this.onAutoCompleteSwitchChange}
></TPICodeSetting> ></TPICodeSetting>
</Drawer> </Drawer>

@ -36,6 +36,7 @@ import {
saveUserInputCode, saveUserInputCode,
changeUserCodeTab, changeUserCodeTab,
submitUserCode, submitUserCode,
getUserProgramDetail
// isUpdateCodeCtx // isUpdateCodeCtx
} from './ojForUser'; } from './ojForUser';
@ -79,6 +80,7 @@ export default {
changeSubmitLoadingStatus, changeSubmitLoadingStatus,
submitUserCode, submitUserCode,
changePublishLoadingStatus, changePublishLoadingStatus,
isMyPublish isMyPublish,
getUserProgramDetail
// isUpdateCodeCtx // isUpdateCodeCtx
} }

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2019-11-27 13:42:11 * @Date: 2019-11-27 13:42:11
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-11-29 12:03:51 * @LastEditTime: 2019-11-29 20:07:09
*/ */
import types from "./actionTypes"; import types from "./actionTypes";
import { Base64 } from 'js-base64'; import { Base64 } from 'js-base64';
@ -19,7 +19,7 @@ import {
} from "../../services/ojService"; } from "../../services/ojService";
// 进入编程页面时,首先调用开启编程题接口 // 进入编程页面时,首先调用开启编程题接口
export const startProgramQuestion = (id) => { export const startProgramQuestion = (id, props) => {
return (dispatch) => { return (dispatch) => {
fetchStartProgram(id).then(res => { fetchStartProgram(id).then(res => {
const { status, data } = res; const { status, data } = res;
@ -29,21 +29,30 @@ export const startProgramQuestion = (id) => {
type: types.SAVE_USER_PROGRAM_ID, type: types.SAVE_USER_PROGRAM_ID,
payload: identifier payload: identifier
}); });
// 调用用户编程详情接口 // 跳转至开启编程
fetchUserProgramDetail(identifier).then(res => { props.history.push(`/myproblems/${identifier}`);
const { status, data = {} } = res; // Redirect.to
if (status === 200) {
dispatch({
type: types.USER_PROGRAM_DETAIL,
payload: data
});
}
})
} }
}) })
} }
} }
// 获取用户编程题详情
export const getUserProgramDetail = (identifier) => {
// 调用用户编程详情接口
return (dispatch) => {
fetchUserProgramDetail(identifier).then(res => {
const { status, data = {} } = res;
if (status === 200) {
dispatch({
type: types.USER_PROGRAM_DETAIL,
payload: data
});
}
});
}
}
/** /**
* @description 更新代码 * @description 更新代码
* @param {*} identifier * @param {*} identifier

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2019-11-20 16:35:46 * @Date: 2019-11-20 16:35:46
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-11-28 21:21:56 * @LastEditTime: 2019-11-29 18:55:43
*/ */
import types from './actionTypes'; import types from './actionTypes';
import CONST from '../../constants'; import CONST from '../../constants';
@ -204,7 +204,7 @@ export const validateOjForm = (props, type) => {
payload: true payload: true
}); });
setTimeout(() => { setTimeout(() => {
props.history.push('/developer'); props.history.push('/problems');
}, 1000); }, 1000);
} }

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2019-11-27 13:41:48 * @Date: 2019-11-27 13:41:48
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-11-28 17:34:13 * @LastEditTime: 2019-11-29 20:07:57
*/ */
import types from "../actions/actionTypes"; import types from "../actions/actionTypes";
import { Base64 } from 'js-base64'; import { Base64 } from 'js-base64';

Loading…
Cancel
Save