Skip to content
Snippets Groups Projects
Commit 1bf578d6 authored by Sivan Duijn's avatar Sivan Duijn
Browse files

feat: added graph query result redux slice

parent 1cb80804
No related branches found
No related tags found
2 merge requests!7refactor(rawjsonvis): moves rawjsonvis into own component,!1feat: added graph query result redux slice
Pipeline #114957 canceled
Showing
with 361 additions and 30846 deletions
# image: node:16-alpine
# stages:
# - setup
# - test
# - docker
# - deploy
image: node:16-alpine
stages:
- setup
- test
# install-dependencies:
# stage: setup
# interruptible: true
# only:
# - main
# - merge_requests
# cache:
# key:
# files:
# - yarn.lock
# paths:
# - node_modules
# - .yarn
# script:
# - yarn install --pure-lockfile --cache-folder .yarn
# artifacts:
# paths:
# - node_modules
install-dependencies:
stage: setup
interruptible: true
only:
- main
- merge_requests
cache:
key:
files:
- yarn.lock
paths:
- node_modules
- .yarn
script:
- yarn install --pure-lockfile --cache-folder .yarn
artifacts:
paths:
- node_modules
# .distributed:
# interruptible: true
# only:
# - main
# - merge_requests
# needs:
# - install-dependencies
# artifacts:
# paths:
# - node_modules/.cache/nx
.distributed:
interruptible: true
only:
- main
- merge_requests
needs:
- install-dependencies
artifacts:
paths:
- node_modules/.cache/nx
# build:
# stage: test
# extends: .distributed
# script:
# - yarn nx affected --base=HEAD~1 --target=build --parallel --max-parallel=3
build:
stage: test
extends: .distributed
script:
- yarn nx affected --base=HEAD~1 --target=build --parallel --max-parallel=3
# test:
# stage: test
# extends: .distributed
# script:
# - yarn nx affected --base=HEAD~1 --target=test --parallel --max-parallel=2
# docker:
# image: docker:stable
# stage: docker
# tags:
# - docker
# only:
# - main
# - develop
# script:
# - docker build --progress plain -f ./apps/frontend/Dockerfile . -t $CI_PROJECT_NAME:latest
# after_script:
# - docker login datastropheregistry.azurecr.io -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD
# - if [[ ! -z $CI_COMMIT_BRANCH+x ]]; then DOCKER_TAG=$CI_COMMIT_BRANCH; else DOCKER_TAG=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME; fi
# - docker tag $CI_PROJECT_NAME datastropheregistry.azurecr.io/$CI_PROJECT_NAME:$DOCKER_TAG
# - docker push datastropheregistry.azurecr.io/$CI_PROJECT_NAME:$DOCKER_TAG
# dependencies:
# - build
# deploy:
# stage: deploy
# only:
# - main
# - develop
# script:
# - apk add --update --no-cache openssh-client >/dev/null
# - mkdir ~/.ssh/
# - eval $(ssh-agent -s)
# - echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
# - chmod 600 ~/.ssh/id_rsa
# - ssh-add ~/.ssh/id_rsa
# - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
# - ssh -fN -L 1234:science-vs260.science.uu.nl:22 sivan@up.science.uu.nl
# # Copy kubernetes files over
# - scp -r -o StrictHostKeyChecking=no -P 1234 -i ~/.ssh/id_rsa deployments/* root@localhost:/root/kubernetes/$CI_PROJECT_NAME
# # Deploy all yml files
# - ssh -p 1234 -i ~/.ssh/id_rsa root@localhost "for i in kubernetes/$CI_PROJECT_NAME/*.yml; do kubectl apply -f \$i; done"
# # Perform rolling update for deployment
# - ssh -p 1234 -i ~/.ssh/id_rsa root@localhost "kubectl rollout restart -f kubernetes/$CI_PROJECT_NAME/deployment.yml"
# dependencies: []
test:
stage: test
extends: .distributed
script:
- yarn nx affected --base=HEAD~1 --target=test --parallel --max-parallel=2
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import {
assignNewGraphQueryResult,
useAppDispatch,
useGraphQueryResult,
} from '@graphpolaris/shared/data-access/store';
import React, { useEffect } from 'react';
import styles from './app.module.scss';
import ReactJSONView from 'react-json-view';
import NxWelcome from './nx-welcome';
const RawJSONVis = React.memo(() => {
const graphQueryResult = useGraphQueryResult();
console.log('update rawjson');
useEffect(() => {
console.log('update rawjson useEffect');
}, [graphQueryResult]);
useEffect(() => {
return () => {
console.log('unloaded RawJSONVis');
};
}, []);
return (
<div style={{ overflowY: 'auto' }}>
<div
style={{
marginTop: '40px',
paddingLeft: '30px',
}}
>
<ReactJSONView
src={graphQueryResult}
collapsed={1}
quotesOnKeys={false}
displayDataTypes={false}
/>
</div>
</div>
);
});
export function App() {
const dispatch = useAppDispatch();
return (
<>
<div>
<button
onClick={() =>
dispatch(
assignNewGraphQueryResult({
nodes: [
{ id: 'agent/007', attributes: { name: 'Daniel Craig' } },
],
links: [],
})
)
}
>
Load in mock result
</button>
<button
onClick={() =>
dispatch(assignNewGraphQueryResult({ nodes: [], links: [] }))
}
>
Remove mock result
</button>
</div>
<RawJSONVis />
<NxWelcome title="graphpolaris" />
<div />
</>
......
import { store } from '@graphpolaris/shared/data-access/store';
import { StrictMode } from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './app/app';
ReactDOM.render(
<StrictMode>
<App />
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
document.getElementById('root')
);
{
"presets": [["@nrwl/web/babel", { "useBuiltIns": "usage" }]]
}
{
"extends": ["../../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
# shared-data-access-store
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test shared-data-access-store` to execute the unit tests via [Jest](https://jestjs.io).
module.exports = {
displayName: 'shared-data-access-store',
preset: '../../../../jest.preset.js',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
},
},
transform: {
'^.+\\.[tj]sx?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../../../coverage/libs/shared/data-access/store',
};
{
"root": "libs/shared/data-access/store",
"sourceRoot": "libs/shared/data-access/store/src",
"projectType": "library",
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/shared/data-access/store/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/shared/data-access/store"],
"options": {
"jestConfig": "libs/shared/data-access/store/jest.config.js",
"passWithNoTests": true
}
}
},
"tags": []
}
export * from './lib/store';
export * from './lib/hooks';
export {
selectGraphQueryResult,
selectGraphQueryResultLinks,
selectGraphQueryResultNodes,
assignNewGraphQueryResult,
} from './lib/graphQueryResultSlice';
// Exported types
export type { Node, Edge, GraphQueryResult } from './lib/graphQueryResultSlice';
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import type { RootState } from './store';
export interface GraphQueryResultFromBackend {
nodes: {
id: string;
attributes: { [key: string]: unknown };
}[];
links: {
attributes: { [key: string]: unknown };
from: string;
to: string;
}[];
// TODO: Also include type in node and edge
// TODO: The backend should send all the different entitytypes and relationtypes in the result
}
export interface Node {
id: string;
attributes: { [key: string]: unknown };
/* type: string[]; */
}
export interface Edge {
attributes: { [key: string]: unknown };
from: string;
to: string;
/* type: string; */
}
// Define a type for the slice state
export interface GraphQueryResult {
nodes: Node[];
edges: Edge[];
// Describes what entities there are in this graph query result.
nodeTypes: string[];
}
// Define the initial state using that type
const initialState: GraphQueryResult = {
nodes: [],
edges: [],
nodeTypes: [],
};
export const graphQueryResultSlice = createSlice({
name: 'graphQueryResult',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
assignNewGraphQueryResult: (
state,
action: PayloadAction<GraphQueryResultFromBackend>
) => {
// Maybe do some data quality checking and parsing
// ...
// Collect all the different nodetypes in the result
const nodeTypes: string[] = [];
action.payload.nodes.forEach((node) => {
// Note: works only for arangodb
const nodeType = node.id.split('/')[0];
if (!nodeTypes.includes(nodeType)) nodeTypes.push(nodeType);
});
// Assign new state
state.nodes = action.payload.nodes;
state.edges = action.payload.links;
state.nodeTypes = nodeTypes;
},
},
});
export const { assignNewGraphQueryResult } = graphQueryResultSlice.actions;
// Other code such as selectors can use the imported `RootState` type
export const selectGraphQueryResult = (state: RootState) =>
state.graphQueryResult;
export const selectGraphQueryResultNodes = (state: RootState) =>
state.graphQueryResult.nodes;
export const selectGraphQueryResultLinks = (state: RootState) =>
state.graphQueryResult.edges;
export default graphQueryResultSlice.reducer;
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import { selectGraphQueryResult } from './graphQueryResultSlice';
import type { RootState, AppDispatch } from './store';
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
// Gives the graphQueryResult from the store
export const useGraphQueryResult = () => useAppSelector(selectGraphQueryResult);
describe('sharedDataAccessStore', () => {
it('should work', () => {
expect(true).toEqual(true);
});
});
import { configureStore } from '@reduxjs/toolkit';
import graphQueryResultSlice from './graphQueryResultSlice';
export const store = configureStore({
reducer: {
graphQueryResult: graphQueryResultSlice,
},
});
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {counter: CounterState}
export type AppDispatch = typeof store.dispatch;
{
"extends": "../../../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": []
},
"include": ["**/*.ts"],
"exclude": ["**/*.spec.ts"]
}
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts"
]
}
This diff is collapsed.
......@@ -9,9 +9,12 @@
},
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.7.1",
"core-js": "^3.6.5",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-json-view": "^1.21.3",
"react-redux": "^7.2.6",
"regenerator-runtime": "0.13.7",
"tslib": "^2.0.0"
},
......
......@@ -14,7 +14,11 @@
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {}
"paths": {
"@graphpolaris/shared/data-access/store": [
"libs/shared/data-access/store/src/index.ts"
]
}
},
"exclude": ["node_modules", "tmp"]
}
......@@ -2,6 +2,7 @@
"version": 2,
"projects": {
"graphpolaris": "apps/graphpolaris",
"graphpolaris-e2e": "apps/graphpolaris-e2e"
"graphpolaris-e2e": "apps/graphpolaris-e2e",
"shared-data-access-store": "libs/shared/data-access/store"
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment