From 7af7b32bd57302bb89d8f9c3b134c0856b84792a Mon Sep 17 00:00:00 2001 From: Jaanus Sellin Date: Wed, 28 Feb 2024 12:39:33 +0200 Subject: [PATCH] feat: application overview ux improvements (#6371) 1. Added navigation from environments to instances 2. Last seen is now shown as TimeAgo 3. Added icons for total environments and features 4. Fixed schema ![image](https://github.com/Unleash/unleash/assets/964450/4d0a51a9-7141-4854-ada9-72676e42239c) --- .../application/ApplicationChart.tsx | 63 ++++++++++++++++++- .../ApplicationIssues/ApplicationIssues.tsx | 3 +- .../application/ApplicationOverview.test.tsx | 4 +- .../application/ApplicationOverview.tsx | 1 + .../ConnectedInstances/ConnectedInstances.tsx | 2 +- .../useConnectedInstancesTable.tsx | 3 +- ...application-overview-environment-schema.ts | 1 + 7 files changed, 69 insertions(+), 8 deletions(-) diff --git a/frontend/src/component/application/ApplicationChart.tsx b/frontend/src/component/application/ApplicationChart.tsx index 6ac6c612b2..fee9d4551e 100644 --- a/frontend/src/component/application/ApplicationChart.tsx +++ b/frontend/src/component/application/ApplicationChart.tsx @@ -5,12 +5,13 @@ import { useNavigate } from 'react-router-dom'; import { FC, useLayoutEffect, useRef, useState } from 'react'; import { ApplicationOverviewSchema } from '../../openapi'; import { useRequiredPathParam } from '../../hooks/useRequiredPathParam'; -import { WarningAmberRounded } from '@mui/icons-material'; import { HelpIcon } from '../common/HelpIcon/HelpIcon'; +import { CloudCircle, Flag, WarningAmberRounded } from '@mui/icons-material'; +import TimeAgo from 'react-timeago'; const StyledTable = styled('table')(({ theme }) => ({ fontSize: theme.fontSizes.smallerBody, - marginTop: theme.spacing(2), + marginTop: theme.spacing(1), })); const StyledCell = styled('td')(({ theme }) => ({ @@ -78,6 +79,23 @@ const StyledStatus = styled(Typography)<{ alignItems: 'center', })); +const StyledIconRow = styled(Box)(({ theme }) => ({ + display: 'flex', + gap: theme.spacing(3), + color: theme.palette.secondary.main, + paddingTop: theme.spacing(2), +})); + +const StyledIconContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + gap: theme.spacing(0.5), +})); +const StyledText = styled(Box)(({ theme }) => ({ + color: theme.palette.text.primary, + display: 'flex', + alignItems: 'center', +})); + const useElementWidth = () => { const elementRef = useRef(null); const [width, setWidth] = useState('100%'); @@ -117,6 +135,29 @@ interface IApplicationChartProps { data: ApplicationOverviewSchema; } +interface IApplicationCountersProps { + environmentCount: number; + featureCount: number; +} + +const ApplicationCounters = ({ + environmentCount, + featureCount, +}: IApplicationCountersProps) => { + return ( + + + + {environmentCount} + + + + {featureCount} + + + ); +}; + export const ApplicationChart = ({ data }: IApplicationChartProps) => { const applicationName = useRequiredPathParam('name'); const { elementRef, width } = useElementWidth(); @@ -164,6 +205,10 @@ export const ApplicationChart = ({ data }: IApplicationChartProps) => { > {applicationName} + @@ -189,6 +234,12 @@ export const ApplicationChart = ({ data }: IApplicationChartProps) => { { + navigate( + `/applications/${applicationName}/instances?environment=${environment.name}`, + ); + }} > {environment.name} environment @@ -224,7 +275,13 @@ export const ApplicationChart = ({ data }: IApplicationChartProps) => { Last seen: - {environment.lastSeen} + diff --git a/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx b/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx index 1340cbf0a3..963adbc63c 100644 --- a/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx +++ b/frontend/src/component/application/ApplicationIssues/ApplicationIssues.tsx @@ -12,12 +12,13 @@ const WarningContainer = styled(Box)(({ theme }) => ({ const WarningHeader = styled(Box)(({ theme }) => ({ display: 'flex', padding: theme.spacing(2, 3, 2, 3), - alignItems: 'flex-start', + alignItems: 'center', gap: theme.spacing(1.5), alignSelf: 'stretch', borderRadius: `${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px 0 0`, border: `1px solid ${theme.palette.warning.border}`, background: theme.palette.warning.light, + color: theme.palette.warning.main, })); const SmallText = styled(Box)(({ theme }) => ({ diff --git a/frontend/src/component/application/ApplicationOverview.test.tsx b/frontend/src/component/application/ApplicationOverview.test.tsx index 7eea7239bf..864234a271 100644 --- a/frontend/src/component/application/ApplicationOverview.test.tsx +++ b/frontend/src/component/application/ApplicationOverview.test.tsx @@ -22,7 +22,7 @@ test('Display application overview with environments', async () => { { name: 'development', instanceCount: 999, - lastSeen: '2024-02-22T20:20:24.740', + lastSeen: new Date().toISOString(), sdks: ['unleash-client-node:5.5.0-beta.0'], }, ], @@ -47,7 +47,7 @@ test('Display application overview with environments', async () => { await screen.findByText('development environment'); await screen.findByText('999'); await screen.findByText('unleash-client-node:5.5.0-beta.0'); - await screen.findByText('2024-02-22T20:20:24.740'); + await screen.findByText('1 second ago'); }); test('Display application overview without environments', async () => { diff --git a/frontend/src/component/application/ApplicationOverview.tsx b/frontend/src/component/application/ApplicationOverview.tsx index 85fed61fc0..2571be7b1b 100644 --- a/frontend/src/component/application/ApplicationOverview.tsx +++ b/frontend/src/component/application/ApplicationOverview.tsx @@ -48,6 +48,7 @@ const ApplicationOverview = () => { {data.projects.map((project) => ( { e.preventDefault(); navigate(`/projects/${project}`); diff --git a/frontend/src/component/application/ConnectedInstances/ConnectedInstances.tsx b/frontend/src/component/application/ConnectedInstances/ConnectedInstances.tsx index 9c8ff50814..30497a8af1 100644 --- a/frontend/src/component/application/ConnectedInstances/ConnectedInstances.tsx +++ b/frontend/src/component/application/ConnectedInstances/ConnectedInstances.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useMemo, useState } from 'react'; +import { FC, useEffect, useMemo } from 'react'; import { formatDateYMDHMS } from 'utils/formatDate'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useConnectedInstancesTable } from './useConnectedInstancesTable'; diff --git a/frontend/src/component/application/ConnectedInstances/useConnectedInstancesTable.tsx b/frontend/src/component/application/ConnectedInstances/useConnectedInstancesTable.tsx index 751ac8215e..e149640ef3 100644 --- a/frontend/src/component/application/ConnectedInstances/useConnectedInstancesTable.tsx +++ b/frontend/src/component/application/ConnectedInstances/useConnectedInstancesTable.tsx @@ -2,6 +2,7 @@ import { useMemo } from 'react'; import { HighlightCell } from 'component/common/Table/cells/HighlightCell/HighlightCell'; import { useTable, useGlobalFilter, useSortBy } from 'react-table'; import { sortTypes } from 'utils/sortTypes'; +import { TimeAgoCell } from '../../common/Table/cells/TimeAgoCell/TimeAgoCell'; type ConnectedInstancesTableData = { instanceId: string; @@ -39,7 +40,7 @@ export const useConnectedInstancesTable = ( { Header: 'Last seen', accessor: 'lastSeen', - Cell: HighlightCell, + Cell: TimeAgoCell, styles: { width: '20%', }, diff --git a/src/lib/openapi/spec/application-overview-environment-schema.ts b/src/lib/openapi/spec/application-overview-environment-schema.ts index 037b01d364..c8602b1acc 100644 --- a/src/lib/openapi/spec/application-overview-environment-schema.ts +++ b/src/lib/openapi/spec/application-overview-environment-schema.ts @@ -28,6 +28,7 @@ export const applicationOverviewEnvironmentSchema = { }, lastSeen: { type: 'string', + nullable: true, format: 'date-time', example: '2023-04-19T08:15:14.000Z', description: 'The last time the application environment was seen',