Skip to content

Commit

Permalink
Merge pull request #414 from dls-controls/feature/linkTheming
Browse files Browse the repository at this point in the history
Feature/link theming
  • Loading branch information
blondejamtart authored Oct 15, 2018
2 parents 27ef222 + e8311a2 commit 7396e40
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 41 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
# Changelog
## 1.3.0 (15/10/2018)
Features:
- Hidden links are now clickable/selectable/deletable in the same way normal links are.
- Added saved configuration for generating canned data from PandA simulator
- Minor style tweaks

Fixes:
- Errors from malcolm regarding the layout attribute no longer overwrite the subscription ID and cause a crash.
- Orphaned attributes now get hidden as soon as the block meta is updated to orphan them (n.b. this bug still exists for orphaned group expanders).
- Selected blocks/links state now reset properly when swapping between multiple layout attributes.
- Navigating to a layout via the nav bar now fires the necessary subscription requests.
- Highlighting text and dragging & dropping onto the layout no longer causes a crash.

## 1.2.0 (8/10/2018)
Features:
- Table widget swapped for react-virtualized based component for improved performance and styling
Expand Down
10 changes: 1 addition & 9 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ body {
}
}

.srd-default-link--hover-path {
stroke: #ffffffa6 !important;
}

.srd-default-link--highlight-path {
stroke: #f50057 !important;
}

