diff --git a/app/public/favicon.ico b/app/public/favicon.ico index b2b454a..6d83eb7 100644 Binary files a/app/public/favicon.ico and b/app/public/favicon.ico differ diff --git a/app/src/actions/actionTypes.js b/app/src/actions/actionTypes.js index c675ff8..7e25c3b 100644 --- a/app/src/actions/actionTypes.js +++ b/app/src/actions/actionTypes.js @@ -1,3 +1,5 @@ +//TODO:DM - this file feels overly anti-DRY... investigate if better way to track action type names or maybe just use strings directly + export const SUBMIT_QUERY = 'SUBMIT_QUERY'; export const REQUEST_QUERY = 'REQUEST_QUERY'; export const RECEIVE_QUERY = 'RECEIVE_QUERY'; @@ -12,5 +14,6 @@ export const FETCH_ENTITIES = 'FETCH_ENTITIES'; export const RECEIVE_ENTITY = 'RECEIVE_ENTITY'; export const ADD_WATCH_QSL_QUERY = 'ADD_WATCH_QSL_QUERY'; export const RECEIVE_QSL_RESP = 'RECEIVE_QSL_RESP'; +export const CLEAR_WATCHES = 'CLEAR_WATCHES'; export const SHOW_NOTIFY = 'SHOW_NOTIFY'; \ No newline at end of file diff --git a/app/src/actions/entityActions.js b/app/src/actions/entityActions.js index b9f9dde..29dee81 100644 --- a/app/src/actions/entityActions.js +++ b/app/src/actions/entityActions.js @@ -45,4 +45,8 @@ export const fetchQslQuery = query => { export const receiveQslResp = results => ({ type: types.RECEIVE_QSL_RESP, results +}); + +export const clearWatches = () => ({ + type: types.CLEAR_WATCHES }); \ No newline at end of file diff --git a/app/src/components/graph/GraphContainer.js b/app/src/components/graph/GraphContainer.js index 5505ecd..d412b0a 100644 --- a/app/src/components/graph/GraphContainer.js +++ b/app/src/components/graph/GraphContainer.js @@ -56,6 +56,8 @@ class GraphContainer extends Component { } componentWillUnmount() { + const { clearWatches } = this.props.entityActions; + clearWatches(); clearInterval(this.intervalHandle); } diff --git a/app/src/components/home/Home.js b/app/src/components/home/Home.js index 459c991..2911168 100644 --- a/app/src/components/home/Home.js +++ b/app/src/components/home/Home.js @@ -8,7 +8,7 @@ import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button'; import './Home.css'; -import logo from './map.png'; +import logo from './katlas-logo-blue-300px.png'; import { ENTER_KEYCODE, ENTER_KEYSTR } from '../../config/appConfig'; import * as queryActions from '../../actions/queryActions'; import { validateQslQuery } from '../../utils/validate'; diff --git a/app/src/components/home/katlas-logo-blue-300px.png b/app/src/components/home/katlas-logo-blue-300px.png new file mode 100644 index 0000000..f1ec7e5 Binary files /dev/null and b/app/src/components/home/katlas-logo-blue-300px.png differ diff --git a/app/src/components/home/map.png b/app/src/components/home/map.png deleted file mode 100644 index 20dd78b..0000000 Binary files a/app/src/components/home/map.png and /dev/null differ diff --git a/app/src/components/menuBar/MenuBar.js b/app/src/components/menuBar/MenuBar.js index 3a41972..606c808 100644 --- a/app/src/components/menuBar/MenuBar.js +++ b/app/src/components/menuBar/MenuBar.js @@ -7,7 +7,7 @@ import IconButton from '@material-ui/core/IconButton'; import Typography from '@material-ui/core/Typography'; import { withStyles } from '@material-ui/core/styles'; -import logo from './map.png'; +import logo from './katlas-logo-white-300px.png'; const styles = theme => ({ root: { diff --git a/app/src/components/menuBar/katlas-logo-white-300px.png b/app/src/components/menuBar/katlas-logo-white-300px.png new file mode 100644 index 0000000..bf79fa0 Binary files /dev/null and b/app/src/components/menuBar/katlas-logo-white-300px.png differ diff --git a/app/src/components/menuBar/map.png b/app/src/components/menuBar/map.png deleted file mode 100644 index 7b7210a..0000000 Binary files a/app/src/components/menuBar/map.png and /dev/null differ diff --git a/app/src/config/appConfig.js b/app/src/config/appConfig.js index 9d5fcfa..afa3e2a 100644 --- a/app/src/config/appConfig.js +++ b/app/src/config/appConfig.js @@ -5,7 +5,7 @@ export const NODE_DEFAULT_STR = 'default'; export const NODE_DEFAULT_COLOR = '#2575E2'; export const NODE_ICON_FONT = 'FontAwesome'; export const NODE_ICON_FONT_SIZE = 40; -export const NODE_LABEL_MAX_LENGTH = 40; +export const NODE_LABEL_MAX_LENGTH = 30; export const NODE_LABEL_SPLIT_CHAR = '-'; //Node icons to be displayed in ased on Node types used in app diff --git a/app/src/config/visjsConfig.js b/app/src/config/visjsConfig.js index 3cd3e79..1bf0b33 100644 --- a/app/src/config/visjsConfig.js +++ b/app/src/config/visjsConfig.js @@ -35,6 +35,7 @@ export const options = { improvedLayout: true, hierarchical: { enabled: true, + nodeSpacing: 150, blockShifting: true, edgeMinimization: true, sortMethod: 'hubsize', @@ -42,6 +43,6 @@ export const options = { } }, physics: { - enabled: true + enabled: false } }; \ No newline at end of file diff --git a/app/src/index.js b/app/src/index.js index b994fd2..36e5b9a 100644 --- a/app/src/index.js +++ b/app/src/index.js @@ -31,7 +31,7 @@ let theme = createMuiTheme({ palette: { primary: { light: '#63ccff', - main: '#326CE5', + main: '#144CB6', dark: '#2b333c', }, secondary: { diff --git a/app/src/reducers/entityReducer.js b/app/src/reducers/entityReducer.js index 6fcf2a7..083c250 100644 --- a/app/src/reducers/entityReducer.js +++ b/app/src/reducers/entityReducer.js @@ -4,7 +4,7 @@ import initialState from './initialState'; import { SET_ROOT_UID, ADD_WATCH_UID, FETCH_ENTITY, FETCH_ENTITIES, RECEIVE_ENTITY, RECEIVE_QSL_RESP, - ADD_WATCH_QSL_QUERY + ADD_WATCH_QSL_QUERY, CLEAR_WATCHES } from '../actions/actionTypes'; import { EdgeLabels } from '../config/appConfig'; @@ -67,6 +67,16 @@ export default function entity(state = initialState.entity, action) { newState.results = potentialResults; } return newState; + case CLEAR_WATCHES: + newState = { + ...state, + rootUid: '', + entitiesByUid: {}, + qslQuery: '', + results: {}, + isWaiting: false, + }; + return newState; default: return state; } diff --git a/app/src/utils/graph.js b/app/src/utils/graph.js index 04549b1..9598b78 100644 --- a/app/src/utils/graph.js +++ b/app/src/utils/graph.js @@ -31,7 +31,7 @@ let edges, nodes; let legendTypesObj = {}; let legendStatusesObj = {}; -function parseDgraphData(data) { +function parseDgraphData(data, level) { if (data === null || data === undefined ) { console.error("Empty data"); return; @@ -43,11 +43,14 @@ function parseDgraphData(data) { //Store entire block in map, so we can use to create edges later //Edges cannot be created here as we may not have got the uid still //As json from dgraph has randomized order and uid may be after Array elements - uidMap.set(uid, data); + uidMap.set(uid, { + data, + level + }); } //if this key is a relationship type (as defined in EdgeLabels) recurse to get children nodes if (EdgeLabels.indexOf(key) > -1) { - _.forEach(val, (item) => parseDgraphData(item)); + _.forEach(val, (item) => parseDgraphData(item, level + 1)); } }); } @@ -94,7 +97,7 @@ function getVisFormatEdge(fromUid, toUid, relation) { }; } -function getVisFormatNode(uid, nodeName, nodeObjtype, nodeStatus) { +function getVisFormatNode(uid, nodeName, nodeObjtype, nodeStatus, level) { let idParam = uid; let titleParam = ""; @@ -110,14 +113,15 @@ function getVisFormatNode(uid, nodeName, nodeObjtype, nodeStatus) { const color = NodeStatusColorMap.get(nodeStatus || NODE_DEFAULT_STR); const n = { + level, id: idParam, - uid: uid, + uid, label: nodeName, icon:{ face: NODE_ICON_FONT, code: getNodeIcon(nodeObjtype), size: NODE_ICON_FONT_SIZE, - color: color, + color, }, name: nodeName, title: titleParam, @@ -129,7 +133,7 @@ function getVisFormatNode(uid, nodeName, nodeObjtype, nodeStatus) { }; legendStatusesObj[nodeStatus] = { code: getNodeIcon(NODE_DEFAULT_STR), - color: color, + color, }; return n; } @@ -146,11 +150,11 @@ function validateJSONData(uid, nodeName, nodeObjtype) { export function getVisData(data) { let existingUids = {}; clearVisData(); - parseDgraphData(data); + parseDgraphData(data, 0); - for (const [uid, v] of uidMap.entries()) { + for (const [uid, val] of uidMap.entries()) { let nodeName = "", nodeObjtype = "", nodeStatus = ""; - const block = v; + const { data: block, level } = val; for (const prop in block) { if (!block.hasOwnProperty(prop)) { @@ -183,7 +187,7 @@ export function getVisData(data) { } } validateJSONData(uid, nodeName, nodeObjtype); - let n = getVisFormatNode(uid, nodeName, nodeObjtype, nodeStatus); + let n = getVisFormatNode(uid, nodeName, nodeObjtype, nodeStatus, level); if(!existingUids[n.uid]){ nodes.push(n); existingUids[n.uid] = true; @@ -222,18 +226,13 @@ export function colorMixer(rgbA, rgbB, amountToMix){ return "rgb("+r+","+g+","+b+")"; } -//Function to split long label names. If too long, name is split by its middle -//dash '-' char across 2 lines of text. If there are no '-' chars, name is not split +//split long label names; if too long, split by its middle char across 2 lines function nameSplitter(name){ let splitName = name; if (typeof name !== 'string') return name; if (name.length > NODE_LABEL_MAX_LENGTH){ - let nnDashSplit = name.split(NODE_LABEL_SPLIT_CHAR); - if(nnDashSplit.length > 1){ - splitName = nnDashSplit.slice(0, nnDashSplit.length/2).join(NODE_LABEL_SPLIT_CHAR) + - NODE_LABEL_SPLIT_CHAR + '\n' + - nnDashSplit.slice(nnDashSplit.length/2).join(NODE_LABEL_SPLIT_CHAR); - } + splitName = name.slice(0, name.length/2) + '\n' + + name.slice(name.length/2); } return splitName; }