Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
matejkubinec committed Oct 23, 2024
2 parents 5b56511 + 7829a4d commit 4585d2b
Show file tree
Hide file tree
Showing 26 changed files with 2,188 additions and 1,014 deletions.
8 changes: 5 additions & 3 deletions ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

[Percona Monitoring and Management (PMM)](https://www.percona.com/software/database-tools/percona-monitoring-and-management) is a best-of-breed open source database monitoring solution. It helps you reduce complexity, optimize performance, and improve the security of your business-critical database environments, no matter where they are located or deployed.
PMM helps users to:
* Reduce Complexity
* Optimize Database Performance
* Improve Data Security

- Reduce Complexity
- Optimize Database Performance
- Improve Data Security

See the [PMM Documentation](https://www.percona.com/doc/percona-monitoring-and-management/2.x/index.html) for more information.

## Pre-Requisites

Make sure you have the following installed:

- [node 18](https://nodejs.org/en) (you can also use [nvm](https://github.com/nvm-sh/nvm) to manage node versions)
- [yarn](https://yarnpkg.com/)

Expand Down
15 changes: 7 additions & 8 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
"date-fns": "^2.30.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1"
"react-markdown": "^9.0.1",
"react-router-dom": "^6.23.1",
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.0"
},
"devDependencies": {
"@percona/eslint-config-react": "^1.0.0",
Expand All @@ -49,13 +52,9 @@
"jsdom": "^24.1.1",
"prettier": "^3.2.5",
"typescript": "^5.4.5",
"vite": "^5.3.5",
"vite": "^5.4.6",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.0.5"
},
"resolutions": {
"braces": "^3.0.3",
"vite": "^5.3.5"
"vitest": "^2.1.1"
},
"prettier": "@percona/prettier-config"
}
}
8 changes: 8 additions & 0 deletions ui/src/api/updates.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AxiosResponse } from 'axios';
import {
GetChangeLogsResponse,
GetUpdateStatusBody,
GetUpdateStatusResponse,
GetUpdatesParams,
Expand Down Expand Up @@ -33,3 +34,10 @@ export const getUpdateStatus = async (body: GetUpdateStatusBody) => {
>('/server/updates:getStatus', body);
return res.data;
};

export const getChangeLogs = async (): Promise<GetChangeLogsResponse> => {
const res = await api.get<GetChangeLogsResponse>(
'/server/updates/changelogs'
);
return res.data;
};
2 changes: 1 addition & 1 deletion ui/src/components/main/Main.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('Main', () => {
</TestWrapper>
);

expect(screen.queryByTestId('pmm-loading-indicator')).not.toBeNull()
expect(screen.queryByTestId('pmm-loading-indicator')).not.toBeNull();
});

it("doesn't show loading", () => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/contexts/user/user.context.types.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { User } from "types/user.types";
import { User } from 'types/user.types';

export interface UserContextProps {
isLoading: boolean;
Expand Down
30 changes: 22 additions & 8 deletions ui/src/hooks/api/useUpdates.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { checkForUpdates, startUpdate } from 'api/updates';
import { checkForUpdates, getChangeLogs, startUpdate } from 'api/updates';
import {
useMutation,
UseMutationOptions,
useQuery,
UseQueryOptions,
} from '@tanstack/react-query';
import { StartUpdateBody, StartUpdateResponse } from 'types/updates.types';
import {
GetChangeLogsResponse,
GetUpdatesResponse,
StartUpdateBody,
StartUpdateResponse,
} from 'types/updates.types';
import { AxiosError } from 'axios';

export const useCheckUpdates = () =>
export const useCheckUpdates = (
options?: UseQueryOptions<GetUpdatesResponse>
) =>
useQuery({
queryKey: ['checkUpdates'],
queryFn: async () => {
Expand All @@ -24,16 +32,22 @@ export const useCheckUpdates = () =>
throw error;
}
},
...options,
});

export const useStartUpdate = (
options?: UseMutationOptions<
StartUpdateResponse | undefined,
unknown,
StartUpdateBody
>
options?: UseMutationOptions<StartUpdateResponse, unknown, StartUpdateBody>
) =>
useMutation({
mutationFn: (args) => startUpdate(args),
...options,
});

export const useChangeLogs = (
options?: UseQueryOptions<GetChangeLogsResponse>
) =>
useQuery({
queryKey: ['changeLogs'],
queryFn: getChangeLogs,
...options,
});
24 changes: 24 additions & 0 deletions ui/src/icons/pmm/check.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SvgIcon, SvgIconProps } from '@mui/material';

