diff --git a/package.json b/package.json index 08608a45..e1ceaa7d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "react-bootstrap": "^2.7.2", "react-copy-to-clipboard": "^5.0.1", "react-dom": "18.2.0", - "react-hexgrid": "1.0.4", "react-highlight-words": "^0.20.0", "react-joyride": "^2.5.3", "react-loading-skeleton": "^3.2.1", diff --git a/server.js b/server.js index b66a9b6a..3288d5e3 100644 --- a/server.js +++ b/server.js @@ -93,18 +93,6 @@ app }); }); - server.get('/problems/project', (req, res) => { - app.render(req, res, '/problems-dashboard-by-project'); - }); - - server.get('/problems', (req, res) => { - app.render(req, res, '/problems-dashboard-by-project-hex'); - }); - - server.get('/problems/identifier', (req, res) => { - app.render(req, res, '/problems-dashboard'); - }); - server.get('/projects/:projectSlug/:environmentSlug/facts', (req, res) => { app.render(req, res, '/facts', { openshiftProjectName: req.params.environmentSlug, diff --git a/src/components/Honeycomb/index.js b/src/components/Honeycomb/index.js deleted file mode 100644 index e84a179f..00000000 --- a/src/components/Honeycomb/index.js +++ /dev/null @@ -1,240 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { GridGenerator, HexGrid, Hexagon, Layout, Text } from 'react-hexgrid'; - -import ProblemsByProject from 'components/ProblemsByProject'; -import * as R from 'ramda'; - -const config = { - width: 1200, - height: 100, - layout: { width: 4, height: 4, flat: false, spacing: 1.08 }, - origin: { x: 0, y: 0 }, - map: 'rectangle', -}; - -const Honeycomb = ({ data, filter }) => { - - const { projectsProblems } = data || []; - const [projects, setProjects] = useState(projects); - const [projectInView, setProjectInView] = useState(false); - const [display, setDisplay] = useState({ type: 'normal', multiplier: 2 }); - - const generator = GridGenerator.getGenerator(config.map); - const projectCount = projectsProblems && parseInt(projectsProblems.length); - const displayMultiple = display && parseInt(display.multiplier * 8); - let rows = projectsProblems && parseInt(projectCount / displayMultiple); - - const hexs = generator.apply(config, [displayMultiple, ++rows]); - const layout = config.layout; - const size = { - x: parseInt(display.hexSize * layout.width), - y: parseInt(display.hexSize * layout.height), - }; - - const handleHexClick = project => { - const { environments, id, name } = project || []; - const problems = - environments && - environments - .filter(e => e instanceof Object) - .map(e => { - return e.problems; - }); - - const problemsPerProject = Array.prototype.concat.apply([], problems); - const critical = problemsPerProject.filter(p => p.severity === 'CRITICAL').length; - const high = problemsPerProject.filter(p => p.severity === 'HIGH').length; - const medium = problemsPerProject.filter(p => p.severity === 'MEDIUM').length; - const low = problemsPerProject.filter(p => p.severity === 'LOW').length; - - setProjectInView({ - name: name, - environments: environments, - severityCount: { critical: critical, high: high, medium: medium, low: low }, - }); - }; - - const flattenProblems = project => { - const { environments } = project || []; - const filterProblems = - environments && - environments - .filter(e => e instanceof Object) - .map(e => { - return e.problems; - }); - return Array.prototype.concat.apply([], filterProblems); - }; - - const sortByProjects = projects => { - return ( - projects && - projects.sort((a, b) => { - const aProblems = flattenProblems(a); - const bProblems = flattenProblems(b); - - return bProblems.length - aProblems.length; - }) - ); - }; - - const getClassName = critical => { - if (critical === 0) { - return 'no-critical'; - } - if (critical === 1) { - return 'light-red'; - } else if (critical >= 1 && critical <= 5) { - return 'red'; - } else if (critical >= 5 && critical < 10) { - return 'dark-red'; - } else if (critical >= 10) { - return 'darker-red'; - } - }; - - useEffect(() => { - const count = projectsProblems && projectsProblems.length; - if (count <= 48) setDisplay({ type: 'normal', multiplier: 2, hexSize: 4, viewBox: '180 -20 100 100' }); - if (count >= 49 && count <= 120) - setDisplay({ type: 'small', multiplier: 3, hexSize: 2, viewBox: '125 -20 100 100' }); - if (count >= 121 && count <= 384) - setDisplay({ type: 'smaller', multiplier: 4, hexSize: 1, viewBox: '70 -10 100 100' }); - if (count >= 385) setDisplay({ type: 'smallest', multiplier: 5, hexSize: 0.66, viewBox: '30 -10 100 100' }); - - const filterProjects = !filter.showCleanProjects - ? projectsProblems && - projectsProblems.filter(p => { - return !R.isEmpty(flattenProblems(p)); - }) - : projectsProblems && projectsProblems; - - const sortProjects = filterProjects && sortByProjects(filterProjects); - - setProjects(sortProjects); - }, [projectsProblems, filter]); - - return ( -
- {projects && ( -
-
- -
-
- )} - {projects && ( - <> - - - {hexs.slice(0, projects.length).map((hex, i) => { - const project = projects[i] || null; - const { environments, id, name } = project; - const filterProblems = - environments && - environments - .filter(e => e instanceof Object) - .map(e => { - return e.problems; - }); - - const problemsPerProject = Array.prototype.concat.apply([], filterProblems); - const critical = problemsPerProject.filter(p => p.severity === 'CRITICAL').length; - const problemCount = problemsPerProject.length || 0; - - const HexText = () => { - const classes = display.type !== 'normal' ? 'no-text' : 'text'; - - if (problemsPerProject.length) { - return {`P: ${problemCount}, C: ${critical}`}; - } else { - return {`P: ${problemCount}`}; - } - }; - - return ( - handleHexClick(project)} - > - - - ); - })} - - -
-
-
- {projectInView ? ( - <> -
- -
- {projectInView.environments && - projectInView.environments.map(environment => { - const problems = Array.prototype.concat.apply([], environment.problems); - - return ( -
-
- -
-
    -
  • - - {Object.keys(problems).length} -
  • -
  • - - - {problems.filter(p => p.severity === 'CRITICAL').length} - -
  • -
  • - - - {problems.filter(p => p.severity === 'HIGH').length} - -
  • -
  • - - - {problems.filter(p => p.severity === 'MEDIUM').length} - -
  • -
  • - - - {problems.filter(p => p.severity === 'LOW').length} - -
  • -
-
-
- -
- ); - })} - - ) : ( -
No project selected
- )} -
-
-
- - )} -
- ); -}; - -export default Honeycomb; diff --git a/src/components/Honeycomb/index.stories.tsx b/src/components/Honeycomb/index.stories.tsx deleted file mode 100644 index 7d5a54e9..00000000 --- a/src/components/Honeycomb/index.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; - -import { Meta, StoryObj } from '@storybook/react'; - -import { ProjectsProblems } from '../../../.storybook/mocks/api'; -import Honeycomb from './index'; - -const meta: Meta = { - component: Honeycomb, - title: 'Components/Honeycomb', -}; - -export const Default: StoryObj = { - render: (data, args) => { - return data && ; - }, - args: { - //@ts-ignore - projectsProblems: ProjectsProblems(1243), - }, -}; - -export const NoProjects = () => ; - -export default meta; diff --git a/src/pages/problems-dashboard-by-project-hex.js b/src/pages/problems-dashboard-by-project-hex.js deleted file mode 100644 index f52e7210..00000000 --- a/src/pages/problems-dashboard-by-project-hex.js +++ /dev/null @@ -1,117 +0,0 @@ -import React, { useState } from 'react'; - -import Head from 'next/head'; - -import { useQuery } from '@apollo/react-hooks'; -import SelectFilter from 'components/Filters'; -import getSeverityEnumQuery, { getSourceOptions } from 'components/Filters/helpers'; -import Honeycomb from 'components/Honeycomb'; -import MainLayout from 'layouts/MainLayout'; -import AllProjectsProblemsQuery from 'lib/query/AllProjectsProblems'; -import { LoadingPageNoHeader } from 'pages/_loading'; -import * as R from 'ramda'; - -import { ProblemsByDashBoard } from '../styles/pageStyles'; - -/** - * Displays problems page by project. - * - */ -const ProblemsDashboardByProjectPageHexDisplay = () => { - const [showCleanProjects, setShowCleanProjects] = useState(true); - const [source, setSource] = useState([]); - const [severity, setSeverity] = useState(['CRITICAL']); - const [envType, setEnvType] = useState('PRODUCTION'); - - const { data: severities, loading: severityLoading } = useQuery(getSeverityEnumQuery); - const { data: sources, loading: sourceLoading } = useQuery(getSourceOptions); - - const { data: projectsProblems, loading: projectsProblemsLoading } = useQuery(AllProjectsProblemsQuery, { - variables: { - severity: severity, - source: source, - envType: envType, - }, - }); - - const handleEnvTypeChange = envType => setEnvType(envType.value); - const handleShowAllProjectsCheck = () => setShowCleanProjects(!showCleanProjects); - - const handleSourceChange = source => { - let values = (source && source.map(s => s.value)) || []; - setSource(values); - }; - - const handleSeverityChange = severity => { - let values = (severity && severity.map(s => s.value)) || []; - setSeverity(values); - }; - - const sourceOptions = sources => { - return sources && sources.map(s => ({ value: s, label: s })); - }; - - const severityOptions = enums => { - return enums && enums.map(s => ({ value: s.name, label: s.name })); - }; - - return ( - - - Problems Dashboard By Project - - -
-
- - - -
-
- - -
-
-
-
- {projectsProblemsLoading && } - {!projectsProblemsLoading && ( - - )} -
-
-
-
- ); -}; - -export default ProblemsDashboardByProjectPageHexDisplay; diff --git a/src/pages/problems-dashboard-by-project.js b/src/pages/problems-dashboard-by-project.js deleted file mode 100644 index 153bca31..00000000 --- a/src/pages/problems-dashboard-by-project.js +++ /dev/null @@ -1,241 +0,0 @@ -import React, { useState } from 'react'; -import { Query } from 'react-apollo'; - -import Head from 'next/head'; - -import { useQuery } from '@apollo/react-hooks'; -import Accordion from 'components/Accordion'; -import SelectFilter from 'components/Filters'; -import getSeverityEnumQuery, { getProjectOptions, getSourceOptions } from 'components/Filters/helpers'; -import ProblemsByProject from 'components/ProblemsByProject'; -import MainLayout from 'layouts/MainLayout'; -import AllProblemsByProjectQuery from 'lib/query/AllProblemsByProject'; -import withQueryErrorNoHeader from 'lib/withQueryErrorNoHeader'; -import withQueryLoadingNoHeader from 'lib/withQueryLoadingNoHeader'; -import * as R from 'ramda'; - -import { StyledProblemsDashBoardByProject } from '../styles/pageStyles'; - -export async function getServerSideProps() { - // TEMPORARY: disable this page from rendering until rework - const isEnabled = false; - if (!isEnabled) { - return { - redirect: { - destination: '/problems-dashboard-by-project-hex', - permanent: false, - }, - }; - } - return { - props: {}, - }; -} - -/** - * Displays the problems overview page by project. - */ -const ProblemsDashboardProductPage = () => { - const [projectSelect, setProjectSelect] = useState([]); - const [source, setSource] = useState([]); - const [severity, setSeverity] = useState(['CRITICAL']); - const [envType, setEnvType] = useState('PRODUCTION'); - - const { data: projects, loading: projectsLoading } = useQuery(getProjectOptions); - const { data: severities, loading: severityLoading } = useQuery(getSeverityEnumQuery); - const { data: sources, loading: sourceLoading } = useQuery(getSourceOptions); - - const handleProjectChange = project => { - let values = (project && project.map(p => p.value)) || []; - setProjectSelect(values); - }; - - const handleEnvTypeChange = envType => { - setEnvType(envType.value); - }; - - const handleSourceChange = source => { - let values = (source && source.map(s => s.value)) || []; - setSource(values); - }; - - const handleSeverityChange = severity => { - let values = (severity && severity.map(s => s.value)) || []; - setSeverity(values); - }; - - const projectOptions = projects => { - return projects && projects.map(p => ({ value: p.name, label: p.name })); - }; - - const sourceOptions = sources => { - return sources && sources.map(s => ({ value: s, label: s })); - }; - - const severityOptions = enums => { - return enums && enums.map(s => ({ value: s.name, label: s.name })); - }; - - return ( - - - Problems Dashboard By Project - - -
-
- - -
-
- - -
-
-
- {projects && ( -
-
- -
-
- )} -
- {projects && - projects.allProjects.map((project, idx) => { - const filterProjectSelect = - projectSelect - .filter(s => { - return s.includes(project.name); - }) - .toString() || ''; - - return ( - - {R.compose( - withQueryLoadingNoHeader, - withQueryErrorNoHeader - )(({ data: { project } }) => { - const { environments, id, name } = project || []; - const filterProblems = - environments && - environments - .filter(e => e instanceof Object) - .map(e => { - return e.problems; - }); - - const problemsPerProject = Array.prototype.concat.apply([], filterProblems); - const critical = problemsPerProject.filter(p => p.severity === 'CRITICAL').length; - const high = problemsPerProject.filter(p => p.severity === 'HIGH').length; - const medium = problemsPerProject.filter(p => p.severity === 'MEDIUM').length; - const low = problemsPerProject.filter(p => p.severity === 'LOW').length; - - const columns = { - name, - problemCount: problemsPerProject.length, - }; - - return ( - <> - {environments && ( -
-
- - {!environments.length &&
No Environments
} -
-
    -
  • - - {Object.keys(problemsPerProject).length} Problems -
  • -
  • - - {critical} -
  • -
  • - - {high} -
  • -
  • - - {medium} -
  • -
  • - - {low} -
  • -
-
- {environments.map((environment, idx) => ( -
- - -
- ))} -
-
-
- )} - - ); - })} -
- ); - })} -
-
-
-
- ); -}; - -export default ProblemsDashboardProductPage; diff --git a/src/stories/problems-dashboard-by-project-hex.stories.tsx b/src/stories/problems-dashboard-by-project-hex.stories.tsx deleted file mode 100644 index 65464b77..00000000 --- a/src/stories/problems-dashboard-by-project-hex.stories.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; - -import { Meta, StoryObj } from '@storybook/react'; -import QueryError from 'components/errors/QueryError'; -import { graphql } from 'msw'; - -import { ProjectsProblems } from '../../.storybook/mocks/api'; -import ProblemsDashboardProductPageHexDisplay from '../pages/problems-dashboard-by-project-hex'; - -const meta: Meta = { - title: 'Pages/Problems by hex', - component: ProblemsDashboardProductPageHexDisplay, -}; -type Story = StoryObj; - -export const Default: Story = { - parameters: { - msw: { - handlers: [ - graphql.query('getAllProjectsProblemsQuery', (_, res, ctx) => { - return res( - ctx.delay(), - ctx.data({ - projectsProblems: ProjectsProblems(123), - }) - ); - }), - ], - }, - }, -}; - -export const Loading: Story = { - parameters: { - msw: { - handlers: [ - graphql.operation((_, res, ctx) => { - return res(ctx.delay('infinite')); - }), - ], - }, - }, -}; - -export const Error: Story = { - parameters: { - msw: { - handlers: [ - graphql.operation((_, res, ctx) => { - return res(ctx.status(403)); - }), - ], - }, - }, - render: () => { - return ; - }, -}; - -export default meta; diff --git a/src/stories/problems-dashboard-by-project.stories.tsx b/src/stories/problems-dashboard-by-project.stories.tsx deleted file mode 100644 index a3e81835..00000000 --- a/src/stories/problems-dashboard-by-project.stories.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; -import { graphql } from 'msw'; - -import ProblemsDashboardProductPage from '../pages/problems-dashboard-by-project'; - -const meta: Meta = { - title: 'Pages/Problems by project', - component: ProblemsDashboardProductPage, -}; -type Story = StoryObj; - -export const Default: Story = { - render: () => { - return ( - <> -

Component pending rework

- - ); - }, - // parameters: { - // msw: { - // handlers: [ - // graphql.operation( (_, res, ctx) => { - // return res(ctx.delay("infinite")) - // }), - // ], - // }, - // }, -}; - -export default meta; diff --git a/src/stories/problems-dashboard.stories.tsx b/src/stories/problems-dashboard.stories.tsx deleted file mode 100644 index 449645e6..00000000 --- a/src/stories/problems-dashboard.stories.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { faker } from '@faker-js/faker'; -import { Meta, StoryObj } from '@storybook/react'; -import { graphql } from 'msw'; - -import { ProblemIdentifier } from '../../.storybook/mocks/mocks'; -import ProblemsDashboardPage from '../pages/problems-dashboard'; - -const meta: Meta = { - title: 'Pages/Problems Dashboard', - component: ProblemsDashboardPage, -}; -type Story = StoryObj; - -faker.seed(123); -const problemData = Array.from({ - length: faker.number.int({ - min: 1, - max: 10, - }), -}).map((_, idx) => { - return ProblemIdentifier(idx); -})[0].problems; - -export const Default: Story = { - parameters: { - msw: { - handlers: [ - graphql.query('getAllProblemsQuery', (_, res, ctx) => { - return res( - ctx.delay(), - ctx.data({ - problems: problemData, - }) - ); - }), - ], - }, - }, -}; -export const Loading: Story = { - parameters: { - msw: { - handlers: [ - graphql.operation((_, res, ctx) => { - return res(ctx.delay('infinite')); - }), - ], - }, - }, -}; - -export default meta; diff --git a/yarn.lock b/yarn.lock index 8b6434f6..3be67db7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1239,6 +1239,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.17.2", "@babel/runtime@^7.6.3": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.11.tgz#7a9ba3bbe406ad6f9e8dd4da2ece453eb23a77a4" + integrity sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.18.10", "@babel/template@^7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" @@ -5381,7 +5388,7 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== -classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: +classnames@^2.2.6, classnames@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== @@ -11278,13 +11285,6 @@ react-floater@^0.7.6: react-proptype-conditional-require "^1.0.4" tree-changes "^0.9.1" -react-hexgrid@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/react-hexgrid/-/react-hexgrid-1.0.4.tgz#e5a29484bd57694ef5b341b55377d98c2e71d418" - integrity sha512-Hw6fD2T5exCHAZzB2YW5OTDp94E32EIdRQhKOSVpSUkkBLB4VD6Rtd6SEQu+iDc5X4nmIV7IKLNThlfepejcSA== - dependencies: - classnames "^2.2.5" - react-highlight-words@^0.20.0: version "0.20.0" resolved "https://registry.yarnpkg.com/react-highlight-words/-/react-highlight-words-0.20.0.tgz#c60bfff5d14678c8f0e8fbe4bdcf083e6c70d507" @@ -11304,7 +11304,7 @@ react-is@18.1.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67" integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -11581,6 +11581,11 @@ regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.3, regenerator-runtime@^ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regenerator-transform@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"