mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 02:10:59 +00:00
[web] Add keys argument for dump_dict in optmanager.
This commit is contained in:
parent
2e6f56c4e7
commit
aa01a62df7
@ -409,14 +409,15 @@ def dump_defaults(opts):
|
|||||||
return ruamel.yaml.round_trip_dump(s)
|
return ruamel.yaml.round_trip_dump(s)
|
||||||
|
|
||||||
|
|
||||||
def dump_dicts(opts):
|
def dump_dicts(opts, keys: typing.List[str]=None):
|
||||||
"""
|
"""
|
||||||
Dumps the options into a list of dict object.
|
Dumps the options into a list of dict object.
|
||||||
|
|
||||||
Return: A list like: { "anticache": { type: "bool", default: false, value: true, help: "help text"} }
|
Return: A list like: { "anticache": { type: "bool", default: false, value: true, help: "help text"} }
|
||||||
"""
|
"""
|
||||||
options_dict = {}
|
options_dict = {}
|
||||||
for k in sorted(opts.keys()):
|
keys = keys if keys else opts.keys()
|
||||||
|
for k in sorted(keys):
|
||||||
o = opts._options[k]
|
o = opts._options[k]
|
||||||
t = typecheck.typespec_to_str(o.typespec)
|
t = typecheck.typespec_to_str(o.typespec)
|
||||||
option = {
|
option = {
|
||||||
|
@ -341,6 +341,7 @@ def test_dump_defaults():
|
|||||||
def test_dump_dicts():
|
def test_dump_dicts():
|
||||||
o = options.Options()
|
o = options.Options()
|
||||||
assert optmanager.dump_dicts(o)
|
assert optmanager.dump_dicts(o)
|
||||||
|
assert optmanager.dump_dicts(o, ['http2', 'anticomp'])
|
||||||
|
|
||||||
|
|
||||||
class TTypes(optmanager.OptManager):
|
class TTypes(optmanager.OptManager):
|
||||||
|
@ -255,8 +255,8 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
|||||||
|
|
||||||
def test_options(self):
|
def test_options(self):
|
||||||
j = json(self.fetch("/options"))
|
j = json(self.fetch("/options"))
|
||||||
assert type(j) == list
|
assert type(j) == dict
|
||||||
assert type(j[0]) == dict
|
assert type(j['anticache']) == dict
|
||||||
|
|
||||||
def test_option_update(self):
|
def test_option_update(self):
|
||||||
assert self.put_json("/options", {"anticache": True}).code == 200
|
assert self.put_json("/options", {"anticache": True}).code == 200
|
||||||
|
138
web/src/js/components/Modal/OptionMaster.jsx
Normal file
138
web/src/js/components/Modal/OptionMaster.jsx
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { update as updateOptions } from '../../ducks/options'
|
||||||
|
|
||||||
|
PureBooleanOption.PropTypes = {
|
||||||
|
value: PropTypes.bool.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
function PureBooleanOption({ value, onChange, name, help}) {
|
||||||
|
return (
|
||||||
|
<div className="menu-entry">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
checked={value}
|
||||||
|
onChange={onChange}
|
||||||
|
title={help}
|
||||||
|
/>
|
||||||
|
{ name }
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PureStringOption.PropTypes = {
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
function PureStringOption( { value, onChange, name, help }) {
|
||||||
|
let onKeyDown = (e) => {e.stopPropagation()}
|
||||||
|
return (
|
||||||
|
<div className="menu-entry">
|
||||||
|
<label>
|
||||||
|
{ name }
|
||||||
|
<input type="text"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
title={help}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PureNumberOption.PropTypes = {
|
||||||
|
value: PropTypes.number.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
function PureNumberOption( {value, onChange, name, help }) {
|
||||||
|
let onKeyDown = (e) => {e.stopPropagation()}
|
||||||
|
return (
|
||||||
|
<div className="menu-entry">
|
||||||
|
<label>
|
||||||
|
{ name }
|
||||||
|
<input type="number"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
title={help}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PureChoicesOption.PropTypes = {
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
function PureChoicesOption( { value, onChange, name, help, choices }) {
|
||||||
|
return (
|
||||||
|
<div className="menu-entry">
|
||||||
|
<label htmlFor="">
|
||||||
|
{ name }
|
||||||
|
<select name={name} onChange={onChange} title={help} selected={value}>
|
||||||
|
{ choices.map(choice => (
|
||||||
|
<option value={choice}> {choice} </option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const OptionTypes = {
|
||||||
|
bool: PureBooleanOption,
|
||||||
|
str: PureStringOption,
|
||||||
|
int: PureNumberOption,
|
||||||
|
"optional str": PureStringOption,
|
||||||
|
"sequence of str": PureStringOption,
|
||||||
|
}
|
||||||
|
|
||||||
|
Wrapper.displayName = 'OptionWrapper'
|
||||||
|
|
||||||
|
|
||||||
|
function Wrapper({option, options, updateOptions, ...props}) {
|
||||||
|
let optionObj = options[option],
|
||||||
|
WrappedComponent = null
|
||||||
|
if (optionObj.choices) {
|
||||||
|
WrappedComponent = PureChoicesOption
|
||||||
|
} else {
|
||||||
|
WrappedComponent = OptionTypes[optionObj.type]
|
||||||
|
}
|
||||||
|
|
||||||
|
let onChange = (e) => {
|
||||||
|
switch (optionObj.type) {
|
||||||
|
case 'bool' :
|
||||||
|
updateOptions({[option]: !optionObj.value})
|
||||||
|
break
|
||||||
|
case 'int':
|
||||||
|
updateOptions({[option]: parseInt(e.target.value)})
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
updateOptions({[option]: e.target.value})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <WrappedComponent
|
||||||
|
children={props.children}
|
||||||
|
value={optionObj.value}
|
||||||
|
onChange={onChange}
|
||||||
|
name={option}
|
||||||
|
help={optionObj.help}
|
||||||
|
choices={optionObj.choices}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
state => ({
|
||||||
|
options: state.options,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
updateOptions,
|
||||||
|
}
|
||||||
|
)(Wrapper)
|
@ -1,48 +0,0 @@
|
|||||||
import PropTypes from 'prop-types'
|
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { update as updateOptions } from '../../ducks/options'
|
|
||||||
|
|
||||||
MenuToggle.propTypes = {
|
|
||||||
value: PropTypes.bool.isRequired,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
children: PropTypes.node.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
export function MenuToggle({ value, onChange, children }) {
|
|
||||||
return (
|
|
||||||
<div className="menu-entry">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox"
|
|
||||||
checked={value}
|
|
||||||
onChange={onChange}/>
|
|
||||||
{children}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionsToggle.propTypes = {
|
|
||||||
option: PropTypes.string.isRequired,
|
|
||||||
children: PropTypes.node.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
export function OptionsToggle({ option, children, options, updateOptions }) {
|
|
||||||
return (
|
|
||||||
<MenuToggle
|
|
||||||
value={ options[option].value }
|
|
||||||
onChange={() => {console.log(options[option]);
|
|
||||||
updateOptions({ [option]: !(options[option].value)}) }}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</MenuToggle>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionsToggle = connect(
|
|
||||||
state => ({
|
|
||||||
options: state.options,
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
updateOptions,
|
|
||||||
}
|
|
||||||
)(OptionsToggle)
|
|
Loading…
Reference in New Issue
Block a user