This commit is contained in:
futpib 2018-11-22 17:12:53 +03:00
parent f0eec6fbdc
commit 558f0b37e1
10 changed files with 212 additions and 2 deletions

View File

@ -6,5 +6,7 @@ module.exports = createActionCreators({
SET: null,
TOGGLE: null,
RESET_DEFAULTS: null,
SET_ADD: (key, value) => ({ key, value }),
SET_DELETE: (key, value) => ({ key, value }),
},
});

View File

@ -46,5 +46,8 @@ module.exports = createActionCreators({
SET_DEFAULT_SINK_BY_NAME: name => ({ name }),
SET_DEFAULT_SOURCE_BY_NAME: name => ({ name }),
REMOTE_SERVER_CONNECT: null,
REMOTE_SERVER_DISCONNECT: null,
},
});

View File

@ -290,6 +290,10 @@ class Node extends NodeBase {
}
EdgeBase.calculateOffset = function (nodeSize, source, target) {
// if (!source || !target) {
// return this.getDefaultIntersectResponse();
// }
const arrowVector = math.matrix([ target.x - source.x, target.y - source.y ]);
const offsetLength = Math.max(0, Math.min((0.75 * size), (math.norm(arrowVector) / 2) - 40));
const offsetVector = math.dotMultiply(arrowVector, (offsetLength / math.norm(arrowVector)) || 0);

View File

@ -0,0 +1,83 @@
const r = require('r-dom');
const React = require('react');
const { connect } = require('react-redux');
const { bindActionCreators } = require('redux');
const Modal = require('react-modal');
const Button = require('../button');
const Label = require('../label');
const Input = require('../input');
const {
preferences: preferencesActions,
} = require('../../actions');
class AddRemoteServerModal extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
address: 'tcp:remote-computer.lan',
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const { address } = this.state;
this.props.setAdd('remoteServerAddresses', address);
this.props.onRequestClose();
}
render() {
const { isOpen, onRequestClose } = this.props;
return r(Modal, {
isOpen,
onRequestClose,
}, [
r.h3('Add remote server'),
r.form({
onSubmit: this.handleSubmit,
}, [
r(Label, {
title: 'PULSE_SERVER syntax',
}, [
r.div('Server address:'),
r.p([
r(Input, {
style: { width: '100%' },
autoFocus: true,
value: this.state.address,
onChange: e => this.setState({ address: e.target.value }),
}),
]),
]),
r.div({
className: 'button-group',
}, [
r(Button, {
onClick: onRequestClose,
}, 'Cancel'),
r(Button, {
type: 'submit',
}, 'Confirm'),
]),
]),
]);
}
}
module.exports = connect(
null,
dispatch => bindActionCreators(preferencesActions, dispatch),
)(AddRemoteServerModal);

View File

@ -30,6 +30,7 @@ const ConnectToServerModal = require('./connect-to-server');
const ConfirmationModal = require('./confirmation');
const NewGraphObjectModal = require('./new-graph-object');
const LoadModuleModal = require('./load-module');
const AddRemoteServerModal = require('./add-remote-server-modal');
Modal.setAppElement('#root');
@ -50,6 +51,7 @@ class Modals extends React.PureComponent {
connectToServerModalOpen: false,
newGraphObjectModalOpen: false,
loadModuleModalOpen: false,
addRemoteServerModalOpen: false,
modalDefaults: undefined,
@ -58,6 +60,7 @@ class Modals extends React.PureComponent {
openNewGraphObjectModal: this.openNewGraphObjectModal.bind(this),
openLoadModuleModal: this.openLoadModuleModal.bind(this),
openAddRemoteServerModal: this.openAddRemoteServerModal.bind(this),
},
};
this.state = this.initialState;
@ -117,6 +120,10 @@ class Modals extends React.PureComponent {
});
}
openAddRemoteServerModal() {
this.setState({ addRemoteServerModalOpen: true });
}
handleCancel() {
this.setState(this.initialState);
}
@ -156,6 +163,11 @@ class Modals extends React.PureComponent {
defaults: this.state.modalDefaults,
}),
r(AddRemoteServerModal, {
isOpen: this.state.addRemoteServerModalOpen,
onRequestClose: this.handleCancel,
}),
]);
}
}

View File

