From a0ce41d67ec64000ae4aeb9aeb541ebc5172265a Mon Sep 17 00:00:00 2001 From: Matej Kubinec <32638572+matejkubinec@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:23:50 +0100 Subject: [PATCH 1/8] PMM-13419 Fix tour (#777) * PMM-13419 Fix tour * PMM-13419 Run prettier --- public/app/core/components/AppChrome/AppChromeMenu.tsx | 7 ++++++- public/app/percona/shared/core/hooks/tour.ts | 4 ++++ .../app/percona/tour/steps/alerting/alerting.messages.ts | 4 ++-- public/app/percona/tour/steps/alerting/alerting.steps.tsx | 6 +++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/public/app/core/components/AppChrome/AppChromeMenu.tsx b/public/app/core/components/AppChrome/AppChromeMenu.tsx index ee58fb39bc640..54676cd7c0aaf 100644 --- a/public/app/core/components/AppChrome/AppChromeMenu.tsx +++ b/public/app/core/components/AppChrome/AppChromeMenu.tsx @@ -2,6 +2,7 @@ import { css } from '@emotion/css'; import { useDialog } from '@react-aria/dialog'; import { FocusScope } from '@react-aria/focus'; import { OverlayContainer, useOverlay } from '@react-aria/overlays'; +import { useTour } from '@reactour/tour'; import React, { useRef } from 'react'; import CSSTransition from 'react-transition-group/CSSTransition'; @@ -30,11 +31,15 @@ export function AppChromeMenu({}: Props) { const isOpen = state.megaMenuOpen && !state.megaMenuDocked; const onClose = () => chrome.setMegaMenuOpen(false); + // @PERCONA + const { isOpen: isTourOpen } = useTour(); + const { overlayProps, underlayProps } = useOverlay( { - isDismissable: true, + isDismissable: !isTourOpen, isOpen: true, onClose, + isKeyboardDismissDisabled: !!isTourOpen, shouldCloseOnInteractOutside: (element) => { // don't close when clicking on the menu toggle, let the toggle button handle that // this prevents some nasty flickering when the menu is open and the toggle button is clicked diff --git a/public/app/percona/shared/core/hooks/tour.ts b/public/app/percona/shared/core/hooks/tour.ts index 4ebe487a14f34..84229d61a9262 100644 --- a/public/app/percona/shared/core/hooks/tour.ts +++ b/public/app/percona/shared/core/hooks/tour.ts @@ -1,6 +1,7 @@ import { useTour } from '@reactour/tour'; import { useCallback, useEffect, useMemo } from 'react'; +import { useGrafana } from 'app/core/context/GrafanaContext'; import * as TourActions from 'app/percona/shared/core/reducers/tour'; import { TourStep, TourType } from 'app/percona/shared/core/reducers/tour'; import { useAppDispatch } from 'app/store/store'; @@ -14,6 +15,7 @@ const usePerconaTour = () => { const { steps, tour } = useSelector(getTour); const reactTour = useTour(); const tourSteps = useMemo(() => (tour ? steps[tour] : []), [tour, steps]); + const { chrome } = useGrafana(); useEffect(() => { if (reactTour.setSteps) { @@ -31,6 +33,8 @@ const usePerconaTour = () => { const startTour = useCallback( async (tour: TourType) => { + chrome.setMegaMenuOpen(true); + const firstStep = steps[tour][0]; // wait for the first step element to visible diff --git a/public/app/percona/tour/steps/alerting/alerting.messages.ts b/public/app/percona/tour/steps/alerting/alerting.messages.ts index 2e4ce165d7c75..f6b6d8bea9b85 100644 --- a/public/app/percona/tour/steps/alerting/alerting.messages.ts +++ b/public/app/percona/tour/steps/alerting/alerting.messages.ts @@ -39,8 +39,8 @@ export const Messages = { alert: 'Alert Groups show grouped alerts.', grouping: "Group common alerts into a single alert group to ensure that PMM doesn't fire duplicate alerts.", }, - admin: { - title: 'Admin', + settings: { + title: 'Settings', configure: 'Use this to configure Alertmanagers in raw JSON format.', }, }; diff --git a/public/app/percona/tour/steps/alerting/alerting.steps.tsx b/public/app/percona/tour/steps/alerting/alerting.steps.tsx index af1560eb39d53..5fa37778b76eb 100644 --- a/public/app/percona/tour/steps/alerting/alerting.steps.tsx +++ b/public/app/percona/tour/steps/alerting/alerting.steps.tsx @@ -79,10 +79,10 @@ export const getAlertingTourSteps = (isAdmin = false): TourStep[] => [ ...(isAdmin ? [ { - selector: '[aria-label="Admin"]', + selector: '[aria-label="Settings"]', content: ( - -

{Messages.admin.configure}

+ +

{Messages.settings.configure}

), }, From ddd77e01c6acb0f3e0e4d394c45d95533f6f78e7 Mon Sep 17 00:00:00 2001 From: Matej Kubinec <32638572+matejkubinec@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:05:23 +0100 Subject: [PATCH 2/8] PMM-7 Check target branch when checking out UI tests (#791) * PMM-7 Check target branch when checking out UI tests * PMM-7 Skip target branch if head_ref one available --- .github/workflows/ui-tests.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 33797c40914fd..78ff5d8a65245 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -55,9 +55,20 @@ jobs: repository: percona/pmm-ui-tests path: ./pmm-ui-tests - - name: Checkout UI tests in main branch + - name: Checkout UI tests in ${{ github.base_ref }} branch uses: percona-platform/checkout@v2 if: ${{ steps.branch_checkout.outcome != 'success' }} + continue-on-error: true + id: target_branch_checkout + with: + token: ${{ secrets.ROBOT_TOKEN }} + ref: ${{ github.base_ref }} + repository: percona/pmm-ui-tests + path: ./pmm-ui-tests + + - name: Checkout UI tests in main branch + uses: percona-platform/checkout@v2 + if: ${{ steps.branch_checkout.outcome != 'success' && steps.target_branch_checkout.outcome != 'success' }} with: token: ${{ secrets.ROBOT_TOKEN }} ref: main From f75050d4245a575d4f8c57acdf6a6d97db36a9f2 Mon Sep 17 00:00:00 2001 From: Matej Kubinec <32638572+matejkubinec@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:57:06 +0100 Subject: [PATCH 3/8] PMM-13548 Add service node selection fixes (#787) * PMM-13548 Use FinalForm to store selected node & preselect pmm-server * PMM-13548 Fix warnings in unit tests related to nodes fetching --- .../FormParts/FormParts.test.tsx | 8 ++++--- .../MongoDBConnectionDetails.test.tsx | 8 ++++--- .../MySQLConnectionDetails.test.tsx | 8 ++++--- .../NodesAgents/NodesAgents.constants.tsx | 1 + .../NodesAgents/NodesAgents.test.tsx | 10 ++++++++ .../FormParts/NodesAgents/NodesAgents.tsx | 24 +++++++++++++++---- .../PostgreSQLConnectionDetails.test.tsx | 12 ++++++---- 7 files changed, 52 insertions(+), 19 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx index f7050cf756c07..129effdf898a1 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import { FormApi, FormState } from 'final-form'; import React from 'react'; import { Form } from 'react-final-form'; @@ -13,6 +13,8 @@ import { trackingOptions, rdsTrackingOptions } from './FormParts.constants'; import { LabelsFormPart } from './Labels/Labels'; import { MainDetailsFormPart } from './MainDetails/MainDetails'; +jest.mock('app/percona/inventory/Inventory.service'); + const form: Partial = { change: jest.fn(), /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ @@ -31,7 +33,7 @@ describe('MainDetailsFormPart ::', () => { ); const fields = container.querySelectorAll('input'); - expect(fields.length).toBe(8); + await waitFor(() => expect(fields.length).toBe(8)); expect(screen.getByTestId('address-text-input')).toBeDisabled(); expect(screen.getByTestId('serviceName-text-input')).not.toBeDisabled(); @@ -51,7 +53,7 @@ describe('MainDetailsFormPart ::', () => { ); const fields = container.querySelectorAll('input'); - expect(fields.length).toBe(8); + await waitFor(() => expect(fields.length).toBe(8)); expect(screen.getByTestId('address-text-input')).not.toBeDisabled(); expect(screen.getByTestId('serviceName-text-input')).not.toBeDisabled(); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx index 8057d857b0813..6839e2b38ac5b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; @@ -7,8 +7,10 @@ import { configureStore } from 'app/store/configureStore'; import { MongoDBConnectionDetails } from './MongoDBConnectionDetails'; +jest.mock('app/percona/inventory/Inventory.service'); + describe('MongoDB connection details:: ', () => { - it('should have max query length attribute', () => { + it('should have max query length attribute', async () => { render(
} /> @@ -18,6 +20,6 @@ describe('MongoDB connection details:: ', () => { const textInput = screen.getByTestId('maxQueryLength-text-input'); fireEvent.change(textInput, { target: { value: '1000' } }); - expect(screen.getByTestId('maxQueryLength-text-input')).toHaveValue('1000'); + await waitFor(() => expect(screen.getByTestId('maxQueryLength-text-input')).toHaveValue('1000')); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx index 902f9960fe5e6..23d57c20ef92e 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; @@ -7,8 +7,10 @@ import { configureStore } from 'app/store/configureStore'; import { MySQLConnectionDetails } from './MySQLConnectionDetails'; +jest.mock('app/percona/inventory/Inventory.service'); + describe('MySQL connection details:: ', () => { - it('should have max query length attribute', () => { + it('should have max query length attribute', async () => { render( } /> @@ -18,6 +20,6 @@ describe('MySQL connection details:: ', () => { const textInput = screen.getByTestId('maxQueryLength-text-input'); fireEvent.change(textInput, { target: { value: '1000' } }); - expect(screen.getByTestId('maxQueryLength-text-input')).toHaveValue('1000'); + await waitFor(() => expect(screen.getByTestId('maxQueryLength-text-input')).toHaveValue('1000')); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx index 262ceefc161b7..bc62f0170f771 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx @@ -1 +1,2 @@ +export const PMM_SERVER_NODE_ID = 'pmm-server'; export const PMM_SERVER_NODE_AGENT_ID = 'pmm-server'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 6e0ace17322a8..05345b66a8084 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -46,6 +46,16 @@ describe('Nodes Agents:: ', () => { submitMock.mockClear(); }); + it('should pick pmm-server node by default when available', async () => { + jest.spyOn(InventoryService, 'getNodes').mockReturnValue(Promise.resolve({ nodes: nodesMock })); + + setup(); + + await waitFor(() => expect(fetchNodesActionActionSpy).toHaveBeenCalled()); + + await waitFor(() => expect(screen.getByTestId('node')).toHaveTextContent(nodesMock[0].node_id)); + }); + it('should not pick any agent when the selected node is not pmm-server', async () => { jest .spyOn(InventoryService, 'getNodes') diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index e63447f677744..02bec8011d9c9 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -1,9 +1,13 @@ -import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { FC, useCallback, useEffect, useMemo } from 'react'; +import { useField } from 'react-final-form'; import { useStyles2 } from '@grafana/ui'; import { Messages } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages'; import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; -import { PMM_SERVER_NODE_AGENT_ID } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; +import { + PMM_SERVER_NODE_AGENT_ID, + PMM_SERVER_NODE_ID, +} from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; import { AgentsOption, NodesOption } from 'app/percona/inventory/Inventory.types'; @@ -14,6 +18,7 @@ import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; import { getNodes } from 'app/percona/shared/core/selectors'; import { isApiCancelError } from 'app/percona/shared/helpers/api'; import { logger } from 'app/percona/shared/helpers/logger'; +import { validators } from 'app/percona/shared/helpers/validatorsForm'; import { useAppDispatch } from 'app/store/store'; import { useSelector } from 'app/types'; @@ -21,8 +26,10 @@ export const NodesAgents: FC = ({ form }) => { const styles = useStyles2(getStyles); const dispatch = useAppDispatch(); const [generateToken] = useCancelToken(); - const [selectedNode, setSelectedNode] = useState(); const { nodes } = useSelector(getNodes); + const { + input: { value: selectedNode }, + } = useField('node'); const nodesOptions = useMemo(() => nodesOptionsMapper(nodes), [nodes]); @@ -49,7 +56,7 @@ export const NodesAgents: FC = ({ form }) => { }; const setNodeAndAgent = (value: NodesOption) => { - setSelectedNode(value); + form?.change('node', value); let selectedAgent: AgentsOption | undefined; if (value.agents && value.agents?.length > 1) { @@ -68,6 +75,12 @@ export const NodesAgents: FC = ({ form }) => { useEffect(() => { if (nodesOptions.length === 0) { loadData(); + } else if (!selectedNode) { + // preselect pmm-server node + const pmmServerNode = nodesOptions.find((node) => node.value === PMM_SERVER_NODE_ID); + if (pmmServerNode) { + setNodeAndAgent(pmmServerNode); + } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [nodesOptions]); @@ -84,8 +97,8 @@ export const NodesAgents: FC = ({ form }) => { data-testid="nodes-selectbox" onChange={(event) => setNodeAndAgent(event as NodesOption)} className={styles.selectField} - value={selectedNode} aria-label={Messages.form.labels.nodesAgents.nodes} + validators={[validators.required]} />
@@ -99,6 +112,7 @@ export const NodesAgents: FC = ({ form }) => { onChange={(event) => changeAgentValue(event as AgentsOption)} className={styles.selectField} aria-label={Messages.form.labels.nodesAgents.agents} + validators={selectedNode ? [validators.required] : undefined} />
diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx index 4b817753588a9..1b0115c062af3 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; @@ -7,8 +7,10 @@ import { configureStore } from 'app/store/configureStore'; import { PostgreSQLConnectionDetails } from './PostgreSQLConnectionDetails'; +jest.mock('app/percona/inventory/Inventory.service'); + describe('PostgreSQL connection details:: ', () => { - it('should have database attribute', () => { + it('should have database attribute', async () => { render( } /> @@ -18,10 +20,10 @@ describe('PostgreSQL connection details:: ', () => { const textInput = screen.getByTestId('database-text-input'); fireEvent.change(textInput, { target: { value: 'db1' } }); - expect(screen.getByTestId('database-text-input')).toHaveValue('db1'); + await waitFor(() => expect(screen.getByTestId('database-text-input')).toHaveValue('db1')); }); - it('should have max query length attribute', () => { + it('should have max query length attribute', async () => { render( } /> @@ -31,6 +33,6 @@ describe('PostgreSQL connection details:: ', () => { const textInput = screen.getByTestId('maxQueryLength-text-input'); fireEvent.change(textInput, { target: { value: '1000' } }); - expect(screen.getByTestId('maxQueryLength-text-input')).toHaveValue('1000'); + await waitFor(() => expect(screen.getByTestId('maxQueryLength-text-input')).toHaveValue('1000')); }); }); From 397ddcd052e1f73057eea13405b8bb079603dee7 Mon Sep 17 00:00:00 2001 From: Matej Kubinec <32638572+matejkubinec@users.noreply.github.com> Date: Wed, 18 Dec 2024 15:11:56 +0100 Subject: [PATCH 4/8] PMM-13542 Reload templates by default (#786) --- .../components/AlertRuleTemplate/AlertRuleTemplate.service.ts | 2 +- .../components/AlertRuleTemplate/AlertRuleTemplate.types.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.service.ts b/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.service.ts index 1e2b6ce870ade..4880e6c76f0b8 100644 --- a/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.service.ts +++ b/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.service.ts @@ -21,7 +21,7 @@ export const AlertRuleTemplateService = { return api .get(BASE_URL, false, { cancelToken: token, - params: { ...payload }, + params: { ...payload, reload: true }, }) .then( ({ totals, templates = [] }): TemplatesList => ({ diff --git a/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.types.ts b/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.types.ts index a8cd25a480947..0295e1c3e58a7 100644 --- a/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.types.ts +++ b/public/app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.types.ts @@ -18,6 +18,7 @@ export interface AlertRuleTemplateGetPayload { page_size: number; index: number; }; + reload?: boolean; } interface AlertRuleTemplatesTotals { From af95a74978cf5a1bbb879d6b3fd00ce49723063c Mon Sep 17 00:00:00 2001 From: Dora <103416234+doracretu3pillar@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:51:04 +0200 Subject: [PATCH 5/8] Replaced updateDescription and added sorting to the versions (#789) --- .../PerconaUpdateVersion.constants.ts | 6 +++--- .../PerconaUpdateVersion.styles.ts | 3 +++ .../PerconaUpdateVersion.tsx | 8 ++++---- .../core/reducers/updates/updates.utils.ts | 16 +++++++++------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.constants.ts b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.constants.ts index 2f35d18455960..7929df9306b39 100644 --- a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.constants.ts +++ b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.constants.ts @@ -1,12 +1,12 @@ export const Messages = { titleOneUpdate: 'New update available', titleMultipleUpdates: 'New updates available', - howToUpdate: 'How to update', - howToUpdateDescription: - "We are inaugurating a new process for updating PMM. It's a new interface with an improved user experience and is ready for the future of PMM. Click on Go to Updates Page to find out more.", newVersions: 'New Versions', readMore: 'Read more', fullReleaseNotes: 'Full release notes here', goToUpdatesPage: 'Go to updates page', snooze: 'Dismiss', + readyForAnUpdate: 'Ready for an upgrade?', + updateDescription: + "We've streamlined our update process with a new, user-friendly interface. One click gets you all the latest improvements.", }; diff --git a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.styles.ts b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.styles.ts index 45dd1980d2bf0..eaa4d4d3fee77 100644 --- a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.styles.ts +++ b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.styles.ts @@ -40,4 +40,7 @@ export const getStyles = ({ v1: { spacing, colors, typography } }: GrafanaTheme2 color: ${colors.textBlue}; }, `, + readyForUpdate: css` + margin-top: 10px; + `, }); diff --git a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx index e5ad28d961162..45811294dde4f 100644 --- a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx +++ b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx @@ -67,8 +67,8 @@ const PerconaUpdateVersion = () => { {Messages.fullReleaseNotes}

-
{Messages.howToUpdate}
-

{Messages.howToUpdateDescription}

+
{Messages.readyForAnUpdate}
+ {Messages.updateDescription}