chore (litmus-portal): Added argo workflow representation using dagre d3 graph (#1975)
- Argo workflow representation using dagre d3 - Subscription fixes - removed unnecessary re-rendering - refactoring of few components - renaming to appropriate names for few components Signed-off-by: arkajyotiMukherjee <arkajyoti.mukherjee@mayadata.io>
This commit is contained in:
parent
85a0fede89
commit
7f7cb65980
|
|
@ -18,6 +18,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"new-cap": 0,
|
||||||
|
"no-underscore-dangle": 0,
|
||||||
|
"react/static-property-placement": [
|
||||||
|
"warn",
|
||||||
|
"property assignment",
|
||||||
|
{ "defaultProps": "static public field" }
|
||||||
|
],
|
||||||
|
"lines-between-class-members": 0,
|
||||||
|
"no-restricted-syntax": 0,
|
||||||
"no-nested-ternary": 0,
|
"no-nested-ternary": 0,
|
||||||
"no-plusplus": 0,
|
"no-plusplus": 0,
|
||||||
"dot-notation": 0,
|
"dot-notation": 0,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
/// <reference types="Cypress" />
|
/// <reference types="Cypress" />
|
||||||
import React from 'react';
|
|
||||||
import { mount } from 'cypress-react-unit-test';
|
import { mount } from 'cypress-react-unit-test';
|
||||||
|
import React from 'react';
|
||||||
import CustomSlider from '../../src/components/Sections/Workflow/WeightSlider';
|
import CustomSlider from '../../src/components/Sections/CreateWorkflow/WeightSlider';
|
||||||
|
|
||||||
describe('Testing Custom Slider with different values', () => {
|
describe('Testing Custom Slider with different values', () => {
|
||||||
[10, 5, 2].map((i) => {
|
[10, 5, 2].map((i) => {
|
||||||
|
|
|
||||||
|
|
@ -2612,9 +2612,142 @@
|
||||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
|
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
|
||||||
},
|
},
|
||||||
"@types/d3": {
|
"@types/d3": {
|
||||||
"version": "3.5.43",
|
"version": "5.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.43.tgz",
|
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-5.7.2.tgz",
|
||||||
"integrity": "sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w==",
|
"integrity": "sha512-7/wClB8ycneWGy3jdvLfXKTd5SoTg9hji7IdJ0RuO9xTY54YpJ8zlcFADcXhY1J3kCBwxp+/1jeN6a5OMwgYOw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-array": "^1",
|
||||||
|
"@types/d3-axis": "*",
|
||||||
|
"@types/d3-brush": "*",
|
||||||
|
"@types/d3-chord": "*",
|
||||||
|
"@types/d3-collection": "*",
|
||||||
|
"@types/d3-color": "*",
|
||||||
|
"@types/d3-contour": "*",
|
||||||
|
"@types/d3-dispatch": "*",
|
||||||
|
"@types/d3-drag": "*",
|
||||||
|
"@types/d3-dsv": "*",
|
||||||
|
"@types/d3-ease": "*",
|
||||||
|
"@types/d3-fetch": "*",
|
||||||
|
"@types/d3-force": "*",
|
||||||
|
"@types/d3-format": "*",
|
||||||
|
"@types/d3-geo": "*",
|
||||||
|
"@types/d3-hierarchy": "*",
|
||||||
|
"@types/d3-interpolate": "*",
|
||||||
|
"@types/d3-path": "*",
|
||||||
|
"@types/d3-polygon": "*",
|
||||||
|
"@types/d3-quadtree": "*",
|
||||||
|
"@types/d3-random": "*",
|
||||||
|
"@types/d3-scale": "*",
|
||||||
|
"@types/d3-scale-chromatic": "*",
|
||||||
|
"@types/d3-selection": "*",
|
||||||
|
"@types/d3-shape": "*",
|
||||||
|
"@types/d3-time": "*",
|
||||||
|
"@types/d3-time-format": "*",
|
||||||
|
"@types/d3-timer": "*",
|
||||||
|
"@types/d3-transition": "*",
|
||||||
|
"@types/d3-voronoi": "*",
|
||||||
|
"@types/d3-zoom": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-array": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-51vHWuUyDOi+8XuwPrTw3cFqyh2Slg9y8COYkRfjCPG9TfYqY0hoNPzv/8BrcAy0FeQBzqEo/D/8Nk2caOQJnA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-axis": {
|
||||||
|
"version": "1.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-BZISgSD5M8TgURyNtcPAmUB9sk490CO1Thb6/gIn0WZTt3Y50IssX+2Z0vTccoqZksUDTep0b+o4ofXslvNbqg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-brush": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Exx14trm/q2cskHyMjCrdDllOQ35r1/pmZXaOIt8bBHwYNk722vWY3VxHvN0jdFFX7p2iL3+gD+cGny/aEmhlw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-chord": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-UA6lI9CVW5cT5Ku/RV4hxoFn4mKySHm7HEgodtfRthAj1lt9rKZEPon58vyYfk+HIAm33DtJJgZwMXy2QgyPXw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-collection": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-collection/-/d3-collection-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-y5lGlazdc0HNO0F3UUX2DPE7OmYvd9Kcym4hXwrJcNUkDaypR5pX+apuMikl9LfTxKItJsY9KYvzBulpCKyvuQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-color": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-6pBxzJ8ZP3dYEQ4YjQ+NVbQaOflfgXq/JbDiS99oLobM2o72uAST4q6yPxHv6FOTCRC/n35ktuo8pvw/S4M7sw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-contour": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-AUCUIjEnC5lCGBM9hS+MryRaFLIrPls4Rbv6ktqbd+TK/RXZPwOy9rtBWmGpbeXcSOYCJTUDwNJuEnmYPJRxHQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-array": "*",
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-dispatch": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-lCDtqoYez0TgFN3FljBXrz2icqeSzD0gufGook6DPBia+NOh2TBfogjHIsmNa/a+ZOewlHtq4cgLY80O1uLymw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-drag": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-rWB5SPvkYVxW3sqUxHOJUZwifD0KqvKwvt1bhNqcLpW6Azsd0BJgRNcyVW8GAferaAk5r8dzeZnf9zKlg9+xMQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-dsv": {
|
||||||
|
"version": "1.0.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-1.0.36.tgz",
|
||||||
|
"integrity": "sha512-jbIWQ27QJcBNMZbQv0NSQMHnBDCmxghAxePxgyiPH1XPCRkOsTBei7jcdi3fDrUCGpCV3lKrSZFSlOkhUQVClA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-ease": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-U5ADevQ+W6fy32FVZZC9EXallcV/Mi12A5Tkd0My5MrC7T8soMQEhlDAg88XUWm0zoCQlB4XV0en/24LvuDB4Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-fetch": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-o9c0ItT5/Gl3wbNuVpzRnYX1t3RghzeWAjHUVLuyZJudiTxC4f/fC0ZPFWLQ2lVY8pAMmxpV8TJ6ETYCgPeI3A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-dsv": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-force": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-jqK+I36uz4kTBjyk39meed5y31Ab+tXYN/x1dn3nZEus9yOHCLc+VrcIYLc/aSQ0Y7tMPRlIhLetulME76EiiA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-format": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-KAWvReOKMDreaAwOjdfQMm0HjcUMlQG47GwqdVKgmm20vTd2pucj0a70c3gUSHrnsmo6H2AMrkBsZU2UhJLq8A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/d3-geo": {
|
"@types/d3-geo": {
|
||||||
|
|
@ -2626,6 +2759,142 @@
|
||||||
"@types/geojson": "*"
|
"@types/geojson": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/d3-hierarchy": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-vvSaIDf/Ov0o3KwMT+1M8+WbnnlRiGjlGD5uvk83a1mPCTd/E5x12bUJ/oP55+wUY/4Kb5kc67rVpVGJ2KUHxg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-interpolate": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-z8Zmi08XVwe8e62vP6wcA+CNuRhpuUU5XPEfqpG0hRypDE5BWNthQHB1UNWWDB7ojCbGaN4qBdsWp5kWxhT1IQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-color": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-path": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-AZGHWslq/oApTAHu9+yH/Bnk63y9oFOMROtqPAtxl5uB6qm1x2lueWdVEjsjjV3Qc2+QfuzKIwIR5MvVBakfzA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-polygon": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-Xuw0eSjQQKs8jTiNbntWH0S+Xp+JyhqxmQ0YAQ3rDu6c3kKMFfgsaGN7Jv5u3zG6yVX/AsLP/Xs/QRjmi9g43Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-quadtree": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-0ajFawWicfjsaCLh6NzxOyVDYhQAmMFbsiI3MPGLInorauHFEh9/Cl6UHNf+kt/J1jfoxKY/ZJaKAoDpbvde5Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-random": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-Jui+Zn28pQw/3EayPKaN4c/PqTvqNbIPjHkgIIFnxne1FdwNjfHtAIsZIBMKlquQNrrMjFzCrlF2gPs3xckqaA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-scale": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-oQFanN0/PiR2oySHfj+zAAkK1/p4LD32Nt1TMVmzk+bYHk7vgIg/iTXQWitp1cIkDw4LMdcgvO63wL+mNs47YA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-time": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-scale-chromatic": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-9/D7cOBKdZdTCPc6re0HeSUFBM0aFzdNdmYggUWT9SRRiYSOa6Ys2xdTwHKgc1WS3gGfwTMatBOdWCS863REsg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-selection": {
|
||||||
|
"version": "1.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-1.4.2.tgz",
|
||||||
|
"integrity": "sha512-ksY8UxvTXpzD91Dy3D9zZg98yF2ZEPMKJd8ZQJlZt1QH3Xxr08s6fESEdC2l0Kbe6Xd9VhaoJX06cRaMR1lEnA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-shape": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-LtD8EaNYCaBRzHzaAiIPrfcL3DdIysc81dkGlQvv7WQP3+YXV7b0JJTtR1U3bzeRieS603KF4wUo+ZkJVenh8w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-path": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-time": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-aKf62rRQafDQmSiv1NylKhIMmznsjRN+MnXRXTqHoqm0U/UZzVpdrtRnSIfdiLS616OuC1soYeX1dBg2n1u8Xw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-time-format": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-tJSyXta8ZyJ52wDDHA96JEsvkbL6jl7wowGmuf45+fAkj5Y+SQOnz0N7/H68OWmPshPsAaWMQh+GAws44IzH3g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-timer": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-WvfJ3LFxBbWjqRGz9n7GJt08RrTHPJDVsIwwoCMROlqF+iDacYiAFjf9oqnq0mXpb2juA2N/qjKP+MKdal3YNQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-transition": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-/F+O2r4oz4G9ATIH3cuSCMGphAnl7VDx7SbENEK0NlI/FE8Jx2oiIrv0uTrpg7yF/AmuWbqp7AGdEHAPIh24Gg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/d3-voronoi": {
|
||||||
|
"version": "1.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.9.tgz",
|
||||||
|
"integrity": "sha512-DExNQkaHd1F3dFPvGA/Aw2NGyjMln6E9QzsiqOcBgnE+VInYnFBHBBySbZQts6z6xD+5jTfKCP7M4OqMyVjdwQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/d3-zoom": {
|
||||||
|
"version": "1.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-1.7.4.tgz",
|
||||||
|
"integrity": "sha512-5jnFo/itYhJeB2khO/lKe730kW/h2EbKMOvY0uNp3+7NdPm4w63DwPEMxifQZ7n902xGYK5DdU67FmToSoy4VA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3-interpolate": "*",
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/dagre": {
|
||||||
|
"version": "0.7.44",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/dagre/-/dagre-0.7.44.tgz",
|
||||||
|
"integrity": "sha512-N6HD+79w77ZVAaVO7JJDW5yJ9LAxM62FpgNGO9xEde+KVYjDRyhIMzfiErXpr1g0JPon9kwlBzoBK6s4fOww9Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/dagre-d3": {
|
||||||
|
"version": "0.4.39",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/dagre-d3/-/dagre-d3-0.4.39.tgz",
|
||||||
|
"integrity": "sha512-JZySpfIQPRSTx38B4P5pPGeV4Pqgb0qE/aIiS60qD+j0c3mYP/AHiiwlsrrLCVZWY7OJdvD3dp+aD1HvpjPBzA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/d3": "^3",
|
||||||
|
"@types/dagre": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3": {
|
||||||
|
"version": "3.5.43",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.43.tgz",
|
||||||
|
"integrity": "sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/eslint-visitor-keys": {
|
"@types/eslint-visitor-keys": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
||||||
|
|
@ -2732,6 +3001,14 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/d3": "^3"
|
"@types/d3": "^3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3": {
|
||||||
|
"version": "3.5.43",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.43.tgz",
|
||||||
|
"integrity": "sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/prop-types": {
|
"@types/prop-types": {
|
||||||
|
|
@ -6766,15 +7043,74 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"d3": {
|
"d3": {
|
||||||
"version": "3.5.17",
|
"version": "5.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
"resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz",
|
||||||
"integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g="
|
"integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "1",
|
||||||
|
"d3-axis": "1",
|
||||||
|
"d3-brush": "1",
|
||||||
|
"d3-chord": "1",
|
||||||
|
"d3-collection": "1",
|
||||||
|
"d3-color": "1",
|
||||||
|
"d3-contour": "1",
|
||||||
|
"d3-dispatch": "1",
|
||||||
|
"d3-drag": "1",
|
||||||
|
"d3-dsv": "1",
|
||||||
|
"d3-ease": "1",
|
||||||
|
"d3-fetch": "1",
|
||||||
|
"d3-force": "1",
|
||||||
|
"d3-format": "1",
|
||||||
|
"d3-geo": "1",
|
||||||
|
"d3-hierarchy": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-path": "1",
|
||||||
|
"d3-polygon": "1",
|
||||||
|
"d3-quadtree": "1",
|
||||||
|
"d3-random": "1",
|
||||||
|
"d3-scale": "2",
|
||||||
|
"d3-scale-chromatic": "1",
|
||||||
|
"d3-selection": "1",
|
||||||
|
"d3-shape": "1",
|
||||||
|
"d3-time": "1",
|
||||||
|
"d3-time-format": "2",
|
||||||
|
"d3-timer": "1",
|
||||||
|
"d3-transition": "1",
|
||||||
|
"d3-voronoi": "1",
|
||||||
|
"d3-zoom": "1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"d3-array": {
|
"d3-array": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
|
||||||
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
|
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
|
||||||
},
|
},
|
||||||
|
"d3-axis": {
|
||||||
|
"version": "1.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ=="
|
||||||
|
},
|
||||||
|
"d3-brush": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dispatch": "1",
|
||||||
|
"d3-drag": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-selection": "1",
|
||||||
|
"d3-transition": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-chord": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "1",
|
||||||
|
"d3-path": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-collection": {
|
"d3-collection": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
|
||||||
|
|
@ -6785,6 +7121,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
|
||||||
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
|
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
|
||||||
},
|
},
|
||||||
|
"d3-contour": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-dispatch": {
|
"d3-dispatch": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
|
||||||
|
|
@ -6799,11 +7143,29 @@
|
||||||
"d3-selection": "1"
|
"d3-selection": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-dsv": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==",
|
||||||
|
"requires": {
|
||||||
|
"commander": "2",
|
||||||
|
"iconv-lite": "0.4",
|
||||||
|
"rw": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-ease": {
|
"d3-ease": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.6.tgz",
|
||||||
"integrity": "sha512-SZ/lVU7LRXafqp7XtIcBdxnWl8yyLpgOmzAk0mWBI9gXNzLDx5ybZgnRbH9dN/yY5tzVBqCQ9avltSnqVwessQ=="
|
"integrity": "sha512-SZ/lVU7LRXafqp7XtIcBdxnWl8yyLpgOmzAk0mWBI9gXNzLDx5ybZgnRbH9dN/yY5tzVBqCQ9avltSnqVwessQ=="
|
||||||
},
|
},
|
||||||
|
"d3-fetch": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dsv": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-force": {
|
"d3-force": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
|
||||||
|
|
@ -6815,6 +7177,11 @@
|
||||||
"d3-timer": "1"
|
"d3-timer": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-format": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
|
||||||
|
},
|
||||||
"d3-geo": {
|
"d3-geo": {
|
||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz",
|
||||||
|
|
@ -6841,11 +7208,43 @@
|
||||||
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
|
||||||
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
|
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
|
||||||
},
|
},
|
||||||
|
"d3-polygon": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
|
||||||
|
},
|
||||||
"d3-quadtree": {
|
"d3-quadtree": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
|
||||||
"integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
|
"integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
|
||||||
},
|
},
|
||||||
|
"d3-random": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ=="
|
||||||
|
},
|
||||||
|
"d3-scale": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^1.2.0",
|
||||||
|
"d3-collection": "1",
|
||||||
|
"d3-format": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-time": "1",
|
||||||
|
"d3-time-format": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-scale-chromatic": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==",
|
||||||
|
"requires": {
|
||||||
|
"d3-color": "1",
|
||||||
|
"d3-interpolate": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-selection": {
|
"d3-selection": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.1.tgz",
|
||||||
|
|
@ -6859,6 +7258,19 @@
|
||||||
"d3-path": "1"
|
"d3-path": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-time": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
|
||||||
|
},
|
||||||
|
"d3-time-format": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-time": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-timer": {
|
"d3-timer": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
|
||||||
|
|
@ -6877,6 +7289,11 @@
|
||||||
"d3-timer": "1"
|
"d3-timer": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-voronoi": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg=="
|
||||||
|
},
|
||||||
"d3-zoom": {
|
"d3-zoom": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz",
|
||||||
|
|
@ -6889,6 +7306,168 @@
|
||||||
"d3-transition": "1"
|
"d3-transition": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dagre": {
|
||||||
|
"version": "0.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz",
|
||||||
|
"integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==",
|
||||||
|
"requires": {
|
||||||
|
"graphlib": "^2.1.8",
|
||||||
|
"lodash": "^4.17.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dagre-d3": {
|
||||||
|
"version": "0.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz",
|
||||||
|
"integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3": "^5.14",
|
||||||
|
"dagre": "^0.8.5",
|
||||||
|
"graphlib": "^2.1.8",
|
||||||
|
"lodash": "^4.17.15"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"d3": {
|
||||||
|
"version": "5.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz",
|
||||||
|
"integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "1",
|
||||||
|
"d3-axis": "1",
|
||||||
|
"d3-brush": "1",
|
||||||
|
"d3-chord": "1",
|
||||||
|
"d3-collection": "1",
|
||||||
|
"d3-color": "1",
|
||||||
|
"d3-contour": "1",
|
||||||
|
"d3-dispatch": "1",
|
||||||
|
"d3-drag": "1",
|
||||||
|
"d3-dsv": "1",
|
||||||
|
"d3-ease": "1",
|
||||||
|
"d3-fetch": "1",
|
||||||
|
"d3-force": "1",
|
||||||
|
"d3-format": "1",
|
||||||
|
"d3-geo": "1",
|
||||||
|
"d3-hierarchy": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-path": "1",
|
||||||
|
"d3-polygon": "1",
|
||||||
|
"d3-quadtree": "1",
|
||||||
|
"d3-random": "1",
|
||||||
|
"d3-scale": "2",
|
||||||
|
"d3-scale-chromatic": "1",
|
||||||
|
"d3-selection": "1",
|
||||||
|
"d3-shape": "1",
|
||||||
|
"d3-time": "1",
|
||||||
|
"d3-time-format": "2",
|
||||||
|
"d3-timer": "1",
|
||||||
|
"d3-transition": "1",
|
||||||
|
"d3-voronoi": "1",
|
||||||
|
"d3-zoom": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-axis": {
|
||||||
|
"version": "1.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ=="
|
||||||
|
},
|
||||||
|
"d3-brush": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dispatch": "1",
|
||||||
|
"d3-drag": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-selection": "1",
|
||||||
|
"d3-transition": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-chord": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "1",
|
||||||
|
"d3-path": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-contour": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-dsv": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==",
|
||||||
|
"requires": {
|
||||||
|
"commander": "2",
|
||||||
|
"iconv-lite": "0.4",
|
||||||
|
"rw": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-fetch": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dsv": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-format": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
|
||||||
|
},
|
||||||
|
"d3-polygon": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
|
||||||
|
},
|
||||||
|
"d3-random": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ=="
|
||||||
|
},
|
||||||
|
"d3-scale": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^1.2.0",
|
||||||
|
"d3-collection": "1",
|
||||||
|
"d3-format": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-time": "1",
|
||||||
|
"d3-time-format": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-scale-chromatic": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==",
|
||||||
|
"requires": {
|
||||||
|
"d3-color": "1",
|
||||||
|
"d3-interpolate": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-time": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
|
||||||
|
},
|
||||||
|
"d3-time-format": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-time": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"damerau-levenshtein": {
|
"damerau-levenshtein": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
|
||||||
|
|
@ -10169,6 +10748,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
|
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
|
||||||
},
|
},
|
||||||
|
"graphlib": {
|
||||||
|
"version": "2.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
|
||||||
|
"integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
|
||||||
|
"requires": {
|
||||||
|
"lodash": "^4.17.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
"graphql": {
|
"graphql": {
|
||||||
"version": "15.3.0",
|
"version": "15.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz",
|
||||||
|
|
@ -15700,6 +16287,13 @@
|
||||||
"topojson-client": "^3.1.0",
|
"topojson-client": "^3.1.0",
|
||||||
"webgl-context": "^2.2.0",
|
"webgl-context": "^2.2.0",
|
||||||
"world-calendars": "^1.0.3"
|
"world-calendars": "^1.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"d3": {
|
||||||
|
"version": "3.5.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
||||||
|
"integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pn": {
|
"pn": {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
"@material-ui/pickers": "^3.2.10",
|
"@material-ui/pickers": "^3.2.10",
|
||||||
"ace-builds": "^1.4.12",
|
"ace-builds": "^1.4.12",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
|
"d3": "^5.16.0",
|
||||||
|
"dagre-d3": "^0.6.4",
|
||||||
"date-fns": "^2.14.0",
|
"date-fns": "^2.14.0",
|
||||||
"graphql": "^15.3.0",
|
"graphql": "^15.3.0",
|
||||||
"i18next": "^19.7.0",
|
"i18next": "^19.7.0",
|
||||||
|
|
@ -74,6 +76,8 @@
|
||||||
"not op_mini all"
|
"not op_mini all"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/d3": "^5.7.2",
|
||||||
|
"@types/dagre-d3": "^0.4.39",
|
||||||
"@types/js-yaml": "^3.12.5",
|
"@types/js-yaml": "^3.12.5",
|
||||||
"@types/jsonwebtoken": "^8.5.0",
|
"@types/jsonwebtoken": "^8.5.0",
|
||||||
"@types/plotly.js": "^1.50.15",
|
"@types/plotly.js": "^1.50.15",
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import Breadcrumbs from '@material-ui/core/Breadcrumbs';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import useStyles from './styles';
|
|
||||||
import { history } from '../../redux/configureStore';
|
import { history } from '../../redux/configureStore';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
interface CustomBreadcrumbsProps {
|
interface CustomBreadcrumbsProps {
|
||||||
location: string;
|
location: string;
|
||||||
|
|
@ -12,7 +12,7 @@ interface CustomBreadcrumbsProps {
|
||||||
const CustomBreadcrumbs: React.FC<CustomBreadcrumbsProps> = ({ location }) => {
|
const CustomBreadcrumbs: React.FC<CustomBreadcrumbsProps> = ({ location }) => {
|
||||||
const path: string[] = location.split('/');
|
const path: string[] = location.split('/');
|
||||||
|
|
||||||
let intermediatRoutes: string = '/';
|
let intermediateRoutes: string = '/';
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
|
|
@ -22,11 +22,12 @@ const CustomBreadcrumbs: React.FC<CustomBreadcrumbsProps> = ({ location }) => {
|
||||||
<Breadcrumbs aria-label="breadcrumb">
|
<Breadcrumbs aria-label="breadcrumb">
|
||||||
{path.map((path: string) => {
|
{path.map((path: string) => {
|
||||||
if (path) {
|
if (path) {
|
||||||
intermediatRoutes += path;
|
intermediateRoutes += path;
|
||||||
|
|
||||||
const link = (
|
const link = (
|
||||||
<Link
|
<Link
|
||||||
to={intermediatRoutes}
|
key={path}
|
||||||
|
to={intermediateRoutes}
|
||||||
className={classes.breadCrumb}
|
className={classes.breadCrumb}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.push(`/${path}`);
|
history.push(`/${path}`);
|
||||||
|
|
@ -36,7 +37,7 @@ const CustomBreadcrumbs: React.FC<CustomBreadcrumbsProps> = ({ location }) => {
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|
||||||
intermediatRoutes += '/';
|
intermediateRoutes += '/';
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
import * as d3 from 'd3';
|
||||||
|
import dagreD3, { GraphLabel, Node } from 'dagre-d3';
|
||||||
|
import React, { Component, createRef } from 'react';
|
||||||
|
|
||||||
|
interface GraphProps {
|
||||||
|
nodes: d3Node[];
|
||||||
|
links: d3Link[];
|
||||||
|
zoomable?: boolean;
|
||||||
|
fitBoundaries?: boolean;
|
||||||
|
height?: string;
|
||||||
|
width?: string;
|
||||||
|
config?: GraphLabel;
|
||||||
|
animate?: number;
|
||||||
|
className?: string;
|
||||||
|
shape?: shapes;
|
||||||
|
onNodeClick?: nodeClick;
|
||||||
|
onRelationshipClick?: relationshipClick;
|
||||||
|
}
|
||||||
|
type shapes = 'rect' | 'circle' | 'ellipse';
|
||||||
|
type labelType = 'html' | 'svg' | 'string';
|
||||||
|
|
||||||
|
type nodeClick = (nodeData: {
|
||||||
|
d3node: Node;
|
||||||
|
original: d3Node | undefined;
|
||||||
|
}) => void;
|
||||||
|
|
||||||
|
type relationshipClick = (nodeData: {
|
||||||
|
d3source: Node;
|
||||||
|
source: d3Node | undefined;
|
||||||
|
d3target: Node;
|
||||||
|
target: d3Node | undefined;
|
||||||
|
}) => void;
|
||||||
|
|
||||||
|
export type d3Node = {
|
||||||
|
id: any;
|
||||||
|
label: string;
|
||||||
|
class?: string;
|
||||||
|
labelType?: labelType;
|
||||||
|
config?: object;
|
||||||
|
};
|
||||||
|
export type d3Link = {
|
||||||
|
source: string;
|
||||||
|
target: string;
|
||||||
|
class?: string;
|
||||||
|
label?: string;
|
||||||
|
config?: object;
|
||||||
|
};
|
||||||
|
type Relationship = {
|
||||||
|
v: any;
|
||||||
|
w: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DagreGraph extends Component<GraphProps> {
|
||||||
|
svg = createRef<SVGSVGElement>();
|
||||||
|
innerG = createRef<SVGSVGElement>();
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
zoomable: false,
|
||||||
|
fitBoundaries: false,
|
||||||
|
className: 'dagre-d3-react',
|
||||||
|
};
|
||||||
|
componentDidMount() {
|
||||||
|
this._drawChart();
|
||||||
|
}
|
||||||
|
componentDidUpdate() {
|
||||||
|
this._drawChart();
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawChart = () => {
|
||||||
|
const {
|
||||||
|
nodes,
|
||||||
|
links,
|
||||||
|
zoomable,
|
||||||
|
fitBoundaries,
|
||||||
|
config,
|
||||||
|
animate,
|
||||||
|
shape,
|
||||||
|
onNodeClick,
|
||||||
|
onRelationshipClick,
|
||||||
|
} = this.props;
|
||||||
|
const g = new dagreD3.graphlib.Graph().setGraph(config || {});
|
||||||
|
|
||||||
|
nodes.forEach((node) =>
|
||||||
|
g.setNode(node.id, {
|
||||||
|
label: node.label,
|
||||||
|
class: node.class || '',
|
||||||
|
labelType: node.labelType || 'string',
|
||||||
|
...node.config,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shape) {
|
||||||
|
g.nodes().forEach((v) => {
|
||||||
|
g.node(v).shape = shape;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
links.forEach((link) => {
|
||||||
|
g.setEdge(link.source, link.target, {
|
||||||
|
label: link.label || '',
|
||||||
|
class: link.class || '',
|
||||||
|
...link.config,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const render = new dagreD3.render();
|
||||||
|
const svg: any = d3.select(this.svg.current);
|
||||||
|
const inner: any = d3.select(this.innerG.current);
|
||||||
|
|
||||||
|
const zoom = d3
|
||||||
|
.zoom()
|
||||||
|
.on('zoom', () => inner.attr('transform', d3.event.transform));
|
||||||
|
|
||||||
|
if (zoomable) {
|
||||||
|
svg.call(zoom);
|
||||||
|
}
|
||||||
|
if (animate) {
|
||||||
|
g.graph().transition = function transition(selection) {
|
||||||
|
return selection.transition().duration(animate || 1000);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render(inner, g);
|
||||||
|
|
||||||
|
if (fitBoundaries) {
|
||||||
|
// @BertCh recommendation for fitting boundaries
|
||||||
|
const { width, height, x, y } = inner.node().getBBox();
|
||||||
|
const parent = inner.node().parentElement || inner.node().parentNode;
|
||||||
|
const fullWidth = parent.clientWidth || parent.parentNode.clientWidth;
|
||||||
|
const fullHeight = parent.clientHeight || parent.parentNode.clientHeight;
|
||||||
|
const midX = x + width / 2;
|
||||||
|
const midY = y + height / 2;
|
||||||
|
|
||||||
|
if (width === 0 || height === 0) return; // nothing to fit
|
||||||
|
const scale = 0.9 / Math.max(width / fullWidth, height / fullHeight);
|
||||||
|
const translate = [
|
||||||
|
fullWidth / 2 - scale * midX,
|
||||||
|
fullHeight / 2 - scale * midY,
|
||||||
|
];
|
||||||
|
const transform = d3.zoomIdentity
|
||||||
|
.translate(translate[0], translate[1])
|
||||||
|
.scale(scale);
|
||||||
|
|
||||||
|
svg
|
||||||
|
.transition()
|
||||||
|
.duration(animate || 0) // milliseconds
|
||||||
|
.call(zoom.transform, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onNodeClick) {
|
||||||
|
svg.selectAll('g.node').on('click', (id: any) => {
|
||||||
|
const _node: Node = g.node(id);
|
||||||
|
const _original = this._getNodeData(id);
|
||||||
|
onNodeClick({ d3node: _node, original: _original });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (onRelationshipClick) {
|
||||||
|
svg
|
||||||
|
.selectAll('g.edgeLabel, g.edgePath')
|
||||||
|
.on('click', (id: Relationship) => {
|
||||||
|
const _source = g.node(id.v);
|
||||||
|
const _original_source = this._getNodeData(id.v);
|
||||||
|
|
||||||
|
const _target = g.node(id.w);
|
||||||
|
const _original_target = this._getNodeData(id.w);
|
||||||
|
onRelationshipClick({
|
||||||
|
d3source: _source,
|
||||||
|
source: _original_source,
|
||||||
|
d3target: _target,
|
||||||
|
target: _original_target,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_getNodeData(id: any) {
|
||||||
|
const { nodes } = this.props;
|
||||||
|
return nodes.find((node) => node.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { width, height, className } = this.props;
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
ref={this.svg}
|
||||||
|
className={className || ''}
|
||||||
|
>
|
||||||
|
<g ref={this.innerG} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DagreGraph;
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
|
IconButton,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
Popover,
|
||||||
TableCell,
|
TableCell,
|
||||||
Typography,
|
Typography,
|
||||||
IconButton,
|
|
||||||
MenuItem,
|
|
||||||
Menu,
|
|
||||||
Popover,
|
|
||||||
Button,
|
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
|
||||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
|
||||||
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
||||||
|
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||||
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import useStyles from './styles';
|
import React from 'react';
|
||||||
import LinearProgressBar from '../../ReturningHome/ProgressBar/LinearProgressBar';
|
|
||||||
import { history } from '../../../../redux/configureStore';
|
|
||||||
import { WorkflowRun } from '../../../../models/workflowData';
|
import { WorkflowRun } from '../../../../models/workflowData';
|
||||||
|
import { history } from '../../../../redux/configureStore';
|
||||||
|
import LinearProgressBar from '../../ReturningHome/ProgressBar/LinearProgressBar';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
interface TableDataProps {
|
interface TableDataProps {
|
||||||
data: WorkflowRun;
|
data: WorkflowRun;
|
||||||
|
|
@ -170,10 +170,7 @@ const TableData: React.FC<TableDataProps> = ({ data, deleteRow }) => {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
value="Workflow"
|
value="Workflow"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
history.push({
|
history.push(`/workflows/${data.workflow_name}/schedule`)
|
||||||
pathname: '/schedule',
|
|
||||||
state: data,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className={classes.expDiv}>
|
<div className={classes.expDiv}>
|
||||||
|
|
@ -1,64 +1,62 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import SearchIcon from '@material-ui/icons/Search';
|
|
||||||
import {
|
import {
|
||||||
InputBase,
|
|
||||||
InputAdornment,
|
|
||||||
FormControl,
|
FormControl,
|
||||||
InputLabel,
|
|
||||||
Select,
|
|
||||||
MenuItem,
|
|
||||||
Typography,
|
|
||||||
TableContainer,
|
|
||||||
Table,
|
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
TableCell,
|
|
||||||
TableBody,
|
|
||||||
TablePagination,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
|
InputAdornment,
|
||||||
|
InputBase,
|
||||||
|
InputLabel,
|
||||||
|
MenuItem,
|
||||||
|
Select,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TablePagination,
|
||||||
|
TableRow,
|
||||||
|
Typography,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
||||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import React, { useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import useStyles from './styles';
|
|
||||||
import { WORKFLOW_DETAILS } from '../../../../graphql';
|
import { WORKFLOW_DETAILS } from '../../../../graphql';
|
||||||
import TableData from './TableData';
|
|
||||||
import {
|
import {
|
||||||
|
ExecutionData,
|
||||||
Workflow,
|
Workflow,
|
||||||
WorkflowDataVars,
|
WorkflowDataVars,
|
||||||
WorkflowRun,
|
WorkflowRun,
|
||||||
ExecutionData,
|
|
||||||
} from '../../../../models/workflowData';
|
} from '../../../../models/workflowData';
|
||||||
import Loader from '../../../Loader';
|
import { RootState } from '../../../../redux/reducers';
|
||||||
import {
|
import {
|
||||||
sortAlphaAsc,
|
sortAlphaAsc,
|
||||||
sortAlphaDesc,
|
sortAlphaDesc,
|
||||||
sortNumAsc,
|
sortNumAsc,
|
||||||
sortNumDesc,
|
sortNumDesc,
|
||||||
} from '../../../../utils/sort';
|
} from '../../../../utils/sort';
|
||||||
import { UserData } from '../../../../models/user';
|
import Loader from '../../../Loader';
|
||||||
import { RootState } from '../../../../redux/reducers';
|
import useStyles from './styles';
|
||||||
|
import TableData from './TableData';
|
||||||
|
|
||||||
interface FilterOption {
|
interface FilterOption {
|
||||||
search: string;
|
search: string;
|
||||||
cluster: string;
|
cluster: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PaginationData {
|
interface PaginationData {
|
||||||
pageNo: number;
|
pageNo: number;
|
||||||
rowsPerPage: number;
|
rowsPerPage: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SortData {
|
interface SortData {
|
||||||
startDate: { sort: boolean; ascending: boolean };
|
startDate: { sort: boolean; ascending: boolean };
|
||||||
name: { sort: boolean; ascending: boolean };
|
name: { sort: boolean; ascending: boolean };
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScheduleWorkflow = () => {
|
const BrowseSchedule = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const userData: UserData = useSelector((state: RootState) => state.userData);
|
const selectedProjectID = useSelector(
|
||||||
const { selectedProjectID } = userData;
|
(state: RootState) => state.userData.selectedProjectID
|
||||||
|
);
|
||||||
|
|
||||||
// Apollo query to get the scheduled data
|
// Apollo query to get the scheduled data
|
||||||
const { data, loading, error } = useQuery<Workflow, WorkflowDataVars>(
|
const { data, loading, error } = useQuery<Workflow, WorkflowDataVars>(
|
||||||
|
|
@ -329,4 +327,4 @@ const ScheduleWorkflow = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ScheduleWorkflow;
|
export default BrowseSchedule;
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
|
import { Divider, Typography } from '@material-ui/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Typography, Divider } from '@material-ui/core';
|
|
||||||
import useStyles from './styles';
|
|
||||||
import { preDefinedWorkflowData } from '../../../../models';
|
|
||||||
import Head from './Head';
|
|
||||||
import ExperimentDetails from './ExperimentDetails';
|
|
||||||
import Recommendation from './Recommendation';
|
|
||||||
import Scaffold from '../../../../containers/layouts/Scaffold';
|
import Scaffold from '../../../../containers/layouts/Scaffold';
|
||||||
import ButtonOutlined from '../../../Button/ButtonOutline';
|
import { preDefinedWorkflowData } from '../../../../models/predefinedWorkflow';
|
||||||
|
import { LocationState } from '../../../../models/routerModel';
|
||||||
import { history } from '../../../../redux/configureStore';
|
import { history } from '../../../../redux/configureStore';
|
||||||
import ButtonFilled from '../../../Button/ButtonFilled';
|
import ButtonFilled from '../../../Button/ButtonFilled';
|
||||||
import { LocationState } from '../../../../models/routerModel';
|
import ButtonOutlined from '../../../Button/ButtonOutline';
|
||||||
|
import ExperimentDetails from './ExperimentDetails';
|
||||||
|
import Head from './Head';
|
||||||
|
import Recommendation from './Recommendation';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
interface LocationObjectProps {
|
interface LocationObjectProps {
|
||||||
workflowData: preDefinedWorkflowData;
|
workflowData: preDefinedWorkflowData;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
|
IconButton,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
TableCell,
|
TableCell,
|
||||||
Typography,
|
Typography,
|
||||||
IconButton,
|
|
||||||
MenuItem,
|
|
||||||
Menu,
|
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||||
import CustomStatus from '../CustomStatus/Status';
|
import React from 'react';
|
||||||
import LinearProgressBar from '../../ReturningHome/ProgressBar/LinearProgressBar';
|
import { ExecutionData, WorkflowRun } from '../../../../models/workflowData';
|
||||||
import useStyles from './styles';
|
|
||||||
import timeDifferenceForDate from '../../../../utils/datesModifier';
|
|
||||||
import { history } from '../../../../redux/configureStore';
|
import { history } from '../../../../redux/configureStore';
|
||||||
import { WorkflowRun, ExecutionData } from '../../../../models/workflowData';
|
import timeDifferenceForDate from '../../../../utils/datesModifier';
|
||||||
|
import LinearProgressBar from '../../ReturningHome/ProgressBar/LinearProgressBar';
|
||||||
|
import CustomStatus from '../CustomStatus/Status';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
interface TableDataProps {
|
interface TableDataProps {
|
||||||
data: WorkflowRun;
|
data: WorkflowRun;
|
||||||
|
|
@ -99,10 +99,7 @@ const TableData: React.FC<TableDataProps> = ({ data, exeData }) => {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
value="Workflow"
|
value="Workflow"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
history.push({
|
history.push(`/workflows/${data.workflow_name}/details`)
|
||||||
pathname: '/workflows/workflow-underground',
|
|
||||||
state: data,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Show the workflow
|
Show the workflow
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,12 @@ import {
|
||||||
TableRow,
|
TableRow,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import moment from 'moment';
|
|
||||||
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
||||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||||
|
import moment from 'moment';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { WORKFLOW_DETAILS, WORKFLOW_EVENTS } from '../../../../graphql';
|
import { WORKFLOW_DETAILS, WORKFLOW_EVENTS } from '../../../../graphql';
|
||||||
import { UserData } from '../../../../models/user';
|
|
||||||
import {
|
import {
|
||||||
ExecutionData,
|
ExecutionData,
|
||||||
Workflow,
|
Workflow,
|
||||||
|
|
@ -25,16 +24,15 @@ import {
|
||||||
WorkflowSubscription,
|
WorkflowSubscription,
|
||||||
} from '../../../../models/workflowData';
|
} from '../../../../models/workflowData';
|
||||||
import { RootState } from '../../../../redux/reducers';
|
import { RootState } from '../../../../redux/reducers';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
sortAlphaAsc,
|
sortAlphaAsc,
|
||||||
sortAlphaDesc,
|
sortAlphaDesc,
|
||||||
sortNumAsc,
|
sortNumAsc,
|
||||||
sortNumDesc,
|
sortNumDesc,
|
||||||
} from '../../../../utils/sort';
|
} from '../../../../utils/sort';
|
||||||
|
import HeaderSection from './HeaderSection';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import TableData from './TableData';
|
import TableData from './TableData';
|
||||||
import HeaderSection from './headerSection';
|
|
||||||
|
|
||||||
interface FilterOptions {
|
interface FilterOptions {
|
||||||
search: string;
|
search: string;
|
||||||
|
|
@ -61,8 +59,9 @@ interface DateData {
|
||||||
|
|
||||||
const BrowseWorkflow = () => {
|
const BrowseWorkflow = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const userData: UserData = useSelector((state: RootState) => state.userData);
|
const selectedProjectID = useSelector(
|
||||||
const { selectedProjectID } = userData;
|
(state: RootState) => state.userData.selectedProjectID
|
||||||
|
);
|
||||||
|
|
||||||
// Query to get workflows
|
// Query to get workflows
|
||||||
const { subscribeToMore, data, error } = useQuery<Workflow, WorkflowDataVars>(
|
const { subscribeToMore, data, error } = useQuery<Workflow, WorkflowDataVars>(
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PredifinedWorkflows from '../../../PredifinedWorkflows';
|
|
||||||
import workflowData from '../../../PredifinedWorkflows/data';
|
|
||||||
import { history } from '../../../../redux/configureStore';
|
import { history } from '../../../../redux/configureStore';
|
||||||
import parsed from '../../../../utils/yamlUtils';
|
import parsed from '../../../../utils/yamlUtils';
|
||||||
|
import PredifinedWorkflows from '../../../PredifinedWorkflows';
|
||||||
|
import workflowData from '../../../PredifinedWorkflows/data';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
|
|
||||||
const Templates = () => {
|
const Templates = () => {
|
||||||
|
|
@ -24,7 +24,7 @@ const Templates = () => {
|
||||||
testWeights.push(10);
|
testWeights.push(10);
|
||||||
});
|
});
|
||||||
history.push({
|
history.push({
|
||||||
pathname: `/workflows/${workflowData[index].title}`,
|
pathname: `/workflows/${workflowData[index].title}/template`,
|
||||||
state: {
|
state: {
|
||||||
workflowData: workflowData[index],
|
workflowData: workflowData[index],
|
||||||
testNames,
|
testNames,
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
import { AppBar, Box, Typography } from '@material-ui/core';
|
|
||||||
import { createStyles, withStyles } from '@material-ui/core/styles';
|
|
||||||
import Tab from '@material-ui/core/Tab';
|
|
||||||
import Tabs from '@material-ui/core/Tabs';
|
|
||||||
import React from 'react';
|
|
||||||
import { history } from '../../../../redux/configureStore';
|
|
||||||
import ButtonFilled from '../../../Button/ButtonFilled';
|
|
||||||
import BrowseWorkflow from '../BrowseWorkflow';
|
|
||||||
import useStyles from './styles';
|
|
||||||
import ScheduleWorkflow from '../ScheduleWorkflow';
|
|
||||||
import Templates from '../Templates';
|
|
||||||
|
|
||||||
interface TabPanelProps {
|
|
||||||
children?: React.ReactNode;
|
|
||||||
index: number;
|
|
||||||
value: number;
|
|
||||||
}
|
|
||||||
const TabPanel: React.FC<TabPanelProps> = ({ children, index, value }) => {
|
|
||||||
return (
|
|
||||||
<div role="tabpanel" hidden={value !== index}>
|
|
||||||
{value === index && (
|
|
||||||
<Box p={3}>
|
|
||||||
<>{children}</>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
interface StyledTabProps {
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
const StyledTab = withStyles((theme) =>
|
|
||||||
createStyles({
|
|
||||||
root: {
|
|
||||||
textTransform: 'none',
|
|
||||||
color: 'rgba(0,0,0,0.5)',
|
|
||||||
fontSize: '0.95rem',
|
|
||||||
paddingTop: theme.spacing(1.875),
|
|
||||||
paddingBottom: theme.spacing(1.875),
|
|
||||||
width: '15.9375rem',
|
|
||||||
'&:focus': {
|
|
||||||
opacity: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
)((props: StyledTabProps) => <Tab {...props} />);
|
|
||||||
|
|
||||||
const CenteredTabs = () => {
|
|
||||||
const classes = useStyles();
|
|
||||||
const [value, setValue] = React.useState(0);
|
|
||||||
|
|
||||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
|
||||||
setValue(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<section className="Header section">
|
|
||||||
<div className={classes.header}>
|
|
||||||
<Typography variant="h4">Chaos Workflows</Typography>
|
|
||||||
<div className={classes.scheduleBtn}>
|
|
||||||
<ButtonFilled
|
|
||||||
isPrimary={false}
|
|
||||||
handleClick={() => history.push('/create-workflow')}
|
|
||||||
>
|
|
||||||
<>Schedule a workflow</>
|
|
||||||
</ButtonFilled>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<AppBar position="static" color="default" className={classes.appBar}>
|
|
||||||
<Tabs
|
|
||||||
value={value}
|
|
||||||
onChange={handleChange}
|
|
||||||
indicatorColor="secondary"
|
|
||||||
textColor="secondary"
|
|
||||||
variant="fullWidth"
|
|
||||||
>
|
|
||||||
<StyledTab label="Browse workflows" />
|
|
||||||
<StyledTab label="Schedules" />
|
|
||||||
<StyledTab label="Templates" />
|
|
||||||
<StyledTab label="Analytics" />
|
|
||||||
</Tabs>
|
|
||||||
</AppBar>
|
|
||||||
<TabPanel value={value} index={0}>
|
|
||||||
<BrowseWorkflow />
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel value={value} index={1}>
|
|
||||||
<ScheduleWorkflow />
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel value={value} index={2}>
|
|
||||||
<Templates />
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel value={value} index={3}>
|
|
||||||
Item Four
|
|
||||||
</TabPanel>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default CenteredTabs;
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
import { makeStyles } from '@material-ui/core';
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
|
||||||
header: {
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginTop: theme.spacing(2.5),
|
|
||||||
marginBottom: theme.spacing(2.5),
|
|
||||||
},
|
|
||||||
scheduleBtn: {
|
|
||||||
marginLeft: 'auto',
|
|
||||||
},
|
|
||||||
appBar: {
|
|
||||||
background: 'transparent',
|
|
||||||
boxShadow: 'none',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default useStyles;
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
|
|
@ -6,16 +7,14 @@ import {
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import Radio from '@material-ui/core/Radio';
|
import Radio from '@material-ui/core/Radio';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useLazyQuery } from '@apollo/client';
|
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
import { GET_CLUSTER } from '../../../../graphql';
|
||||||
|
import useActions from '../../../../redux/actions';
|
||||||
|
import * as WorkflowActions from '../../../../redux/actions/workflow';
|
||||||
|
import { RootState } from '../../../../redux/reducers';
|
||||||
import ButtonFilled from '../../../Button/ButtonFilled';
|
import ButtonFilled from '../../../Button/ButtonFilled';
|
||||||
import ButtonOutLine from '../../../Button/ButtonOutline';
|
import ButtonOutLine from '../../../Button/ButtonOutline';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import { GET_CLUSTER } from '../../../../graphql';
|
|
||||||
import { RootState } from '../../../../redux/reducers';
|
|
||||||
import { UserData } from '../../../../models/user';
|
|
||||||
import useActions from '../../../../redux/actions';
|
|
||||||
import * as WorkflowActions from '../../../../redux/actions/workflow';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check is image which is used as
|
Check is image which is used as
|
||||||
|
|
@ -41,7 +40,9 @@ const WorkflowCluster: React.FC<WorkflowClusterProps> = ({ gotoStep }) => {
|
||||||
const workflow = useActions(WorkflowActions);
|
const workflow = useActions(WorkflowActions);
|
||||||
const [isTragetSelected, setTarget] = React.useState(true);
|
const [isTragetSelected, setTarget] = React.useState(true);
|
||||||
const [isRegistered, setRegistration] = React.useState(true);
|
const [isRegistered, setRegistration] = React.useState(true);
|
||||||
const userData: UserData = useSelector((state: RootState) => state.userData);
|
const selectedProjectID = useSelector(
|
||||||
|
(state: RootState) => state.userData.selectedProjectID
|
||||||
|
);
|
||||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setValue((event.target as HTMLInputElement).value);
|
setValue((event.target as HTMLInputElement).value);
|
||||||
};
|
};
|
||||||
|
|
@ -51,7 +52,7 @@ const WorkflowCluster: React.FC<WorkflowClusterProps> = ({ gotoStep }) => {
|
||||||
if (data && data.getCluster.length !== 0) {
|
if (data && data.getCluster.length !== 0) {
|
||||||
workflow.setWorkflowDetails({
|
workflow.setWorkflowDetails({
|
||||||
clusterid: data.getCluster[0].cluster_id,
|
clusterid: data.getCluster[0].cluster_id,
|
||||||
project_id: userData.selectedProjectID,
|
project_id: selectedProjectID,
|
||||||
});
|
});
|
||||||
gotoStep(1);
|
gotoStep(1);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -63,7 +64,7 @@ const WorkflowCluster: React.FC<WorkflowClusterProps> = ({ gotoStep }) => {
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
getCluster({
|
getCluster({
|
||||||
variables: {
|
variables: {
|
||||||
project_id: userData.selectedProjectID,
|
project_id: selectedProjectID,
|
||||||
cluster_type: 'internal',
|
cluster_type: 'internal',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Nodes } from '../../../../models/workflowData';
|
||||||
|
import useActions from '../../../../redux/actions';
|
||||||
|
import * as NodeSelectionActions from '../../../../redux/actions/nodeSelection';
|
||||||
|
import DagreGraph, { d3Link, d3Node } from '../../../DagreGraph';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
|
interface GraphData {
|
||||||
|
nodes: d3Node[];
|
||||||
|
links: d3Link[];
|
||||||
|
}
|
||||||
|
interface ArgoWorkflowProps {
|
||||||
|
nodes: Nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArgoWorkflow: React.FC<ArgoWorkflowProps> = ({ nodes }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
// Redux action call for updating selected node
|
||||||
|
const nodeSelection = useActions(NodeSelectionActions);
|
||||||
|
|
||||||
|
const [graphData, setGraphData] = useState<GraphData>({
|
||||||
|
nodes: [],
|
||||||
|
links: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const data: GraphData = {
|
||||||
|
nodes: [],
|
||||||
|
links: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const key of Object.keys(nodes)) {
|
||||||
|
const node = nodes[key];
|
||||||
|
|
||||||
|
data.nodes.push({
|
||||||
|
id: key,
|
||||||
|
class: `${node.phase} ${node.type}`,
|
||||||
|
label: node.type !== 'StepGroup' ? node.name : '',
|
||||||
|
labelType: 'html',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (node.children) {
|
||||||
|
node.children.map((child) =>
|
||||||
|
data.links.push({
|
||||||
|
source: key,
|
||||||
|
target: child,
|
||||||
|
config: {
|
||||||
|
arrowheadStyle: 'display: arrowhead',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setGraphData({
|
||||||
|
nodes: [...data.nodes],
|
||||||
|
links: [...data.links],
|
||||||
|
});
|
||||||
|
}, [nodes]);
|
||||||
|
|
||||||
|
return graphData.nodes.length ? (
|
||||||
|
<DagreGraph
|
||||||
|
className={classes.dagreGraph}
|
||||||
|
nodes={graphData.nodes}
|
||||||
|
links={graphData.links}
|
||||||
|
config={{
|
||||||
|
ranker: 'tight-tree',
|
||||||
|
}}
|
||||||
|
animate={1000}
|
||||||
|
shape="rect"
|
||||||
|
fitBoundaries
|
||||||
|
zoomable
|
||||||
|
onNodeClick={({ original }) => {
|
||||||
|
const nodeID = Object.keys(nodes).filter(
|
||||||
|
(key) => key === original?.id
|
||||||
|
)[0];
|
||||||
|
nodeSelection.selectNode(nodes[nodeID]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div>Loading Graph...</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArgoWorkflow;
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { makeStyles, Theme } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
|
dagreGraph: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
|
||||||
|
// Styles for nodes
|
||||||
|
'& g g.nodes': {
|
||||||
|
'& g.node': {
|
||||||
|
cursor: 'pointer',
|
||||||
|
color: theme.palette.common.white,
|
||||||
|
'& rect': {
|
||||||
|
rx: '0.2rem',
|
||||||
|
ry: '0.2rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'& g.Succeeded': {
|
||||||
|
fill: theme.palette.primary.dark,
|
||||||
|
},
|
||||||
|
'& g.Running': {
|
||||||
|
fill: theme.palette.warning.main,
|
||||||
|
},
|
||||||
|
'& g.Pending': {
|
||||||
|
fill: theme.palette.customColors.gray,
|
||||||
|
},
|
||||||
|
'& g.Failed': {
|
||||||
|
fill: theme.palette.error.dark,
|
||||||
|
},
|
||||||
|
'& g.StepGroup': {
|
||||||
|
fill: theme.palette.customColors.gray,
|
||||||
|
cursor: 'default',
|
||||||
|
'& rect': {
|
||||||
|
rx: '0.625rem !important',
|
||||||
|
ry: '0.625rem !important',
|
||||||
|
transform: 'scale(0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Styles for edges
|
||||||
|
'& g g.edgePaths': {
|
||||||
|
stroke: theme.palette.customColors.gray,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default useStyles;
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
// TODO: remove this after creating UI for node details sidebar
|
||||||
|
import { Typography } from '@material-ui/core';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { ExecutionData } from '../../../../models/workflowData';
|
||||||
|
import { RootState } from '../../../../redux/reducers';
|
||||||
|
import timeDifference from '../../../../utils/datesModifier';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
|
interface WorkflowInfoProps {
|
||||||
|
workflow_name: string;
|
||||||
|
execution_data: ExecutionData;
|
||||||
|
cluster_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SidebarState {
|
||||||
|
currentRunningNodes: string[];
|
||||||
|
executedNodes: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorkflowInfo: React.FC<WorkflowInfoProps> = ({
|
||||||
|
workflow_name,
|
||||||
|
execution_data,
|
||||||
|
cluster_name,
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
// Get selected node data from redux
|
||||||
|
const selectedNode = useSelector((state: RootState) => state.selectedNode);
|
||||||
|
|
||||||
|
const [duration, setDuration] = useState<number>(0);
|
||||||
|
const [data, setData] = useState<SidebarState>({
|
||||||
|
currentRunningNodes: [],
|
||||||
|
executedNodes: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDuration(
|
||||||
|
(parseInt(execution_data.finishedAt, 10) -
|
||||||
|
parseInt(execution_data.startedAt, 10)) /
|
||||||
|
60
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the Workflow is Running [Data is being received through Subscription]
|
||||||
|
// Set the currently executed node in a local state
|
||||||
|
const executedNodes: string[] = [];
|
||||||
|
const currentRunningNodes: string[] = [];
|
||||||
|
|
||||||
|
for (const val of Object.values(execution_data.nodes))
|
||||||
|
if (val.type !== 'StepGroup' && val.phase === 'Running')
|
||||||
|
currentRunningNodes.push(val.name);
|
||||||
|
else if (val.type !== 'StepGroup' && val.phase === 'Succeeded')
|
||||||
|
executedNodes.push(val.name);
|
||||||
|
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
currentRunningNodes,
|
||||||
|
executedNodes,
|
||||||
|
});
|
||||||
|
}, [execution_data.nodes, execution_data.phase]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.root}>
|
||||||
|
{/* Workflow Information */}
|
||||||
|
<Typography className={classes.header} variant="h6">
|
||||||
|
<span className={classes.bold}>Workflow Information</span>
|
||||||
|
</Typography>
|
||||||
|
<hr className={classes.divider} />
|
||||||
|
<div className={classes.heightMaintainer}>
|
||||||
|
<Typography className={classes.workflowSpacing}>
|
||||||
|
<span className={classes.bold}>Workflow name:</span>
|
||||||
|
<br />
|
||||||
|
{workflow_name}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
{/* Workflow Details
|
||||||
|
@param State
|
||||||
|
@param Start Time
|
||||||
|
@param End Time
|
||||||
|
@param Duration
|
||||||
|
@param Namespace */}
|
||||||
|
|
||||||
|
<div className={classes.workflowSpacing}>
|
||||||
|
<div className={classes.heightMaintainer}>
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>State:</span> {execution_data.phase}
|
||||||
|
</Typography>
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>Start time:</span>{' '}
|
||||||
|
{timeDifference(execution_data.startedAt)}
|
||||||
|
</Typography>
|
||||||
|
{execution_data.phase !== 'Running' ? (
|
||||||
|
<>
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>End time:</span>{' '}
|
||||||
|
{timeDifference(execution_data.finishedAt)}
|
||||||
|
</Typography>
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>Duration:</span>{' '}
|
||||||
|
{`${duration.toFixed(1)} minutes`}
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>Namespace:</span>{' '}
|
||||||
|
{execution_data.namespace}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
{/* Workflow Node Details
|
||||||
|
@param Currently Running Node
|
||||||
|
@param Executed Nodes */}
|
||||||
|
|
||||||
|
<div className={classes.workflowSpacing}>
|
||||||
|
<div className={classes.heightMaintainer}>
|
||||||
|
{execution_data.phase === 'Running' ? (
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>Currently Running Nodes:</span>{' '}
|
||||||
|
<ul>
|
||||||
|
{data.currentRunningNodes.map((node) => (
|
||||||
|
<li key={node}>{node}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>Executed Nodes:</span>{' '}
|
||||||
|
{data.executedNodes.length ? (
|
||||||
|
<ul>
|
||||||
|
{data.executedNodes.map((node) => (
|
||||||
|
<li key={node}>{node}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
) : (
|
||||||
|
<Typography>No executed nodes</Typography>
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
{/* Cluster Details
|
||||||
|
@param Cluster Name */}
|
||||||
|
|
||||||
|
<div className={classes.workflowSpacing}>
|
||||||
|
<div className={classes.heightMaintainer}>
|
||||||
|
<Typography>
|
||||||
|
<span className={classes.bold}>Cluster:</span> {cluster_name}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WorkflowInfo;
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
/* eslint-disable */
|
|
||||||
|
|
||||||
import { Typography } from '@material-ui/core';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { ExecutionData, Node } from '../../../../models/workflowData';
|
|
||||||
import timeDifference from '../../../../utils/datesModifier';
|
|
||||||
import useStyles from './styles';
|
|
||||||
|
|
||||||
interface WorkflowRepresentationProps {
|
|
||||||
workflow_name: string;
|
|
||||||
execution_data: string;
|
|
||||||
cluster_name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SidebarProps extends ExecutionData {
|
|
||||||
current_running_node: string[];
|
|
||||||
executed_nodes: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const SideBar: React.FC<WorkflowRepresentationProps> = ({
|
|
||||||
workflow_name,
|
|
||||||
execution_data,
|
|
||||||
cluster_name,
|
|
||||||
}) => {
|
|
||||||
const classes = useStyles();
|
|
||||||
|
|
||||||
const [duration, setDuration] = useState<number>(0);
|
|
||||||
const [data, setData] = useState<SidebarProps>({
|
|
||||||
creationTimestamp: '',
|
|
||||||
event_type: '',
|
|
||||||
finishedAt: '',
|
|
||||||
name: '',
|
|
||||||
namespace: '',
|
|
||||||
nodes: {},
|
|
||||||
current_running_node: [],
|
|
||||||
executed_nodes: [],
|
|
||||||
phase: '',
|
|
||||||
startedAt: '',
|
|
||||||
uid: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (execution_data !== undefined) {
|
|
||||||
const execData = JSON.parse(execution_data) as ExecutionData;
|
|
||||||
|
|
||||||
// Setting initial data to the data received from query/subscription
|
|
||||||
setData({
|
|
||||||
...data,
|
|
||||||
...execData,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [(JSON.parse(execution_data) as ExecutionData).phase]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setDuration(
|
|
||||||
(parseInt(data.finishedAt, 10) - parseInt(data.startedAt, 10)) / 60
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the Workflow is Running [Data is being received through Subscription]
|
|
||||||
// Set the currently executed node in a local state
|
|
||||||
|
|
||||||
if (data.phase === 'Running' && data.nodes !== undefined) {
|
|
||||||
const dataObj: Node[] = Object.values(data.nodes as Node);
|
|
||||||
|
|
||||||
const currentlyRunningNodes: string[] = [];
|
|
||||||
|
|
||||||
dataObj.map((val) => {
|
|
||||||
if (val.type !== 'StepGroup' && val.phase === 'Running') {
|
|
||||||
currentlyRunningNodes.push(val.name);
|
|
||||||
}
|
|
||||||
setData({
|
|
||||||
...data,
|
|
||||||
current_running_node: [
|
|
||||||
...data.executed_nodes,
|
|
||||||
...currentlyRunningNodes,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// If the Workflow has Succeeded or Failed
|
|
||||||
// Store all the executed nodes in an array
|
|
||||||
|
|
||||||
const dataObj: Node[] = Object.values(data.nodes as Node);
|
|
||||||
|
|
||||||
const executedNodes: string[] = [];
|
|
||||||
dataObj.map((val) => {
|
|
||||||
if (val.name.charAt(0) === '[') {
|
|
||||||
val.name = 'Step Group ' + val.name.substring(1, val.name.length - 1);
|
|
||||||
}
|
|
||||||
executedNodes.push(val.name);
|
|
||||||
setData({
|
|
||||||
...data,
|
|
||||||
executed_nodes: [...data.executed_nodes, ...executedNodes],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [data.nodes]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes.root}>
|
|
||||||
{/* Workflow Information */}
|
|
||||||
<Typography className={classes.header} variant="h6">
|
|
||||||
<span className={classes.bold}>Workflow Information</span>
|
|
||||||
</Typography>
|
|
||||||
<hr className={classes.divider} />
|
|
||||||
<div className={classes.heightMaintainer}>
|
|
||||||
<Typography className={classes.workflowSpacing}>
|
|
||||||
<span className={classes.bold}>Workflow name:</span>
|
|
||||||
<br />
|
|
||||||
{workflow_name}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
{/* Workflow Details
|
|
||||||
@param State
|
|
||||||
@param Start Time
|
|
||||||
@param End Time
|
|
||||||
@param Duration
|
|
||||||
@param Namespace */}
|
|
||||||
|
|
||||||
<div className={classes.workflowSpacing}>
|
|
||||||
<div className={classes.heightMaintainer}>
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>State:</span> {data.phase}
|
|
||||||
</Typography>
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>Start time:</span>{' '}
|
|
||||||
{timeDifference(data.startedAt)}
|
|
||||||
</Typography>
|
|
||||||
{data.phase !== 'Running' ? (
|
|
||||||
<>
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>End time:</span>{' '}
|
|
||||||
{timeDifference(data.finishedAt)}
|
|
||||||
</Typography>
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>Duration:</span>{' '}
|
|
||||||
{`${duration.toFixed(1)} minutes`}
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>Namespace:</span> {data.namespace}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
{/* Workflow Node Details
|
|
||||||
@param Currently Running Node
|
|
||||||
@param Executed Nodes */}
|
|
||||||
|
|
||||||
<div className={classes.workflowSpacing}>
|
|
||||||
<div className={classes.heightMaintainer}>
|
|
||||||
{data.phase === 'Running' ? (
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>Currently Running Nodes:</span>{' '}
|
|
||||||
{
|
|
||||||
<ul>
|
|
||||||
{data.current_running_node.map((node) => {
|
|
||||||
return <li>{node}</li>;
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
</Typography>
|
|
||||||
) : (
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>Executed Nodes:</span>{' '}
|
|
||||||
{
|
|
||||||
<ul>
|
|
||||||
{data.executed_nodes.map((node) => {
|
|
||||||
return <li>{node}</li>;
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
{/* Cluster Details
|
|
||||||
@param Cluster Name */}
|
|
||||||
|
|
||||||
<div className={classes.workflowSpacing}>
|
|
||||||
<div className={classes.heightMaintainer}>
|
|
||||||
<Typography>
|
|
||||||
<span className={classes.bold}>Cluster:</span> {cluster_name}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SideBar;
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { Box, createStyles, Tab, withStyles } from '@material-ui/core';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface TabPanelProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
index: number;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
const TabPanel: React.FC<TabPanelProps> = ({ children, index, value }) => {
|
||||||
|
return (
|
||||||
|
<div role="tabpanel" hidden={value !== index}>
|
||||||
|
{value === index && (
|
||||||
|
<Box p={3}>
|
||||||
|
<>{children}</>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
interface StyledTabProps {
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
const StyledTab = withStyles((theme) =>
|
||||||
|
createStyles({
|
||||||
|
root: {
|
||||||
|
textTransform: 'none',
|
||||||
|
color: 'rgba(0,0,0,0.5)',
|
||||||
|
fontSize: '0.95rem',
|
||||||
|
paddingTop: theme.spacing(1.875),
|
||||||
|
paddingBottom: theme.spacing(1.875),
|
||||||
|
width: '15.9375rem',
|
||||||
|
'&:focus': {
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)((props: StyledTabProps) => <Tab {...props} />);
|
||||||
|
|
||||||
|
export { TabPanel, StyledTab };
|
||||||
|
|
@ -1,32 +1,31 @@
|
||||||
import React from 'react';
|
import { useMutation } from '@apollo/client';
|
||||||
import Step from '@material-ui/core/Step';
|
import Step from '@material-ui/core/Step';
|
||||||
import { StepIconProps } from '@material-ui/core/StepIcon';
|
import { StepIconProps } from '@material-ui/core/StepIcon';
|
||||||
import StepLabel from '@material-ui/core/StepLabel';
|
import StepLabel from '@material-ui/core/StepLabel';
|
||||||
import Stepper from '@material-ui/core/Stepper';
|
import Stepper from '@material-ui/core/Stepper';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useMutation } from '@apollo/client';
|
|
||||||
import YAML from 'yaml';
|
import YAML from 'yaml';
|
||||||
|
import Unimodal from '../../containers/layouts/Unimodal';
|
||||||
|
import { CREATE_WORKFLOW } from '../../graphql';
|
||||||
|
import { experimentMap, WorkflowData } from '../../models/workflow';
|
||||||
|
import useActions from '../../redux/actions';
|
||||||
|
import * as WorkflowActions from '../../redux/actions/workflow';
|
||||||
|
import { history } from '../../redux/configureStore';
|
||||||
|
import { RootState } from '../../redux/reducers';
|
||||||
|
import parsed from '../../utils/yamlUtils';
|
||||||
import ButtonFilled from '../Button/ButtonFilled';
|
import ButtonFilled from '../Button/ButtonFilled';
|
||||||
import ButtonOutline from '../Button/ButtonOutline';
|
import ButtonOutline from '../Button/ButtonOutline';
|
||||||
import ReliablityScore from '../Sections/Workflow/ReliabilityScore';
|
import ChooseWorkflow from '../Sections/CreateWorkflow/ChooseWorkflow/index';
|
||||||
import ScheduleWorkflow from '../Sections/Workflow/ScheduleWorkflow';
|
import ReliablityScore from '../Sections/CreateWorkflow/ReliabilityScore';
|
||||||
import VerifyCommit from '../Sections/Workflow/VerifyCommit';
|
import ScheduleWorkflow from '../Sections/CreateWorkflow/ScheduleWorkflow';
|
||||||
import ChooseAWorkflowCluster from '../Sections/Workflow/WorkflowCluster';
|
import TuneWorkflow from '../Sections/CreateWorkflow/TuneWorkflow/index';
|
||||||
|
import VerifyCommit from '../Sections/CreateWorkflow/VerifyCommit';
|
||||||
|
import ChooseAWorkflowCluster from '../Sections/CreateWorkflow/WorkflowCluster';
|
||||||
import QontoConnector from './quontoConnector';
|
import QontoConnector from './quontoConnector';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import useQontoStepIconStyles from './useQontoStepIconStyles';
|
import useQontoStepIconStyles from './useQontoStepIconStyles';
|
||||||
import TuneWorkflow from '../Sections/Workflow/TuneWorkflow/index';
|
|
||||||
import ChooseWorkflow from '../Sections/Workflow/ChooseWorkflow/index';
|
|
||||||
import { WorkflowData, experimentMap } from '../../models/workflow';
|
|
||||||
import { UserData } from '../../models/user';
|
|
||||||
import { RootState } from '../../redux/reducers';
|
|
||||||
import useActions from '../../redux/actions';
|
|
||||||
import * as WorkflowActions from '../../redux/actions/workflow';
|
|
||||||
import parsed from '../../utils/yamlUtils';
|
|
||||||
import { CREATE_WORKFLOW } from '../../graphql';
|
|
||||||
import Unimodal from '../../containers/layouts/Unimodal';
|
|
||||||
import { history } from '../../redux/configureStore';
|
|
||||||
|
|
||||||
function getSteps(): string[] {
|
function getSteps(): string[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -127,12 +126,10 @@ const CustomStepper = () => {
|
||||||
clusterid,
|
clusterid,
|
||||||
} = workflowData;
|
} = workflowData;
|
||||||
|
|
||||||
const userData: UserData = useSelector((state: RootState) => state.userData);
|
const selectedProjectID = useSelector(
|
||||||
|
(state: RootState) => state.userData.selectedProjectID
|
||||||
const { selectedProjectID } = userData;
|
);
|
||||||
|
|
||||||
const workflow = useActions(WorkflowActions);
|
const workflow = useActions(WorkflowActions);
|
||||||
|
|
||||||
const steps = getSteps();
|
const steps = getSteps();
|
||||||
|
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ const ErrorPage = lazy(() => import('../../pages/ErrorPage'));
|
||||||
const Workflows = lazy(() => import('../../pages/Workflows'));
|
const Workflows = lazy(() => import('../../pages/Workflows'));
|
||||||
const CreateWorkflow = lazy(() => import('../../pages/CreateWorkflow'));
|
const CreateWorkflow = lazy(() => import('../../pages/CreateWorkflow'));
|
||||||
const LoginPage = lazy(() => import('../../pages/LoginPage'));
|
const LoginPage = lazy(() => import('../../pages/LoginPage'));
|
||||||
const WorkflowUnderground = lazy(() =>
|
const WorkflowDetails = lazy(() => import('../../pages/WorkflowDetails'));
|
||||||
import('../../pages/WorkflowUnderground')
|
|
||||||
);
|
|
||||||
const BrowseTemplate = lazy(() =>
|
const BrowseTemplate = lazy(() =>
|
||||||
import('../../components/Sections/ChaosWorkflows/BrowseTemplate')
|
import('../../components/Sections/ChaosWorkflows/BrowseTemplate')
|
||||||
);
|
);
|
||||||
|
|
@ -60,18 +58,27 @@ const Routes: React.FC<RoutesProps> = ({ userData, isProjectAvailable }) => {
|
||||||
<Route exact path="/login" component={LoginPage} />
|
<Route exact path="/login" component={LoginPage} />
|
||||||
<Route exact path="/workflows" component={Workflows} />
|
<Route exact path="/workflows" component={Workflows} />
|
||||||
<Route exact path="/create-workflow" component={CreateWorkflow} />
|
<Route exact path="/create-workflow" component={CreateWorkflow} />
|
||||||
<Route exact path="/schedule" component={SchedulePage} />
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path="/workflows/workflow-underground"
|
|
||||||
component={WorkflowUnderground}
|
|
||||||
/>
|
|
||||||
<Route exact path="/community" component={Community} />
|
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/workflows/:workflowName"
|
path="/workflows/:workflowName"
|
||||||
|
component={WorkflowDetails}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/workflows/:workflowName/details"
|
||||||
|
component={WorkflowDetails}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/workflows/:scheduleId/schedule"
|
||||||
|
component={SchedulePage}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/workflows/:templateName/template"
|
||||||
component={BrowseTemplate}
|
component={BrowseTemplate}
|
||||||
/>
|
/>
|
||||||
|
<Route exact path="/community" component={Community} />
|
||||||
<Route exact path="/settings" component={Settings} />
|
<Route exact path="/settings" component={Settings} />
|
||||||
<Route exact path="/404" component={ErrorPage} />
|
<Route exact path="/404" component={ErrorPage} />
|
||||||
<Redirect to="/404" />
|
<Redirect to="/404" />
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
import { Box, Divider } from '@material-ui/core';
|
import { Box, Divider } from '@material-ui/core';
|
||||||
import AppBar from '@material-ui/core/AppBar';
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
import Toolbar from '@material-ui/core/Toolbar';
|
import Toolbar from '@material-ui/core/Toolbar';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { useQuery } from '@apollo/client';
|
import CustomBreadCrumbs from '../../../components/BreadCrumbs';
|
||||||
|
import { GET_USER } from '../../../graphql';
|
||||||
import { Message, NotificationIds, Project } from '../../../models/header';
|
import { Message, NotificationIds, Project } from '../../../models/header';
|
||||||
import {
|
import {
|
||||||
UserData,
|
|
||||||
CurrentUserDetails,
|
|
||||||
CurrentUserDedtailsVars,
|
CurrentUserDedtailsVars,
|
||||||
|
CurrentUserDetails,
|
||||||
|
UserData,
|
||||||
} from '../../../models/user';
|
} from '../../../models/user';
|
||||||
import { RootState } from '../../../redux/reducers';
|
import { RootState } from '../../../redux/reducers';
|
||||||
import CustomBreadCrumbs from '../../../components/BreadCrumbs';
|
|
||||||
import NotificationsDropdown from './NotificationDropdown';
|
import NotificationsDropdown from './NotificationDropdown';
|
||||||
import ProfileDropdownSection from './ProfileDropdownSection';
|
import ProfileDropdownSection from './ProfileDropdownSection';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import { GET_USER } from '../../../graphql';
|
|
||||||
|
|
||||||
const Header: React.FC = () => {
|
const Header: React.FC = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
@ -44,7 +44,6 @@ const Header: React.FC = () => {
|
||||||
setSelectedProject(selectedProjectID);
|
setSelectedProject(selectedProjectID);
|
||||||
// send POST request with #selectedProjectID to update active
|
// send POST request with #selectedProjectID to update active
|
||||||
// project on db or persist it in redux or cookie.
|
// project on db or persist it in redux or cookie.
|
||||||
// window.location.reload(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchRandomProjects = useCallback(() => {
|
const fetchRandomProjects = useCallback(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
import { AnalyticsAction } from './analytics';
|
import { AnalyticsAction } from './analytics';
|
||||||
|
import { NodeSelectionAction } from './nodeSelection';
|
||||||
import { UserAction } from './user';
|
import { UserAction } from './user';
|
||||||
import { WorkflowAction } from './workflow';
|
import { WorkflowAction } from './workflow';
|
||||||
|
|
||||||
export * from './predefinedWorkflow';
|
export type Action =
|
||||||
|
| UserAction
|
||||||
export type Action = UserAction | AnalyticsAction | WorkflowAction;
|
| AnalyticsAction
|
||||||
|
| WorkflowAction
|
||||||
|
| NodeSelectionAction;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Node } from './workflowData';
|
||||||
|
|
||||||
|
export enum NodeSelectionActions {
|
||||||
|
SELECT_NODE = 'SELECT_NODE',
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NodeSelectionActionType<T, P> {
|
||||||
|
type: T;
|
||||||
|
payload: P;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NodeSelectionAction = NodeSelectionActionType<
|
||||||
|
typeof NodeSelectionActions.SELECT_NODE,
|
||||||
|
Node
|
||||||
|
>;
|
||||||
|
|
@ -23,6 +23,6 @@ export interface workflowDetails {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectWorkflowCallBackType {
|
interface SelectWorkflowCallBackType {
|
||||||
(selectedWorkflow: workflowDetails): void;
|
(selectedWorkflow: workflowDetails): void;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ export interface Node {
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Nodes {
|
||||||
|
[index: string]: Node;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExecutionData {
|
export interface ExecutionData {
|
||||||
event_type: string;
|
event_type: string;
|
||||||
uid: string;
|
uid: string;
|
||||||
|
|
@ -16,7 +20,7 @@ export interface ExecutionData {
|
||||||
phase: string;
|
phase: string;
|
||||||
startedAt: string;
|
startedAt: string;
|
||||||
finishedAt: string;
|
finishedAt: string;
|
||||||
nodes: object;
|
nodes: Nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkflowRun {
|
export interface WorkflowRun {
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,15 @@ import {
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import CustomDate from '../../components/DateTime/CustomDate/index';
|
|
||||||
import CustomTime from '../../components/DateTime/CustomTime/index';
|
|
||||||
import SetTime from './SetTime/index';
|
|
||||||
import useStyles from './styles';
|
|
||||||
import Scaffold from '../../containers/layouts/Scaffold';
|
|
||||||
import ButtonFilled from '../../components/Button/ButtonFilled';
|
import ButtonFilled from '../../components/Button/ButtonFilled';
|
||||||
import ButtonOutline from '../../components/Button/ButtonOutline';
|
import ButtonOutline from '../../components/Button/ButtonOutline';
|
||||||
|
import CustomDate from '../../components/DateTime/CustomDate/index';
|
||||||
|
import CustomTime from '../../components/DateTime/CustomTime/index';
|
||||||
|
import Scaffold from '../../containers/layouts/Scaffold';
|
||||||
|
import SetTime from './SetTime/index';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
// To be changed to a Location Generic
|
const SchedulePage: React.FC = () => {
|
||||||
interface WorkflowScheduleProps {
|
|
||||||
location: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SchedulePage: React.FC<WorkflowScheduleProps> = () => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const start = 0;
|
const start = 0;
|
||||||
const end = 10;
|
const end = 10;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
|
import { Typography } from '@material-ui/core';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import Loader from '../../components/Loader';
|
||||||
|
import ArgoWorkflow from '../../components/Sections/WorkflowDetails/ArgoWorkflow';
|
||||||
|
import WorkflowInfo from '../../components/Sections/WorkflowDetails/WorkflowInfo';
|
||||||
|
import Scaffold from '../../containers/layouts/Scaffold';
|
||||||
|
import { WORKFLOW_DETAILS, WORKFLOW_EVENTS } from '../../graphql';
|
||||||
|
import {
|
||||||
|
ExecutionData,
|
||||||
|
Workflow,
|
||||||
|
WorkflowDataVars,
|
||||||
|
WorkflowSubscription,
|
||||||
|
} from '../../models/workflowData';
|
||||||
|
import { RootState } from '../../redux/reducers';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
|
const WorkflowDetails: React.FC = () => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
// Getting the workflow nome from the pathname
|
||||||
|
const workflowName = pathname.split('/')[2];
|
||||||
|
|
||||||
|
// get ProjectID
|
||||||
|
const selectedProjectID = useSelector(
|
||||||
|
(state: RootState) => state.userData.selectedProjectID
|
||||||
|
);
|
||||||
|
|
||||||
|
// Query to get workflows
|
||||||
|
const { subscribeToMore, data, error } = useQuery<Workflow, WorkflowDataVars>(
|
||||||
|
WORKFLOW_DETAILS,
|
||||||
|
{ variables: { projectID: selectedProjectID } }
|
||||||
|
);
|
||||||
|
|
||||||
|
const workflow = data?.getWorkFlowRuns.filter(
|
||||||
|
(w) => w.workflow_name === workflowName
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
// Using subscription to get realtime data
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
workflow?.execution_data &&
|
||||||
|
(JSON.parse(workflow?.execution_data) as ExecutionData).phase ===
|
||||||
|
'Running'
|
||||||
|
) {
|
||||||
|
subscribeToMore<WorkflowSubscription>({
|
||||||
|
document: WORKFLOW_EVENTS,
|
||||||
|
variables: { projectID: selectedProjectID },
|
||||||
|
updateQuery: (prev, { subscriptionData }) => {
|
||||||
|
if (!subscriptionData.data) return prev;
|
||||||
|
const modifiedWorkflows = prev.getWorkFlowRuns.slice();
|
||||||
|
const newWorkflow = subscriptionData.data.workflowEventListener;
|
||||||
|
|
||||||
|
// Updating the query data
|
||||||
|
let i = 0;
|
||||||
|
for (; i < modifiedWorkflows.length; i++) {
|
||||||
|
if (
|
||||||
|
modifiedWorkflows[i].workflow_run_id ===
|
||||||
|
newWorkflow.workflow_run_id
|
||||||
|
) {
|
||||||
|
modifiedWorkflows[i] = newWorkflow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i === modifiedWorkflows.length)
|
||||||
|
modifiedWorkflows.unshift(newWorkflow);
|
||||||
|
|
||||||
|
return { ...prev, getWorkFlowRuns: modifiedWorkflows };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Scaffold>
|
||||||
|
{workflow ? (
|
||||||
|
<div className={classes.root}>
|
||||||
|
<div className={classes.workflowGraph}>
|
||||||
|
<Typography className={classes.heading}>
|
||||||
|
{workflow.workflow_name}
|
||||||
|
</Typography>
|
||||||
|
<Typography>
|
||||||
|
Click on test to see detailed log of your workflow
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* Argo Workflow DAG Graph */}
|
||||||
|
<ArgoWorkflow
|
||||||
|
nodes={
|
||||||
|
(JSON.parse(workflow.execution_data) as ExecutionData).nodes
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<WorkflowInfo
|
||||||
|
workflow_name={workflow.workflow_name}
|
||||||
|
execution_data={
|
||||||
|
JSON.parse(workflow?.execution_data) as ExecutionData
|
||||||
|
}
|
||||||
|
cluster_name={workflow.cluster_name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : error ? (
|
||||||
|
<Typography>An error has occurred while fetching the data</Typography>
|
||||||
|
) : (
|
||||||
|
<Loader />
|
||||||
|
)}
|
||||||
|
</Scaffold>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WorkflowDetails;
|
||||||
|
|
@ -3,8 +3,8 @@ import { makeStyles, Theme } from '@material-ui/core/styles';
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
root: {
|
root: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
|
||||||
marginTop: theme.spacing(3),
|
marginTop: theme.spacing(3),
|
||||||
|
height: '75vh',
|
||||||
},
|
},
|
||||||
heading: {
|
heading: {
|
||||||
fontSize: '2rem',
|
fontSize: '2rem',
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
import { useSubscription } from '@apollo/client';
|
|
||||||
import { Typography } from '@material-ui/core';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import SideBar from '../../components/Sections/WorkflowUnderground/WorkflowRepresentation';
|
|
||||||
import Scaffold from '../../containers/layouts/Scaffold';
|
|
||||||
import { WORKFLOW_EVENTS } from '../../graphql';
|
|
||||||
import { LocationState } from '../../models/routerModel';
|
|
||||||
import {
|
|
||||||
ExecutionData,
|
|
||||||
WorkflowRun,
|
|
||||||
WorkflowSubscription,
|
|
||||||
} from '../../models/workflowData';
|
|
||||||
import capitalize from '../../utils/capitalize';
|
|
||||||
import useStyles from './styles';
|
|
||||||
import { UserData } from '../../models/user';
|
|
||||||
import { RootState } from '../../redux/reducers';
|
|
||||||
|
|
||||||
interface WorkflowUndergroundProps {
|
|
||||||
location: LocationState<WorkflowRun>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const WorkflowUnderground: React.FC<WorkflowUndergroundProps> = ({
|
|
||||||
location,
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const classes = useStyles();
|
|
||||||
const userData: UserData = useSelector((state: RootState) => state.userData);
|
|
||||||
const { selectedProjectID } = userData;
|
|
||||||
const [data, setData] = useState<WorkflowRun>(location.state);
|
|
||||||
const dataSub = useSubscription<WorkflowSubscription>(WORKFLOW_EVENTS, {
|
|
||||||
variables: { projectID: selectedProjectID },
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const workflowCompleted: boolean =
|
|
||||||
(JSON.parse(location.state.execution_data) as ExecutionData).phase ===
|
|
||||||
'Succeeded';
|
|
||||||
|
|
||||||
if (workflowCompleted && location.state.execution_data !== undefined)
|
|
||||||
setData(location.state);
|
|
||||||
else setData(dataSub.data?.workflowEventListener ?? location.state);
|
|
||||||
}, [location.state, dataSub.data, data.execution_data]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Scaffold>
|
|
||||||
<div className={classes.root}>
|
|
||||||
<div className={classes.workflowGraph}>
|
|
||||||
<Typography className={classes.heading}>
|
|
||||||
{data.workflow_name
|
|
||||||
.split('-')
|
|
||||||
.map((text) => `${capitalize(text)} `)}
|
|
||||||
</Typography>
|
|
||||||
<Typography>{t('workflowUnderground.heading')}</Typography>
|
|
||||||
</div>
|
|
||||||
<SideBar
|
|
||||||
workflow_name={data.workflow_name}
|
|
||||||
execution_data={data.execution_data}
|
|
||||||
cluster_name={data.cluster_name}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Scaffold>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WorkflowUnderground;
|
|
||||||
|
|
@ -1,11 +1,64 @@
|
||||||
|
import { AppBar, Typography } from '@material-ui/core';
|
||||||
|
import Tabs from '@material-ui/core/Tabs';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import WorkflowTabs from '../../components/Sections/ChaosWorkflows/WorkflowTabs';
|
import ButtonFilled from '../../components/Button/ButtonFilled';
|
||||||
|
import BrowseSchedule from '../../components/Sections/ChaosWorkflows/BrowseSchedule';
|
||||||
|
import BrowseWorkflow from '../../components/Sections/ChaosWorkflows/BrowseWorkflow';
|
||||||
|
import Templates from '../../components/Sections/ChaosWorkflows/Templates';
|
||||||
|
import { StyledTab, TabPanel } from '../../components/Tabs';
|
||||||
import Scaffold from '../../containers/layouts/Scaffold';
|
import Scaffold from '../../containers/layouts/Scaffold';
|
||||||
|
import { history } from '../../redux/configureStore';
|
||||||
|
import useStyles from './styles';
|
||||||
|
|
||||||
const Workflows = () => {
|
const Workflows = () => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const [value, setValue] = React.useState(0);
|
||||||
|
|
||||||
|
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||||
|
setValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Scaffold>
|
<Scaffold>
|
||||||
<WorkflowTabs />
|
<section className="Header section">
|
||||||
|
<div className={classes.header}>
|
||||||
|
<Typography variant="h4">Chaos Workflows</Typography>
|
||||||
|
<div className={classes.scheduleBtn}>
|
||||||
|
<ButtonFilled
|
||||||
|
isPrimary={false}
|
||||||
|
handleClick={() => history.push('/create-workflow')}
|
||||||
|
>
|
||||||
|
<>Schedule a workflow</>
|
||||||
|
</ButtonFilled>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<AppBar position="static" color="default" className={classes.appBar}>
|
||||||
|
<Tabs
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
indicatorColor="secondary"
|
||||||
|
textColor="secondary"
|
||||||
|
variant="fullWidth"
|
||||||
|
>
|
||||||
|
<StyledTab label="Browse workflows" />
|
||||||
|
<StyledTab label="Schedules" />
|
||||||
|
<StyledTab label="Templates" />
|
||||||
|
<StyledTab label="Analytics" />
|
||||||
|
</Tabs>
|
||||||
|
</AppBar>
|
||||||
|
<TabPanel value={value} index={0}>
|
||||||
|
<BrowseWorkflow />
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel value={value} index={1}>
|
||||||
|
<BrowseSchedule />
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel value={value} index={2}>
|
||||||
|
<Templates />
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel value={value} index={3}>
|
||||||
|
Analytics comming soon
|
||||||
|
</TabPanel>
|
||||||
</Scaffold>
|
</Scaffold>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
heading: {
|
header: {
|
||||||
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
marginTop: theme.spacing(2.5),
|
marginTop: theme.spacing(2.5),
|
||||||
marginLeft: theme.spacing(11),
|
marginBottom: theme.spacing(2.5),
|
||||||
marginBottom: theme.spacing(0),
|
},
|
||||||
fontFamily: 'Ubuntu',
|
scheduleBtn: {
|
||||||
fontSize: '2.25rem',
|
marginLeft: 'auto',
|
||||||
display: 'inline-block',
|
},
|
||||||
|
appBar: {
|
||||||
|
background: 'transparent',
|
||||||
|
boxShadow: 'none',
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* eslint-disable import/prefer-default-export */
|
||||||
|
import {
|
||||||
|
NodeSelectionAction,
|
||||||
|
NodeSelectionActions,
|
||||||
|
} from '../../models/nodeSelection';
|
||||||
|
import { Node } from '../../models/workflowData';
|
||||||
|
|
||||||
|
export function selectNode(node: Node): NodeSelectionAction {
|
||||||
|
return {
|
||||||
|
type: NodeSelectionActions.SELECT_NODE,
|
||||||
|
payload: node,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ if (dev) {
|
||||||
middleware = composeWithDevTools(middleware);
|
middleware = composeWithDevTools(middleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
const persistedReducer = persistReducer(persistConfig, rootReducer(history));
|
const persistedReducer = persistReducer(persistConfig, rootReducer());
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = createStore(persistedReducer, {}, middleware) as any;
|
const store = createStore(persistedReducer, {}, middleware) as any;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import { History } from 'history'; // eslint-disable-line import/no-extraneous-dependencies
|
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import { CommunityData } from '../../models/analytics';
|
import { CommunityData } from '../../models/analytics';
|
||||||
import { UserData } from '../../models/user';
|
import { UserData } from '../../models/user';
|
||||||
import { WorkflowData } from '../../models/workflow';
|
import { WorkflowData } from '../../models/workflow';
|
||||||
|
import { Node } from '../../models/workflowData';
|
||||||
import * as analyticsReducer from './analytics';
|
import * as analyticsReducer from './analytics';
|
||||||
|
import * as nodeSelectionReducer from './nodeSelection';
|
||||||
import * as userReducer from './user';
|
import * as userReducer from './user';
|
||||||
import * as workflowReducer from './workflow';
|
import * as workflowReducer from './workflow';
|
||||||
|
|
||||||
|
|
@ -11,13 +12,13 @@ export interface RootState {
|
||||||
communityData: CommunityData;
|
communityData: CommunityData;
|
||||||
userData: UserData;
|
userData: UserData;
|
||||||
workflowData: WorkflowData;
|
workflowData: WorkflowData;
|
||||||
|
selectedNode: Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (
|
export default () =>
|
||||||
history: History // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
||||||
) =>
|
|
||||||
combineReducers({
|
combineReducers({
|
||||||
...analyticsReducer,
|
...analyticsReducer,
|
||||||
...userReducer,
|
...userReducer,
|
||||||
...workflowReducer,
|
...workflowReducer,
|
||||||
|
...nodeSelectionReducer,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import {
|
||||||
|
NodeSelectionAction,
|
||||||
|
NodeSelectionActions,
|
||||||
|
} from '../../models/nodeSelection';
|
||||||
|
import { Node } from '../../models/workflowData';
|
||||||
|
import createReducer from './createReducer';
|
||||||
|
|
||||||
|
const initialState: Node = {
|
||||||
|
children: null,
|
||||||
|
finishedAt: '',
|
||||||
|
name: '',
|
||||||
|
phase: '',
|
||||||
|
startedAt: '',
|
||||||
|
type: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectedNode = createReducer<Node>(initialState, {
|
||||||
|
[NodeSelectionActions.SELECT_NODE](state: Node, action: NodeSelectionAction) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default selectedNode;
|
||||||
|
|
@ -24,6 +24,7 @@ declare module '@material-ui/core/styles/createPalette' {
|
||||||
customColors: {
|
customColors: {
|
||||||
white: (opacity: number) => string;
|
white: (opacity: number) => string;
|
||||||
black: (opacity: number) => string;
|
black: (opacity: number) => string;
|
||||||
|
gray: string;
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
disabled: string;
|
disabled: string;
|
||||||
|
|
@ -34,6 +35,7 @@ declare module '@material-ui/core/styles/createPalette' {
|
||||||
customColors?: {
|
customColors?: {
|
||||||
white?: (opacity: number) => string;
|
white?: (opacity: number) => string;
|
||||||
black?: (opacity: number) => string;
|
black?: (opacity: number) => string;
|
||||||
|
gray?: string;
|
||||||
};
|
};
|
||||||
input?: {
|
input?: {
|
||||||
disabled?: string;
|
disabled?: string;
|
||||||
|
|
@ -80,15 +82,16 @@ function customTheme(options: ThemeOptions) {
|
||||||
white: (opacity: number): string => {
|
white: (opacity: number): string => {
|
||||||
let op = opacity;
|
let op = opacity;
|
||||||
if (op < 0) op = 0;
|
if (op < 0) op = 0;
|
||||||
if (op > 100) op = 100;
|
if (op > 1) op = 1;
|
||||||
return `rgba(255, 255, 255, ${op})`;
|
return `rgba(255, 255, 255, ${op})`;
|
||||||
},
|
},
|
||||||
black: (opacity: number): string => {
|
black: (opacity: number): string => {
|
||||||
let op = opacity;
|
let op = opacity;
|
||||||
if (op < 0) op = 0;
|
if (op < 0) op = 0;
|
||||||
if (op > 100) op = 100;
|
if (op > 1) op = 1;
|
||||||
return `rgba(0, 0, 0, ${op})`;
|
return `rgba(0, 0, 0, ${op})`;
|
||||||
},
|
},
|
||||||
|
gray: '#5D6173',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue