Admin panel: App health check (#10546)

closes https://github.com/twentyhq/core-team-issues/issues/441
whats new - 
- app health with the proposed format -- update, scratched this format
in favor of a more concise and more intentional health check. Now we
will check app health only based on pendingMigrations
<del>
```
status: 
  system: {
    nodeVersion
  },
  overview: {
    totalWorkspaces,
    criticalWorkspaces,
    workspacesWithPendingMigrations,
    healthDistribution: {
      healthy,
      warning,
      critical,
    }
  },
 problematicWorkspaces: [
    {
      workspaceId,
      severity,
      pendingMigrations,
      issuesSummary: {
        structural,
        data,
        relationship
      }
    }
  ]
  ```
</del>

- errorMessage and details seperation -- before we used to send error in details which made it difficult if we want both error and details on the front -- usecase >>
suppose app health indicator is not healthy but still want to send details
- stateHistory with timestamp -- this is something I introduced, not sure about this. Basically the thought process was to store the LastState of the details, incase of no connection or timeout errors. This is not yet used on the front, just the endpoint. But it could be used on the front too
- name unifying ⁠https://discord.com/channels/1130383047699738754/1346454192776155156
- json tree https://discord.com/channels/1130383047699738754/1346458558048501760
- match figma design https://discord.com/channels/1130383047699738754/1346451659647094815
- fix the collapse/open styles in tables https://discord.com/channels/1130383047699738754/1346452051974160406
- shift eye icon to expanded container https://discord.com/channels/1130383047699738754/1346452282669010987
- use H2Title for title and description of env variables groups https://discord.com/channels/1130383047699738754/1346434955936530452
This commit is contained in:
nitin
2025-03-07 01:49:41 +05:30
committed by GitHub
parent f6314e52fe
commit 3061576302
34 changed files with 808 additions and 244 deletions

View File

@ -2,6 +2,7 @@ import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import { useState } from 'react';
import {
AnimatedExpandableContainer,
@ -10,6 +11,7 @@ import {
IconEyeOff,
LightIconButton,
} from 'twenty-ui';
type SettingsAdminEnvVariablesRowProps = {
variable: {
name: string;
@ -26,8 +28,23 @@ const StyledTruncatedCell = styled(TableCell)`
cursor: pointer;
`;
const StyledButton = styled(motion.button)`
align-items: center;
border: none;
display: flex;
justify-content: center;
padding-inline: ${({ theme }) => theme.spacing(1)};
background-color: transparent;
height: 24px;
width: 24px;
box-sizing: border-box;
cursor: pointer;
`;
const MotionIconChevronDown = motion(IconChevronRight);
const StyledExpandedDetails = styled.div`
background-color: ${({ theme }) => theme.background.tertiary};
background-color: ${({ theme }) => theme.background.secondary};
border-radius: ${({ theme }) => theme.border.radius.sm};
margin: ${({ theme }) => theme.spacing(2)} 0;
padding: ${({ theme }) => theme.spacing(2)};
@ -40,7 +57,8 @@ const StyledExpandedDetails = styled.div`
`;
const StyledDetailLabel = styled.div`
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${({ theme }) => theme.font.color.tertiary};
font-weight: ${({ theme }) => theme.font.weight.regular};
padding-right: ${({ theme }) => theme.spacing(4)};
`;
@ -56,12 +74,16 @@ const StyledExpandedLabel = styled.div`
overflow: visible;
`;
const StyledTransitionedIconChevronRight = styled(IconChevronRight)`
cursor: pointer;
transform: ${({ $isExpanded }: { $isExpanded: boolean }) =>
$isExpanded ? 'rotate(90deg)' : 'rotate(0deg)'};
transition: ${({ theme }) =>
`transform ${theme.animation.duration.normal}s ease`};
const StyledValueContainer = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;
const StyledTableRow = styled(TableRow)<{ isExpanded: boolean }>`
background-color: ${({ isExpanded, theme }) =>
isExpanded ? theme.background.transparent.light : 'transparent'};
margin-bottom: ${({ theme }) => theme.spacing(0.5)};
`;
export const SettingsAdminEnvVariablesRow = ({
@ -85,44 +107,51 @@ export const SettingsAdminEnvVariablesRow = ({
return (
<>
<TableRow
<StyledTableRow
onClick={() => setIsExpanded(!isExpanded)}
gridAutoColumns="4fr 3fr 2fr 1fr 1fr"
gridAutoColumns="5fr 4fr 3fr 1fr"
isExpanded={isExpanded}
>
<StyledTruncatedCell color="primary">
<StyledTruncatedCell color={theme.font.color.primary}>
<StyledEllipsisLabel>{variable.name}</StyledEllipsisLabel>
</StyledTruncatedCell>
<StyledTruncatedCell>
<StyledEllipsisLabel>{variable.description}</StyledEllipsisLabel>
</StyledTruncatedCell>
<StyledTruncatedCell>
<StyledTruncatedCell align="right">
<StyledEllipsisLabel>{displayValue}</StyledEllipsisLabel>
</StyledTruncatedCell>
<TableCell align="right">
{variable.sensitive && variable.value !== '' && (
<LightIconButton
Icon={showSensitiveValue ? IconEyeOff : IconEye}
size="small"
accent="secondary"
onClick={handleToggleVisibility}
<StyledButton onClick={() => setIsExpanded(!isExpanded)}>
<MotionIconChevronDown
size={theme.icon.size.md}
color={theme.font.color.tertiary}
initial={false}
animate={{ rotate: isExpanded ? 90 : 0 }}
/>
)}
</StyledButton>
</TableCell>
<TableCell align="right">
<StyledTransitionedIconChevronRight
$isExpanded={isExpanded}
size={theme.icon.size.sm}
/>
</TableCell>
</TableRow>
</StyledTableRow>
<AnimatedExpandableContainer isExpanded={isExpanded} mode="fit-content">
<StyledExpandedDetails>
<StyledDetailLabel>Name:</StyledDetailLabel>
<StyledDetailLabel>Name</StyledDetailLabel>
<StyledEllipsisLabel>{variable.name}</StyledEllipsisLabel>
<StyledDetailLabel>Description:</StyledDetailLabel>
<StyledDetailLabel>Description</StyledDetailLabel>
<StyledExpandedLabel>{variable.description}</StyledExpandedLabel>
<StyledDetailLabel>Value:</StyledDetailLabel>
<StyledExpandedLabel>{displayValue}</StyledExpandedLabel>
<StyledDetailLabel>Value</StyledDetailLabel>
<StyledExpandedLabel>
<StyledValueContainer>
{displayValue}
{variable.sensitive && variable.value !== '' && (
<LightIconButton
Icon={showSensitiveValue ? IconEyeOff : IconEye}
size="small"
accent="secondary"
onClick={handleToggleVisibility}
/>
)}
</StyledValueContainer>
</StyledExpandedLabel>
</StyledExpandedDetails>
</AnimatedExpandableContainer>
</>