export const CheckIcon = (props: SvgIconProps) => (
<SvgIcon
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
xmlns="https://www.w3.org/2000/svg"
{...props}
>
<g clip-path="url(#clip0)">
<path
d="M3.85 19.95C3.75 19.95 3.65 19.9 3.6 19.85C3.45 19.7 3.45 19.45 3.6 19.3L4.2 18.7C4.35 18.55 4.6 18.55 4.75 18.7C4.9 18.85 4.9 19.1 4.75 19.25L4.15 19.85C4.05 19.9 3.95 19.95 3.85 19.95ZM11.6 23.15C11.4 23.15 11.2 23 11.2 22.75V21.95C11.2 21.75 11.35 21.55 11.6 21.55C11.8 21.55 12 21.7 12 21.95V22.75C11.95 22.95 11.8 23.15 11.6 23.15ZM22.5 12.2H21.7C21.5 12.2 21.3 12.05 21.3 11.8C21.3 11.6 21.45 11.4 21.7 11.4H22.5C22.7 11.4 22.9 11.55 22.9 11.8C22.9 12 22.75 12.2 22.5 12.2ZM1.45 12.2H0.65C0.45 12.2 0.25 12.05 0.25 11.8C0.25 11.6 0.4 11.4 0.65 11.4H1.45C1.65 11.4 1.85 11.55 1.85 11.8C1.85 12 1.65 12.2 1.45 12.2ZM1.45 16.35C1.3 16.35 1.15 16.25 1.1 16.1C1 15.9 1.1 15.7 1.3 15.6L2.05 15.3C2.25 15.2 2.45 15.3 2.55 15.5C2.65 15.7 2.55 15.9 2.35 16L1.6 16.3C1.55 16.35 1.5 16.35 1.45 16.35ZM7.35 22.3C7.3 22.3 7.25 22.3 7.2 22.25C7 22.15 6.9 21.95 7 21.75L7.3 21C7.4 20.8 7.6 20.7 7.8 20.8C8 20.9 8.1 21.1 8 21.3L7.7 22.05C7.65 22.2 7.5 22.3 7.35 22.3ZM4.1 4.75C4 4.75 3.9 4.7 3.8 4.6L3.2 4C3.05 3.85 3.05 3.6 3.2 3.45C3.35 3.3 3.6 3.3 3.75 3.45L4.35 4.05C4.5 4.2 4.5 4.45 4.35 4.6C4.3 4.7 4.2 4.75 4.1 4.75ZM19 4.75C18.9 4.75 18.8 4.7 18.7 4.65C18.55 4.5 18.55 4.25 18.7 4.1L19.3 3.5C19.45 3.35 19.7 3.35 19.85 3.5C20 3.65 20 3.9 19.85 4.05L19.25 4.65C19.2 4.7 19.1 4.75 19 4.75ZM11.55 1.65C11.35 1.65 11.15 1.45 11.15 1.25V0.4C11.15 0.2 11.35 0 11.55 0C11.75 0 11.95 0.2 11.95 0.4V1.25C11.95 1.45 11.75 1.65 11.55 1.65ZM7.55 2.4C7.4 2.4 7.25 2.3 7.2 2.15L6.9 1.35C6.8 1.15 6.9 0.9 7.1 0.85C7.3 0.75 7.55 0.85 7.6 1.05L7.9 1.85C8 2.05 7.9 2.3 7.7 2.35C7.65 2.4 7.6 2.4 7.55 2.4ZM21.35 8.2C21.2 8.2 21.05 8.1 21 7.95C20.9 7.75 21 7.5 21.2 7.45L22 7.15C22.2 7.05 22.45 7.15 22.5 7.35C22.6 7.55 22.5 7.8 22.3 7.85L21.5 8.15C21.45 8.2 21.4 8.2 21.35 8.2ZM15.65 2.45C15.6 2.45 15.55 2.45 15.5 2.4C15.3 2.3 15.2 2.1 15.3 1.9L15.65 1.1C15.75 0.9 15.95 0.8 16.15 0.9C16.35 1 16.45 1.2 16.35 1.4L16 2.2C15.95 2.35 15.8 2.45 15.65 2.45ZM1.8 8.1C1.75 8.1 1.7 8.1 1.65 8.05L0.85 7.7C0.65 7.6 0.55 7.4 0.65 7.2C0.75 7 0.95 6.9 1.15 7L1.95 7.35C2.15 7.45 2.25 7.65 2.15 7.85C2.1 8 1.95 8.1 1.8 8.1ZM14.6 8.75C13.8 7.95 12.7 7.5 11.55 7.5C10.4 7.5 9.3 7.95 8.5 8.75C6.8 10.45 6.8 13.2 8.5 14.85C9.3 15.65 10.4 16.1 11.55 16.1C12.7 16.1 13.8 15.65 14.6 14.85C15.4 14.05 15.85 12.95 15.85 11.8C15.9 10.65 15.4 9.55 14.6 8.75ZM13.75 14C13.15 14.6 12.35 14.9 11.55 14.9C10.7 14.9 9.95 14.6 9.35 14C8.15 12.8 8.15 10.8 9.35 9.6C9.65 9.3 9.95 9.1 10.35 8.95C10.45 8.9 10.6 8.9 10.7 8.95C10.8 9 10.9 9.1 10.9 9.25C10.95 9.4 11 9.55 11.1 9.65C11.4 9.95 11.9 9.95 12.15 9.65C12.25 9.55 12.3 9.45 12.35 9.3C12.4 9.2 12.45 9.1 12.55 9.05C12.65 9 12.8 9 12.9 9.05C13.2 9.2 13.5 9.4 13.75 9.65C14.95 10.8 14.95 12.8 13.75 14ZM13.2 10.15C13.1 10.05 13 9.95 12.9 9.9C12.85 10 12.75 10.1 12.7 10.15C12.1 10.75 11.1 10.75 10.5 10.15C10.4 10.05 10.3 9.95 10.25 9.85C10.1 9.95 10 10.05 9.85 10.15C8.95 11.05 8.95 12.55 9.85 13.45C10.3 13.9 10.9 14.15 11.5 14.15C12.1 14.15 12.7 13.9 13.15 13.45C14.1 12.55 14.1 11.05 13.2 10.15ZM14.6 8.75C13.8 7.95 12.7 7.5 11.55 7.5C10.4 7.5 9.3 7.95 8.5 8.75C6.8 10.45 6.8 13.2 8.5 14.85C9.3 15.65 10.4 16.1 11.55 16.1C12.7 16.1 13.8 15.65 14.6 14.85C15.4 14.05 15.85 12.95 15.85 11.8C15.9 10.65 15.4 9.55 14.6 8.75ZM13.75 14C13.15 14.6 12.35 14.9 11.55 14.9C10.7 14.9 9.95 14.6 9.35 14C8.15 12.8 8.15 10.8 9.35 9.6C9.65 9.3 9.95 9.1 10.35 8.95C10.45 8.9 10.6 8.9 10.7 8.95C10.8 9 10.9 9.1 10.9 9.25C10.95 9.4 11 9.55 11.1 9.65C11.4 9.95 11.9 9.95 12.15 9.65C12.25 9.55 12.3 9.45 12.35 9.3C12.4 9.2 12.45 9.1 12.55 9.05C12.65 9 12.8 9 12.9 9.05C13.2 9.2 13.5 9.4 13.75 9.65C14.95 10.8 14.95 12.8 13.75 14ZM13.2 10.15C13.1 10.05 13 9.95 12.9 9.9C12.85 10 12.75 10.1 12.7 10.15C12.1 10.75 11.1 10.75 10.5 10.15C10.4 10.05 10.3 9.95 10.25 9.85C10.1 9.95 10 10.05 9.85 10.15C8.95 11.05 8.95 12.55 9.85 13.45C10.3 13.9 10.9 14.15 11.5 14.15C12.1 14.15 12.7 13.9 13.15 13.45C14.1 12.55 14.1 11.05 13.2 10.15ZM17.05 6.3C15.6 4.8 13.65 4 11.55 4C9.45 4 7.5 4.8 6.05 6.3C3 9.35 3 14.3 6.05 17.35C7.5 18.85 9.5 19.65 11.55 19.65C13.1 19.65 14.6 19.2 15.85 18.35C16.25 18.05 16.65 17.75 17.05 17.35C17.45 16.95 17.75 16.55 18.05 16.15C20.1 13.05 19.7 8.9 17.05 6.3ZM15.15 15.4C14.2 16.35 12.9 16.9 11.55 16.9C10.2 16.9 8.9 16.35 7.95 15.4C5.95 13.4 5.95 10.15 7.95 8.2C8.9 7.25 10.2 6.7 11.55 6.7C12.9 6.7 14.2 7.25 15.15 8.2C16.1 9.15 16.65 10.45 16.65 11.8C16.65 13.15 16.15 14.45 15.15 15.4ZM11.55 7.5C10.4 7.5 9.3 7.95 8.5 8.75C6.8 10.45 6.8 13.2 8.5 14.85C9.3 15.65 10.4 16.1 11.55 16.1C12.7 16.1 13.8 15.65 14.6 14.85C15.4 14.05 15.85 12.95 15.85 11.8C15.85 10.65 15.4 9.55 14.6 8.75C13.8 7.95 12.7 7.5 11.55 7.5ZM13.75 14C13.15 14.6 12.35 14.9 11.55 14.9C10.7 14.9 9.95 14.6 9.35 14C8.15 12.8 8.15 10.8 9.35 9.6C9.65 9.3 9.95 9.1 10.35 8.95C10.45 8.9 10.6 8.9 10.7 8.95C10.8 9 10.9 9.1 10.9 9.25C10.95 9.4 11 9.55 11.1 9.65C11.4 9.95 11.9 9.95 12.15 9.65C12.25 9.55 12.3 9.45 12.35 9.3C12.4 9.2 12.45 9.1 12.55 9.05C12.65 9 12.8 9 12.9 9.05C13.2 9.2 13.5 9.4 13.75 9.65C14.95 10.8 14.95 12.8 13.75 14ZM12.9 9.9C12.85 10 12.75 10.1 12.7 10.15C12.1 10.75 11.1 10.75 10.5 10.15C10.4 10.05 10.3 9.95 10.25 9.85C10.1 9.95 10 10.05 9.85 10.15C8.95 11.05 8.95 12.55 9.85 13.45C10.3 13.9 10.9 14.15 11.5 14.15C12.1 14.15 12.7 13.9 13.15 13.45C14.05 12.55 14.05 11.05 13.15 10.15C13.1 10.05 13 10 12.9 9.9ZM22.85 20.1L18.45 16.9C18.4 16.95 18.35 17.05 18.25 17.1C18.2 17.15 18.15 17.2 18.1 17.3C17.95 17.5 17.75 17.7 17.6 17.9C17.4 18.1 17.2 18.25 17 18.45C16.95 18.5 16.9 18.55 16.8 18.6C16.75 18.65 16.65 18.75 16.55 18.8L19.75 23.2C20.15 23.75 20.8 24.1 21.5 24.1C22.05 24.1 22.6 23.9 23 23.45C23.45 23 23.7 22.4 23.65 21.75C23.7 21.05 23.35 20.45 22.85 20.1Z"
fill="#000"
/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</SvgIcon>
);
16 changes: 16 additions & 0 deletions ui/src/icons/pmm/dashboards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { SvgIcon, SvgIconProps } from '@mui/material';

export const DashboardsIcon = (props: SvgIconProps) => (
<SvgIcon
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M9 3V21C9 21.5304 8.78929 22.0391 8.41421 22.4142C8.03914 22.7893 7.53043 23 7 23H3C2.46957 23 1.96086 22.7893 1.58579 22.4142C1.21071 22.0391 1 21.5304 1 21V3C1 2.46957 1.21071 1.96086 1.58579 1.58579C1.96086 1.21071 2.46957 1 3 1H7C7.53043 1 8.03914 1.21071 8.41421 1.58579C8.78929 1.96086 9 2.46957 9 3ZM15 16.7H21C21.5304 16.7 22.0391 16.9107 22.4142 17.2858C22.7893 17.6609 23 18.1696 23 18.7V21C23 21.5304 22.7893 22.0391 22.4142 22.4142C22.0391 22.7893 21.5304 23 21 23H15C14.4696 23 13.9609 22.7893 13.5858 22.4142C13.2107 22.0391 13 21.5304 13 21V18.7C13 18.1696 13.2107 17.6609 13.5858 17.2858C13.9609 16.9107 14.4696 16.7 15 16.7ZM15 1H21C21.5304 1 22.0391 1.21071 22.4142 1.58579C22.7893 1.96086 23 2.46957 23 3V10.7C23 11.2304 22.7893 11.7391 22.4142 12.1142C22.0391 12.4893 21.5304 12.7 21 12.7H15C14.4696 12.7 13.9609 12.4893 13.5858 12.1142C13.2107 11.7391 13 11.2304 13 10.7V3C13 2.46957 13.2107 1.96086 13.5858 1.58579C13.9609 1.21071 14.4696 1 15 1Z"
stroke="#9FA7B3"
strokeWidth="2"
/>
</SvgIcon>
);
4 changes: 4 additions & 0 deletions ui/src/icons/pmm/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export * from './pmm';
export * from './check';
export * from './dashboards';
export * from './node';
export * from './percona';
17 changes: 17 additions & 0 deletions ui/src/icons/pmm/node.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { SvgIcon, SvgIconProps } from '@mui/material';

export const NodeIcon = (props: SvgIconProps) => (
<SvgIcon
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
xmlns="https://www.w3.org/2000/svg"
{...props}
>
<path
d="M19.0374 13.0366V9.96332C19.3008 9.90668 19.5575 9.81334 19.7941 9.67666H19.7974C21.015 8.97178 21.4468 7.40818 20.7375 6.16665C19.8439 4.62697 17.7047 4.46883 16.5975 5.74331L13.9375 4.20998C14.4943 2.53956 13.2292 0.833313 11.5008 0.833313C9.74562 0.833313 8.51027 2.5584 9.0608 4.20998L6.40414 5.74664C5.22781 4.41796 3.12698 4.67417 2.26083 6.16665C1.43127 7.61735 2.16266 9.56505 3.96745 9.96665V13.0366C0.997887 13.6307 1.38358 18.12 4.48747 18.12C5.19572 18.12 5.90226 17.821 6.4008 17.2566L9.0608 18.7933C8.50807 20.4302 9.73952 22.1666 11.5008 22.1666C13.1589 22.1666 14.4973 20.5746 13.9375 18.7933L16.5975 17.2566C17.7585 18.5683 19.8627 18.3371 20.7375 16.84C20.7375 16.8366 20.7375 16.8366 20.7408 16.8333C21.5815 15.3502 20.8005 13.4161 19.0374 13.0366ZM16.2208 16.7033V16.7066L13.6475 18.19C12.6513 16.617 10.3413 16.7338 9.3508 18.19L6.78081 16.7066C7.00773 16.2523 7.10701 15.6689 7.01417 15.11C6.94874 15.0445 6.70491 13.0696 4.63412 12.9867V10.0166C6.23211 10.0166 7.66579 8.06995 6.78081 6.29999L9.35413 4.81334C9.36529 4.83566 9.52852 5.05628 9.55412 5.07335C10.2403 5.87945 11.3026 6.1337 12.2108 5.86664C12.2208 5.86664 12.2308 5.85997 12.2408 5.85997C12.756 5.68831 13.1361 5.41265 13.1675 5.34996C13.3508 5.1933 13.5142 5.01662 13.6475 4.81334L16.2208 6.29665C15.5381 7.74759 16.131 9.69945 18.3708 10.0166V12.9867C16.5823 13.0716 15.4079 14.917 16.2208 16.7033Z"
fill="#000"
></path>
</SvgIcon>
);
30 changes: 30 additions & 0 deletions ui/src/icons/pmm/percona.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { SvgIcon, SvgIconProps } from '@mui/material';

export const PerconaIcon = (props: SvgIconProps) => (
<SvgIcon
width="180"
height="155"
viewBox="0 0 180 155"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M146.326 97.5456C165.421 85.0641 171.669 59.6045 160.113 39.5944C154.323 29.5574 144.964 22.3694 133.767 19.3679C123.393 16.5828 112.557 17.7217 103.021 22.5397L90 0L62.9722 46.8108L0.500977 155H179.499L146.326 97.5456ZM130.705 30.8347C138.844 33.0024 145.617 38.2285 149.835 45.5052C158.127 59.8493 153.819 78.0428 140.373 87.2318L108.967 32.8428C115.733 29.5894 123.364 28.8798 130.705 30.8347ZM90 23.7566L158.914 143.118H118.592L69.8302 58.6891L89.9964 23.7602L90 23.7566ZM21.0858 143.118L62.9686 70.5923L104.851 143.118H21.0858Z"
fill="url(#paint0_linear_10938_713)"
/>
<defs>
<linearGradient
id="paint0_linear_10938_713"
x1="21.9981"
y1="142.5"
x2="161.498"
y2="65.9999"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#FC3519" />
<stop offset="1" stop-color="#F0D136" />
</linearGradient>
</defs>
</SvgIcon>
);
57 changes: 57 additions & 0 deletions ui/src/pages/updates/change-log/ChangeLog.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { render } from '@testing-library/react';
import { ChangeLog } from './ChangeLog';

