Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KED-1650] New graphing algorithm & feature flags #185

Merged
merged 43 commits into from
Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a6fd8e0
Remove unnecessary null props
richardwestenra Apr 30, 2020
00bf444
Don't use a button for node-list-row when !onClick
richardwestenra Apr 30, 2020
61f470a
Remove unused modifier classes
richardwestenra Apr 30, 2020
52012c1
Add --button modifier class for row hover state
richardwestenra Apr 30, 2020
f65734a
Combine duplicate classes and remove unused
richardwestenra Apr 30, 2020
4dadbe6
Add new selected node state
richardwestenra Apr 30, 2020
62ffcca
Improve consistency of row transitions
richardwestenra Apr 30, 2020
3414bad
Prevent a node being selected when disabled
richardwestenra Apr 30, 2020
be6ac2c
Remove node clicked state when disabled
richardwestenra Apr 30, 2020
9cde1f9
Fix node-list-row button styling
richardwestenra Apr 30, 2020
9eaacd7
Use disabled button instead of text
richardwestenra Apr 30, 2020
6cae100
Fix icon opacity when disabled
richardwestenra Apr 30, 2020
91a14bf
Fix tests
richardwestenra Apr 30, 2020
9eff809
Add a new test for TOGGLE_NODES_DISABLED reducer
richardwestenra Apr 30, 2020
4f99a6d
Fix node-list hover/selected bg colours
richardwestenra May 1, 2020
899c97f
[KED-989] Added new graphing approach concept
bru5 May 6, 2020
d0ed892
[KED-1650] Refactor and tidy graph code
bru5 May 7, 2020
2791c80
Merge branch 'develop' into feature/graph-concept
bru5 May 12, 2020
3aba5d3
[KED-1650] Improve graph concept
bru5 May 14, 2020
3a44d15
[KED-1650] Refactor graph concept
bru5 May 18, 2020
bceb5fc
[KED-1650] Refactor graph concept
bru5 May 19, 2020
4f85def
[KED-1698] Add layers to graph concept and improve layout
bru5 May 22, 2020
788bcba
[KED-1697] Added feature flags with flag for graph concept
bru5 May 22, 2020
09964c1
Merge branch 'develop' into feature/graph-concept
bru5 May 22, 2020
748aa94
[KED-1650] Refactoring, add comments and docs
bru5 May 27, 2020
2c711e2
[KED-1650] Added tests and some refactoring
bru5 Jun 1, 2020
a9eba5c
Merge branch 'develop' into feature/graph-concept
bru5 Jun 4, 2020
4ecf994
[KED-1650] Fix exception object
bru5 Jun 4, 2020
29eba7d
[KED-1698] Fix layer constraints
bru5 Jun 16, 2020
da956ef
[KED-1650] Change flags URL format
bru5 Jun 16, 2020
0ad21eb
[KED-1650] Refactor and simplify
bru5 Jun 16, 2020
e170d88
[KED-1650] Improve code clarity
bru5 Jun 16, 2020
671938b
[KED-1650] Add empty value for flags
bru5 Jun 17, 2020
83bfe09
[KED-1650] Improve routing
bru5 Jun 18, 2020
95a1e15
[KED-1698] Fix layer solving
bru5 Jun 19, 2020
3fac281
[KED-1650] Update readme with flags
bru5 Jun 19, 2020
c154833
[KED-1650] Update license info
bru5 Jun 19, 2020
b38bb3f
Merge branch 'develop' into feature/graph-concept
bru5 Jun 19, 2020
d1d12dd
[KED-1650] Update readme
bru5 Jun 22, 2020
c6c66c6
[KED-1650] Update license info
bru5 Jun 22, 2020
f92d68f
[KED-1650] Update license info
bru5 Jun 23, 2020
75c6302
[KED-1650] Update readme
bru5 Jun 23, 2020
5b8f4e5
[KED-1650] Improve clarity
bru5 Jun 23, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions COPYING.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
=========================
The Kiwi licensing terms
=========================
Kiwi is licensed under the terms of the Modified BSD License (also known as
New or Revised BSD), as follows:

Copyright (c) 2013, Nucleic Development Team

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

Neither the name of the Nucleic Development Team nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

About Kiwi
----------
Chris Colbert began the Kiwi project in December 2013 in an effort to
create a blisteringly fast UI constraint solver. Chris is still the
project lead.

The Nucleic Development Team is the set of all contributors to the Nucleic
project and its subprojects.

The core team that coordinates development on GitHub can be found here:
http://github.com/nucleic. The current team consists of:

* Chris Colbert

Our Copyright Policy
--------------------
Nucleic uses a shared copyright model. Each contributor maintains copyright
over their contributions to Nucleic. But, it is important to note that these
contributions are typically only changes to the repositories. Thus, the Nucleic
source code, in its entirety is not the copyright of any single person or
institution. Instead, it is the collective copyright of the entire Nucleic
Development Team. If individual contributors want to maintain a record of what
changes/contributions they have specific copyright on, they should indicate
their copyright in the commit message of the change, when they commit the
change to one of the Nucleic repositories.