:-moz-focusring {
color: white !important;
color: inherit !important;
}
66 changes: 66 additions & 0 deletions src/layout/__snapshots__/layout.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,72 @@ exports[`Layout renders correctly 1`] = `
"portMouseDown": [Function],
"routingMatrix": Array [],
"selectedHandler": [Function],
"theme": Object {
"palette": Object {
"action": Object {
"active": "rgba(0, 0, 0, 0.54)",
"disabled": "rgba(0, 0, 0, 0.26)",
"disabledBackground": "rgba(0, 0, 0, 0.12)",
"hover": "rgba(0, 0, 0, 0.08)",
"hoverOpacity": 0.08,
"selected": "rgba(0, 0, 0, 0.14)",
},
"augmentColor": [Function],
"background": Object {
"default": "#fafafa",
"paper": "#fff",
},
"common": Object {
"black": "#000",
"white": "#fff",
},
"contrastThreshold": 3,
"divider": "rgba(0, 0, 0, 0.12)",
"error": Object {
"contrastText": "#fff",
"dark": "#d32f2f",
"light": "#e57373",
"main": "#f44336",
},
"getContrastText": [Function],
"grey": Object {
"100": "#f5f5f5",
"200": "#eeeeee",
"300": "#e0e0e0",
"400": "#bdbdbd",
"50": "#fafafa",
"500": "#9e9e9e",
"600": "#757575",
"700": "#616161",
"800": "#424242",
"900": "#212121",
"A100": "#d5d5d5",
"A200": "#aaaaaa",
"A400": "#303030",
"A700": "#616161",
},
"primary": Object {
"contrastText": "#fff",
"dark": "#303f9f",
"light": "#7986cb",
"main": "#3f51b5",
},
"secondary": Object {
"contrastText": "#fff",
"dark": "#c51162",
"light": "#ff4081",
"main": "#f50057",
},
"text": Object {
"disabled": "rgba(0, 0, 0, 0.38)",
"hint": "rgba(0, 0, 0, 0.38)",
"primary": "rgba(0, 0, 0, 0.87)",
"secondary": "rgba(0, 0, 0, 0.54)",
},
"tonalOffset": 0.2,
"type": "light",
},
},
"vAdjustmentFactor": 0,
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/layout/blockPort/blockPortWidget.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ class BlockPortWidget extends BaseWidget {
role="presentation"
style={{ maxWidth: '1px', paddingLeft: '4px' }}
>
<div className={this.props.classes.port} />
<div
className={this.props.classes.port}
style={{ maxWidth: '1px' }}
/>
</div>
) : (
<div
Expand Down
23 changes: 15 additions & 8 deletions src/layout/layout.component.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withTheme } from '@material-ui/core/styles';
import { DiagramWidget } from 'storm-react-diagrams';
import navigationActions from '../malcolm/actions/navigation.actions';
import {
Expand Down Expand Up @@ -52,6 +53,7 @@ class Layout extends React.Component {
this.props.layoutEngine.mouseDownHandler = this.props.mouseDownHandler;
this.props.layoutEngine.portMouseDown = this.props.portMouseDown;
this.props.layoutEngine.linkClickHandler = this.props.linkClickHandler;
this.props.layoutEngine.theme.palette = this.props.theme.palette;
return (
<div
id="LayoutDiv"
Expand Down Expand Up @@ -109,6 +111,9 @@ Layout.propTypes = {
portMouseDown: PropTypes.func,
mouseDownHandler: PropTypes.func,
linkClickHandler: PropTypes.func,
theme: PropTypes.shape({
palette: PropTypes.shape({}),
}),
}).isRequired,
selectHandler: PropTypes.func.isRequired,
clickHandler: PropTypes.func.isRequired,
Expand All @@ -119,6 +124,9 @@ Layout.propTypes = {
linkClickHandler: PropTypes.func.isRequired,
layoutClickHandler: PropTypes.func.isRequired,
locked: PropTypes.bool.isRequired,
theme: PropTypes.shape({
palette: PropTypes.shape({}),
}).isRequired,
};

export const mapStateToProps = state => ({
Expand Down Expand Up @@ -237,13 +245,10 @@ export const mapDispatchToProps = dispatch => ({
makeBlockVisible: (event, engine) => {
const blockMri = event.dataTransfer.getData('storm-diagram-node');
const position = engine.getRelativeMousePoint(event);
// Other items can be dropped onto the layout;
// prevent them from triggering the dispatch
if (blockMri !== '') {
dispatch(layoutAction.makeBlockVisible(blockMri, position));
// close the palette after an item is dropped on to the layout
dispatch(navigationActions.updateChildPanel(''));
}
dispatch(layoutAction.makeBlockVisible(blockMri, position));

// close the palette after an item is dropped on to the layout
dispatch(navigationActions.updateChildPanel(''));
},

deleteSelected: () => {
Expand All @@ -252,4 +257,6 @@ export const mapDispatchToProps = dispatch => ({
},
});

export default connect(mapStateToProps, mapDispatchToProps)(Layout);
export default connect(mapStateToProps, mapDispatchToProps)(
withTheme()(Layout)
);
14 changes: 7 additions & 7 deletions src/layout/layout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,24 @@ describe('Layout', () => {
},
},
};
state.malcolm.layoutEngine.theme = {};
});

it('renders correctly', () => {
const wrapper = shallow(<Layout store={mockStore(state)} />);
expect(wrapper).toMatchSnapshot();
expect(wrapper.dive()).toMatchSnapshot();
});

it('onFocus sets hasFocus state to true', () => {
state.malcolm.layoutState.selectedBlocks = ['PANDA:SEQ1'];
const wrapper = shallow(<Layout store={mockStore(state)} />);
expect(wrapper.state()).toEqual({ hasFocus: false });
const wrapper = shallow(<Layout store={mockStore(state)} />).dive();
wrapper.find('#LayoutDiv').simulate('focus');
expect(wrapper.state()).toEqual({ hasFocus: true });
});

it('onBlur sets hasFocus state to false', () => {
state.malcolm.layoutState.selectedBlocks = ['PANDA:SEQ1'];
const wrapper = shallow(<Layout store={mockStore(state)} />);
const wrapper = shallow(<Layout store={mockStore(state)} />).dive();
expect(wrapper.state()).toEqual({ hasFocus: false });
wrapper.setState({ hasFocus: true });
expect(wrapper.state()).toEqual({ hasFocus: true });
Expand All @@ -114,7 +114,7 @@ describe('Layout', () => {

it('delete key sends delete block action if layout has focus', () => {
state.malcolm.layoutState.selectedBlocks = ['PANDA:SEQ1'];
const wrapper = shallow(<Layout store={mockStore(state)} />);
const wrapper = shallow(<Layout store={mockStore(state)} />).dive();
wrapper.setState({ hasFocus: true });
wrapper.find('#LayoutDiv').simulate('keyup', { key: 'Delete' });
expect(layoutActions.deleteBlocks).toHaveBeenCalled();
Expand All @@ -123,7 +123,7 @@ describe('Layout', () => {

it('backspace key sends delete block action if layout has focus', () => {
state.malcolm.layoutState.selectedBlocks = ['PANDA:SEQ1'];
const wrapper = shallow(<Layout store={mockStore(state)} />);
const wrapper = shallow(<Layout store={mockStore(state)} />).dive();
wrapper.setState({ hasFocus: true });
wrapper.find('#LayoutDiv').simulate('keyup', { key: 'Backspace' });

Expand All @@ -133,7 +133,7 @@ describe('Layout', () => {

it('delete key doesnt send delete block action if layout doesnt have focus', () => {
state.malcolm.layoutState.selectedBlocks = ['PANDA:SEQ1'];
const wrapper = shallow(<Layout store={mockStore(state)} />);
const wrapper = shallow(<Layout store={mockStore(state)} />).dive();
wrapper.setState({ hasFocus: false });
wrapper.find('#LayoutDiv').simulate('keyup', { key: 'Delete' });
expect(layoutActions.deleteBlocks).not.toHaveBeenCalled();
Expand Down
6 changes: 2 additions & 4 deletions src/layout/link/__snapshots__/link.factory.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,19 @@ exports[`LinkFactory generates react widget 1`] = `
key="link-0"
>
<path
className="srd-default-link--highlight-path "
d="M 0,0 C 50,0 50,0 100,0"
onClick={[Function]}
stroke="rgba(255,255,255,0.5)"
stroke="rgba(217, 217, 217, 0.4)"
strokeWidth={3}
/>
<path
className="srd-default-link--highlight-path "
d="M 0,0 C 50,0 50,0 100,0"
data-linkid="1"
data-point={0}
onClick={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
stroke="rgba(255,255,255,0.5)"
stroke="rgba(217, 217, 217, 0.4)"
strokeLinecap="round"
strokeOpacity={0}
strokeWidth={20}
Expand Down
23 changes: 15 additions & 8 deletions src/layout/link/link.factory.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import React from 'react';
import { DefaultLinkFactory } from 'storm-react-diagrams';
import { emphasize, fade } from '@material-ui/core/styles/colorManipulator';
import { green } from '@material-ui/core/colors';
import MalcolmLinkModel from './link.model';
import MalcolmAutoLinkSegment from './autoLinkSegment';

const findHightlightClass = (model, widget, selected, hovering) => {
if (selected || !model.targetPort) {
return widget.bem('--highlight-path');
}
return hovering ? widget.bem('--hover-path') : '';
};
/* eslint class-methods-use-this: ["error", { "exceptMethods": ["generateReactWidget", "getNewInstance", "generateLinkSegment"] }] */
class MalcolmLinkFactory extends DefaultLinkFactory {
constructor() {
Expand All @@ -28,11 +24,22 @@ class MalcolmLinkFactory extends DefaultLinkFactory {
}

generateLinkSegment(model, widget, selected, hovering, path) {
let strokeColor;
if (model.theme) {
strokeColor = selected
? model.theme.palette.secondary.main
: fade(emphasize(model.theme.palette.background.default, 0.8), 0.4);
} else {
// This is a link which is currently being made
// TODO: this color should be taken from the theme directly,
// but the link doesn't know about the theme until
// it has been created
strokeColor = green.A400;
}
return (
<path
className={findHightlightClass(model, widget, selected, hovering)}
strokeWidth={model.width}
stroke={model.color}
stroke={strokeColor}
strokeDasharray={
model.sourcePort.portType === 'HIDDEN' ? '8' : undefined
}
Expand Down
6 changes: 6 additions & 0 deletions src/layout/link/link.factory.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ describe('LinkFactory', () => {
link.sourcePort = {
in: false,
};
link.theme = {
palette: {
background: { default: '#424242' },
secondary: { main: '#ff0000' },
},
};

const engine = new DiagramEngine();
engine.nodesRendered = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports[`MalcolmMiddlePanel renders alarmed correctly 1`] = `
<div
className="MiddlePanelContainer-layoutArea-2"
>
<Connect(Layout) />
<Connect(WithTheme(Layout)) />
<div
className="MiddlePanelContainer-alarm-3"
style={
Expand Down Expand Up @@ -109,7 +109,7 @@ exports[`MalcolmMiddlePanel renders errored correctly 1`] = `
<div
className="MiddlePanelContainer-layoutArea-2"
>
<Connect(Layout) />
<Connect(WithTheme(Layout)) />
<div
className="MiddlePanelContainer-alarm-3"
style={
Expand Down Expand Up @@ -171,7 +171,7 @@ exports[`MalcolmMiddlePanel renders layout correctly 1`] = `
<div
className="MiddlePanelContainer-layoutArea-2"
>
<Connect(Layout) />
<Connect(WithTheme(Layout)) />
<div
className="MiddlePanelContainer-alarm-3"
style={
Expand Down Expand Up @@ -233,7 +233,7 @@ exports[`MalcolmMiddlePanel renders pending correctly 1`] = `
<div
className="MiddlePanelContainer-layoutArea-2"
>
<Connect(Layout) />
<Connect(WithTheme(Layout)) />
<div
className="MiddlePanelContainer-alarm-3"
style={
Expand Down
2 changes: 2 additions & 0 deletions src/malcolm/reducer/layout/layoutEngine.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const buildLayoutEngine = (
engine.clickHandler = () => {};
engine.mouseDownHandler = () => {};
engine.linkClickHandler = () => {};
engine.theme = {};

const nodes = layout.blocks.map(b =>
buildBlockNode(
Expand Down Expand Up @@ -86,6 +87,7 @@ export const buildLayoutEngine = (
newLink.selected = selectedLinks.some(
linkId => linkId === newLink.id
);
newLink.theme = engine.theme;
newLink.clickHandler = linkId => {
engine.linkClickHandler(linkId);
};
Expand Down

0 comments on commit 7396e40

Please sign in to comment.