const mocks = vi.hoisted(() => ({
useChangeLogs: vi.fn(),
}));

vi.mock('hooks/api/useUpdates', () => ({
useChangeLogs: mocks.useChangeLogs,
}));

describe('ChangeLog', () => {
beforeEach(() => {
mocks.useChangeLogs.mockClear();
});

it('is not visible when loading', () => {
mocks.useChangeLogs.mockReturnValueOnce({
isLoading: true,
});
const { container } = render(<ChangeLog />);

expect(container).toBeEmptyDOMElement();
});

it('is not visible if there are no release notes available', () => {
mocks.useChangeLogs.mockReturnValueOnce({
data: { updates: [] },
});
const { container } = render(<ChangeLog />);

expect(container).toBeEmptyDOMElement();
});

it("doesn't render divider after last change log", () => {
mocks.useChangeLogs.mockReturnValueOnce({
data: { updates: [{ version: '0.0.1', releaseNotesText: '# 0.0.1' }] },
});
const { container } = render(<ChangeLog />);

expect(container.getElementsByTagName('hr')).toHaveLength(1);
});

it('renders divider between change logs', () => {
mocks.useChangeLogs.mockReturnValueOnce({
data: {
updates: [
{ version: '0.0.1', releaseNotesText: '# 0.0.1' },
{ version: '0.0.2', releaseNotesText: '# 0.0.2' },
],
},
});
const { container } = render(<ChangeLog />);

expect(container.getElementsByTagName('hr')).toHaveLength(2);
});
});
25 changes: 25 additions & 0 deletions ui/src/pages/updates/change-log/ChangeLog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Divider, Stack } from '@mui/material';
import { useChangeLogs } from 'hooks/api/useUpdates';
import { FC } from 'react';
import { ReleaseNotes } from './release-notes';