With this in mind, the following banner should be used in any source code file
to indicate the copyright and license terms:

#------------------------------------------------------------------------------
# Copyright (c) 2013, Nucleic Development Team & H. Rutjes.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ As a JavaScript React component, the project is designed to be used in two diffe

The React component exposes props that can be used to supply data and customise its behaviour. For information about the props, their expected prop-types and default values, see [/src/components/app/index.js](https://github.com/quantumblacklabs/kedro-viz/blob/master/src/components/app/index.js). For examples of the expected data input format, see the mock data examples in [/src/utils/data](https://github.com/quantumblacklabs/kedro-viz/tree/master/src/utils/data), and compare the [resulting demo](https://quantumblacklabs.github.io/kedro-viz/).

## Flags

The following flags are available in the latest release to toggle experimental features:

- `newgraph` - Improved graphing algorithm (default `false`).

### Setting flags

To enable or disable a flagged feature, add the flag as a parameter with the value `true` or `false` to the end of the URL in your browser when running Kedro-Viz, e.g.

`http://localhost:4141/?data=demo&newgraph=true`

This provided setting will then persist for all sessions on your machine, until it is otherwise changed.

### Viewing flags

See the message in your browser's console for info regarding the available flags and their values as currently set on your machine.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow this. What message? What console?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reworded with some extra information including a link to a Mozilla article explaining the developer console, does that help?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does. So much better 🚀


## What licence do you use?

Kedro-Viz is licensed under the [Apache 2.0](https://github.com/quantumblacklabs/kedro-viz/blob/master/LICENSE.md) License.
Expand Down
8 changes: 8 additions & 0 deletions legal_header.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@
#
# See the License for the specific language governing permissions and
# limitations under the License.

#------------------------------------------------------------------------------
# Copyright (c) 2013, Nucleic Development Team & H. Rutjes.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"d3-transition": "^1.2.0",
"d3-zoom": "^1.7.3",
"dagre": "git+https://github.com/richardwestenra/dagre.git#manual-ranking",
"kiwi.js": "^1.1.2",
"konami-code": "^0.2.1",
"react-custom-scrollbars": "^4.2.1",
"react-flip-toolkit": "^7.0.7",
Expand Down
11 changes: 11 additions & 0 deletions src/actions/actions.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import animals from '../utils/data/animals.mock';
import {
CHANGE_FLAG,
RESET_DATA,
TOGGLE_LAYERS,
TOGGLE_EXPORT_MODAL,
Expand All @@ -8,6 +9,7 @@ import {
TOGGLE_THEME,
UPDATE_CHART_SIZE,
UPDATE_FONT_LOADED,
changeFlag,
resetData,
toggleLayers,
toggleExportModal,
Expand Down Expand Up @@ -174,4 +176,13 @@ describe('actions', () => {
};
expect(updateFontLoaded(fontLoaded)).toEqual(expectedAction);
});

it('should create an action to change a flag', () => {
const expectedAction = {
type: CHANGE_FLAG,
name: 'testFlag',
value: true
};
expect(changeFlag('testFlag', true)).toEqual(expectedAction);
});
});
15 changes: 15 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,18 @@ export function updateFontLoaded(fontLoaded) {
fontLoaded
};
}

export const CHANGE_FLAG = 'CHANGE_FLAG';

/**
* Change the given feature flag
* @param {string} name The flag name
* @param {value} value The value to set
*/
export function changeFlag(name, value) {
return {
type: CHANGE_FLAG,
name,
value
};
}
9 changes: 9 additions & 0 deletions src/components/app/app.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import App from './index';
import getRandomPipeline from '../../utils/random-data';
import animals from '../../utils/data/animals.mock';
import loremIpsum from '../../utils/data/lorem-ipsum.mock';
import { Flags } from '../../utils/flags';