@ -7,6 +7,8 @@ const {
propEq,
sortBy,
prop,
merge,
keys,
} = require('ramda');
const React = require('react');
@ -16,12 +18,66 @@ const r = require('r-dom');
const { connect } = require('react-redux');
const { bindActionCreators } = require('redux');
const { pulse: pulseActions } = require('../../actions');
const {
pulse: pulseActions,
preferences: preferencesActions,
} = require('../../actions');
const { formatModuleArgs } = require('../../utils/module-args');
const { getRemoteServerByAddress } = require('../../selectors');
const Button = require('../button');
const Label = require('../label');
const RemoteServer = connect(
(state, props) => ({
remoteServer: getRemoteServerByAddress(props.address)(state),
}),
dispatch => ({
actions: bindActionCreators(merge(pulseActions, preferencesActions), dispatch),
}),
)(({ address, remoteServer = {}, actions }) => {
const { targetState, state } = remoteServer;
const hostname = path([ 'serverInfo', 'hostname' ], remoteServer);
return r.div([
r.div({
style: { display: 'flex', justifyContent: 'space-between' },
}, [
r(Label, {
userSelect: true,
}, [
hostname || address,
]),
targetState === 'ready' ? r(Button, {
onClick: () => {
actions.remoteServerDisconnect(address);
},
}, 'Disconnect') : r(React.Fragment, [
r(Button, {
onClick: () => {
actions.remoteServerDisconnect(address);
actions.setDelete('remoteServerAddresses', address);
},
}, 'Forget'),
r(Button, {
onClick: () => {
actions.remoteServerConnect(address);
},
}, 'Connect'),
]),
]),
state === 'ready' ? r(React.Fragment, [
// TODO
]) : targetState === 'ready' ? r(Label, [
'Connecting...',
]) : null,
]);
});
class Cards extends React.Component {
constructor(props) {
super(props);
@ -52,6 +108,8 @@ class Cards extends React.Component {
values(this.props.modules),
));
const remoteServerAddresses = keys(this.props.preferences.remoteServerAddresses);
return r.div({
classSet: {
panel: true,
@ -123,6 +181,24 @@ class Cards extends React.Component {
},
}, 'Allow incoming connections...'),
r.hr(),
remoteServerAddresses.length > 0 ? r(React.Fragment, [
r(Label, [
'Remote servers:',
]),
...map(address => r(RemoteServer, { address }), remoteServerAddresses),
]) : r(Label, [
'No known servers',
]),
r(Button, {
onClick: () => {
this.props.openAddRemoteServerModal();
},
}, 'Add a server...'),
this.props.preferences.showDebugInfo && r.pre({
style: {
fontSize: '0.75em',

View File

@ -20,6 +20,8 @@ div[tabindex="-1"]:focus {
user-select: none;
padding: 8px;
cursor: pointer;
}
.button:hover {
@ -37,6 +39,11 @@ div[tabindex="-1"]:focus {
top: 1px;
}
.button:disabled {
border-color: var(--unfocusedBorders);
cursor: not-allowed;
}
.button-group {
display: flex;
justify-content: space-between;

View File

@ -1,6 +1,10 @@
const {
merge,
over,
lensProp,
not,
omit,
} = require('ramda');
const { handleActions } = require('redux-actions');
@ -27,11 +31,17 @@ const initialState = {
doNotAskForConfirmations: false,
showDebugInfo: false,
remoteServerAddresses: {},
};
const reducer = handleActions({
[preferences.set]: (state, { payload }) => merge(state, payload),
[preferences.toggle]: (state, { payload }) => merge(state, { [payload]: !state[payload] }),
[preferences.toggle]: (state, { payload }) => over(lensProp(payload), not, state),
[preferences.setAdd]: (state, { payload: { key, value } }) => over(lensProp(key), merge({ [value]: true }), state),
[preferences.setDelete]: (state, { payload: { key, value } }) => over(lensProp(key), omit([ value ]), state),
[preferences.resetDefaults]: () => initialState,
}, initialState);

View File

@ -8,6 +8,8 @@ const {
pick,
equals,
takeLast,
over,
lensPath,
} = require('ramda');
const { combineReducers } = require('redux');
@ -27,6 +29,8 @@ const initialState = {
infos: fromPairs(map(({ key }) => [ key, {} ], things)),
log: { items: [] },
remoteServers: {},
};
const logMaxItems = 3;
@ -127,6 +131,11 @@ const reducer = combineReducers({
})),
}, initialState.log.items),
}),
remoteServers: handleActions({
[pulse.remoteServerConnect]: (state, { payload }) => over(lensPath([ payload, 'targetState' ]), always('ready'), state),
[pulse.remoteServerDisconnect]: (state, { payload }) => over(lensPath([ payload, 'targetState' ]), always('closed'), state),
}, initialState.remoteServers),
});
module.exports = {

View File

@ -66,6 +66,8 @@ const getDefaultSinkPai = createSelector(
(sinks, defaultSinkName) => find(propEq('name', defaultSinkName), values(sinks)),
);
const getRemoteServerByAddress = address => state => state.pulse.remoteServers[address];
module.exports = {
getPaiByTypeAndIndex,
getDerivedMonitorSources,
@ -80,4 +82,6 @@ module.exports = {
getDefaultSinkPai,
getDefaultSourcePai,
getRemoteServerByAddress,
};