mirror of
https://gitlink.org.cn/Gitlink/forgeplus.git
synced 2026-05-08 06:01:43 +08:00
init project
This commit is contained in:
35
public/react/src/modules/test/ShareTest.js
Normal file
35
public/react/src/modules/test/ShareTest.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
|
||||
<!-- 微信sdk https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 -->
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
|
||||
*/
|
||||
|
||||
if(window.wx) {
|
||||
wx.ready(function () { //需在用户可能点击分享按钮前就先调用
|
||||
alert('got wx1')
|
||||
wx.updateAppMessageShareData({
|
||||
title: ' title', // 分享标题
|
||||
desc: 'hello world', // 分享描述
|
||||
link: 'https://www.educoder.net', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
|
||||
imgUrl: 'https://test-newweb.educoder.net/images/educoder/headNavLogo.png', // 分享图标
|
||||
success: function () {
|
||||
// 设置成功
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// wx.onMenuShareAppMessage({
|
||||
// title:' title', // 分享标题
|
||||
// desc:'hello world', // 分享描述
|
||||
// link: 'https://www.educoder.net', //location.href, // 分享链接
|
||||
// imgUrl: 'https://pre-newweb.educoder.net/images/educoder/headNavLogo.png', // 分享图标
|
||||
// type: '', // 分享类型,music、video或link,不填默认为link
|
||||
// dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
|
||||
// success: function () {
|
||||
// // 用户确认分享后执行的回调函数
|
||||
// },
|
||||
// cancel: function () {
|
||||
// // 用户取消分享后执行的回调函数
|
||||
// }
|
||||
// });
|
||||
}
|
||||
25
public/react/src/modules/test/TestCrop.js
Normal file
25
public/react/src/modules/test/TestCrop.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Cropper from '../../common/components/Cropper'
|
||||
import ChangeHeaderPicModal from '../user/account/ChangeHeaderPicModal'
|
||||
class TestCrop extends Component {
|
||||
state = {
|
||||
};
|
||||
|
||||
handleChange = (info) => {
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const props = this.props;
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => { this.refs['changeHeaderPicModal'].setVisible(true)}}>open</button>
|
||||
<ChangeHeaderPicModal ref="changeHeaderPicModal"></ChangeHeaderPicModal>
|
||||
<Cropper></Cropper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default (TestCrop);
|
||||
144
public/react/src/modules/test/TestRC.js
Normal file
144
public/react/src/modules/test/TestRC.js
Normal file
@@ -0,0 +1,144 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import moment from 'moment'
|
||||
import Select, {Option, OptGroup} from 'rc-select';
|
||||
import 'rc-select/assets/index.css';
|
||||
|
||||
import { Upload, Icon, message } from 'antd';
|
||||
|
||||
import 'antd/lib/upload/style/index.css'
|
||||
import Radio, { RadioGroup } from 'material-ui/Radio';
|
||||
import Checkbox from 'material-ui/Checkbox';
|
||||
import { withStyles } from 'material-ui/styles';
|
||||
|
||||
const Dragger = Upload.Dragger;
|
||||
|
||||
const props = {
|
||||
name: 'file',
|
||||
multiple: true,
|
||||
action: '//jsonplaceholder.typicode.com/posts/',
|
||||
onChange(info) {
|
||||
const status = info.file.status;
|
||||
if (status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully.`);
|
||||
} else if (status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
},
|
||||
};
|
||||
// -------------------------------------------
|
||||
|
||||
function getBase64(img, callback) {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('load', () => callback(reader.result));
|
||||
reader.readAsDataURL(img);
|
||||
}
|
||||
|
||||
function beforeUpload(file) {
|
||||
const isJPG = file.type === 'image/jpeg';
|
||||
// if (!isJPG) {
|
||||
// message.error('You can only upload JPG file!');
|
||||
// }
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
if (!isLt2M) {
|
||||
message.error('Image must smaller than 2MB!');
|
||||
}
|
||||
// return isJPG && isLt2M;
|
||||
return isLt2M;
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
const children = [];
|
||||
for (let i = 10; i < 36; i++) {
|
||||
// value={i}
|
||||
children.push(
|
||||
<Option key={i.toString(36) + i} disabled={i === 10} title={`中文${i}`} >
|
||||
中文{i}
|
||||
</Option>
|
||||
);
|
||||
}
|
||||
// DOC https://v1-0-0.material-ui.com/customization/themes/
|
||||
const myStyles = theme => ({
|
||||
// root: {
|
||||
// color: 'inherit',
|
||||
// textDecoration: 'inherit',
|
||||
// '&:hover': {
|
||||
// textDecoration: 'underline',
|
||||
// },
|
||||
// },
|
||||
// 使用主题的主色
|
||||
primary: {
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
radio: {
|
||||
'&$checked': {
|
||||
color: '#4B8DF8'
|
||||
},
|
||||
color: 'red'
|
||||
},
|
||||
checked: {}
|
||||
});
|
||||
|
||||
class TestRC extends Component {
|
||||
state = {
|
||||
loading: false,
|
||||
};
|
||||
|
||||
handleChange = (info) => {
|
||||
if (info.file.status === 'uploading') {
|
||||
this.setState({ loading: true });
|
||||
return;
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
// Get this url from response in real world.
|
||||
getBase64(info.file.originFileObj, imageUrl => this.setState({
|
||||
imageUrl,
|
||||
loading: false,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const uploadButton = (
|
||||
<div>
|
||||
<Icon type={this.state.loading ? 'loading' : 'plus'} />
|
||||
<div className="ant-upload-text">Upload</div>
|
||||
</div>
|
||||
);
|
||||
const imageUrl = this.state.imageUrl;
|
||||
/*
|
||||
|
||||
labelStyle={{color: 'yellow'}}
|
||||
iconStyle={{ fill: 'red', color: 'blue' }}
|
||||
*/
|
||||
const props = this.props;
|
||||
return (
|
||||
<div>
|
||||
<Radio
|
||||
label='My checkbox'
|
||||
classes={{root: props.classes.radio, checked: props.classes.checked}}
|
||||
>111</Radio>
|
||||
<Checkbox label='My checkbox'
|
||||
classes={{root: props.classes.radio, checked: props.classes.checked}}
|
||||
|
||||
/>
|
||||
<Upload
|
||||
name="avatar"
|
||||
listType="picture-card"
|
||||
className="avatar-uploader"
|
||||
showUploadList={false}
|
||||
action="//jsonplaceholder.typicode.com/posts/"
|
||||
beforeUpload={beforeUpload}
|
||||
onChange={this.handleChange}
|
||||
>
|
||||
{imageUrl ? <img src={imageUrl} alt="avatar" /> : uploadButton}
|
||||
</Upload>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(myStyles)(TestRC);
|
||||
63
public/react/src/modules/test/codemirror/TestCodeMirror.js
Normal file
63
public/react/src/modules/test/codemirror/TestCodeMirror.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import CodeMirror from 'react-codeMirror'
|
||||
|
||||
require('codemirror/lib/codemirror.css');
|
||||
require('codemirror/mode/javascript/javascript');
|
||||
require('codemirror/mode/xml/xml');
|
||||
require('codemirror/mode/markdown/markdown');
|
||||
/*
|
||||
|
||||
*/
|
||||
class TestCodeMirror extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.updateCode = this.updateCode.bind(this)
|
||||
|
||||
this.state = {
|
||||
code: '// Code\n //2 \n //3 \n //4 \n //5 \n\n\n\n\n\n\n'
|
||||
}
|
||||
}
|
||||
|
||||
updateCode(newCode) {
|
||||
this.setState({
|
||||
code: newCode,
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var readOnlyLines = [0,1,2,3,8];
|
||||
|
||||
this.refs.editor.getCodeMirror().on('beforeChange',function(cm,change) {
|
||||
console.log('change.from.line', change.from.line)
|
||||
if ( readOnlyLines.indexOf(change.from.line) !== -1
|
||||
// 有问题:如果用回车将有内容的行挤到不可编辑的行,那么无法删除掉不可编辑行里的内容了
|
||||
// 解决办法:将所需的行数固定写好,禁用掉回车键。
|
||||
// || change.from.line > ( readOnlyLines[readOnlyLines.length -1] + 1 )
|
||||
) {
|
||||
change.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
setCode() {
|
||||
this.setState({
|
||||
code: 'test'
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
var options = {
|
||||
lineNumbers: true,
|
||||
mode: 'javascript',
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.setCode.bind(this)}>set</button>
|
||||
<CodeMirror ref="editor" value={this.state.code} onChange={this.updateCode} options={options} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default TestCodeMirror;
|
||||
110
public/react/src/modules/test/dnd/TestDragBeautiful.js
Normal file
110
public/react/src/modules/test/dnd/TestDragBeautiful.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import React, { Component } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||
import styled from "styled-components";
|
||||
|
||||
// fake data generator
|
||||
const getItems = count =>
|
||||
Array.from({ length: count }, (v, k) => k).map(k => ({
|
||||
id: `item-${k}`,
|
||||
content: `item ${k}`
|
||||
}));
|
||||
|
||||
// a little function to help us with reordering the result
|
||||
const reorder = (list, startIndex, endIndex) => {
|
||||
const result = Array.from(list);
|
||||
const [removed] = result.splice(startIndex, 1);
|
||||
result.splice(endIndex, 0, removed);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const List = styled.div`
|
||||
background: lightgrey;
|
||||
padding: 10px;
|
||||
`;
|
||||
|
||||
const Item = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid grey;
|
||||
background: white;
|
||||
&:hover {
|
||||
background: lightgrey;
|
||||
}
|
||||
`;
|
||||
|
||||
const DragHandle = styled.div`
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 8px;
|
||||
background: grey;
|
||||
visibility: hidden;
|
||||
&:hover {
|
||||
background: black;
|
||||
}
|
||||
${Item}:hover & {
|
||||
visibility: visible;
|
||||
}
|
||||
`;
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
items: getItems(10)
|
||||
};
|
||||
this.onDragEnd = this.onDragEnd.bind(this);
|
||||
}
|
||||
|
||||
onDragEnd(result) {
|
||||
// dropped outside the list
|
||||
if (!result.destination) {
|
||||
return;
|
||||
}
|
||||
|
||||
const items = reorder(
|
||||
this.state.items,
|
||||
result.source.index,
|
||||
result.destination.index
|
||||
);
|
||||
|
||||
this.setState({
|
||||
items
|
||||
});
|
||||
}
|
||||
|
||||
// Normally you would want to split things out into separate components.
|
||||
// But in this example everything is just done in one place for simplicity
|
||||
render() {
|
||||
return (
|
||||
<DragDropContext onDragEnd={this.onDragEnd}>
|
||||
<Droppable droppableId="droppable">
|
||||
{(provided, snapshot) => (
|
||||
<List ref={provided.innerRef}>
|
||||
{this.state.items.map((item, index) => (
|
||||
<Draggable key={item.id} draggableId={item.id} index={index}>
|
||||
{(provided, snapshot) => (
|
||||
<Item ref={provided.innerRef} {...provided.draggableProps}>
|
||||
<DragHandle {...provided.dragHandleProps} />
|
||||
{item.content}
|
||||
</Item>
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
</List>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
|
||||
// Put the thing into the DOM!
|
||||
// ReactDOM.render(<App />, document.getElementById("root"));
|
||||
30
public/react/src/modules/test/index.js
Normal file
30
public/react/src/modules/test/index.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import React, { Component } from 'react';
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import MonacoTest from './monaco'
|
||||
import TestCrop from './TestCrop'
|
||||
import TestDragBeautiful from './dnd/TestDragBeautiful'
|
||||
|
||||
class TestIndex extends Component {
|
||||
state = {
|
||||
loading: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div style={{height: '100%'}}>
|
||||
test page
|
||||
|
||||
<Switch {...this.props}>
|
||||
<Route exact path="/test/monacoTest" component={MonacoTest}></Route>
|
||||
<Route exact path="/test/testCrop" component={TestCrop}></Route>
|
||||
<Route exact path="/test/dragBeautifulTest" component={TestDragBeautiful}></Route>
|
||||
</Switch>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TestIndex;
|
||||
195
public/react/src/modules/test/md/TestMaterialDesign.js
Normal file
195
public/react/src/modules/test/md/TestMaterialDesign.js
Normal file
@@ -0,0 +1,195 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
|
||||
// import Divider from 'material-ui/Divider';
|
||||
// import Dialog, {
|
||||
// DialogActions,
|
||||
// DialogContent,
|
||||
// DialogContentText,
|
||||
// DialogTitle,
|
||||
// } from 'material-ui/Dialog';
|
||||
|
||||
// import AppBar from 'material-ui/AppBar';
|
||||
|
||||
// import getMuiTheme from 'material-ui/styles/getMuiTheme'
|
||||
|
||||
|
||||
// import MobileTearSheet from '../../../MobileTearSheet';
|
||||
|
||||
// import ActionGrade from 'material-ui/svg-icons/action/grade';
|
||||
// import Divider from 'material-ui/Divider';
|
||||
// import Avatar from 'material-ui/Avatar';
|
||||
|
||||
|
||||
// import PropTypes from 'prop-types';
|
||||
|
||||
// import Tabs, { Tab } from 'material-ui/Tabs';
|
||||
|
||||
// import Input, { InputLabel } from 'material-ui/Input';
|
||||
// import { FormControl, FormHelperText } from 'material-ui/Form';
|
||||
|
||||
|
||||
import { IIHOC as DebuggerHOC, stringify } from './ii_debug'
|
||||
|
||||
const style = {
|
||||
paper: {
|
||||
display: 'inline-block',
|
||||
float: 'left',
|
||||
margin: '16px 32px 16px 0',
|
||||
},
|
||||
rightIcon: {
|
||||
textAlign: 'center',
|
||||
lineHeight: '24px',
|
||||
},
|
||||
};
|
||||
/*
|
||||
<AppBar
|
||||
title="Title"
|
||||
iconClassNameRight="muidocs-icon-navigation-expand-more"
|
||||
/>
|
||||
*/
|
||||
|
||||
// https://material-ui-next.com/discover-more/showcase/
|
||||
// class TestMaterialDesign extends Component {
|
||||
|
||||
// // ------------------------------------------------
|
||||
// // static childContextTypes = {
|
||||
// // muiTheme: PropTypes.object
|
||||
// // }
|
||||
|
||||
// // getChildContext() {
|
||||
// // return {
|
||||
// // muiTheme: getMuiTheme()
|
||||
// // }
|
||||
// // }
|
||||
// // ------------------------------------------------
|
||||
|
||||
// state = {
|
||||
// open: false,
|
||||
// value: 0,
|
||||
// };
|
||||
|
||||
// handleOpen = () => {
|
||||
// this.setState({open: true});
|
||||
// };
|
||||
|
||||
// handleClose = () => {
|
||||
// this.setState({open: false});
|
||||
// };
|
||||
|
||||
// handleChange = (event, value) => {
|
||||
// this.setState({ value });
|
||||
// };
|
||||
// onGoldRewardInputChange(event) {
|
||||
// this.setState({ goldRewardInput: event.target.value });
|
||||
// }
|
||||
// render() {
|
||||
|
||||
// const {value} = this.state
|
||||
|
||||
// return (
|
||||
|
||||
// <Dialog
|
||||
// open={true}
|
||||
// onClose={this.handleGoldRewardDialogClose}
|
||||
// >
|
||||
// <DialogTitle id="alert-dialog-title">{"奖励设置"}</DialogTitle>
|
||||
// <DialogContent>
|
||||
|
||||
// <FormControl aria-describedby="name-error-text">
|
||||
// <InputLabel htmlFor="goldReward">1请输入奖励的金币数量</InputLabel>
|
||||
// <Input id="goldReward" type="number" value={this.state.goldRewardInput} onChange={(e) => this.onGoldRewardInputChange(e)} />
|
||||
|
||||
// </FormControl>
|
||||
// </DialogContent>
|
||||
// <DialogActions>
|
||||
// </DialogActions>
|
||||
// </Dialog>
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// const TestMaterialDesign = () => (
|
||||
|
||||
// <FlatButton label="Primary" primary={true} />
|
||||
// );
|
||||
|
||||
// export default TestMaterialDesign;
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Props Proxy and state abstraction demonstration
|
||||
function PPHOC(WrappedComponent) {
|
||||
return class PP extends React.Component {
|
||||
componentDidMount() {
|
||||
// console.log('componentDidMount1 componentDidMount1 ')
|
||||
}
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = { fields: {} }
|
||||
}
|
||||
|
||||
getField(fieldName) {
|
||||
if (!this.state.fields[fieldName]) {
|
||||
// TODO 从服务端取state对应的数据
|
||||
// 共享state
|
||||
this.state.fields[fieldName] = {
|
||||
value: '',
|
||||
onChange: event => {
|
||||
this.state.fields[fieldName].value = event.target.value
|
||||
this.forceUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
value: this.state.fields[fieldName].value,
|
||||
onChange: this.state.fields[fieldName].onChange
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = Object.assign({}, this.props, {
|
||||
fields: this.getField.bind(this),
|
||||
})
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
PP HOC
|
||||
</h2>
|
||||
<p>Im a Props Proxy HOC that abstracts controlled inputs</p>
|
||||
<WrappedComponent {...props}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Example extends React.Component {
|
||||
componentDidMount() {
|
||||
console.log('componentDidMount componentDidMount ')
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
Wrapped Component
|
||||
</h2>
|
||||
<p>
|
||||
Props
|
||||
</p>
|
||||
<pre>{stringify(this.props)}</pre>
|
||||
<form>
|
||||
<label>Automatically controlled input!</label>
|
||||
<input type="email" {...this.props.fields('email')}/>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const EnhancedExample = DebuggerHOC(PPHOC(Example))
|
||||
|
||||
// module.exports = EnhancedExample;
|
||||
|
||||
export default EnhancedExample
|
||||
68
public/react/src/modules/test/md/ii_debug.js
Normal file
68
public/react/src/modules/test/md/ii_debug.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
function replacer(key, value) {
|
||||
if (typeof value === 'function') {
|
||||
return `function ${value.name}() {...}`
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export function stringify(value) {
|
||||
return JSON.stringify(value, replacer, 2)
|
||||
}
|
||||
|
||||
// II debug example
|
||||
// We are using the Inheritance Inversion technique to display
|
||||
// the current state and props of the WrappedComponent (the component you want to debug).
|
||||
// This is based on the technique that Mickael Jackson and Ryan Florence recommend
|
||||
export function IIHOC(WrappedComponent) {
|
||||
return class II extends WrappedComponent {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
HOC Debugger Component
|
||||
</h2>
|
||||
<p>
|
||||
Props
|
||||
</p>
|
||||
<pre>{stringify(this.props)}</pre>
|
||||
<p>
|
||||
State
|
||||
</p>
|
||||
<pre>{stringify(this.state)}</pre>
|
||||
{super.render()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Example extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
name: 'fran',
|
||||
email: 'franleplant@gmail.com'
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
Wrapped Component
|
||||
</h2>
|
||||
<p>Im a wrapped component</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// const EnhancedExample = IIHOC(Example)
|
||||
|
||||
// ReactDOM.render(<EnhancedExample date={(new Date).toISOString()}
|
||||
// callback={function test() {}}/>, document.getElementById('root'))
|
||||
17
public/react/src/modules/test/monaco/index.js
Normal file
17
public/react/src/modules/test/monaco/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import TPIMonaco from '../../page/component/monaco/TPIMonaco'
|
||||
class MonacoTest extends Component {
|
||||
state = {
|
||||
loading: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
console.log('monacoTest render')
|
||||
return (
|
||||
<TPIMonaco repositoryCode={'asdfasdf'}></TPIMonaco>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MonacoTest;
|
||||
85
public/react/src/modules/test/urlquery/TestUrlQuery.js
Normal file
85
public/react/src/modules/test/urlquery/TestUrlQuery.js
Normal file
@@ -0,0 +1,85 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { addUrlProps, UrlQueryParamTypes } from 'react-url-query';
|
||||
|
||||
/**
|
||||
* Specify how the URL gets decoded here. This is an object that takes the prop
|
||||
* name as a key, and a query param specifier as the value. The query param
|
||||
* specifier can have a `type`, indicating how to decode the value from the
|
||||
* URL, and a `queryParam` field that indicates which key in the query
|
||||
* parameters should be read (this defaults to the prop name if not provided).
|
||||
*/
|
||||
const urlPropsQueryConfig = {
|
||||
bar: { type: UrlQueryParamTypes.string },
|
||||
foo: { type: UrlQueryParamTypes.number, queryParam: 'fooInUrl' },
|
||||
};
|
||||
|
||||
class TestUrlQuery extends PureComponent {
|
||||
static propTypes = {
|
||||
bar: PropTypes.string,
|
||||
foo: PropTypes.number,
|
||||
// change handlers are automatically generated and passed if a config is provided
|
||||
// and `addChangeHandlers` isn't false. They use `replaceIn` by default, just
|
||||
// updating that single query parameter and keeping the other existing ones.
|
||||
onChangeFoo: PropTypes.func,
|
||||
onChangeBar: PropTypes.func,
|
||||
onChangeUrlQueryParams: PropTypes.func,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
foo: 123,
|
||||
bar: 'bar',
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
foo, bar, onChangeFoo, onChangeBar, onChangeUrlQueryParams
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>foo</td>
|
||||
<td>{foo}</td>
|
||||
<td>(url query param)</td>
|
||||
<td>
|
||||
<button onClick={() => onChangeFoo(Math.round(Math.random() * 1000))}>
|
||||
Change foo
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bar</td>
|
||||
<td>{bar}</td>
|
||||
<td>(url query param)</td>
|
||||
<td>
|
||||
<button onClick={() => onChangeBar(Math.random().toString(32).substring(8))}>
|
||||
Change bar
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={4}>
|
||||
<button onClick={() => onChangeUrlQueryParams({
|
||||
foo: Math.round(Math.random() * 1000),
|
||||
bar: Math.random().toString(32).substring(8),
|
||||
})}>
|
||||
Change both with one URL update
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We use the addUrlProps higher-order component to map URL query parameters
|
||||
* to props for TestUrlQuery. In this case the mapping happens automatically by
|
||||
* first decoding the URL query parameters based on the urlPropsQueryConfig.
|
||||
*/
|
||||
export default addUrlProps({ urlPropsQueryConfig })(TestUrlQuery);
|
||||
Reference in New Issue
Block a user