style(config): external controller config modal style tweak
This commit is contained in:
parent
b6da06c4ff
commit
9517d02996
8 changed files with 58 additions and 24 deletions
|
@ -58,7 +58,7 @@ function APIConfig2() {
|
||||||
tabIndex="1"
|
tabIndex="1"
|
||||||
onKeyDown={handleContentOnKeyDown}
|
onKeyDown={handleContentOnKeyDown}
|
||||||
>
|
>
|
||||||
<div className={s0.header}>RESTful API config for Clash</div>
|
<div className={s0.header}>Clash External Controller Config</div>
|
||||||
<div className={s0.body}>
|
<div className={s0.body}>
|
||||||
<div className={s0.group}>
|
<div className={s0.group}>
|
||||||
<div className={s0.label}>Hostname and Port</div>
|
<div className={s0.label}>Hostname and Port</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
.inputs {
|
.inputs {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
div:nth-child(2) {
|
input:nth-child(2) {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ import APIConfig from 'c/APIConfig';
|
||||||
import { closeModal } from 'd/modals';
|
import { closeModal } from 'd/modals';
|
||||||
import { fetchConfigs } from 'd/configs';
|
import { fetchConfigs } from 'd/configs';
|
||||||
|
|
||||||
|
import s0 from './APIDiscovery.module.scss';
|
||||||
|
|
||||||
const mapStateToProps = s => ({
|
const mapStateToProps = s => ({
|
||||||
modals: s.modals
|
modals: s.modals
|
||||||
});
|
});
|
||||||
|
@ -26,6 +28,8 @@ export default function APIDiscovery() {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={modals.apiConfig}
|
isOpen={modals.apiConfig}
|
||||||
|
className={s0.content}
|
||||||
|
overlayClassName={s0.overlay}
|
||||||
shouldCloseOnOverlayClick={false}
|
shouldCloseOnOverlayClick={false}
|
||||||
shouldCloseOnEsc={false}
|
shouldCloseOnEsc={false}
|
||||||
onRequestClose={() => closeModal('apiConfig')}
|
onRequestClose={() => closeModal('apiConfig')}
|
||||||
|
|
7
src/components/APIDiscovery.module.scss
Normal file
7
src/components/APIDiscovery.module.scss
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
.content {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
background: #222;
|
||||||
|
}
|
|
@ -1,12 +1,15 @@
|
||||||
.btn {
|
.btn {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: #ddd;
|
color: #bebebe;
|
||||||
background: #606060;
|
background: #232323;
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: darken(#555, 3%);
|
background: #387cec;
|
||||||
|
border: 1px solid #387cec;
|
||||||
|
color: #fff;
|
||||||
|
// background: darken(#555, 3%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,26 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
|
import cx from 'classnames';
|
||||||
|
|
||||||
import s0 from './Modal.module.scss';
|
import s0 from './Modal.module.scss';
|
||||||
|
|
||||||
function ModalAPIConfig({ isOpen, onRequestClose, children, ...otherProps }) {
|
function ModalAPIConfig({
|
||||||
|
isOpen,
|
||||||
|
onRequestClose,
|
||||||
|
className,
|
||||||
|
overlayClassName,
|
||||||
|
children,
|
||||||
|
...otherProps
|
||||||
|
}) {
|
||||||
|
const contentCls = cx(className, s0.content);
|
||||||
|
const overlayCls = cx(overlayClassName, s0.overlay);
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onRequestClose={onRequestClose}
|
onRequestClose={onRequestClose}
|
||||||
contentLabel="API-Config"
|
className={contentCls}
|
||||||
className={s0.content}
|
overlayClassName={overlayCls}
|
||||||
overlayClassName={s0.overlay}
|
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -22,7 +31,9 @@ function ModalAPIConfig({ isOpen, onRequestClose, children, ...otherProps }) {
|
||||||
ModalAPIConfig.propTypes = {
|
ModalAPIConfig.propTypes = {
|
||||||
isOpen: PropTypes.bool.isRequired,
|
isOpen: PropTypes.bool.isRequired,
|
||||||
onRequestClose: PropTypes.func.isRequired,
|
onRequestClose: PropTypes.func.isRequired,
|
||||||
children: PropTypes.node.isRequired
|
children: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
overlayClassName: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default React.memo(ModalAPIConfig);
|
export default React.memo(ModalAPIConfig);
|
||||||
|
|
|
@ -61,8 +61,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica,
|
||||||
'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
|
Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol,
|
||||||
|
'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,13 @@ import { openModal } from 'd/modals';
|
||||||
import * as trafficAPI from 'a/traffic';
|
import * as trafficAPI from 'a/traffic';
|
||||||
|
|
||||||
const CompletedFetchConfigs = 'configs/CompletedFetchConfigs';
|
const CompletedFetchConfigs = 'configs/CompletedFetchConfigs';
|
||||||
const OptimisticUpdateConfigs = 'proxies/OptimisticUpdateConfigs';
|
const OptimisticUpdateConfigs = 'configs/OptimisticUpdateConfigs';
|
||||||
|
const MarkHaveFetchedConfig = 'configs/MarkHaveFetchedConfig';
|
||||||
|
|
||||||
export const getConfigs = s => s.configs;
|
export const getConfigs = s => s.configs;
|
||||||
|
|
||||||
// maybe we should put this flag in the redux store
|
|
||||||
// but since is not related a UI element and only make sense to this chunk
|
|
||||||
// of code, I'm going to leave it here
|
|
||||||
let successfullyFetchedConfigsBefore = false;
|
|
||||||
export function fetchConfigs() {
|
export function fetchConfigs() {
|
||||||
return async dispatch => {
|
return async (dispatch, getState) => {
|
||||||
let res;
|
let res;
|
||||||
try {
|
try {
|
||||||
res = await configsAPI.fetchConfigs();
|
res = await configsAPI.fetchConfigs();
|
||||||
|
@ -41,13 +38,24 @@ export function fetchConfigs() {
|
||||||
payload
|
payload
|
||||||
});
|
});
|
||||||
|
|
||||||
// side effect
|
const configsCurr = getConfigs(getState());
|
||||||
if (successfullyFetchedConfigsBefore === false) {
|
|
||||||
successfullyFetchedConfigsBefore = true;
|
if (configsCurr.haveFetchedConfig) {
|
||||||
// normally user will land on the "traffic chart" page first
|
// normally user will land on the "traffic chart" page first
|
||||||
// calling this here will let the data start streaming
|
// calling this here will let the data start streaming
|
||||||
// the traffic chart should already subscribed to the streaming
|
// the traffic chart should already subscribed to the streaming
|
||||||
trafficAPI.fetchData();
|
trafficAPI.fetchData();
|
||||||
|
} else {
|
||||||
|
dispatch(markHaveFetchedConfig());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function markHaveFetchedConfig() {
|
||||||
|
return {
|
||||||
|
type: MarkHaveFetchedConfig,
|
||||||
|
payload: {
|
||||||
|
haveFetchedConfig: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -91,15 +99,15 @@ const initialState = {
|
||||||
'redir-port': 0,
|
'redir-port': 0,
|
||||||
'allow-lan': false,
|
'allow-lan': false,
|
||||||
mode: 'Rule',
|
mode: 'Rule',
|
||||||
'log-level': 'info'
|
'log-level': 'info',
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
haveFetchedConfig: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function reducer(state = initialState, { type, payload }) {
|
export default function reducer(state = initialState, { type, payload }) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// case CompletedRequestDelayForProxy:
|
case MarkHaveFetchedConfig:
|
||||||
// case OptimisticSwitchProxy:
|
|
||||||
case OptimisticUpdateConfigs:
|
case OptimisticUpdateConfigs:
|
||||||
case CompletedFetchConfigs: {
|
case CompletedFetchConfigs: {
|
||||||
return { ...state, ...payload };
|
return { ...state, ...payload };
|
||||||
|
|
Loading…
Reference in a new issue