export const ChangeLog: FC = () => {
const { data, isLoading } = useChangeLogs();
const changeLogs = data?.updates || [];

if (isLoading || !changeLogs.length) {
return null;
}

return (
<Stack>
<Divider sx={{ mx: 2, my: 4 }} />
{changeLogs.map((changeLog, idx) => (
<Stack key={changeLog.version} sx={{ px: 2 }}>
<ReleaseNotes content={changeLog.releaseNotesText} />
{idx !== changeLogs.length - 1 && <Divider sx={{ my: 4 }} />}
</Stack>
))}
</Stack>
);
};
22 changes: 22 additions & 0 deletions ui/src/pages/updates/change-log/code-block/CodeBlock.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { render, screen } from '@testing-library/react';
import { CodeBlock } from './CodeBlock';

describe('CodeBlock', () => {
it('shows inline if code is single line', () => {
const code = `This is a single line`;
render(<CodeBlock>{code}</CodeBlock>);

expect(screen.getByRole('paragraph')).toHaveStyle({
display: 'inline-block',
});
});

it('shows correctly for multiline code', () => {
const code = `This is line 1\nThis is line 2`;
render(<CodeBlock>{code}</CodeBlock>);

expect(screen.getByRole('paragraph')).not.toHaveStyle({
display: 'inline-block',
});
});
});
20 changes: 20 additions & 0 deletions ui/src/pages/updates/change-log/code-block/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Typography } from '@mui/material';
import { FC, PropsWithChildren } from 'react';

export const CodeBlock: FC<PropsWithChildren> = ({ children }) => {
const isSingleLine =
typeof children === 'string' && children.split('\n').length < 2;

return (
<Typography
sx={(theme) => ({
display: isSingleLine ? 'inline-block' : undefined,
fontFamily: 'Roboto Mono, monospace',
whiteSpace: 'pre',
backgroundColor: theme.palette.grey[200],
})}
>
{children}
</Typography>
);
};
1 change: 1 addition & 0 deletions ui/src/pages/updates/change-log/code-block/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './CodeBlock';
1 change: 1 addition & 0 deletions ui/src/pages/updates/change-log/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ChangeLog';
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
ContentPaste,
Dangerous,
Edit,
Settings,
ArrowDownward,
MoreVert,
AddCircle,
MoreHoriz,
} from '@mui/icons-material';
import { CheckIcon, DashboardsIcon, NodeIcon, PerconaIcon } from 'icons';

export const IconMap: Record<string, JSX.Element> = {
danger: <Dangerous htmlColor="#ff1744" />,
note: <Edit htmlColor="#448aff" />,
percona: <PerconaIcon />,
configuration: <Settings />,
inventory: <ContentPaste />,
arrowdown: <ArrowDownward />,
ellipsisv: <MoreVert />,
settings: <Settings />,
checks: <CheckIcon />,
dashboards: <DashboardsIcon />,
node: <NodeIcon />,
addinstance: <AddCircle />,
bouncingellipsis: <MoreHoriz />,
};
Loading

0 comments on commit 4585d2b

Please sign in to comment.