From 33b5e4abacf71a536666c36d1f0af5ef501254b9 Mon Sep 17 00:00:00 2001 From: olav Date: Mon, 21 Feb 2022 13:47:54 +0100 Subject: [PATCH 1/6] feat: add new feature metrics page (#716) * refactor: ensure that [hidden] overrides other display styles * refactor: use numeric font weights * refactor: remove unnecessary Jest mock * refactor: add a fullWidth prop to GeneralSelect * refactor: remove unnecessary label id prop * refactor: the showActive prop is optional * refactor: add hooks for managing query string state * refactor: add a hour/minute timestamp formatter * refactor: add labels to button icons * feat: add new feature metrics page * refactor: remove prev feature metrics page * refactor: use new metric boxes on overview page * refactor: lazy-load the new metrics page * refactor: fix type error when formatting unknown error * refactor: extract interfaces for props * refactor: destructure all props * refactor: expand arg names * refactor: reorg component dirs and files * refactor: improve chart element label * refactor: hide chart dots until hover * refactor: add section titles to environments/applications * refactor: simplify FeatureMetricsHours types * refactor: sort chart tooltip items * refactor: add more chart labels * refactor: always show a dot in single point charts * refactor: improve chart tooltip styles * refactor: adjut metric page spacing * refactor: decrease legend box size * refactor: move date fmt fn inline * refactor: improve chart legend styles * refactor: increase Cypress timeouts * refactor: sort environment and application chips * refactor: format files * refactor: use stable lists of apps and envs * refactor: fix FeatureMetrics dir name * refactor: avoid ScrollToTop on query string change * refactor: use ConditionallyRender instead of inline condition * refactor: use makeStyles instead of styled API --- .../feature-toggle/feature.spec.js | 14 +- frontend/package.json | 5 +- frontend/src/app.css | 4 + .../common/GeneralSelect/GeneralSelect.tsx | 24 ++- .../common/StatusChip/StatusChip.tsx | 2 +- frontend/src/component/common/util.js | 12 ++ .../FeatureMetrics/FeatureMetrics.styles.ts | 25 +-- .../FeatureMetrics/FeatureMetrics.tsx | 156 ++++++++++++++---- .../FeatureMetricsChart.tsx | 68 ++++++++ .../FeatureMetricsChart/createChartData.ts | 51 ++++++ .../FeatureMetricsChart/createChartOptions.ts | 106 ++++++++++++ .../FeatureMetricsChips.styles.ts | 25 +++ .../FeatureMetricsChips.tsx | 48 ++++++ .../FeatureMetricsContent.tsx | 47 ++++++ .../FeatureMetricsEmpty.tsx | 16 ++ .../FeatureMetricsHours.tsx | 57 +++++++ .../FeatureMetricsStats.styles.ts | 32 ++++ .../FeatureMetricsStats.tsx | 57 +++++++ .../FeatureMetricsStatsRaw.tsx | 29 ++++ .../FeatureMetricsTable.tsx | 71 ++++++++ .../FeatureEnvironmentMetrics.styles.ts | 79 --------- .../FeatureEnvironmentMetrics.tsx | 141 ---------------- .../FeatureOverviewEnvironment.styles.ts | 88 ---------- .../FeatureOverviewEnvironmentFooter.tsx | 59 ++----- .../FeatureSeenApplications.styles.ts | 15 -- .../FeatureSeenApplications.tsx | 46 ------ .../feature/FeatureView/FeatureView.tsx | 72 ++++---- .../menu/__tests__/breadcrumb-test.jsx | 3 - frontend/src/component/scroll-to-top.jsx | 2 +- .../useFeatureMetricsRaw.ts | 51 ++++++ .../src/hooks/useQueryStringNumberState.ts | 19 +++ frontend/src/hooks/useQueryStringState.ts | 25 +++ frontend/src/interfaces/featureToggle.ts | 16 ++ frontend/src/themes/main-theme.ts | 8 +- frontend/yarn.lock | 15 ++ 35 files changed, 958 insertions(+), 530 deletions(-) create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsChart/FeatureMetricsChart.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsChart/createChartData.ts create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsChart/createChartOptions.ts create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsChips/FeatureMetricsChips.styles.ts create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsChips/FeatureMetricsChips.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsContent/FeatureMetricsContent.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsEmpty/FeatureMetricsEmpty.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsHours/FeatureMetricsHours.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsStats/FeatureMetricsStats.styles.ts create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsStats/FeatureMetricsStats.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsStats/FeatureMetricsStatsRaw.tsx create mode 100644 frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetricsTable/FeatureMetricsTable.tsx delete mode 100644 frontend/src/component/feature/FeatureView/FeatureOverview/FeatureEnvironmentMetrics/FeatureEnvironmentMetrics.styles.ts delete mode 100644 frontend/src/component/feature/FeatureView/FeatureOverview/FeatureEnvironmentMetrics/FeatureEnvironmentMetrics.tsx delete mode 100644 frontend/src/component/feature/FeatureView/FeatureSeenApplications/FeatureSeenApplications.styles.ts delete mode 100644 frontend/src/component/feature/FeatureView/FeatureSeenApplications/FeatureSeenApplications.tsx create mode 100644 frontend/src/hooks/api/getters/useFeatureMetricsRaw/useFeatureMetricsRaw.ts create mode 100644 frontend/src/hooks/useQueryStringNumberState.ts create mode 100644 frontend/src/hooks/useQueryStringState.ts diff --git a/frontend/cypress/integration/feature-toggle/feature.spec.js b/frontend/cypress/integration/feature-toggle/feature.spec.js index 4446d50a25..a808390cae 100644 --- a/frontend/cypress/integration/feature-toggle/feature.spec.js +++ b/frontend/cypress/integration/feature-toggle/feature.spec.js @@ -129,7 +129,7 @@ describe('feature toggle', () => { }); it('Can add a gradual rollout strategy to the development environment', () => { - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/strategies`); cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click(); cy.get('[data-test=ADD_NEW_STRATEGY_CARD_BUTTON_ID-2').click(); @@ -172,7 +172,7 @@ describe('feature toggle', () => { }); it('can update a strategy in the development environment', () => { - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/strategies`); cy.get('[data-test=STRATEGY_ACCORDION_ID-flexibleRollout').click(); @@ -219,7 +219,7 @@ describe('feature toggle', () => { }); it('can delete a strategy in the development environment', () => { - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/strategies`); cy.intercept( @@ -238,7 +238,7 @@ describe('feature toggle', () => { }); it('Can add a userid strategy to the development environment', () => { - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/strategies`); cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click(); cy.get('[data-test=ADD_NEW_STRATEGY_CARD_BUTTON_ID-3').click(); @@ -285,7 +285,7 @@ describe('feature toggle', () => { it('Can add two variant to the feature', () => { const variantName = 'my-new-variant'; const secondVariantName = 'my-second-variant'; - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/variants`); cy.intercept( 'PATCH', @@ -315,7 +315,7 @@ describe('feature toggle', () => { cy.wait('@variantcreation'); }); it('Can set weight to fixed value for one of the variants', () => { - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/variants`); cy.get('[data-test=VARIANT_EDIT_BUTTON]').first().click(); @@ -352,7 +352,7 @@ describe('feature toggle', () => { it(`can delete variant`, () => { const variantName = 'to-be-deleted'; - cy.wait(500); + cy.wait(1000); cy.visit(`/projects/default/features/${featureToggleName}/variants`); cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); cy.get('[data-test=VARIANT_NAME_INPUT]').type(variantName); diff --git a/frontend/package.json b/frontend/package.json index c8ef4e2ff5..861c6c73b6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,6 +48,7 @@ "@types/debounce": "1.2.1", "@types/deep-diff": "1.0.1", "@types/jest": "27.4.0", + "@types/lodash.clonedeep": "4.5.6", "@types/node": "14.18.12", "@types/react": "17.0.39", "@types/react-dom": "17.0.11", @@ -56,6 +57,8 @@ "@types/react-test-renderer": "17.0.1", "@types/react-timeago": "4.1.3", "@welldone-software/why-did-you-render": "6.2.3", + "chart.js": "^3.7.1", + "chartjs-adapter-date-fns": "^2.0.0", "classnames": "2.3.1", "copy-to-clipboard": "3.3.1", "craco": "0.0.3", @@ -66,12 +69,12 @@ "deep-diff": "1.0.2", "fast-json-patch": "3.1.0", "http-proxy-middleware": "2.0.3", - "@types/lodash.clonedeep": "4.5.6", "lodash.clonedeep": "4.5.0", "lodash.flow": "3.5.0", "prettier": "2.5.1", "prop-types": "15.8.1", "react": "17.0.2", + "react-chartjs-2": "^4.0.1", "react-dnd": "14.0.5", "react-dnd-html5-backend": "14.1.0", "react-dom": "17.0.2", diff --git a/frontend/src/app.css b/frontend/src/app.css index 3b145e53ac..1e9cb390a2 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -133,6 +133,10 @@ p { font-size: var(--p-size); } +[hidden] { + display: none !important; +} + @media screen and (max-width: 1024px) { :root { --drawer-padding: 0.75rem 1.25rem; diff --git a/frontend/src/component/common/GeneralSelect/GeneralSelect.tsx b/frontend/src/component/common/GeneralSelect/GeneralSelect.tsx index fb3d7f1842..4c76656312 100644 --- a/frontend/src/component/common/GeneralSelect/GeneralSelect.tsx +++ b/frontend/src/component/common/GeneralSelect/GeneralSelect.tsx @@ -7,6 +7,7 @@ export interface ISelectOption { title?: string; label?: string; } + export interface ISelectMenuProps { name: string; id: string; @@ -14,16 +15,19 @@ export interface ISelectMenuProps { label?: string; options: ISelectOption[]; style?: object; - onChange?: ( - event: React.ChangeEvent<{ name?: string; value: unknown }>, - child: React.ReactNode - ) => void; + onChange?: OnGeneralSelectChange; disabled?: boolean; + fullWidth?: boolean; className?: string; classes?: any; defaultValue?: string; } +export type OnGeneralSelectChange = ( + event: React.ChangeEvent<{ name?: string; value: unknown }>, + child: React.ReactNode +) => void; + const GeneralSelect: React.FC = ({ name, value = '', @@ -35,6 +39,7 @@ const GeneralSelect: React.FC = ({ disabled = false, className, classes, + fullWidth, ...rest }) => { const renderSelectItems = () => @@ -50,10 +55,13 @@ const GeneralSelect: React.FC = ({ )); return ( - - - {label} - + + {label}