From a958797a8a7e5f0424720749aee5a448581a178c Mon Sep 17 00:00:00 2001 From: Jaanus Sellin Date: Thu, 29 Feb 2024 12:25:42 +0200 Subject: [PATCH] feat: add creation buttons to application features and strategies (#6387) ![image](https://github.com/Unleash/unleash/assets/964450/2c8215af-3ab3-43e6-bdeb-1ae36aad3aa3) --- .../ApplicationIssues/ApplicationIssues.tsx | 72 ++++++++++++++++--- .../application/ApplicationOverview.test.tsx | 45 ++++++++++++ 2 files changed, 106 insertions(+), 11 deletions(-) diff --git a/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx b/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx index 963adbc63c..0292c641be 100644 --- a/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx +++ b/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx @@ -1,12 +1,20 @@ import { Box, styled } from '@mui/material'; -import { ConditionallyRender } from '../../common/ConditionallyRender/ConditionallyRender'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { WarningAmberRounded } from '@mui/icons-material'; import { ApplicationOverviewIssuesSchema } from 'openapi'; +import { Link } from 'react-router-dom'; +import { + CREATE_FEATURE, + CREATE_STRATEGY, +} from 'component/providers/AccessProvider/permissions'; +import { useContext } from 'react'; +import AccessContext from 'contexts/AccessContext'; const WarningContainer = styled(Box)(({ theme }) => ({ display: 'flex', flexDirection: 'column', alignSelf: 'stretch', + fontSize: theme.fontSizes.smallBody, })); const WarningHeader = styled(Box)(({ theme }) => ({ @@ -21,11 +29,7 @@ const WarningHeader = styled(Box)(({ theme }) => ({ color: theme.palette.warning.main, })); -const SmallText = styled(Box)(({ theme }) => ({ - fontSize: theme.fontSizes.smallBody, -})); - -const WarningHeaderText = styled(SmallText)(({ theme }) => ({ +const WarningHeaderText = styled(Box)(({ theme }) => ({ color: theme.palette.warning.dark, fontWeight: theme.fontWeight.bold, })); @@ -36,7 +40,6 @@ const StyledList = styled('ul')(({ theme }) => ({ const StyledListElement = styled('li')(({ theme }) => ({ fontWeight: theme.fontWeight.bold, - fontSize: theme.fontSizes.smallBody, })); const IssueContainer = styled(Box)(({ theme }) => ({ @@ -62,6 +65,20 @@ const IssueTextContainer = styled(Box)(({ theme }) => ({ border: `1px solid ${theme.palette.divider}`, })); +const IssueRowContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'row', + gap: theme.spacing(1.5), + alignItems: 'center', +})); + +const StyledLink = styled(Link)(() => ({ + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + textDecoration: 'underline', +})); + export interface IApplicationIssuesProps { issues: ApplicationOverviewIssuesSchema[]; } @@ -85,6 +102,7 @@ const resolveIssueText = (issue: ApplicationOverviewIssuesSchema) => { }; export const ApplicationIssues = ({ issues }: IApplicationIssuesProps) => { + const { hasAccess } = useContext(AccessContext); return ( 0} @@ -100,12 +118,44 @@ export const ApplicationIssues = ({ issues }: IApplicationIssuesProps) => { {issues.map((issue) => ( - {resolveIssueText(issue)} + {resolveIssueText(issue)} {issue.items.map((item) => ( - - {item} - + + + {item} + + + Create feature flag + + } + /> + + Create strategy type + + } + /> + ))} diff --git a/frontend/src/component/application/ApplicationOverview.test.tsx b/frontend/src/component/application/ApplicationOverview.test.tsx index 864234a271..55538f0b79 100644 --- a/frontend/src/component/application/ApplicationOverview.test.tsx +++ b/frontend/src/component/application/ApplicationOverview.test.tsx @@ -72,3 +72,48 @@ test('Display application overview without environments', async () => { await screen.findByText('my-app'); await screen.findByText('No data available.'); }); + +test('Display application with issues', async () => { + setupApi({ + environments: [ + { + name: 'development', + instanceCount: 999, + lastSeen: new Date().toISOString(), + sdks: ['unleash-client-node:5.5.0-beta.0'], + }, + ], + issues: [ + { + type: 'missingFeatures', + items: ['feature1'], + }, + { + type: 'missingStrategies', + items: ['strategy1'], + }, + ], + featureCount: 1, + projects: ['default'], + }); + render( + + } + /> + , + { + route: '/applications/my-app', + }, + ); + + await screen.findByText( + 'We detected 1 feature flag defined in the SDK that does not exist in Unleash', + ); + await screen.findByText( + 'We detected 1 strategy type defined in the SDK that does not exist in Unleash', + ); + await screen.findByText('feature1'); + await screen.findByText('strategy1'); +});