From ef2afce9af52e890f390f2202dd52eec444131b6 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Wed, 6 Mar 2024 14:27:29 +0100 Subject: [PATCH 1/9] change: [UIE-7308] - notification for resizing database --- packages/api-v4/src/account/types.ts | 1 + packages/api-v4/src/databases/types.ts | 3 +- .../TypeToConfirmDialog.tsx | 7 +- .../DatabaseResize/DatabaseResize.tsx | 71 +++++++------------ .../DatabaseResizeCurrentConfiguration.tsx | 18 ++++- .../DatabaseSummaryClusterConfiguration.tsx | 19 ++++- .../DatabaseLanding/DatabaseLanding.tsx | 10 ++- .../Databases/DatabaseLanding/DatabaseRow.tsx | 22 ++++-- .../manager/src/features/Events/constants.ts | 1 + .../features/Events/eventMessageGenerator.ts | 3 + .../Events/eventMessageGenerator_CMR.tsx | 6 ++ .../components/PlansPanel/PlanContainer.tsx | 16 ++++- .../components/PlansPanel/PlanSelection.tsx | 21 +++++- .../components/PlansPanel/PlansPanel.tsx | 6 ++ 14 files changed, 144 insertions(+), 60 deletions(-) diff --git a/packages/api-v4/src/account/types.ts b/packages/api-v4/src/account/types.ts index f35c3e804e5..955ec311566 100644 --- a/packages/api-v4/src/account/types.ts +++ b/packages/api-v4/src/account/types.ts @@ -288,6 +288,7 @@ export type EventAction = | 'credit_card_updated' | 'database_low_disk_space' | 'database_resize' + | 'database_resize_create' | 'database_backup_restore' | 'database_create' | 'database_credentials_reset' diff --git a/packages/api-v4/src/databases/types.ts b/packages/api-v4/src/databases/types.ts index 3dd34f63984..1e079d38c8d 100644 --- a/packages/api-v4/src/databases/types.ts +++ b/packages/api-v4/src/databases/types.ts @@ -35,7 +35,8 @@ export type DatabaseStatus = | 'resuming' | 'restoring' | 'failed' - | 'degraded'; + | 'degraded' + | 'resizing'; export type DatabaseBackupType = 'snapshot' | 'auto'; diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx index 6bf1f6eb4f5..c4e6e3ae8bb 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx @@ -13,7 +13,12 @@ import { import { usePreferences } from 'src/queries/preferences'; interface EntityInfo { - action?: 'cancellation' | 'deletion' | 'detachment' | 'restoration'; + action?: + | 'cancellation' + | 'deletion' + | 'detachment' + | 'restoration' + | 'resizing'; name?: string | undefined; primaryBtnText: string; subType?: 'CloseAccount' | 'Cluster' | 'ObjectStorage'; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx index 1957bec5b23..e1c03788936 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx @@ -1,4 +1,4 @@ -import { LinodeTypeClass } from '@linode/api-v4'; +// import { LinodeTypeClass } from '@linode/api-v4'; import { Database, DatabaseClusterSizeObject, @@ -8,21 +8,18 @@ import { import { useSnackbar } from 'notistack'; import * as React from 'react'; import { useHistory } from 'react-router-dom'; - -import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel'; import { Box } from 'src/components/Box'; import { CircleProgress } from 'src/components/CircleProgress'; -import { ConfirmationDialog } from 'src/components/ConfirmationDialog/ConfirmationDialog'; import { ErrorState } from 'src/components/ErrorState/ErrorState'; import { Notice } from 'src/components/Notice/Notice'; import { Paper } from 'src/components/Paper'; import { Typography } from 'src/components/Typography'; import { typeLabelDetails } from 'src/features/Linodes/presentation'; import { PlanSelectionType } from 'src/features/components/PlansPanel/types'; -import { getPlanSelectionsByPlanType } from 'src/features/components/PlansPanel/utils'; import { useDatabaseTypesQuery } from 'src/queries/databases'; import { useDatabaseMutation } from 'src/queries/databases'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; +import { TypeToConfirmDialog } from 'src/components/TypeToConfirmDialog/TypeToConfirmDialog'; import { StyledGrid, @@ -87,7 +84,7 @@ export const DatabaseResize = ({ database }: Props) => { const resizeDescription = ( <> - Resize a Database Cluster + Resizing a Database Cluster Adapt the cluster to your needs by resizing to a larger plan. Clusters cannot be resized to smaller plans. @@ -117,22 +114,6 @@ export const DatabaseResize = ({ database }: Props) => { ); - const confirmationDialogActions = ( - setIsResizeConfirmationDialogOpen(false), - }} - /> - ); - const costSummary = ( {`The cost of the resized database is ${summaryText?.price}.`} @@ -220,18 +201,12 @@ export const DatabaseResize = ({ database }: Props) => { }, [database.cluster_size, dbTypes, selectedEngine]); const currentPlan = displayTypes?.find((type) => type.id === database.type); - // create an array of different class of types. - const typeClasses: LinodeTypeClass[] = Object.keys( - getPlanSelectionsByPlanType(displayTypes) - ).map((plan) => (plan === 'shared' ? 'standard' : (plan as LinodeTypeClass))); - const currentPlanClass = currentPlan?.class ?? 'dedicated'; - // We don't have a "Nanodes" tab anymore, so use `shared` - const selectedTypeClass = - currentPlanClass === 'nanode' ? 'standard' : currentPlanClass; - // User cannot switch to different plan type apart from current plan while resizing a DB cluster. So disable rest of the tabs. - const tabsToBeDisabled = typeClasses - .filter((typeClass) => typeClass !== selectedTypeClass) - .map((plan) => (plan === 'standard' ? 'shared' : plan)); + + const disabledPlans = displayTypes?.filter( + (type) => + type.disk < (currentPlan ? currentPlan.disk : 0) || + (currentPlan?.class == 'dedicated' && type.disk == currentPlan?.disk) + ); if (typesLoading) { return ; } @@ -249,15 +224,12 @@ export const DatabaseResize = ({ database }: Props) => { setPlanSelected(selected)} - selectedDiskSize={currentPlan?.disk} selectedId={planSelected} types={displayTypes} /> @@ -275,15 +247,26 @@ export const DatabaseResize = ({ database }: Props) => { Resize Database Cluster - setIsResizeConfirmationDialogOpen(false)} open={isResizeConfirmationDialogOpen} - title={`Resize ${database.label}?`} + title={`Resize Database Cluster ${database.label}?`} > + {resizeError ? ( + + ) : null} {confirmationPopUpMessage} - + ); }; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx index ba01bb75260..3fa048e4ca0 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx @@ -8,6 +8,7 @@ import { ErrorState } from 'src/components/ErrorState/ErrorState'; import { StatusIcon } from 'src/components/StatusIcon/StatusIcon'; import { TooltipIcon } from 'src/components/TooltipIcon'; import { useDatabaseTypesQuery } from 'src/queries/databases'; +import { useInProgressEvents } from 'src/queries/events/events'; import { useRegionsQuery } from 'src/queries/regions'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; @@ -45,6 +46,18 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { const type = types?.find((type) => type.id === database?.type); + const { data: events } = useInProgressEvents(); + + const recentEvent = events?.find( + (event) => + event.entity?.id === database.id && event.entity.type === 'database' + ); + let progress; + if (recentEvent?.action === 'database_resize') { + progress = recentEvent?.percent_complete ?? 0; + database.status = 'resizing'; + } + if (typesLoading) { return ; } @@ -68,7 +81,7 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { }; const STORAGE_COPY = - 'The total disk size is smaller than the selected plan capacity due to the OS overhead.'; + 'The total disk size is smaller than the selected plan capacity due to overhead from the OS.'; return ( <> @@ -88,7 +101,8 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { status={databaseStatusMap[database.status]} sx={{ verticalAlign: 'sub' }} /> - {database.status} + {database.status + + (progress != undefined ? ' (' + progress + '%)' : '')} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx index 2d5125724e2..141a9752c1d 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx @@ -12,6 +12,8 @@ import { useRegionsQuery } from 'src/queries/regions'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; +import { useInProgressEvents } from 'src/queries/events/events'; + import { databaseEngineMap, databaseStatusMap, @@ -57,6 +59,18 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { const type = types?.find((type) => type.id === database?.type); + const { data: events } = useInProgressEvents(); + + const recentEvent = events?.find( + (event) => + event.entity?.id === database.id && event.entity.type === 'database' + ); + let progress; + if (recentEvent?.action === 'database_resize') { + progress = recentEvent?.percent_complete ?? 0; + database.status = 'resizing'; + } + if (!database || !type) { return null; } @@ -72,7 +86,7 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { }; const STORAGE_COPY = - 'The total disk size is smaller than the selected plan capacity due to the OS overhead.'; + 'The total disk size is smaller than the selected plan capacity due to overhead from the OS.'; return ( <> @@ -84,7 +98,8 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { Status - {database.status} + {database.status + + (progress != undefined ? ' (' + progress + '%)' : '')} diff --git a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLanding.tsx b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLanding.tsx index 447d0f189d7..da631d133c3 100644 --- a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLanding.tsx +++ b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLanding.tsx @@ -16,8 +16,8 @@ import { TableSortCell } from 'src/components/TableSortCell'; import { useOrder } from 'src/hooks/useOrder'; import { usePagination } from 'src/hooks/usePagination'; import { useDatabasesQuery } from 'src/queries/databases'; +import { useInProgressEvents } from 'src/queries/events/events'; import { getAPIErrorOrDefault } from 'src/utilities/errorUtils'; - import { DatabaseEmptyState } from './DatabaseEmptyState'; import { DatabaseRow } from './DatabaseRow'; @@ -27,6 +27,8 @@ const DatabaseLanding = () => { const history = useHistory(); const pagination = usePagination(1, preferenceKey); + const { data: events } = useInProgressEvents(); + const { handleOrderChange, order, orderBy } = useOrder( { order: 'desc', @@ -129,7 +131,11 @@ const DatabaseLanding = () => { {data?.data.map((database: DatabaseInstance) => ( - + ))} diff --git a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx index c197e839549..c50b2fc241c 100644 --- a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx +++ b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx @@ -5,7 +5,6 @@ import { } from '@linode/api-v4/lib/databases/types'; import * as React from 'react'; import { Link } from 'react-router-dom'; - import { Chip } from 'src/components/Chip'; import { Hidden } from 'src/components/Hidden'; import { Status, StatusIcon } from 'src/components/StatusIcon/StatusIcon'; @@ -16,6 +15,7 @@ import { useRegionsQuery } from 'src/queries/regions'; import { capitalize } from 'src/utilities/capitalize'; import { isWithinDays, parseAPIDate } from 'src/utilities/date'; import { formatDate } from 'src/utilities/formatDate'; +import { Event } from '@linode/api-v4'; export const databaseStatusMap: Record = { active: 'active', @@ -26,6 +26,7 @@ export const databaseStatusMap: Record = { resuming: 'other', suspended: 'error', suspending: 'other', + resizing: 'other', }; export const databaseEngineMap: Record = { @@ -37,9 +38,10 @@ export const databaseEngineMap: Record = { interface Props { database: DatabaseInstance; + events?: Event[]; } -export const DatabaseRow = ({ database }: Props) => { +export const DatabaseRow = ({ database, events }: Props) => { const { cluster_size, created, @@ -47,7 +49,6 @@ export const DatabaseRow = ({ database }: Props) => { id, label, region, - status, version, } = database; @@ -56,6 +57,18 @@ export const DatabaseRow = ({ database }: Props) => { const actualRegion = regions?.find((r) => r.id === region); + const recentEvent = events?.find( + (event) => + event.entity?.id === database.id && event.entity.type === 'database' + ); + let progress; + if (recentEvent?.action === 'database_resize') { + progress = recentEvent?.percent_complete ?? 0; + database.status = 'resizing'; + } + + const status = database.status; + const configuration = cluster_size === 1 ? ( 'Primary' @@ -82,7 +95,8 @@ export const DatabaseRow = ({ database }: Props) => { - {capitalize(status)} + {capitalize(database.status) + + (progress != undefined ? ' (' + progress + '%)' : '')} {configuration} diff --git a/packages/manager/src/features/Events/constants.ts b/packages/manager/src/features/Events/constants.ts index 4fd19cdef94..edc64d05c45 100644 --- a/packages/manager/src/features/Events/constants.ts +++ b/packages/manager/src/features/Events/constants.ts @@ -17,6 +17,7 @@ export const EVENT_ACTIONS: Event['action'][] = [ 'database_update_failed', 'database_update', 'database_resize', + 'database_resize_create', 'disk_create', 'disk_delete', 'disk_duplicate', diff --git a/packages/manager/src/features/Events/eventMessageGenerator.ts b/packages/manager/src/features/Events/eventMessageGenerator.ts index 6bef2809fee..47481180b1c 100644 --- a/packages/manager/src/features/Events/eventMessageGenerator.ts +++ b/packages/manager/src/features/Events/eventMessageGenerator.ts @@ -128,6 +128,9 @@ export const eventMessageCreators: { [index: string]: CreatorsForStatus } = { scheduled: (e) => `Database ${e.entity!.label} is scheduled for resizing.`, started: (e) => `Database ${e.entity!.label} is resizing.`, }, + database_resize_create: { + notification: (e) => `Database ${e.entity!.label} scheduled to be resized.`, + }, database_update: { finished: (e) => `Database ${e.entity!.label} has been updated.`, }, diff --git a/packages/manager/src/features/Events/eventMessageGenerator_CMR.tsx b/packages/manager/src/features/Events/eventMessageGenerator_CMR.tsx index 77620db876d..e50fae1b63e 100644 --- a/packages/manager/src/features/Events/eventMessageGenerator_CMR.tsx +++ b/packages/manager/src/features/Events/eventMessageGenerator_CMR.tsx @@ -80,6 +80,8 @@ export const eventMessageGenerator = ( return 'image uploading'; case 'volume_migrate': return `Volume ${e.entity?.label} is being upgraded to NVMe.`; + case 'database_resize': + return 'resizing'; default: // If we haven't handled it explicitly here, it doesn't count as @@ -92,5 +94,9 @@ export const eventLabelGenerator = (e: Event) => { if (['disk_imagize'].includes(e.action)) { return e.secondary_entity?.label; } + + if (e.action == 'database_resize') { + return `Database ${e.entity!.label}`; + } return e.entity?.label; }; diff --git a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx index d71b507dc57..93cfd88a08c 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx @@ -47,6 +47,8 @@ export interface Props { selectedId?: string; selectedRegionId?: Region['id']; showTransfer?: boolean; + disabledTypes?: PlanSelectionType[]; + disabledTypesToolTip?: string; } export const PlanContainer = (props: Props) => { @@ -63,6 +65,8 @@ export const PlanContainer = (props: Props) => { selectedId, selectedRegionId, showTransfer, + disabledTypes, + disabledTypesToolTip, } = props; const location = useLocation(); @@ -85,13 +89,21 @@ export const PlanContainer = (props: Props) => { const renderPlanSelection = React.useCallback(() => { return plans.map((plan, id) => { + const planIsDisabled = + disabledTypes?.find((element) => element === plan) != undefined; + const isPlanSoldOut = getIsPlanSoldOut({ + plan, + regionAvailabilities, + selectedRegionId, + }); + return ( { selectedRegionId={selectedRegionId} showTransfer={showTransfer} type={plan} + planIsDisabled={planIsDisabled} + disabledToolTip={disabledTypesToolTip} /> ); }); diff --git a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx index f5a6bb7b358..aa2da2c9d6a 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx @@ -45,6 +45,8 @@ export interface PlanSelectionProps { selectedRegionId?: Region['id']; showTransfer?: boolean; type: PlanSelectionType; + planIsDisabled?: boolean; + disabledToolTip?: string; } const getDisabledClass = ( @@ -54,6 +56,19 @@ const getDisabledClass = ( return disabledClasses.includes(typeClass); }; +const getToolTip = ( + sizeTooSmall: boolean, + planIsDisabled?: boolean, + disabledToolTip?: string +) => { + if (planIsDisabled) { + return disabledToolTip; + } else if (sizeTooSmall) { + return 'This plan is too small for the selected image.'; + } + return undefined; +}; + export const PlanSelection = (props: PlanSelectionProps) => { const { currentPlanHeading, @@ -70,6 +85,8 @@ export const PlanSelection = (props: PlanSelectionProps) => { selectedRegionId, showTransfer, type, + planIsDisabled, + disabledToolTip, } = props; const flags = useFlags(); @@ -84,9 +101,7 @@ export const PlanSelection = (props: PlanSelectionProps) => { const diskSize = selectedDiskSize ? selectedDiskSize : 0; const planTooSmall = diskSize > type.disk; - const tooltip = planTooSmall - ? 'This plan is too small for the selected image.' - : undefined; + const tooltip = getToolTip(planTooSmall, planIsDisabled, disabledToolTip); const isSamePlan = type.heading === currentPlanHeading; const isGPU = type.class === 'gpu'; const isDisabledClass = getDisabledClass(type.class, disabledClasses ?? []); diff --git a/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx b/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx index 6b93da07f6f..6fac1ae62e5 100644 --- a/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx @@ -47,6 +47,8 @@ interface Props { tabDisabledMessage?: string; tabbedPanelInnerClass?: string; types: PlanSelectionType[]; + disabledTypes?: PlanSelectionType[]; + disabledTypesToolTip?: string; } export const PlansPanel = (props: Props) => { @@ -66,6 +68,8 @@ export const PlansPanel = (props: Props) => { selectedRegionID, showTransfer, types, + disabledTypes, + disabledTypesToolTip, } = props; const flags = useFlags(); @@ -188,6 +192,8 @@ export const PlansPanel = (props: Props) => { selectedId={selectedId} selectedRegionId={selectedRegionID} showTransfer={showTransfer} + disabledTypes={disabledTypes} + disabledTypesToolTip={disabledTypesToolTip} /> ); From 372da20d40439c5a15b795768840aad9c42d3f52 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Wed, 6 Mar 2024 17:20:32 +0100 Subject: [PATCH 2/9] Added changeset: Added event type for database resize create --- packages/api-v4/.changeset/pr-10262-added-1709742032135.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/api-v4/.changeset/pr-10262-added-1709742032135.md diff --git a/packages/api-v4/.changeset/pr-10262-added-1709742032135.md b/packages/api-v4/.changeset/pr-10262-added-1709742032135.md new file mode 100644 index 00000000000..045f50335b8 --- /dev/null +++ b/packages/api-v4/.changeset/pr-10262-added-1709742032135.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Added +--- + +Added event type for database resize create ([#10262](https://github.com/linode/manager/pull/10262)) From feab47156b0650a4c078dc7058f6695dbfda0d19 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Wed, 6 Mar 2024 17:26:52 +0100 Subject: [PATCH 3/9] Added changeset: bell icon / alert changes : display a progress bar which disappears after resize complete, update status from Active to Resizing, show resizing progress in percentage, and revert to Active status when finished. Option to switch between dedicated and shared plans, with the exception of switching from dedicated plan to a shared plan of the same size. --- .../manager/.changeset/pr-10262-changed-1709742412767.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-10262-changed-1709742412767.md diff --git a/packages/manager/.changeset/pr-10262-changed-1709742412767.md b/packages/manager/.changeset/pr-10262-changed-1709742412767.md new file mode 100644 index 00000000000..6a98ad841dc --- /dev/null +++ b/packages/manager/.changeset/pr-10262-changed-1709742412767.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +bell icon / alert changes : display a progress bar which disappears after resize complete, update status from Active to Resizing, show resizing progress in percentage, and revert to Active status when finished. Option to switch between dedicated and shared plans, with the exception of switching from dedicated plan to a shared plan of the same size. ([#10262](https://github.com/linode/manager/pull/10262)) From 9d3d4f6ceb56ff43692eb5b8e08dd65bf424b311 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Fri, 8 Mar 2024 15:26:12 +0100 Subject: [PATCH 4/9] change: [UIE-7308] - refactoring --- .../pr-10262-changed-1709742412767.md | 2 +- .../DatabaseResize/DatabaseResize.test.tsx | 2 +- .../DatabaseResize/DatabaseResize.tsx | 15 +++++-------- .../DatabaseResizeCurrentConfiguration.tsx | 17 ++++---------- .../DatabaseSummaryClusterConfiguration.tsx | 17 ++++---------- .../Databases/DatabaseLanding/DatabaseRow.tsx | 16 +++++--------- .../src/features/Databases/utilities.ts | 22 +++++++++++++++++++ .../components/PlansPanel/PlanContainer.tsx | 12 +++++----- .../components/PlansPanel/PlanSelection.tsx | 2 +- .../components/PlansPanel/PlansPanel.tsx | 12 +++++----- 10 files changed, 56 insertions(+), 61 deletions(-) create mode 100644 packages/manager/src/features/Databases/utilities.ts diff --git a/packages/manager/.changeset/pr-10262-changed-1709742412767.md b/packages/manager/.changeset/pr-10262-changed-1709742412767.md index 6a98ad841dc..f6dcacb6887 100644 --- a/packages/manager/.changeset/pr-10262-changed-1709742412767.md +++ b/packages/manager/.changeset/pr-10262-changed-1709742412767.md @@ -2,4 +2,4 @@ "@linode/manager": Changed --- -bell icon / alert changes : display a progress bar which disappears after resize complete, update status from Active to Resizing, show resizing progress in percentage, and revert to Active status when finished. Option to switch between dedicated and shared plans, with the exception of switching from dedicated plan to a shared plan of the same size. ([#10262](https://github.com/linode/manager/pull/10262)) +Notifications for database resize events ([#10262](https://github.com/linode/manager/pull/10262)) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.test.tsx index d37d71ea695..a339b426de0 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.test.tsx @@ -118,7 +118,7 @@ describe('database resize', () => { 'false' ); fireEvent.click(resizeButton); - getByText(`Resize ${database.label}?`); + getByText(`Resize Database Cluster ${database.label}?`); }); }); }); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx index e1c03788936..b7d9376d4be 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx @@ -72,12 +72,9 @@ export const DatabaseResize = ({ database }: Props) => { updateDatabase({ type: planSelected, }).then(() => { - enqueueSnackbar( - `Your database cluster ${database.label} is being resized.`, - { - variant: 'info', - } - ); + enqueueSnackbar(`Database cluster ${database.label} is being resized.`, { + variant: 'info', + }); history.push(`/databases/${database.engine}/${database.id}`); }); }; @@ -205,7 +202,7 @@ export const DatabaseResize = ({ database }: Props) => { const disabledPlans = displayTypes?.filter( (type) => type.disk < (currentPlan ? currentPlan.disk : 0) || - (currentPlan?.class == 'dedicated' && type.disk == currentPlan?.disk) + (currentPlan?.class === 'dedicated' && type.disk === currentPlan?.disk) ); if (typesLoading) { return ; @@ -226,8 +223,8 @@ export const DatabaseResize = ({ database }: Props) => { setPlanSelected(selected)} selectedId={planSelected} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx index 3fa048e4ca0..b519f227ccf 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx @@ -8,11 +8,11 @@ import { ErrorState } from 'src/components/ErrorState/ErrorState'; import { StatusIcon } from 'src/components/StatusIcon/StatusIcon'; import { TooltipIcon } from 'src/components/TooltipIcon'; import { useDatabaseTypesQuery } from 'src/queries/databases'; -import { useInProgressEvents } from 'src/queries/events/events'; import { useRegionsQuery } from 'src/queries/regions'; +import { useInProgressEvents } from 'src/queries/events/events'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; - +import { getResizeProgress } from '../../utilities'; import { databaseEngineMap, databaseStatusMap, @@ -47,16 +47,7 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { const type = types?.find((type) => type.id === database?.type); const { data: events } = useInProgressEvents(); - - const recentEvent = events?.find( - (event) => - event.entity?.id === database.id && event.entity.type === 'database' - ); - let progress; - if (recentEvent?.action === 'database_resize') { - progress = recentEvent?.percent_complete ?? 0; - database.status = 'resizing'; - } + const progress = getResizeProgress(database, events); if (typesLoading) { return ; @@ -102,7 +93,7 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { sx={{ verticalAlign: 'sub' }} /> {database.status + - (progress != undefined ? ' (' + progress + '%)' : '')} + (progress !== undefined ? ' (' + progress + '%)' : '')} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx index 141a9752c1d..f5b1ccdb9ca 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx @@ -9,10 +9,10 @@ import { TooltipIcon } from 'src/components/TooltipIcon'; import { Typography } from 'src/components/Typography'; import { useDatabaseTypesQuery } from 'src/queries/databases'; import { useRegionsQuery } from 'src/queries/regions'; +import { useInProgressEvents } from 'src/queries/events/events'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; - -import { useInProgressEvents } from 'src/queries/events/events'; +import { getResizeProgress } from '../../utilities'; import { databaseEngineMap, @@ -60,16 +60,7 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { const type = types?.find((type) => type.id === database?.type); const { data: events } = useInProgressEvents(); - - const recentEvent = events?.find( - (event) => - event.entity?.id === database.id && event.entity.type === 'database' - ); - let progress; - if (recentEvent?.action === 'database_resize') { - progress = recentEvent?.percent_complete ?? 0; - database.status = 'resizing'; - } + const progress = getResizeProgress(database, events); if (!database || !type) { return null; @@ -99,7 +90,7 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { {database.status + - (progress != undefined ? ' (' + progress + '%)' : '')} + (progress !== undefined ? ' (' + progress + '%)' : '')} diff --git a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx index c50b2fc241c..8b7d9867b70 100644 --- a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx +++ b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx @@ -1,4 +1,5 @@ import { + Database, DatabaseInstance, DatabaseStatus, Engine, @@ -15,6 +16,7 @@ import { useRegionsQuery } from 'src/queries/regions'; import { capitalize } from 'src/utilities/capitalize'; import { isWithinDays, parseAPIDate } from 'src/utilities/date'; import { formatDate } from 'src/utilities/formatDate'; +import { getResizeProgress } from '../utilities'; import { Event } from '@linode/api-v4'; export const databaseStatusMap: Record = { @@ -37,7 +39,7 @@ export const databaseEngineMap: Record = { }; interface Props { - database: DatabaseInstance; + database: DatabaseInstance | Database; events?: Event[]; } @@ -57,15 +59,7 @@ export const DatabaseRow = ({ database, events }: Props) => { const actualRegion = regions?.find((r) => r.id === region); - const recentEvent = events?.find( - (event) => - event.entity?.id === database.id && event.entity.type === 'database' - ); - let progress; - if (recentEvent?.action === 'database_resize') { - progress = recentEvent?.percent_complete ?? 0; - database.status = 'resizing'; - } + const progress = getResizeProgress(database, events); const status = database.status; @@ -96,7 +90,7 @@ export const DatabaseRow = ({ database, events }: Props) => { {capitalize(database.status) + - (progress != undefined ? ' (' + progress + '%)' : '')} + (progress !== undefined ? ' (' + progress + '%)' : '')} {configuration} diff --git a/packages/manager/src/features/Databases/utilities.ts b/packages/manager/src/features/Databases/utilities.ts new file mode 100644 index 00000000000..210e79c58fc --- /dev/null +++ b/packages/manager/src/features/Databases/utilities.ts @@ -0,0 +1,22 @@ +import { Event } from '@linode/api-v4'; +import { Database, DatabaseInstance } from '@linode/api-v4/lib/databases/types'; + +export const getResizeProgress = ( + database: Database | DatabaseInstance, + events: Event[] | undefined +): number | undefined => { + const recentEvent = events?.find( + (event) => + event.entity?.id === database.id && event.entity.type === 'database' + ); + + let progress: number | undefined = 0; + if (recentEvent?.action === 'database_resize') { + progress = recentEvent?.percent_complete ?? 0; + database.status = 'resizing'; + } else { + return undefined; + } + + return progress; +}; diff --git a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx index 93cfd88a08c..37f692f17f5 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx @@ -47,8 +47,8 @@ export interface Props { selectedId?: string; selectedRegionId?: Region['id']; showTransfer?: boolean; - disabledTypes?: PlanSelectionType[]; - disabledTypesToolTip?: string; + disabledPlanTypes?: PlanSelectionType[]; + disabledPlanTypesToolTip?: string; } export const PlanContainer = (props: Props) => { @@ -65,8 +65,8 @@ export const PlanContainer = (props: Props) => { selectedId, selectedRegionId, showTransfer, - disabledTypes, - disabledTypesToolTip, + disabledPlanTypes, + disabledPlanTypesToolTip, } = props; const location = useLocation(); @@ -90,7 +90,7 @@ export const PlanContainer = (props: Props) => { const renderPlanSelection = React.useCallback(() => { return plans.map((plan, id) => { const planIsDisabled = - disabledTypes?.find((element) => element === plan) != undefined; + disabledPlanTypes?.find((element) => element === plan) !== undefined; const isPlanSoldOut = getIsPlanSoldOut({ plan, regionAvailabilities, @@ -117,7 +117,7 @@ export const PlanContainer = (props: Props) => { showTransfer={showTransfer} type={plan} planIsDisabled={planIsDisabled} - disabledToolTip={disabledTypesToolTip} + disabledToolTip={disabledPlanTypesToolTip} /> ); }); diff --git a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx index aa2da2c9d6a..4cb433d323d 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx @@ -60,7 +60,7 @@ const getToolTip = ( sizeTooSmall: boolean, planIsDisabled?: boolean, disabledToolTip?: string -) => { +): string | undefined => { if (planIsDisabled) { return disabledToolTip; } else if (sizeTooSmall) { diff --git a/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx b/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx index 6fac1ae62e5..cfb459cf387 100644 --- a/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx @@ -47,8 +47,8 @@ interface Props { tabDisabledMessage?: string; tabbedPanelInnerClass?: string; types: PlanSelectionType[]; - disabledTypes?: PlanSelectionType[]; - disabledTypesToolTip?: string; + disabledPlanTypes?: PlanSelectionType[]; + disabledPlanTypesToolTip?: string; } export const PlansPanel = (props: Props) => { @@ -68,8 +68,8 @@ export const PlansPanel = (props: Props) => { selectedRegionID, showTransfer, types, - disabledTypes, - disabledTypesToolTip, + disabledPlanTypes, + disabledPlanTypesToolTip, } = props; const flags = useFlags(); @@ -192,8 +192,8 @@ export const PlansPanel = (props: Props) => { selectedId={selectedId} selectedRegionId={selectedRegionID} showTransfer={showTransfer} - disabledTypes={disabledTypes} - disabledTypesToolTip={disabledTypesToolTip} + disabledPlanTypes={disabledPlanTypes} + disabledPlanTypesToolTip={disabledPlanTypesToolTip} /> ); From 6d4c207aa1070d9bf5d4caf328403632bc2746e7 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Fri, 8 Mar 2024 15:51:34 +0100 Subject: [PATCH 5/9] change: [UIE-7308] - refactoring --- .../DatabaseDetail/DatabaseResize/DatabaseResize.tsx | 10 +++++++--- .../DatabaseResizeCurrentConfiguration.tsx | 11 ++++++++--- .../DatabaseSummaryClusterConfiguration.tsx | 11 ++++++++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx index b7d9376d4be..20348e481fe 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx @@ -3,6 +3,7 @@ import { Database, DatabaseClusterSizeObject, DatabasePriceObject, + DatabaseType, Engine, } from '@linode/api-v4/lib/databases/types'; import { useSnackbar } from 'notistack'; @@ -138,7 +139,9 @@ export const DatabaseResize = ({ database }: Props) => { return; } - const selectedPlanType = dbTypes.find((type) => type.id === planSelected); + const selectedPlanType = dbTypes.find( + (type: DatabaseType) => type.id === planSelected + ); if (!selectedPlanType) { setPlanSelected(undefined); setSummaryText(undefined); @@ -173,11 +176,12 @@ export const DatabaseResize = ({ database }: Props) => { if (!dbTypes) { return []; } - return dbTypes.map((type) => { + return dbTypes.map((type: DatabaseType) => { const { label } = type; const formattedLabel = formatStorageUnits(label); const nodePricing = type.engines[selectedEngine].find( - (cluster) => cluster.quantity === database.cluster_size + (cluster: DatabaseClusterSizeObject) => + cluster.quantity === database.cluster_size ); const price = nodePricing?.price ?? { hourly: null, diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx index b519f227ccf..dfe7ef17887 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx @@ -1,4 +1,8 @@ -import { Database, DatabaseInstance } from '@linode/api-v4/lib/databases/types'; +import { + Database, + DatabaseInstance, + DatabaseType, +} from '@linode/api-v4/lib/databases/types'; import { useTheme } from '@mui/material/styles'; import * as React from 'react'; @@ -24,6 +28,7 @@ import { StyledSummaryTextTypography, StyledTitleTypography, } from './DatabaseResizeCurrentConfiguration.style'; +import { Region } from '@linode/api-v4'; interface Props { database: Database; @@ -42,9 +47,9 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { const theme = useTheme(); const { data: regions } = useRegionsQuery(); - const region = regions?.find((r) => r.id === database.region); + const region = regions?.find((r: Region) => r.id === database.region); - const type = types?.find((type) => type.id === database?.type); + const type = types?.find((type: DatabaseType) => type.id === database?.type); const { data: events } = useInProgressEvents(); const progress = getResizeProgress(database, events); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx index f5b1ccdb9ca..06cb6b3ead5 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx @@ -1,4 +1,8 @@ -import { Database, DatabaseInstance } from '@linode/api-v4/lib/databases/types'; +import { + Database, + DatabaseInstance, + DatabaseType, +} from '@linode/api-v4/lib/databases/types'; import { Theme } from '@mui/material/styles'; import * as React from 'react'; import { makeStyles } from 'tss-react/mui'; @@ -18,6 +22,7 @@ import { databaseEngineMap, databaseStatusMap, } from '../../DatabaseLanding/DatabaseRow'; +import { Region } from '@linode/api-v4'; const useStyles = makeStyles()((theme: Theme) => ({ configs: { @@ -55,9 +60,9 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { const { data: types } = useDatabaseTypesQuery(); const { data: regions } = useRegionsQuery(); - const region = regions?.find((r) => r.id === database.region); + const region = regions?.find((r: Region) => r.id === database.region); - const type = types?.find((type) => type.id === database?.type); + const type = types?.find((type: DatabaseType) => type.id === database?.type); const { data: events } = useInProgressEvents(); const progress = getResizeProgress(database, events); From fcd7078f66b286cdd6e3f42224ac46ca2bd5d1ab Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Mon, 11 Mar 2024 19:32:25 +0100 Subject: [PATCH 6/9] change: [UIE-7308] - add DatabaseStatusDisplay component --- ...atabaseResizeCurrentConfiguration.style.ts | 6 - .../DatabaseResizeCurrentConfiguration.tsx | 35 +++-- .../DatabaseStatusDisplay.test.tsx | 130 ++++++++++++++++++ .../DatabaseDetail/DatabaseStatusDisplay.tsx | 64 +++++++++ .../DatabaseSummaryClusterConfiguration.tsx | 19 +-- .../Databases/DatabaseLanding/DatabaseRow.tsx | 25 +--- .../src/features/Databases/utilities.ts | 22 --- 7 files changed, 218 insertions(+), 83 deletions(-) create mode 100644 packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx create mode 100644 packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx delete mode 100644 packages/manager/src/features/Databases/utilities.ts diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts index 0cda918f77e..76cc7fc49a2 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts @@ -46,9 +46,3 @@ export const StyledTitleTypography = styled(Typography, { })(({ theme }) => ({ marginBottom: theme.spacing(2), })); - -export const StyledStatusSpan = styled('span', { label: 'StyledStatusSpan' })( - () => ({ - textTransform: 'capitalize', - }) -); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx index dfe7ef17887..9bb5bdc29d6 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx @@ -5,30 +5,35 @@ import { } from '@linode/api-v4/lib/databases/types'; import { useTheme } from '@mui/material/styles'; import * as React from 'react'; - import { Box } from 'src/components/Box'; import { CircleProgress } from 'src/components/CircleProgress'; import { ErrorState } from 'src/components/ErrorState/ErrorState'; -import { StatusIcon } from 'src/components/StatusIcon/StatusIcon'; import { TooltipIcon } from 'src/components/TooltipIcon'; import { useDatabaseTypesQuery } from 'src/queries/databases'; import { useRegionsQuery } from 'src/queries/regions'; import { useInProgressEvents } from 'src/queries/events/events'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; -import { getResizeProgress } from '../../utilities'; -import { - databaseEngineMap, - databaseStatusMap, -} from '../../DatabaseLanding/DatabaseRow'; +import { databaseEngineMap } from '../../DatabaseLanding/DatabaseRow'; +import { Theme } from '@mui/material/styles'; +import { makeStyles } from 'tss-react/mui'; import { - StyledStatusSpan, StyledSummaryBox, StyledSummaryTextBox, StyledSummaryTextTypography, StyledTitleTypography, } from './DatabaseResizeCurrentConfiguration.style'; import { Region } from '@linode/api-v4'; +import { DatabaseStatusDisplay } from '../DatabaseStatusDisplay'; + +const useStyles = makeStyles()((theme: Theme) => ({ + status: { + alignItems: 'center', + display: 'inline-flex', + textTransform: 'capitalize', + verticalAlign: 'sub', + }, +})); interface Props { database: Database; @@ -45,6 +50,7 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { isLoading: typesLoading, } = useDatabaseTypesQuery(); const theme = useTheme(); + const { classes } = useStyles(); const { data: regions } = useRegionsQuery(); const region = regions?.find((r: Region) => r.id === database.region); @@ -52,8 +58,6 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { const type = types?.find((type: DatabaseType) => type.id === database?.type); const { data: events } = useInProgressEvents(); - const progress = getResizeProgress(database, events); - if (typesLoading) { return ; } @@ -92,14 +96,9 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { Status{' '} - - - {database.status + - (progress !== undefined ? ' (' + progress + '%)' : '')} - +
+ +
Version{' '} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx new file mode 100644 index 00000000000..1a057d87691 --- /dev/null +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import { DatabaseStatusDisplay } from '../DatabaseDetail/DatabaseStatusDisplay'; +import { Event } from '@linode/api-v4'; +import { Database, DatabaseInstance } from '@linode/api-v4/lib/databases/types'; +import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; + +beforeAll(() => mockMatchMedia()); + +describe('DatabaseStatusDisplay component', () => { + it('renders status correctly when recent event status is "started" or "scheduled"', () => { + const mockEvent: Event[] = [ + { + id: 1, + action: 'database_resize', + created: '2024-03-11T17:07:03', + entity: { + id: 7021, + type: 'database', + label: 'db2', + url: '/v4/databases/postgresql/instances/7024', + }, + duration: 164, + percent_complete: 50, + rate: null, + read: false, + seen: false, + status: 'started', + time_remaining: null, + username: null, + secondary_entity: null, + message: null, + }, + ]; + const database: Database | DatabaseInstance = { + id: 7021, + label: 'db2', + type: 'g6-dedicated-2', + engine: 'postgresql', + version: '14.6', + region: 'us-east', + status: 'resizing', + port: 5432, + encrypted: false, + allow_list: [], + cluster_size: 3, + hosts: { + primary: '', + secondary: '', + }, + created: '2024-03-11T15:28:10', + updated: '2024-03-11T15:30:01', + total_disk_size_gb: 0, + used_disk_size_gb: 0, + updates: { + frequency: 'weekly', + duration: 3, + hour_of_day: 0, + day_of_week: 0, + week_of_month: null, + }, + instance_uri: '/v4/databases/postgresql/instances/7021', + }; + const { getByText } = renderWithTheme( + + ); + + expect(getByText('Resizing (50%)')).toBeInTheDocument(); + }); + + it('renders status correctly when recent event status is not "started" or "scheduled"', () => { + const mockEvent: Event[] = [ + { + id: 1, + action: 'database_resize', + created: '2024-03-11T17:07:03', + entity: { + id: 1, + type: 'database', + label: 'db3', + url: '/v4/databases/postgresql/instances/7024', + }, + duration: 164, + percent_complete: 50, + rate: null, + read: false, + seen: false, + status: 'finished', + time_remaining: null, + username: null, + secondary_entity: null, + message: null, + }, + ]; + const database: Database | DatabaseInstance = { + id: 7021, + label: 'db2', + type: 'g6-dedicated-2', + engine: 'postgresql', + version: '14.6', + region: 'us-east', + status: 'active', + port: 5432, + encrypted: false, + allow_list: [], + cluster_size: 3, + hosts: { + primary: '', + secondary: '', + }, + created: '2024-03-11T15:28:10', + updated: '2024-03-11T15:30:01', + total_disk_size_gb: 0, + used_disk_size_gb: 0, + updates: { + frequency: 'weekly', + duration: 3, + hour_of_day: 0, + day_of_week: 0, + week_of_month: null, + }, + instance_uri: '/v4/databases/postgresql/instances/7021', + }; + + const { getByText } = renderWithTheme( + + ); + + expect(getByText('Active')).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx new file mode 100644 index 00000000000..ec3658b13c4 --- /dev/null +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { Typography } from 'src/components/Typography'; +import { capitalize } from 'src/utilities/capitalize'; +import { Event } from '@linode/api-v4'; +import { + Database, + DatabaseInstance, + DatabaseStatus, +} from '@linode/api-v4/lib/databases/types'; +import { Status, StatusIcon } from 'src/components/StatusIcon/StatusIcon'; + +export const databaseStatusMap: Record = { + active: 'active', + degraded: 'inactive', + failed: 'error', + provisioning: 'other', + restoring: 'other', + resuming: 'other', + suspended: 'error', + suspending: 'other', + resizing: 'other', +}; + +export const DatabaseStatusDisplay: React.FC<{ + events: Event[] | undefined; + database: Database | DatabaseInstance; +}> = (props) => { + // recent event + const recentEvent = props.events?.find( + (event) => + event.entity?.id === props.database.id && event.entity.type === 'database' + ); + + // progress + let progress: number | undefined; + if (recentEvent?.action === 'database_resize') { + progress = recentEvent?.percent_complete ?? 0; + } + + // status + let displayedStatus; + if ( + recentEvent?.status === 'started' || + recentEvent?.status === 'scheduled' + ) { + displayedStatus = ( + <> + + + {`Resizing ${progress ? `(${progress}%)` : '(0%)'}`} + + + ); + } else { + displayedStatus = ( + <> + + {capitalize(props.database.status)} + + ); + } + + return displayedStatus; +}; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx index 06cb6b3ead5..23ce46f0ade 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx @@ -6,9 +6,7 @@ import { import { Theme } from '@mui/material/styles'; import * as React from 'react'; import { makeStyles } from 'tss-react/mui'; - import { Box } from 'src/components/Box'; -import { StatusIcon } from 'src/components/StatusIcon/StatusIcon'; import { TooltipIcon } from 'src/components/TooltipIcon'; import { Typography } from 'src/components/Typography'; import { useDatabaseTypesQuery } from 'src/queries/databases'; @@ -16,12 +14,8 @@ import { useRegionsQuery } from 'src/queries/regions'; import { useInProgressEvents } from 'src/queries/events/events'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; -import { getResizeProgress } from '../../utilities'; - -import { - databaseEngineMap, - databaseStatusMap, -} from '../../DatabaseLanding/DatabaseRow'; +import { DatabaseStatusDisplay } from '../DatabaseStatusDisplay'; +import { databaseEngineMap } from '../../DatabaseLanding/DatabaseRow'; import { Region } from '@linode/api-v4'; const useStyles = makeStyles()((theme: Theme) => ({ @@ -65,7 +59,6 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => { const type = types?.find((type: DatabaseType) => type.id === database?.type); const { data: events } = useInProgressEvents(); - const progress = getResizeProgress(database, events); if (!database || !type) { return null; @@ -92,11 +85,9 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => {
Status - - - {database.status + - (progress !== undefined ? ' (' + progress + '%)' : '')} - +
+ +
Version diff --git a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx index 8b7d9867b70..8f15a606507 100644 --- a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx +++ b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseRow.tsx @@ -1,35 +1,20 @@ import { Database, DatabaseInstance, - DatabaseStatus, Engine, } from '@linode/api-v4/lib/databases/types'; import * as React from 'react'; import { Link } from 'react-router-dom'; import { Chip } from 'src/components/Chip'; import { Hidden } from 'src/components/Hidden'; -import { Status, StatusIcon } from 'src/components/StatusIcon/StatusIcon'; import { TableCell } from 'src/components/TableCell'; import { TableRow } from 'src/components/TableRow'; import { useProfile } from 'src/queries/profile'; import { useRegionsQuery } from 'src/queries/regions'; -import { capitalize } from 'src/utilities/capitalize'; import { isWithinDays, parseAPIDate } from 'src/utilities/date'; import { formatDate } from 'src/utilities/formatDate'; -import { getResizeProgress } from '../utilities'; import { Event } from '@linode/api-v4'; - -export const databaseStatusMap: Record = { - active: 'active', - degraded: 'inactive', - failed: 'error', - provisioning: 'other', - restoring: 'other', - resuming: 'other', - suspended: 'error', - suspending: 'other', - resizing: 'other', -}; +import { DatabaseStatusDisplay } from '../DatabaseDetail/DatabaseStatusDisplay'; export const databaseEngineMap: Record = { mongodb: 'MongoDB', @@ -59,10 +44,6 @@ export const DatabaseRow = ({ database, events }: Props) => { const actualRegion = regions?.find((r) => r.id === region); - const progress = getResizeProgress(database, events); - - const status = database.status; - const configuration = cluster_size === 1 ? ( 'Primary' @@ -88,9 +69,7 @@ export const DatabaseRow = ({ database, events }: Props) => { {label} - - {capitalize(database.status) + - (progress !== undefined ? ' (' + progress + '%)' : '')} + {configuration} diff --git a/packages/manager/src/features/Databases/utilities.ts b/packages/manager/src/features/Databases/utilities.ts deleted file mode 100644 index 210e79c58fc..00000000000 --- a/packages/manager/src/features/Databases/utilities.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Event } from '@linode/api-v4'; -import { Database, DatabaseInstance } from '@linode/api-v4/lib/databases/types'; - -export const getResizeProgress = ( - database: Database | DatabaseInstance, - events: Event[] | undefined -): number | undefined => { - const recentEvent = events?.find( - (event) => - event.entity?.id === database.id && event.entity.type === 'database' - ); - - let progress: number | undefined = 0; - if (recentEvent?.action === 'database_resize') { - progress = recentEvent?.percent_complete ?? 0; - database.status = 'resizing'; - } else { - return undefined; - } - - return progress; -}; From 76006ccce63f5c72e2df99234740886ec0280c75 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Wed, 13 Mar 2024 19:07:48 +0100 Subject: [PATCH 7/9] change: [UIE-7308] - refactoring --- .../DatabaseDetail/DatabaseStatusDisplay.tsx | 17 +++++++++-------- .../features/Events/eventMessageGenerator.ts | 6 ++++++ .../components/PlansPanel/PlanContainer.tsx | 12 ++++++------ .../components/PlansPanel/PlanSelection.tsx | 17 +++++++++++++---- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx index ec3658b13c4..fde32c485f4 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx @@ -20,15 +20,16 @@ export const databaseStatusMap: Record = { suspending: 'other', resizing: 'other', }; - -export const DatabaseStatusDisplay: React.FC<{ +interface Props { events: Event[] | undefined; database: Database | DatabaseInstance; -}> = (props) => { +} +export const DatabaseStatusDisplay = (props: Props) => { + const { events, database } = props; // recent event - const recentEvent = props.events?.find( - (event) => - event.entity?.id === props.database.id && event.entity.type === 'database' + const recentEvent = events?.find( + (event: Event) => + event.entity?.id === database.id && event.entity?.type === 'database' ); // progress @@ -54,8 +55,8 @@ export const DatabaseStatusDisplay: React.FC<{ } else { displayedStatus = ( <> - - {capitalize(props.database.status)} + + {capitalize(database.status)} ); } diff --git a/packages/manager/src/features/Events/eventMessageGenerator.ts b/packages/manager/src/features/Events/eventMessageGenerator.ts index 47481180b1c..1d514c1f486 100644 --- a/packages/manager/src/features/Events/eventMessageGenerator.ts +++ b/packages/manager/src/features/Events/eventMessageGenerator.ts @@ -131,6 +131,12 @@ export const eventMessageCreators: { [index: string]: CreatorsForStatus } = { database_resize_create: { notification: (e) => `Database ${e.entity!.label} scheduled to be resized.`, }, + database_scale: { + failed: (e) => `Database ${e.entity!.label} could not be resized.`, + finished: (e) => `Database ${e.entity!.label} has been resized.`, + scheduled: (e) => `Database ${e.entity!.label} is scheduled for resizing.`, + started: (e) => `Database ${e.entity!.label} is resizing.`, + }, database_update: { finished: (e) => `Database ${e.entity!.label} has been updated.`, }, diff --git a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx index 37f692f17f5..57b8d34aeb4 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx @@ -39,6 +39,8 @@ export interface Props { disabled?: boolean; disabledClasses?: LinodeTypeClass[]; hideDisabledHelpIcons?: boolean; + disabledPlanTypes?: PlanSelectionType[]; + disabledPlanTypesToolTip?: string; isCreate?: boolean; linodeID?: number | undefined; onSelect: (key: string) => void; @@ -47,8 +49,6 @@ export interface Props { selectedId?: string; selectedRegionId?: Region['id']; showTransfer?: boolean; - disabledPlanTypes?: PlanSelectionType[]; - disabledPlanTypesToolTip?: string; } export const PlanContainer = (props: Props) => { @@ -57,6 +57,8 @@ export const PlanContainer = (props: Props) => { disabled, disabledClasses, hideDisabledHelpIcons, + disabledPlanTypes, + disabledPlanTypesToolTip, isCreate, linodeID, onSelect, @@ -65,8 +67,6 @@ export const PlanContainer = (props: Props) => { selectedId, selectedRegionId, showTransfer, - disabledPlanTypes, - disabledPlanTypesToolTip, } = props; const location = useLocation(); @@ -106,18 +106,18 @@ export const PlanContainer = (props: Props) => { disabled={disabled || planIsDisabled} disabledClasses={disabledClasses} hideDisabledHelpIcons={hideDisabledHelpIcons} + disabledToolTip={disabledPlanTypesToolTip} idx={id} isCreate={isCreate} key={id} linodeID={linodeID} onSelect={onSelect} + planIsDisabled={planIsDisabled} selectedDiskSize={selectedDiskSize} selectedId={selectedId} selectedRegionId={selectedRegionId} showTransfer={showTransfer} type={plan} - planIsDisabled={planIsDisabled} - disabledToolTip={disabledPlanTypesToolTip} /> ); }); diff --git a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx index 4cb433d323d..cf186c2e049 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx @@ -33,6 +33,7 @@ export interface PlanSelectionProps { currentPlanHeading?: string; disabled?: boolean; disabledClasses?: LinodeTypeClass[]; + disabledToolTip?: string; header?: string; hideDisabledHelpIcons?: boolean; idx: number; @@ -40,13 +41,12 @@ export interface PlanSelectionProps { isLimitedAvailabilityPlan: boolean; linodeID?: number | undefined; onSelect: (key: string) => void; + planIsDisabled?: boolean; selectedDiskSize?: number; selectedId?: string; selectedRegionId?: Region['id']; showTransfer?: boolean; type: PlanSelectionType; - planIsDisabled?: boolean; - disabledToolTip?: string; } const getDisabledClass = ( @@ -75,18 +75,18 @@ export const PlanSelection = (props: PlanSelectionProps) => { disabled, disabledClasses, hideDisabledHelpIcons, + disabledToolTip, idx, isCreate, isLimitedAvailabilityPlan, linodeID, onSelect, + planIsDisabled, selectedDiskSize, selectedId, selectedRegionId, showTransfer, type, - planIsDisabled, - disabledToolTip, } = props; const flags = useFlags(); @@ -130,11 +130,20 @@ export const PlanSelection = (props: PlanSelectionProps) => { price?.monthly )}/mo ($${price?.hourly ?? UNKNOWN_PRICE}/hr)`; + const rowAriaDisabled = + isSamePlan || + planTooSmall || + isPlanSoldOut || + isDisabledClass || + planIsDisabled; + return ( {/* Displays Table Row for larger screens */} !isSamePlan && !isDisabled && !isDisabledClass && !planTooSmall ? onSelect(type.id) From 9a57f53e85bf60102a422fab1c0f98d259d7bbb7 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Mon, 18 Mar 2024 15:45:57 +0100 Subject: [PATCH 8/9] change: [UIE-7308] - refactoring --- .../DatabaseResize/DatabaseResize.tsx | 5 +- ...atabaseResizeCurrentConfiguration.style.ts | 9 ++ .../DatabaseResizeCurrentConfiguration.tsx | 17 +-- .../DatabaseStatusDisplay.test.tsx | 131 +++--------------- .../DatabaseDetail/DatabaseStatusDisplay.tsx | 3 - .../Databases/DatabaseDetail/index.tsx | 19 ++- .../NotificationData/RenderProgressEvent.tsx | 5 +- .../components/PlansPanel/PlanContainer.tsx | 5 +- .../components/PlansPanel/PlanSelection.tsx | 23 ++- .../components/PlansPanel/PlansPanel.tsx | 6 +- 10 files changed, 67 insertions(+), 156 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx index 20348e481fe..baa3d42d498 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx @@ -1,4 +1,3 @@ -// import { LinodeTypeClass } from '@linode/api-v4'; import { Database, DatabaseClusterSizeObject, @@ -82,7 +81,7 @@ export const DatabaseResize = ({ database }: Props) => { const resizeDescription = ( <> - Resizing a Database Cluster + Resize a Database Cluster Adapt the cluster to your needs by resizing to a larger plan. Clusters cannot be resized to smaller plans. @@ -228,7 +227,7 @@ export const DatabaseResize = ({ database }: Props) => { currentPlanHeading={currentPlan?.heading} data-qa-select-plan disabledPlanTypes={disabledPlans} - disabledPlanTypesToolTip="Resizing to smaller plans is not supported." + disabledPlanTypesToolTipText="Resizing to smaller plans is not supported." header="Choose a Plan" onSelect={(selected: string) => setPlanSelected(selected)} selectedId={planSelected} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts index 76cc7fc49a2..a3689e4e874 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.style.ts @@ -46,3 +46,12 @@ export const StyledTitleTypography = styled(Typography, { })(({ theme }) => ({ marginBottom: theme.spacing(2), })); + +export const StyledStatusBox = styled(Box, { + label: 'StyledStatusBox', +})(() => ({ + alignItems: 'center', + display: 'inline-flex', + textTransform: 'capitalize', + verticalAlign: 'sub', +})); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx index 9bb5bdc29d6..1206cb415d2 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx @@ -15,26 +15,16 @@ import { useInProgressEvents } from 'src/queries/events/events'; import { formatStorageUnits } from 'src/utilities/formatStorageUnits'; import { convertMegabytesTo } from 'src/utilities/unitConversions'; import { databaseEngineMap } from '../../DatabaseLanding/DatabaseRow'; -import { Theme } from '@mui/material/styles'; -import { makeStyles } from 'tss-react/mui'; import { StyledSummaryBox, StyledSummaryTextBox, StyledSummaryTextTypography, StyledTitleTypography, + StyledStatusBox, } from './DatabaseResizeCurrentConfiguration.style'; import { Region } from '@linode/api-v4'; import { DatabaseStatusDisplay } from '../DatabaseStatusDisplay'; -const useStyles = makeStyles()((theme: Theme) => ({ - status: { - alignItems: 'center', - display: 'inline-flex', - textTransform: 'capitalize', - verticalAlign: 'sub', - }, -})); - interface Props { database: Database; } @@ -50,7 +40,6 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { isLoading: typesLoading, } = useDatabaseTypesQuery(); const theme = useTheme(); - const { classes } = useStyles(); const { data: regions } = useRegionsQuery(); const region = regions?.find((r: Region) => r.id === database.region); @@ -96,9 +85,9 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => { Status{' '} -
+ -
+
Version{' '} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx index 1a057d87691..feb25df224d 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx @@ -1,128 +1,35 @@ import React from 'react'; import { DatabaseStatusDisplay } from '../DatabaseDetail/DatabaseStatusDisplay'; -import { Event } from '@linode/api-v4'; -import { Database, DatabaseInstance } from '@linode/api-v4/lib/databases/types'; import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; - +import { databaseFactory } from 'src/factories'; +import { entityFactory, eventFactory } from 'src/factories/events'; beforeAll(() => mockMatchMedia()); describe('DatabaseStatusDisplay component', () => { - it('renders status correctly when recent event status is "started" or "scheduled"', () => { - const mockEvent: Event[] = [ - { - id: 1, - action: 'database_resize', - created: '2024-03-11T17:07:03', - entity: { - id: 7021, - type: 'database', - label: 'db2', - url: '/v4/databases/postgresql/instances/7024', - }, - duration: 164, - percent_complete: 50, - rate: null, - read: false, - seen: false, - status: 'started', - time_remaining: null, - username: null, - secondary_entity: null, - message: null, - }, - ]; - const database: Database | DatabaseInstance = { - id: 7021, - label: 'db2', - type: 'g6-dedicated-2', - engine: 'postgresql', - version: '14.6', - region: 'us-east', - status: 'resizing', - port: 5432, - encrypted: false, - allow_list: [], - cluster_size: 3, - hosts: { - primary: '', - secondary: '', - }, - created: '2024-03-11T15:28:10', - updated: '2024-03-11T15:30:01', - total_disk_size_gb: 0, - used_disk_size_gb: 0, - updates: { - frequency: 'weekly', - duration: 3, - hour_of_day: 0, - day_of_week: 0, - week_of_month: null, - }, - instance_uri: '/v4/databases/postgresql/instances/7021', - }; + it(`renders status 'resizing' with percentage when recent event status is 'started' or 'scheduled'`, () => { + const mockEvent = eventFactory.build({ + action: 'database_resize', + percent_complete: 50, + entity: entityFactory.build({ id: 1, type: 'database' }), + }); + const database = databaseFactory.build({ id: 1, status: 'resizing' }); + const { getByText } = renderWithTheme( - + ); - expect(getByText('Resizing (50%)')).toBeInTheDocument(); }); - it('renders status correctly when recent event status is not "started" or "scheduled"', () => { - const mockEvent: Event[] = [ - { - id: 1, - action: 'database_resize', - created: '2024-03-11T17:07:03', - entity: { - id: 1, - type: 'database', - label: 'db3', - url: '/v4/databases/postgresql/instances/7024', - }, - duration: 164, - percent_complete: 50, - rate: null, - read: false, - seen: false, - status: 'finished', - time_remaining: null, - username: null, - secondary_entity: null, - message: null, - }, - ]; - const database: Database | DatabaseInstance = { - id: 7021, - label: 'db2', - type: 'g6-dedicated-2', - engine: 'postgresql', - version: '14.6', - region: 'us-east', - status: 'active', - port: 5432, - encrypted: false, - allow_list: [], - cluster_size: 3, - hosts: { - primary: '', - secondary: '', - }, - created: '2024-03-11T15:28:10', - updated: '2024-03-11T15:30:01', - total_disk_size_gb: 0, - used_disk_size_gb: 0, - updates: { - frequency: 'weekly', - duration: 3, - hour_of_day: 0, - day_of_week: 0, - week_of_month: null, - }, - instance_uri: '/v4/databases/postgresql/instances/7021', - }; + it(`renders status 'active' when recent event status is 'finished' `, () => { + const mockEvent = eventFactory.build({ + action: 'database_resize', + status: 'finished', + entity: entityFactory.build({ id: 1, type: 'database' }), + }); + const database = databaseFactory.build({ id: 1, status: 'active' }); const { getByText } = renderWithTheme( - + ); expect(getByText('Active')).toBeInTheDocument(); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx index fde32c485f4..968c2f4d2cb 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx @@ -26,19 +26,16 @@ interface Props { } export const DatabaseStatusDisplay = (props: Props) => { const { events, database } = props; - // recent event const recentEvent = events?.find( (event: Event) => event.entity?.id === database.id && event.entity?.type === 'database' ); - // progress let progress: number | undefined; if (recentEvent?.action === 'database_resize') { progress = recentEvent?.percent_complete ?? 0; } - // status let displayedStatus; if ( recentEvent?.status === 'started' || diff --git a/packages/manager/src/features/Databases/DatabaseDetail/index.tsx b/packages/manager/src/features/Databases/DatabaseDetail/index.tsx index 77300fc74ce..3abdb75747e 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/index.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/index.tsx @@ -78,19 +78,16 @@ export const DatabaseDetail = () => { routeName: `/databases/${engine}/${id}/backups`, title: 'Backups', }, + { + routeName: `/databases/${engine}/${id}/resize`, + title: 'Resize', + }, { routeName: `/databases/${engine}/${id}/settings`, title: 'Settings', }, ]; - if (flags.databaseResize) { - tabs.push({ - routeName: `/databases/${engine}/${id}/resize`, - title: 'Resize', - }); - } - const getTabIndex = () => { const tabChoice = tabs.findIndex((tab) => Boolean(matchPath(tab.routeName, { path: location.pathname })) @@ -161,14 +158,14 @@ export const DatabaseDetail = () => { - - - {flags.databaseResize ? ( - + ) : null} + + + diff --git a/packages/manager/src/features/NotificationCenter/NotificationData/RenderProgressEvent.tsx b/packages/manager/src/features/NotificationCenter/NotificationData/RenderProgressEvent.tsx index 9a6c9c5aecd..f265cc41834 100644 --- a/packages/manager/src/features/NotificationCenter/NotificationData/RenderProgressEvent.tsx +++ b/packages/manager/src/features/NotificationCenter/NotificationData/RenderProgressEvent.tsx @@ -59,7 +59,10 @@ export const RenderProgressEvent = (props: Props) => { <> - + {eventMessage} void; @@ -58,7 +58,7 @@ export const PlanContainer = (props: Props) => { disabledClasses, hideDisabledHelpIcons, disabledPlanTypes, - disabledPlanTypesToolTip, + disabledPlanTypesToolTipText, isCreate, linodeID, onSelect, @@ -107,6 +107,7 @@ export const PlanContainer = (props: Props) => { disabledClasses={disabledClasses} hideDisabledHelpIcons={hideDisabledHelpIcons} disabledToolTip={disabledPlanTypesToolTip} + disabledToolTip={disabledPlanTypesToolTipText} idx={id} isCreate={isCreate} key={id} diff --git a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx index cf186c2e049..9eec878906a 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx @@ -56,14 +56,19 @@ const getDisabledClass = ( return disabledClasses.includes(typeClass); }; -const getToolTip = ( - sizeTooSmall: boolean, - planIsDisabled?: boolean, - disabledToolTip?: string -): string | undefined => { +const getToolTip = ({ + sizeTooSmall, + planIsDisabled, + disabledToolTip, +}: { + sizeTooSmall: boolean; + planIsDisabled?: boolean; + disabledToolTip?: string; +}) => { if (planIsDisabled) { return disabledToolTip; - } else if (sizeTooSmall) { + } + if (sizeTooSmall) { return 'This plan is too small for the selected image.'; } return undefined; @@ -101,7 +106,11 @@ export const PlanSelection = (props: PlanSelectionProps) => { const diskSize = selectedDiskSize ? selectedDiskSize : 0; const planTooSmall = diskSize > type.disk; - const tooltip = getToolTip(planTooSmall, planIsDisabled, disabledToolTip); + const tooltip = getToolTip({ + sizeTooSmall: planTooSmall, + planIsDisabled: planIsDisabled, + disabledToolTip: disabledToolTip, + }); const isSamePlan = type.heading === currentPlanHeading; const isGPU = type.class === 'gpu'; const isDisabledClass = getDisabledClass(type.class, disabledClasses ?? []); diff --git a/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx b/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx index cfb459cf387..af024bb1c78 100644 --- a/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlansPanel.tsx @@ -48,7 +48,7 @@ interface Props { tabbedPanelInnerClass?: string; types: PlanSelectionType[]; disabledPlanTypes?: PlanSelectionType[]; - disabledPlanTypesToolTip?: string; + disabledPlanTypesToolTipText?: string; } export const PlansPanel = (props: Props) => { @@ -69,7 +69,7 @@ export const PlansPanel = (props: Props) => { showTransfer, types, disabledPlanTypes, - disabledPlanTypesToolTip, + disabledPlanTypesToolTipText, } = props; const flags = useFlags(); @@ -193,7 +193,7 @@ export const PlansPanel = (props: Props) => { selectedRegionId={selectedRegionID} showTransfer={showTransfer} disabledPlanTypes={disabledPlanTypes} - disabledPlanTypesToolTip={disabledPlanTypesToolTip} + disabledPlanTypesToolTipText={disabledPlanTypesToolTipText} /> ); From 7b980d7d3a0c6a7448862a3c4cc90152d80862b2 Mon Sep 17 00:00:00 2001 From: mpolotsk Date: Mon, 18 Mar 2024 21:27:10 +0100 Subject: [PATCH 9/9] change: [UIE-7308] - resolve merge conflicts --- .../features/components/PlansPanel/PlanContainer.tsx | 12 +++--------- .../features/components/PlansPanel/PlanSelection.tsx | 8 +------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx index 37de8f1dba5..6d43e8a26aa 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanContainer.tsx @@ -14,7 +14,7 @@ import { PLAN_SELECTION_NO_REGION_SELECTED_MESSAGE } from 'src/utilities/pricing import { StyledTable, StyledTableCell } from './PlanContainer.styles'; import { PlanSelection } from './PlanSelection'; -import type { TypeWithAvailability } from './types'; +import type { PlanSelectionType, TypeWithAvailability } from './types'; import type { Region } from '@linode/api-v4'; const tableCells = [ @@ -90,13 +90,8 @@ export const PlanContainer = (props: Props) => { const renderPlanSelection = React.useCallback(() => { return plans.map((plan, id) => { const planIsDisabled = - disabledPlanTypes?.find((element) => element === plan) !== undefined; - const isPlanSoldOut = getIsPlanSoldOut({ - plan, - regionAvailabilities, - selectedRegionId, - }); - + disabledPlanTypes?.find((element) => element.id === plan.id) !== + undefined; return ( { disabled={disabled || planIsDisabled} disabledClasses={disabledClasses} hideDisabledHelpIcons={hideDisabledHelpIcons} - disabledToolTip={disabledPlanTypesToolTip} disabledToolTip={disabledPlanTypesToolTipText} idx={id} isCreate={isCreate} diff --git a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx index 9eec878906a..c47d11735cf 100644 --- a/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx +++ b/packages/manager/src/features/components/PlansPanel/PlanSelection.tsx @@ -140,11 +140,7 @@ export const PlanSelection = (props: PlanSelectionProps) => { )}/mo ($${price?.hourly ?? UNKNOWN_PRICE}/hr)`; const rowAriaDisabled = - isSamePlan || - planTooSmall || - isPlanSoldOut || - isDisabledClass || - planIsDisabled; + isSamePlan || planTooSmall || isDisabledClass || planIsDisabled; return ( @@ -158,10 +154,8 @@ export const PlanSelection = (props: PlanSelectionProps) => { ? onSelect(type.id) : undefined } - aria-disabled={isSamePlan || planTooSmall || isDisabled || disabled} aria-label={rowAriaLabel} data-qa-plan-row={type.formattedLabel} - disabled={isSamePlan || planTooSmall || isDisabled || disabled} key={type.id} >