From 0035f18370455c94f2cdbe93df901c6faa67f25a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Fri, 29 Aug 2025 12:19:28 +0100 Subject: [PATCH 1/4] chore: allows you to add a flag from the unknown flags list (#10569) https://linear.app/unleash/issue/2-3826/allow-you-to-create-the-flag-from-the-unknown-flags-list Allows you to add a flag from the unknown flags list. image image --- .../unknownFlags/UnknownFlagsActionsCell.tsx | 54 +++++++++++++++++++ .../unknownFlags/UnknownFlagsTable.tsx | 12 +++++ 2 files changed, 66 insertions(+) create mode 100644 frontend/src/component/unknownFlags/UnknownFlagsActionsCell.tsx diff --git a/frontend/src/component/unknownFlags/UnknownFlagsActionsCell.tsx b/frontend/src/component/unknownFlags/UnknownFlagsActionsCell.tsx new file mode 100644 index 0000000000..dc1a9c81e5 --- /dev/null +++ b/frontend/src/component/unknownFlags/UnknownFlagsActionsCell.tsx @@ -0,0 +1,54 @@ +import Add from '@mui/icons-material/Add'; +import { Box, styled } from '@mui/material'; +import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; +import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions'; +import type { UnknownFlag } from './hooks/useUnknownFlags.js'; +import { Link } from 'react-router-dom'; +import useProjects from 'hooks/api/getters/useProjects/useProjects.js'; +import { DEFAULT_PROJECT_ID } from 'hooks/api/getters/useDefaultProject/useDefaultProjectId.js'; +import AccessContext from 'contexts/AccessContext.js'; +import { useContext } from 'react'; + +const StyledBox = styled(Box)(() => ({ + display: 'flex', + justifyContent: 'center', +})); + +interface IUnknownFlagsActionsCellProps { + unknownFlag: UnknownFlag; +} + +export const UnknownFlagsActionsCell = ({ + unknownFlag, +}: IUnknownFlagsActionsCellProps) => { + const { projects } = useProjects(); + const { hasAccess } = useContext(AccessContext); + + let project = + projects.find(({ id }) => id === DEFAULT_PROJECT_ID) || projects[0]; + if (!hasAccess(CREATE_FEATURE, project?.id)) { + for (const proj of projects) { + if (hasAccess(CREATE_FEATURE, proj.id)) { + project = proj; + break; + } + } + } + + return ( + + + + + + ); +}; diff --git a/frontend/src/component/unknownFlags/UnknownFlagsTable.tsx b/frontend/src/component/unknownFlags/UnknownFlagsTable.tsx index 6710e0f202..714ec76bd5 100644 --- a/frontend/src/component/unknownFlags/UnknownFlagsTable.tsx +++ b/frontend/src/component/unknownFlags/UnknownFlagsTable.tsx @@ -18,6 +18,7 @@ import { useUiFlag } from 'hooks/useUiFlag.js'; import NotFound from 'component/common/NotFound/NotFound.js'; import { UnknownFlagsSeenInUnleashCell } from './UnknownFlagsSeenInUnleashCell.js'; import { HelpIcon } from 'component/common/HelpIcon/HelpIcon.js'; +import { UnknownFlagsActionsCell } from './UnknownFlagsActionsCell.js'; const StyledAlert = styled(Alert)(({ theme }) => ({ marginBottom: theme.spacing(3), @@ -104,6 +105,17 @@ export const UnknownFlagsTable = () => { ), width: 150, }, + { + Header: 'Actions', + align: 'center', + Cell: ({ + row: { original: unknownFlag }, + }: { + row: { original: UnknownFlag }; + }) => , + width: 100, + disableSortBy: true, + }, ], [], ); From f827d5e8321fe426495e575b5c0d62d0ef2ceb92 Mon Sep 17 00:00:00 2001 From: Melinda Fekete Date: Fri, 29 Aug 2025 15:49:26 +0200 Subject: [PATCH 2/4] docs: update links in main readme (#10577) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b626d76bc1..1fe2a5bad8 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Build and Tests](https://img.shields.io/github/actions/workflow/status/Unleash/unleash/build.yaml?branch=main)](https://github.com/Unleash/unleash/actions/workflows/build.yaml) [![Coverage Report](https://img.shields.io/badge/coverage-vitest-green)](https://github.com/Unleash/unleash/actions/workflows/build_coverage.yaml) [![Docker Pulls](https://img.shields.io/docker/pulls/unleashorg/unleash-server)](https://hub.docker.com/r/unleashorg/unleash-server) [![Apache-2.0 license](https://img.shields.io/github/license/unleash/unleash)](https://github.com/Unleash/unleash/blob/main/LICENSE) [![Join Unleash on Slack](https://img.shields.io/badge/slack-join-635dc5?logo=slack)](https://slack.unleash.run) -[Experience Unleash Live Demo →](https://www.getunleash.io/interactive-demo) +[Try Unleash Cloud for free →](https://www.getunleash.io/plans/enterprise-payg?utm_source=readme&utm_medium=oss&utm_content=top-cta) @@ -93,9 +93,9 @@ The above sections show you how to get up and running quickly and easily. When y ## Online demo -Try out [the Unleash online demo](https://www.getunleash.io/interactive-demo). +Try out [the Unleash online demo](https://www.getunleash.io/interactive-demo?utm_source=readme&utm_medium=oss&utm_content=demo-section-cta). -[![The Unleash online demo](./.github/github_online_demo.svg)](https://www.getunleash.io/interactive-demo) +[![The Unleash online demo](./.github/github_online_demo.svg)](https://www.getunleash.io/interactive-demo?utm_source=readme&utm_medium=oss&utm_content=demo-section-cta)
From 758ea69f4f8ae1e0436080eb9778a21deeb3ab61 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Mon, 1 Sep 2025 08:22:44 +0200 Subject: [PATCH 3/4] Update chart colors to increase contrasts between the A series. (#10579) Makes it easier to tell the difference between a1 and a2 in particular. Before: image After: image --- frontend/src/themes/dark-theme.ts | 7 +++---- frontend/src/themes/theme.ts | 7 +++---- frontend/src/themes/themeTypes.ts | 1 - 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/frontend/src/themes/dark-theme.ts b/frontend/src/themes/dark-theme.ts index ee31c286ad..535ed0441c 100644 --- a/frontend/src/themes/dark-theme.ts +++ b/frontend/src/themes/dark-theme.ts @@ -221,10 +221,9 @@ const theme = { */ charts: { A1: '#6C65E5', - A2: '#8C87EB', - A3: '#ADA9F1', - A4: '#CECCF6', - A5: '#F1F0FC', + A2: '#9D98EE', + A3: '#CECCF6', + A4: '#F1F0FC', B1: '#1791AE', C1: '#DF416E', D1: '#D76500', diff --git a/frontend/src/themes/theme.ts b/frontend/src/themes/theme.ts index d50e0cc048..98452b8e19 100644 --- a/frontend/src/themes/theme.ts +++ b/frontend/src/themes/theme.ts @@ -277,10 +277,9 @@ const theme = { */ charts: { A1: '#6C65E5', - A2: '#8C87EB', - A3: '#ADA9F1', - A4: '#CECCF6', - A5: '#F1F0FC', + A2: '#9D98EE', + A3: '#CECCF6', + A4: '#F1F0FC', B1: '#1791AE', C1: '#DF416E', D1: '#D76500', diff --git a/frontend/src/themes/themeTypes.ts b/frontend/src/themes/themeTypes.ts index 6cada0aad0..c750316d2a 100644 --- a/frontend/src/themes/themeTypes.ts +++ b/frontend/src/themes/themeTypes.ts @@ -142,7 +142,6 @@ declare module '@mui/material/styles' { A2: string; A3: string; A4: string; - A5: string; B1: string; C1: string; D1: string; From a7c8f527bda9d39f0a6653697506c2caf08e8682 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Mon, 1 Sep 2025 09:14:02 +0200 Subject: [PATCH 4/4] chore: show N/A for ratio if we can't calculate it (#10580) Also, change the widget title to reflect the order of the ratio. Before: image image After: image image Closes 1-4039 --- .../calculate-ratio/calculate-ratio.test.ts | 16 ++++++++-------- .../insights/calculate-ratio/calculate-ratio.ts | 11 +++++------ .../CreationArchiveRatioTooltip.tsx | 2 +- .../CreationArchiveStats.tsx | 2 +- .../insights/sections/PerformanceInsights.tsx | 2 +- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/frontend/src/component/insights/calculate-ratio/calculate-ratio.test.ts b/frontend/src/component/insights/calculate-ratio/calculate-ratio.test.ts index 61548cd669..39c92b95e5 100644 --- a/frontend/src/component/insights/calculate-ratio/calculate-ratio.test.ts +++ b/frontend/src/component/insights/calculate-ratio/calculate-ratio.test.ts @@ -1,17 +1,17 @@ import { calculateRatio } from './calculate-ratio.ts'; -test('A ratio of anything to 0 is 100', () => { - expect(calculateRatio(0, 0)).toBe(100); - expect(calculateRatio(5, 0)).toBe(100); +test('A ratio of anything to 0 is N/A', () => { + expect(calculateRatio(0, 0)).toBe('N/A'); + expect(calculateRatio(5, 0)).toBe('N/A'); }); test('Normal ratios work as expected', () => { - expect(calculateRatio(0, 1)).toBe(0); - expect(calculateRatio(1, 1)).toBe(100); - expect(calculateRatio(1, 2)).toBe(50); - expect(calculateRatio(5, 2)).toBe(250); + expect(calculateRatio(0, 1)).toBe('0%'); + expect(calculateRatio(1, 1)).toBe('100%'); + expect(calculateRatio(1, 2)).toBe('50%'); + expect(calculateRatio(5, 2)).toBe('250%'); }); test('Numbers are rounded to the nearest integer', () => { - expect(calculateRatio(5, 9)).toBe(56); + expect(calculateRatio(5, 9)).toBe('56%'); }); diff --git a/frontend/src/component/insights/calculate-ratio/calculate-ratio.ts b/frontend/src/component/insights/calculate-ratio/calculate-ratio.ts index ad5e1066a6..b80875bf84 100644 --- a/frontend/src/component/insights/calculate-ratio/calculate-ratio.ts +++ b/frontend/src/component/insights/calculate-ratio/calculate-ratio.ts @@ -1,12 +1,11 @@ export const calculateRatio = ( antecedent: number, consequent: number, -): number => { - const rawRatio = Math.round((antecedent / consequent) * 100); - - if (Number.isNaN(rawRatio) || rawRatio === Number.POSITIVE_INFINITY) { - return 100; +): string => { + if (consequent === 0) { + return 'N/A'; } + const ratio = Math.round((antecedent / consequent) * 100); - return rawRatio; + return `${ratio}%`; }; diff --git a/frontend/src/component/insights/componentsChart/CreationArchiveChart/CreationArchiveRatioTooltip.tsx b/frontend/src/component/insights/componentsChart/CreationArchiveChart/CreationArchiveRatioTooltip.tsx index 721ea7385a..29eb897a4e 100644 --- a/frontend/src/component/insights/componentsChart/CreationArchiveChart/CreationArchiveRatioTooltip.tsx +++ b/frontend/src/component/insights/componentsChart/CreationArchiveChart/CreationArchiveRatioTooltip.tsx @@ -62,7 +62,7 @@ export const CreationArchiveRatioTooltip: FC< fontWeight='bold' sx={{ marginBottom: 1 }} > - Ratio {ratio}% + Ratio {ratio} diff --git a/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx b/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx index 6c9a2251c1..a674165dfe 100644 --- a/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx +++ b/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx @@ -90,7 +90,7 @@ export const CreationArchiveStats: FC = ({ - {isLoading ? '...' : `${currentRatio}%`} + {isLoading ? '...' : currentRatio} diff --git a/frontend/src/component/insights/sections/PerformanceInsights.tsx b/frontend/src/component/insights/sections/PerformanceInsights.tsx index e19f9abd64..4e1caf9ba1 100644 --- a/frontend/src/component/insights/sections/PerformanceInsights.tsx +++ b/frontend/src/component/insights/sections/PerformanceInsights.tsx @@ -113,7 +113,7 @@ export const PerformanceInsights: FC = () => { {isLifecycleGraphsEnabled && isEnterprise() ? ( - +