describe('App', () => {
describe('renders without crashing', () => {
Expand Down Expand Up @@ -35,6 +36,14 @@ describe('App', () => {
});
});

describe('feature flags', () => {
it('it announces flags', () => {
const announceFlags = jest.spyOn(App.prototype, 'announceFlags');
shallow(<App data={loremIpsum} />);
expect(announceFlags).toHaveBeenCalledWith(Flags.defaults());
});
});

describe('throws an error', () => {
it('when data prop is empty', () => {
expect(() => shallow(<App />)).toThrow();
Expand Down
13 changes: 13 additions & 0 deletions src/components/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Wrapper from '../wrapper';
import getInitialState from '../../store/initial-state';
import loadData from '../../store/load-data';
import normalizeData from '../../store/normalize-data';
import { getFlagsMessage } from '../../utils/flags';
import '@quantumblack/kedro-ui/lib/styles/app.css';
import './app.css';

Expand All @@ -19,6 +20,7 @@ class App extends React.Component {
super(props);
const initialState = getInitialState(props);
this.store = configureStore(initialState);
this.announceFlags(initialState.flags);
}

componentDidMount() {
Expand All @@ -32,6 +34,17 @@ class App extends React.Component {
}
}

/**
* Shows a console message regarding the given flags
*/
announceFlags(flags) {
const message = getFlagsMessage(flags);

if (message && typeof jest === 'undefined') {
console.info(message);
}
}

/**
* Load data asynchronously from a JSON file then update the store
*/
Expand Down
8 changes: 8 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,11 @@ export const sidebarWidth = {
open: 400,
closed: 60
};

export const flags = {
newgraph: {
description: 'Improved graphing algorithm',
default: false,
icon: '📈'
}
};
16 changes: 16 additions & 0 deletions src/reducers/flags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CHANGE_FLAG } from '../actions';

function flagsReducer(flagsState = {}, action) {
switch (action.type) {
case CHANGE_FLAG: {
return Object.assign({}, flagsState, {
[action.name]: action.value
});
}

default:
return flagsState;
}
}

export default flagsReducer;
2 changes: 2 additions & 0 deletions src/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import node from './nodes';
import tag from './tags';
import nodeType from './node-type';
import visible from './visible';
import flags from './flags';
import {
RESET_DATA,
TOGGLE_TEXT_LABELS,
Expand Down Expand Up @@ -46,6 +47,7 @@ const combinedReducer = combineReducers({
nodeType,
tag,
visible,
flags,
edge: (state = {}) => state,
id: (state = null) => state,
layer: (state = {}) => state,
Expand Down
12 changes: 12 additions & 0 deletions src/reducers/reducers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { mockState } from '../utils/state.mock';
import reducer from './index';
import normalizeData from '../store/normalize-data';
import {
CHANGE_FLAG,
RESET_DATA,
TOGGLE_LAYERS,
TOGGLE_SIDEBAR,
Expand Down Expand Up @@ -194,4 +195,15 @@ describe('Reducer', () => {
expect(newState.fontLoaded).toBe(true);
});
});

describe('CHANGE_FLAG', () => {
it('should update the state when a flag is changed', () => {
const newState = reducer(mockState.lorem, {
type: CHANGE_FLAG,
name: 'testFlag',
value: true
});
expect(newState.flags.testFlag).toBe(true);
});
});
});
11 changes: 11 additions & 0 deletions src/selectors/flags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createSelector } from 'reselect';

const getFlagsState = state => state.flags;

/**
* Get current flag status from state
*/
export const getCurrentFlags = createSelector(
[getFlagsState],
flags => ({ ...flags })
);
10 changes: 10 additions & 0 deletions src/selectors/flags.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { getCurrentFlags } from './flags';

describe('getCurrentFlags function', () => {
it('should return the current flags from state', () => {
const flags = getCurrentFlags({
flags: { mockFlagA: true, mockFlagB: false }
});
expect(flags).toEqual({ mockFlagA: true, mockFlagB: false });
});
});
51 changes: 24 additions & 27 deletions src/selectors/layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,38 @@ const getLayerName = state => state.layer.name;
export const getLayers = createSelector(
[getLayoutNodes, getVisibleLayerIDs, getLayerName, getGraphSize],
(nodes, layerIDs, layerName, { width }) => {
// Get list of layer Y positions from nodes
const layerY = nodes.reduce((layerY, node) => {
if (!layerY[node.layer]) {
layerY[node.layer] = [];
}
layerY[node.layer].push(node.y);
return layerY;
}, {});
const bounds = {};

for (const node of nodes) {
const layer = node.nearestLayer || node.layer;

/**
* Determine the y position and height of a layer band
* @param {number} id
*/
const calculateYPos = (layerID, prevID, nextID) => {
const yMin = Math.min(...layerY[layerID]);
const yMax = Math.max(...layerY[layerID]);
const prev = layerY[prevID];
const next = layerY[nextID];
const topYGap = prev && yMin - Math.max(...prev);
const bottomYGap = next && Math.min(...next) - yMax;
const yGap = (topYGap || bottomYGap) / 2;
const y = yMin - yGap;
const height = yMax + yGap - y;
return { y, height };
};
if (layer) {
const bound = bounds[layer] || (bounds[layer] = [Infinity, -Infinity]);
if (node.y - node.height < bound[0]) bound[0] = node.y - node.height;
if (node.y + node.height > bound[1]) bound[1] = node.y + node.height;
}
}

return layerIDs.map((id, i) => {
const prevID = layerIDs[i - 1];
const nextID = layerIDs[i + 1];
const currentBound = bounds[id] || [0, 0];
const prevBound = bounds[layerIDs[i - 1]] || [
currentBound[0],
currentBound[0]
];
const nextBound = bounds[layerIDs[i + 1]] || [
currentBound[1],
currentBound[1]
];
const start = (prevBound[1] + currentBound[0]) / 2;
const end = (currentBound[1] + nextBound[0]) / 2;

return {
id,
name: layerName[id],
x: -width / 2,
y: start,
width: width * 2,
...calculateYPos(id, prevID, nextID)
height: Math.max(end - start, 0)
};
});
}
Expand Down
Loading