From 51bc332b81101c9349528f80a75c0b9450e6a4ba Mon Sep 17 00:00:00 2001 From: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:01:51 +0100 Subject: [PATCH 01/56] upcoming: [UIE-10251] - Empty message for `SwitchAccountDrawer` child accounts table (#13412) * fix + test * Added changeset: Empty message for `SwitchAccountDrawer` child accounts table * feedback @bnussman-akamai --- ...r-13412-upcoming-features-1771427444510.md | 5 ++ .../features/Account/SwitchAccountDrawer.tsx | 1 + .../SwitchAccounts/ChildAccountList.tsx | 25 +----- .../ChildAccountsTable.test.tsx | 80 +++++++++++++++++++ .../SwitchAccounts/ChildAccountsTable.tsx | 27 ++++++- 5 files changed, 110 insertions(+), 28 deletions(-) create mode 100644 packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md create mode 100644 packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx diff --git a/packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md b/packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md new file mode 100644 index 00000000000..81c5cb1f276 --- /dev/null +++ b/packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Empty message for `SwitchAccountDrawer` child accounts table ([#13412](https://github.com/linode/manager/pull/13412)) diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index d18e6f105f1..f6b63918268 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -297,6 +297,7 @@ export const SwitchAccountDrawer = (props: Props) => { ? currentParentTokenWithBearer : currentTokenWithBearer } + filter={filter} isLoading={isLoading} isSwitchingChildAccounts={isSwitchingChildAccounts} onClose={onClose} diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx index 5b93722145e..067748156a5 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx @@ -2,8 +2,6 @@ import { Box, CircleProgress, LinkButton, Notice, Stack } from '@linode/ui'; import React from 'react'; import { Waypoint } from 'react-waypoint'; -import { useIsIAMDelegationEnabled } from 'src/features/IAM/hooks/useIsIAMEnabled'; - import type { ChildAccount, Filter, UserType } from '@linode/api-v4'; export interface ChildAccountListProps { @@ -43,8 +41,6 @@ export const ChildAccountList = React.memo( fetchNextPage, isFetchingNextPage, }: ChildAccountListProps) => { - const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled(); - if (isLoading) { return ( @@ -53,11 +49,7 @@ export const ChildAccountList = React.memo( ); } - if ( - !isIAMDelegationEnabled && - childAccounts && - childAccounts.length === 0 - ) { + if (childAccounts && childAccounts.length === 0) { return ( There are no child accounts @@ -69,21 +61,6 @@ export const ChildAccountList = React.memo( ); } - if ( - isIAMDelegationEnabled && - childAccounts && - childAccounts.length === 0 && - !Object.prototype.hasOwnProperty.call(filter, 'company') - ) { - return ( - - You don't have access to other accounts. You must be added to a - delegation by your account administrator to have access to other - accounts. - - ); - } - const renderChildAccounts = childAccounts?.map((childAccount, idx) => { const euuid = childAccount.euuid; return ( diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx new file mode 100644 index 00000000000..b7a4ec14655 --- /dev/null +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx @@ -0,0 +1,80 @@ +import React from 'react'; + +import { accountFactory } from 'src/factories'; +import { renderWithTheme } from 'src/utilities/testHelpers'; + +import { ChildAccountsTable } from './ChildAccountsTable'; + +import type { ChildAccountsTableProps } from './ChildAccountsTable'; + +const childAccounts = accountFactory.buildList(5).map((account, i) => ({ + ...account, + company: `Child Account ${i}`, +})); + +const childAccountsWithMoreThan25 = accountFactory + .buildList(30) + .map((account, i) => ({ + ...account, + company: `Child Account ${i}`, + })); + +const props: ChildAccountsTableProps = { + childAccounts, + currentTokenWithBearer: 'Bearer 123', + onSwitchAccount: vi.fn(), + page: 1, + pageSize: 25, + setIsSwitchingChildAccounts: vi.fn(), + totalResults: 0, + userType: undefined, + filter: {}, + isLoading: false, + isSwitchingChildAccounts: false, + onClose: vi.fn(), + onPageChange: vi.fn(), + onPageSizeChange: vi.fn(), +}; + +describe('ChildAccountsTable', () => { + it('should display a list of child accounts', async () => { + const { getByTestId, getAllByText } = renderWithTheme( + + ); + + expect(getByTestId('child-accounts-table')).toHaveAttribute( + 'aria-label', + 'List of Child Accounts' + ); + + childAccounts.forEach((account) => { + expect(getAllByText(account.company)).toHaveLength(1); + }); + }); + + it('should display pagination when there are more than 25 child accounts', async () => { + const firstPageAccounts = childAccountsWithMoreThan25.slice(0, 25); + + const { getByTestId } = renderWithTheme( + + ); + + expect(getByTestId('child-accounts-table-pagination')).toBeVisible(); + }); + + it('should display an empty state when no child accounts are found', async () => { + const { getByText } = renderWithTheme( + + ); + + expect( + getByText( + /You don't have access to other accounts. You must be added to a delegation by an account administrator to have access to other accounts./ + ) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx index 1f4c316003d..31cd956fb29 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx @@ -1,4 +1,4 @@ -import { Box, CircleProgress, LinkButton, useTheme } from '@linode/ui'; +import { Box, CircleProgress, LinkButton, Notice, useTheme } from '@linode/ui'; import { Pagination } from 'akamai-cds-react-components/Pagination'; import { Table, @@ -10,11 +10,12 @@ import React from 'react'; import { MIN_PAGE_SIZE } from 'src/components/PaginationFooter/PaginationFooter.constants'; -import type { Account, UserType } from '@linode/api-v4'; +import type { Account, Filter, UserType } from '@linode/api-v4'; -interface ChildAccountsTableProps { +export interface ChildAccountsTableProps { childAccounts?: Account[]; currentTokenWithBearer?: string; + filter: Filter; isLoading: boolean; isSwitchingChildAccounts: boolean; onClose: () => void; @@ -42,6 +43,7 @@ interface ChildAccountsTableProps { export const ChildAccountsTable = (props: ChildAccountsTableProps) => { const { + filter, childAccounts, currentTokenWithBearer, isLoading, @@ -74,9 +76,25 @@ export const ChildAccountsTable = (props: ChildAccountsTableProps) => { ); } + if ( + childAccounts && + childAccounts.length === 0 && + !Object.prototype.hasOwnProperty.call(filter, 'company') + ) { + return ( + + You don't have access to other accounts. You must be added to a + delegation by an account administrator to have access to other accounts. + + ); + } + return ( <> - +
{childAccounts?.map((childAccount, idx) => ( @@ -111,6 +129,7 @@ export const ChildAccountsTable = (props: ChildAccountsTableProps) => { {totalResults > MIN_PAGE_SIZE && ( ) => handlePageChange(Number(e.detail)) From c68e4c642d63b1496e218afc8f46a41d816d9734 Mon Sep 17 00:00:00 2001 From: aaleksee-akamai Date: Fri, 20 Feb 2026 09:30:14 +0100 Subject: [PATCH 02/56] feat: [UIE-10184] - IAM: add permissions to UI (#13409) * feat: [UIE-10184] - IAM: add permissions to UI * typo * Added changeset: IAM Parent/Child: add permissions to UI --- packages/api-v4/src/iam/types.ts | 1 + .../pr-13409-added-1771405985553.md | 5 +++ .../Delegations/AccountDelegations.test.tsx | 32 +++++++++++++++++ .../IAM/Delegations/AccountDelegations.tsx | 19 ++++++++-- .../Defaults/DefaultEntityAccess.test.tsx | 34 ++++++++++++++++++ .../Roles/Defaults/DefaultEntityAccess.tsx | 21 +++++++++-- .../IAM/Roles/Defaults/DefaultRoles.test.tsx | 35 +++++++++++++++++++ .../IAM/Roles/Defaults/DefaultRoles.tsx | 28 +++++++++++++-- .../manager/src/features/IAM/Roles/Roles.tsx | 7 ++-- .../UserDelegations/UserDelegations.test.tsx | 35 +++++++++++++++++++ .../Users/UserDelegations/UserDelegations.tsx | 19 ++++++++-- .../features/IAM/Users/UsersTable/Users.tsx | 1 + .../adapters/accountGrantsToPermissions.ts | 1 + .../features/IAM/hooks/useDelegationRole.ts | 6 ++-- .../features/TopMenu/UserMenu/UserMenu.tsx | 3 +- packages/manager/src/routes/IAM/index.ts | 4 ++- 16 files changed, 234 insertions(+), 17 deletions(-) create mode 100644 packages/manager/.changeset/pr-13409-added-1771405985553.md diff --git a/packages/api-v4/src/iam/types.ts b/packages/api-v4/src/iam/types.ts index 1da75c56215..fa36b3e8bf5 100644 --- a/packages/api-v4/src/iam/types.ts +++ b/packages/api-v4/src/iam/types.ts @@ -125,6 +125,7 @@ export type AccountAdmin = | 'view_account_login' | 'view_account_settings' | 'view_child_account' + | 'view_default_delegate_access' | 'view_enrolled_beta_program' | 'view_lock' | 'view_network_usage' diff --git a/packages/manager/.changeset/pr-13409-added-1771405985553.md b/packages/manager/.changeset/pr-13409-added-1771405985553.md new file mode 100644 index 00000000000..1c4b57f817a --- /dev/null +++ b/packages/manager/.changeset/pr-13409-added-1771405985553.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Added +--- + +IAM Parent/Child: add permissions to UI ([#13409](https://github.com/linode/manager/pull/13409)) diff --git a/packages/manager/src/features/IAM/Delegations/AccountDelegations.test.tsx b/packages/manager/src/features/IAM/Delegations/AccountDelegations.test.tsx index 6827a0013b3..b98a0b6c970 100644 --- a/packages/manager/src/features/IAM/Delegations/AccountDelegations.test.tsx +++ b/packages/manager/src/features/IAM/Delegations/AccountDelegations.test.tsx @@ -13,8 +13,17 @@ const mocks = vi.hoisted(() => ({ mockUseGetChildAccountsQuery: vi.fn(), useParams: vi.fn().mockReturnValue({}), useSearch: vi.fn().mockReturnValue({}), + usePermissions: vi.fn().mockReturnValue({}), })); +vi.mock('src/features/IAM/hooks/usePermissions', async () => { + const actual = await vi.importActual('src/features/IAM/hooks/usePermissions'); + return { + ...actual, + usePermissions: mocks.usePermissions, + }; +}); + vi.mock('@tanstack/react-router', async () => { const actual = await vi.importActual('@tanstack/react-router'); return { @@ -53,6 +62,10 @@ describe('AccountDelegations', () => { data: { data: mockDelegations, results: mockDelegations.length }, isLoading: false, }); + mocks.usePermissions.mockReturnValue({ + data: { list_all_child_accounts: true }, + isLoading: false, + }); }); it('should render the delegations table with data', async () => { @@ -93,4 +106,23 @@ describe('AccountDelegations', () => { expect(emptyElement).toBeInTheDocument(); }); }); + + it('should not render if user does not have permissions', () => { + mocks.usePermissions.mockReturnValue({ + data: { + list_all_child_accounts: false, + }, + isLoading: false, + }); + + renderWithTheme(, { + flags: { iamDelegation: { enabled: true }, iam: { enabled: true } }, + initialRoute: '/iam', + }); + expect( + screen.queryByText( + 'You do not have permission to view account delegations.' + ) + ).toBeVisible(); + }); }); diff --git a/packages/manager/src/features/IAM/Delegations/AccountDelegations.tsx b/packages/manager/src/features/IAM/Delegations/AccountDelegations.tsx index 2393e8649f3..ca54e98572f 100644 --- a/packages/manager/src/features/IAM/Delegations/AccountDelegations.tsx +++ b/packages/manager/src/features/IAM/Delegations/AccountDelegations.tsx @@ -1,5 +1,5 @@ import { useGetChildAccountsQuery } from '@linode/queries'; -import { CircleProgress, Paper, Stack } from '@linode/ui'; +import { CircleProgress, Notice, Paper, Stack } from '@linode/ui'; import { useMediaQuery, useTheme } from '@mui/material'; import { useNavigate, useSearch } from '@tanstack/react-router'; import React from 'react'; @@ -10,6 +10,7 @@ import { useOrderV2 } from 'src/hooks/useOrderV2'; import { usePaginationV2 } from 'src/hooks/usePaginationV2'; import { useIsIAMDelegationEnabled } from '../hooks/useIsIAMEnabled'; +import { usePermissions } from '../hooks/usePermissions'; import { AccountDelegationsTable } from './AccountDelegationsTable'; const DELEGATIONS_ROUTE = '/iam/delegations'; @@ -17,6 +18,10 @@ const DELEGATIONS_ROUTE = '/iam/delegations'; export const AccountDelegations = () => { const navigate = useNavigate(); const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled(); + const { data: permissions, isLoading: isPermissionsLoading } = usePermissions( + 'account', + ['list_all_child_accounts'] + ); const { company } = useSearch({ from: '/iam', @@ -78,12 +83,22 @@ export const AccountDelegations = () => { }); }; - if (isLoading) { + if (isLoading || isPermissionsLoading) { return ; } + + if (!permissions?.list_all_child_accounts) { + return ( + + You do not have permission to view account delegations. + + ); + } + if (!isIAMDelegationEnabled) { return null; } + return ( ({ marginTop: theme.tokens.spacing.S16 })}> ({ useIsDefaultDelegationRolesForChildAccount: vi .fn() .mockReturnValue({ isDefaultDelegationRolesForChildAccount: true }), + usePermissions: vi.fn().mockReturnValue({}), })); vi.mock('src/features/IAM/hooks/useDelegationRole', () => ({ @@ -41,6 +42,14 @@ vi.mock('src/queries/entities/entities', async () => { }; }); +vi.mock('src/features/IAM/hooks/usePermissions', async () => { + const actual = await vi.importActual('src/features/IAM/hooks/usePermissions'); + return { + ...actual, + usePermissions: queryMocks.usePermissions, + }; +}); + vi.mock('@tanstack/react-router', async () => { const actual = await vi.importActual('@tanstack/react-router'); return { @@ -51,6 +60,14 @@ vi.mock('@tanstack/react-router', async () => { }); describe('DefaultEntityAccess', () => { + beforeEach(() => { + vi.clearAllMocks(); + + queryMocks.usePermissions.mockReturnValue({ + data: { view_default_delegate_access: true }, + isLoading: false, + }); + }); it('should render', async () => { queryMocks.useGetDefaultDelegationAccessQuery.mockReturnValue({ data: { @@ -92,4 +109,21 @@ describe('DefaultEntityAccess', () => { renderWithTheme(); expect(screen.getByText(ERROR_STATE_TEXT)).toBeVisible(); }); + + it('should not render if user does not have permissions', () => { + queryMocks.usePermissions.mockReturnValue({ + data: { + view_default_delegate_access: false, + }, + isLoading: false, + }); + + renderWithTheme(); + + expect( + screen.queryByText( + 'You do not have permission to view default entity access for delegate users.' + ) + ).toBeVisible(); + }); }); diff --git a/packages/manager/src/features/IAM/Roles/Defaults/DefaultEntityAccess.tsx b/packages/manager/src/features/IAM/Roles/Defaults/DefaultEntityAccess.tsx index 633c1b3d914..61552a9bf45 100644 --- a/packages/manager/src/features/IAM/Roles/Defaults/DefaultEntityAccess.tsx +++ b/packages/manager/src/features/IAM/Roles/Defaults/DefaultEntityAccess.tsx @@ -2,12 +2,14 @@ import { useGetDefaultDelegationAccessQuery } from '@linode/queries'; import { CircleProgress, ErrorState, + Notice, Paper, Stack, Typography, } from '@linode/ui'; import * as React from 'react'; +import { usePermissions } from '../../hooks/usePermissions'; import { AssignedEntitiesTable } from '../../Shared/AssignedEntitiesTable/AssignedEntitiesTable'; import { ERROR_STATE_TEXT, @@ -16,20 +18,35 @@ import { import { NoAssignedRoles } from '../../Shared/NoAssignedRoles/NoAssignedRoles'; export const DefaultEntityAccess = () => { + const { data: permissions, isLoading: isPermissionsLoading } = usePermissions( + 'account', + ['view_default_delegate_access'] + ); const { data: defaultAccess, isLoading: defaultAccessLoading, error, - } = useGetDefaultDelegationAccessQuery({ enabled: true }); + } = useGetDefaultDelegationAccessQuery({ + enabled: permissions?.view_default_delegate_access, + }); const hasAssignedEntities = defaultAccess ? defaultAccess.entity_access.length > 0 : false; - if (defaultAccessLoading) { + if (defaultAccessLoading || isPermissionsLoading) { return ; } + if (!permissions?.view_default_delegate_access) { + return ( + + You do not have permission to view default entity access for delegate + users. + + ); + } + if (error) { return ; } diff --git a/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.test.tsx b/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.test.tsx index b27283a6393..9c560567186 100644 --- a/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.test.tsx +++ b/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.test.tsx @@ -17,6 +17,7 @@ const queryMocks = vi.hoisted(() => ({ useIsDefaultDelegationRolesForChildAccount: vi .fn() .mockReturnValue({ isDefaultDelegationRolesForChildAccount: true }), + usePermissions: vi.fn().mockReturnValue({}), })); vi.mock('@tanstack/react-router', async () => { @@ -35,11 +36,28 @@ vi.mock('@linode/queries', async () => { queryMocks.useGetDefaultDelegationAccessQuery, }; }); + +vi.mock('src/features/IAM/hooks/usePermissions', async () => { + const actual = await vi.importActual('src/features/IAM/hooks/usePermissions'); + return { + ...actual, + usePermissions: queryMocks.usePermissions, + }; +}); + vi.mock('src/features/IAM/hooks/useDelegationRole', () => ({ useIsDefaultDelegationRolesForChildAccount: queryMocks.useIsDefaultDelegationRolesForChildAccount, })); describe('DefaultRoles', () => { + beforeEach(() => { + vi.clearAllMocks(); + + queryMocks.usePermissions.mockReturnValue({ + data: { view_default_delegate_access: true }, + isLoading: false, + }); + }); it('should render', async () => { queryMocks.useGetDefaultDelegationAccessQuery.mockReturnValue({ data: { @@ -84,4 +102,21 @@ describe('DefaultRoles', () => { renderWithTheme(); expect(screen.getByText(ERROR_STATE_TEXT)).toBeVisible(); }); + + it('should not render if user does not have permissions', () => { + queryMocks.usePermissions.mockReturnValue({ + data: { + view_default_delegate_access: false, + }, + isLoading: false, + }); + + renderWithTheme(); + + expect( + screen.queryByText( + 'You do not have permission to view default roles for delegate users.' + ) + ).toBeVisible(); + }); }); diff --git a/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.tsx b/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.tsx index 7c979c02d71..11e60aba199 100644 --- a/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.tsx +++ b/packages/manager/src/features/IAM/Roles/Defaults/DefaultRoles.tsx @@ -1,7 +1,14 @@ import { useGetDefaultDelegationAccessQuery } from '@linode/queries'; -import { CircleProgress, ErrorState, Paper, Typography } from '@linode/ui'; +import { + CircleProgress, + ErrorState, + Notice, + Paper, + Typography, +} from '@linode/ui'; import * as React from 'react'; +import { usePermissions } from '../../hooks/usePermissions'; import { AssignedRolesTable } from '../../Shared/AssignedRolesTable/AssignedRolesTable'; import { ERROR_STATE_TEXT, @@ -10,20 +17,35 @@ import { import { NoAssignedRoles } from '../../Shared/NoAssignedRoles/NoAssignedRoles'; export const DefaultRoles = () => { + const { data: permissions, isLoading: isPermissionsLoading } = usePermissions( + 'account', + ['view_default_delegate_access'] + ); const { data: defaultRolesData, isLoading: defaultRolesLoading, error, - } = useGetDefaultDelegationAccessQuery({ enabled: true }); + } = useGetDefaultDelegationAccessQuery({ + enabled: permissions?.view_default_delegate_access, + }); + const hasAssignedRoles = defaultRolesData ? defaultRolesData.account_access.length > 0 || defaultRolesData.entity_access.length > 0 : false; - if (defaultRolesLoading) { + if (defaultRolesLoading || isPermissionsLoading) { return ; } + if (!permissions?.view_default_delegate_access) { + return ( + + You do not have permission to view default roles for delegate users. + + ); + } + if (error) { return ; } diff --git a/packages/manager/src/features/IAM/Roles/Roles.tsx b/packages/manager/src/features/IAM/Roles/Roles.tsx index 45aa59d204e..d14073ebb3a 100644 --- a/packages/manager/src/features/IAM/Roles/Roles.tsx +++ b/packages/manager/src/features/IAM/Roles/Roles.tsx @@ -19,7 +19,8 @@ export const RolesLanding = () => { permissions?.list_role_permissions ); const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled(); - const { isChildUserType, isProfileLoading } = useDelegationRole(); + const { isChildUserType, isProfileLoading, isDelegateUserType } = + useDelegationRole(); const { roles } = React.useMemo(() => { if (!accountRoles) { @@ -41,7 +42,9 @@ export const RolesLanding = () => { return ( <> - {isChildUserType && isIAMDelegationEnabled && } + {(isChildUserType || isDelegateUserType) && isIAMDelegationEnabled && ( + + )} ({ marginTop: theme.tokens.spacing.S16 })}> Roles diff --git a/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.test.tsx b/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.test.tsx index 8b729db6fcd..9a34910cc71 100644 --- a/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.test.tsx +++ b/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.test.tsx @@ -14,6 +14,7 @@ const queryMocks = vi.hoisted(() => ({ useNavigate: vi.fn().mockReturnValue(vi.fn()), useGetDelegatedChildAccountsForUserQuery: vi.fn().mockReturnValue({}), useAccountRoles: vi.fn().mockReturnValue({}), + usePermissions: vi.fn().mockReturnValue({}), })); vi.mock('@linode/queries', async () => { @@ -26,6 +27,14 @@ vi.mock('@linode/queries', async () => { }; }); +vi.mock('src/features/IAM/hooks/usePermissions', async () => { + const actual = await vi.importActual('src/features/IAM/hooks/usePermissions'); + return { + ...actual, + usePermissions: queryMocks.usePermissions, + }; +}); + vi.mock('@tanstack/react-router', async () => { const actual = await vi.importActual('@tanstack/react-router'); return { @@ -48,6 +57,10 @@ describe('UserDelegations', () => { data: accountRolesFactory.build(), isLoading: false, }); + queryMocks.usePermissions.mockReturnValue({ + data: { list_user_delegate_accounts: true }, + isLoading: false, + }); }); it('should display no roles text if no roles are assigned to user', async () => { @@ -86,4 +99,26 @@ describe('UserDelegations', () => { expect(screen.getByText('Account Delegations')).toBeVisible(); }); + + it('should not render if user does not have permissions', () => { + queryMocks.usePermissions.mockReturnValue({ + data: { + list_user_delegate_accounts: false, + }, + }); + + renderWithTheme(, { + flags: { + iam: { enabled: true }, + iamDelegation: { + enabled: true, + }, + }, + }); + expect( + screen.queryByText( + `You do not have permission to view this user's account delegations.` + ) + ).toBeVisible(); + }); }); diff --git a/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.tsx b/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.tsx index bca7ac4d982..cc0cf34ba74 100644 --- a/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.tsx +++ b/packages/manager/src/features/IAM/Users/UserDelegations/UserDelegations.tsx @@ -1,10 +1,11 @@ import { useGetDelegatedChildAccountsForUserQuery } from '@linode/queries'; -import { CircleProgress, ErrorState } from '@linode/ui'; +import { CircleProgress, ErrorState, Notice } from '@linode/ui'; import { useParams } from '@tanstack/react-router'; import React from 'react'; import { DocumentTitleSegment } from 'src/components/DocumentTitle'; +import { usePermissions } from '../../hooks/usePermissions'; import { ERROR_STATE_TEXT, NO_ACCOUNT_DELEGATIONS_TEXT, @@ -15,22 +16,36 @@ import { UserDelegationsTable } from './UserDelegationsTable'; export const UserDelegations = () => { const { username } = useParams({ from: '/iam/users/$username' }); + const { data: permissions, isLoading: isPermissionsLoading } = usePermissions( + 'account', + ['list_user_delegate_accounts'] + ); + const { data: allDelegatedChildAccounts, isLoading, error, } = useGetDelegatedChildAccountsForUserQuery({ username, + enabled: permissions?.list_user_delegate_accounts, }); const hasDelegatedChildAccounts = allDelegatedChildAccounts ? allDelegatedChildAccounts.data.length > 0 : false; - if (isLoading) { + if (isLoading || isPermissionsLoading) { return ; } + if (!permissions?.list_user_delegate_accounts) { + return ( + + You do not have permission to view this user's account delegations. + + ); + } + if (error) { return ; } diff --git a/packages/manager/src/features/IAM/Users/UsersTable/Users.tsx b/packages/manager/src/features/IAM/Users/UsersTable/Users.tsx index 0b928d251a1..6e4f452a119 100644 --- a/packages/manager/src/features/IAM/Users/UsersTable/Users.tsx +++ b/packages/manager/src/features/IAM/Users/UsersTable/Users.tsx @@ -202,6 +202,7 @@ export const UsersLanding = () => { /> {isChildOrDelegateWithDelegationEnabled && ( { - pagination.handlePageChange(1); - setEntityType(selected ?? null); + const nextEntityType = (selected?.value ?? + ALL_ENTITIES_OPTION.value) as 'all' | EntityType; + navigate({ + to: isDefaultDelegationRolesForChildAccount + ? DEFAULTS_ENTITIES_URL + : USER_ENTITIES_URL, + params: + isDefaultDelegationRolesForChildAccount && !username + ? undefined + : username, + search: (prev) => ({ + ...prev, + page: 1, + entityType: nextEntityType, + }), + }); }} options={filterableOptions} placeholder="All Entities" sx={{ minWidth: 250 }} - value={entityType} + value={selectedEntityTypeOption} />
diff --git a/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.test.tsx b/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.test.tsx index 1bf10ef230e..814084b4731 100644 --- a/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.test.tsx +++ b/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.test.tsx @@ -12,6 +12,8 @@ import { AssignedRolesTable } from './AssignedRolesTable'; const queryMocks = vi.hoisted(() => ({ useAllAccountEntities: vi.fn().mockReturnValue({}), useParams: vi.fn().mockReturnValue({}), + useNavigate: vi.fn(() => vi.fn()), + useSearch: vi.fn().mockReturnValue({}), useAccountRoles: vi.fn().mockReturnValue({}), useUserRoles: vi.fn().mockReturnValue({}), useGetDefaultDelegationAccessQuery: vi.fn().mockReturnValue({}), @@ -44,6 +46,8 @@ vi.mock('@tanstack/react-router', async () => { return { ...actual, useParams: queryMocks.useParams, + useNavigate: queryMocks.useNavigate, + useSearch: queryMocks.useSearch, }; }); @@ -125,14 +129,11 @@ describe('AssignedRolesTable', () => { data: mockEntities, }); - renderWithTheme(); + queryMocks.useSearch.mockReturnValue({ query: 'NonExistentRole' }); - const searchInput = screen.getByPlaceholderText('Search'); - await userEvent.type(searchInput, 'NonExistentRole'); + renderWithTheme(); - await waitFor(() => { - expect(screen.getByText('No items to display.')).toBeVisible(); - }); + expect(screen.getByText('No items to display.')).toBeVisible(); }); it('should filter roles based on search query', async () => { @@ -150,8 +151,7 @@ describe('AssignedRolesTable', () => { renderWithTheme(); - const searchInput = screen.getByPlaceholderText('Search'); - await userEvent.type(searchInput, 'account_linode_admin'); + queryMocks.useSearch.mockReturnValue({ query: 'account_linode_admin' }); await waitFor(() => { expect(screen.queryByText('account_linode_admin')).toBeVisible(); @@ -173,9 +173,7 @@ describe('AssignedRolesTable', () => { renderWithTheme(); - const autocomplete = screen.getByPlaceholderText('All Assigned Roles'); - await userEvent.type(autocomplete, 'Firewall Roles'); - + queryMocks.useSearch.mockReturnValue({ roleType: 'firewall' }); await waitFor(() => { expect(screen.queryByText('account_firewall_creator')).toBeVisible(); }); diff --git a/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.tsx b/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.tsx index d9172e4a0bd..11b9e92e8c5 100644 --- a/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.tsx +++ b/packages/manager/src/features/IAM/Shared/AssignedRolesTable/AssignedRolesTable.tsx @@ -6,7 +6,7 @@ import { import { Button, CircleProgress, Select, Typography } from '@linode/ui'; import { useTheme } from '@mui/material'; import Grid from '@mui/material/Grid'; -import { useNavigate, useParams } from '@tanstack/react-router'; +import { useNavigate, useParams, useSearch } from '@tanstack/react-router'; import React from 'react'; import { CollapsibleTable } from 'src/components/CollapsibleTable/CollapsibleTable'; @@ -70,23 +70,35 @@ const ALL_ROLES_OPTION: SelectOption = { label: 'All Assigned Roles', value: 'all', }; + +const DEFAULTS_ROLES_URL = '/iam/roles/defaults/roles'; +const USER_ROLES_URL = '/iam/users/$username/roles'; + export const AssignedRolesTable = () => { const { username } = useParams({ strict: false }); const navigate = useNavigate(); const theme = useTheme(); - const [order, setOrder] = React.useState<'asc' | 'desc'>('asc'); - const [orderBy, setOrderBy] = React.useState('name'); + const { isDefaultDelegationRolesForChildAccount } = + useIsDefaultDelegationRolesForChildAccount(); + + const { + query: queryParam, + roleType: roleTypeParam, + order: orderParam, + } = useSearch({ + from: isDefaultDelegationRolesForChildAccount + ? DEFAULTS_ROLES_URL + : USER_ROLES_URL, + }); + const order: 'asc' | 'desc' = orderParam ?? 'asc'; + const orderBy: OrderByKeys = 'name'; const [isInitialLoad, setIsInitialLoad] = React.useState(true); const { data: permissions } = usePermissions('account', [ 'is_account_admin', 'update_default_delegate_access', ]); - // Determine if we're on the default roles view based on delegation role and path - const { isDefaultDelegationRolesForChildAccount } = - useIsDefaultDelegationRolesForChildAccount(); - const permissionToCheck = isDefaultDelegationRolesForChildAccount ? permissions?.update_default_delegate_access : permissions?.is_account_admin; @@ -109,13 +121,23 @@ export const AssignedRolesTable = () => { : userRolesLoading; const handleOrderChange = (newOrderBy: OrderByKeys) => { - if (orderBy === newOrderBy) { - setOrder(order === 'asc' ? 'desc' : 'asc'); - } else { - setOrderBy(newOrderBy); - setOrder('asc'); - } + const nextOrder: 'asc' | 'desc' = + orderBy === newOrderBy ? (order === 'asc' ? 'desc' : 'asc') : 'asc'; setIsInitialLoad(false); + navigate({ + to: isDefaultDelegationRolesForChildAccount + ? DEFAULTS_ROLES_URL + : USER_ROLES_URL, + params: + isDefaultDelegationRolesForChildAccount && !username + ? undefined + : username, + search: (prev) => ({ + ...prev, + order: nextOrder, + orderBy: newOrderBy, + }), + }); }; const [isChangeRoleDrawerOpen, setIsChangeRoleDrawerOpen] = @@ -200,11 +222,12 @@ export const AssignedRolesTable = () => { return { filterableOptions, roles }; }, [assignedRoles, accountRoles, entities]); - const [query, setQuery] = React.useState(''); - - const [entityType, setEntityType] = React.useState( - ALL_ROLES_OPTION - ); + const selectedEntityTypeOption = React.useMemo(() => { + const value = roleTypeParam ?? ALL_ROLES_OPTION.value; + return ( + filterableOptions.find((opt) => opt.value === value) || ALL_ROLES_OPTION + ); + }, [filterableOptions, roleTypeParam]); const handleViewEntities = (roleName: AccountRoleType | EntityRoleType) => { const selectedRole = roleName; @@ -219,9 +242,9 @@ export const AssignedRolesTable = () => { const filteredAndSortedRoles = React.useMemo(() => { const rolesToFilter = getFilteredRoles({ - entityType: entityType?.value as 'all' | AccessType, + entityType: roleTypeParam ?? 'all', getSearchableFields, - query, + query: queryParam ?? '', roles, }) as RoleView[]; @@ -246,12 +269,12 @@ export const AssignedRolesTable = () => { } return 0; }); - }, [roles, query, entityType, order, orderBy, isInitialLoad]); + }, [roles, queryParam, roleTypeParam, order, orderBy, isInitialLoad]); const pagination = usePaginationV2({ currentRoute: isDefaultDelegationRolesForChildAccount - ? '/iam/roles/defaults/roles' - : '/iam/users/$username/roles', + ? DEFAULTS_ROLES_URL + : USER_ROLES_URL, initialPage: 1, preferenceKey: ASSIGNED_ROLES_TABLE_PREFERENCE_KEY, clientSidePaginationData: filteredAndSortedRoles, @@ -402,23 +425,48 @@ export const AssignedRolesTable = () => { hideLabel label="Filter" onSearch={(value) => { - pagination.handlePageChange(1); - setQuery(value); + navigate({ + to: isDefaultDelegationRolesForChildAccount + ? DEFAULTS_ROLES_URL + : USER_ROLES_URL, + params: + isDefaultDelegationRolesForChildAccount && !username + ? undefined + : username, + search: (prev) => ({ + ...prev, + page: 1, + query: value !== '' ? value : undefined, + }), + }); }} placeholder="Search" - value={query} + value={queryParam ?? ''} />
+
Content Stored From 4cd71b59ad451f63f00511bb006834aabee8654d Mon Sep 17 00:00:00 2001 From: aaleksee-akamai Date: Tue, 24 Feb 2026 10:54:50 +0100 Subject: [PATCH 07/56] feat: [UIE-10224] - IAM: style fix for long username (#13411) * feat: [UIE-10224] - IAM: style fix for long username * Added changeset: IAM: style fix for long username * fix overflow --- packages/manager/.changeset/pr-13411-fixed-1771418285151.md | 5 +++++ .../manager/src/features/IAM/Users/UserDetailsLanding.tsx | 6 +++++- .../src/features/TopMenu/UserMenu/UserMenuPopover.tsx | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 packages/manager/.changeset/pr-13411-fixed-1771418285151.md diff --git a/packages/manager/.changeset/pr-13411-fixed-1771418285151.md b/packages/manager/.changeset/pr-13411-fixed-1771418285151.md new file mode 100644 index 00000000000..df3ca3affe3 --- /dev/null +++ b/packages/manager/.changeset/pr-13411-fixed-1771418285151.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +IAM: style fix for long username ([#13411](https://github.com/linode/manager/pull/13411)) diff --git a/packages/manager/src/features/IAM/Users/UserDetailsLanding.tsx b/packages/manager/src/features/IAM/Users/UserDetailsLanding.tsx index b909ee87a60..efeecd12a4b 100644 --- a/packages/manager/src/features/IAM/Users/UserDetailsLanding.tsx +++ b/packages/manager/src/features/IAM/Users/UserDetailsLanding.tsx @@ -1,4 +1,4 @@ -import { NewFeatureChip } from '@linode/ui'; +import { NewFeatureChip, useTheme } from '@linode/ui'; import { Outlet, useLoaderData, useParams } from '@tanstack/react-router'; import React from 'react'; @@ -24,6 +24,7 @@ import { DelegateUserChip } from '../Shared/DelegateUserChip'; export const UserDetailsLanding = () => { const flags = useFlags(); + const theme = useTheme(); const { isIAMEnabled } = useIsIAMEnabled(); const showLimitedAvailabilityBadges = flags.iamLimitedAvailabilityBadges && isIAMEnabled; @@ -87,6 +88,9 @@ export const UserDetailsLanding = () => { pathname: location.pathname, sx: { flexWrap: 'nowrap', + [theme.breakpoints.down(380)]: { + flexWrap: 'wrap', + }, '& > div:nth-of-type(3) h1': { display: '-webkit-box', '-webkit-line-clamp': '1', diff --git a/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx b/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx index 8fc36fdae33..4c159f880f0 100644 --- a/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx +++ b/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx @@ -224,6 +224,7 @@ export const UserMenuPopover = (props: UserMenuPopoverProps) => { backgroundColor: theme.tokens.alias.Background.Normal, paddingX: theme.tokens.spacing.S24, paddingY: theme.tokens.spacing.S16, + maxWidth: 304, }), }, }} @@ -250,6 +251,7 @@ export const UserMenuPopover = (props: UserMenuPopoverProps) => { sx={(theme) => ({ color: theme.tokens.alias.Content.Text.Primary.Default, font: theme.tokens.alias.Typography.Label.Bold.L, + overflowWrap: 'break-word', })} > {canSwitchBetweenParentOrProxyAccount && companyNameOrEmail From 595817e293139319e4e1f2ae53c960c626165e67 Mon Sep 17 00:00:00 2001 From: aaleksee-akamai Date: Tue, 24 Feb 2026 11:08:17 +0100 Subject: [PATCH 08/56] feat: [UIE-10256] - IAM: fix useGetChildAccountsQuery (#13419) * feat: [UIE-10256] - IAM: fix useGetChildAccountsQuery * revert * Added changeset: IAM: fix useGetChildAccountsQuery * feedback --- .../queries/.changeset/pr-13419-fixed-1771522382949.md | 5 +++++ packages/queries/src/account/users.ts | 7 +++++++ packages/queries/src/iam/delegation.ts | 4 +--- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 packages/queries/.changeset/pr-13419-fixed-1771522382949.md diff --git a/packages/queries/.changeset/pr-13419-fixed-1771522382949.md b/packages/queries/.changeset/pr-13419-fixed-1771522382949.md new file mode 100644 index 00000000000..084104eb476 --- /dev/null +++ b/packages/queries/.changeset/pr-13419-fixed-1771522382949.md @@ -0,0 +1,5 @@ +--- +"@linode/queries": Fixed +--- + +IAM: fix useGetChildAccountsQuery ([#13419](https://github.com/linode/manager/pull/13419)) diff --git a/packages/queries/src/account/users.ts b/packages/queries/src/account/users.ts index 228f260d7f2..128b4a5e383 100644 --- a/packages/queries/src/account/users.ts +++ b/packages/queries/src/account/users.ts @@ -7,6 +7,7 @@ import { useQueryClient, } from '@tanstack/react-query'; +import { delegationQueries } from '../iam/delegation'; import { profileQueries, useProfile } from '../profile'; import { accountQueries } from './queries'; @@ -78,6 +79,9 @@ export const useUpdateUserMutation = (username: string) => { queryClient.invalidateQueries({ queryKey: accountQueries.users._ctx.paginated._def, }); + queryClient.invalidateQueries({ + queryKey: delegationQueries.childAccounts._def, + }); queryClient.setQueryData( accountQueries.users._ctx.user(user.username).queryKey, user, @@ -109,6 +113,9 @@ export const useAccountUserDeleteMutation = (username: string) => { queryClient.invalidateQueries({ queryKey: accountQueries.users._ctx.paginated._def, }); + queryClient.invalidateQueries({ + queryKey: delegationQueries.childAccounts._def, + }); queryClient.removeQueries({ queryKey: accountQueries.users._ctx.user(username).queryKey, }); diff --git a/packages/queries/src/iam/delegation.ts b/packages/queries/src/iam/delegation.ts index ceed9d79255..d50d49599ba 100644 --- a/packages/queries/src/iam/delegation.ts +++ b/packages/queries/src/iam/delegation.ts @@ -99,7 +99,6 @@ export const useGetChildAccountsQuery = ({ > => { return useQuery({ ...delegationQueries.childAccounts({ params, users, filter }), - placeholderData: keepPreviousData, enabled, }); }; @@ -174,8 +173,7 @@ export const useUpdateChildAccountDelegatesQuery = (): UseMutationResult< onSuccess(_data, { euuid }) { // Invalidate all child accounts queryClient.invalidateQueries({ - queryKey: delegationQueries.childAccounts({ params: {}, users: true }) - .queryKey, + queryKey: delegationQueries.childAccounts._def, }); // Invalidate all child account delegates queryClient.invalidateQueries({ From 8272a9a0630675307507ed3f9861dba441eb6521 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:00:13 +0100 Subject: [PATCH 09/56] chore(deps): Bump axios from 1.12.0 to 1.13.5 (#13390) Bumps [axios](https://github.com/axios/axios) from 1.12.0 to 1.13.5. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.12.0...v1.13.5) --- updated-dependencies: - dependency-name: axios dependency-version: 1.13.5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> --- packages/api-v4/package.json | 2 +- packages/manager/package.json | 2 +- pnpm-lock.yaml | 655 ++++++++++++++++++---------------- 3 files changed, 352 insertions(+), 307 deletions(-) diff --git a/packages/api-v4/package.json b/packages/api-v4/package.json index bb258733a35..a16901f1527 100644 --- a/packages/api-v4/package.json +++ b/packages/api-v4/package.json @@ -41,7 +41,7 @@ "unpkg": "./lib/index.global.js", "dependencies": { "@linode/validation": "workspace:*", - "axios": "~1.12.0", + "axios": "~1.13.5", "ipaddr.js": "^2.0.0", "yup": "^1.4.0" }, diff --git a/packages/manager/package.json b/packages/manager/package.json index af5d2a71767..8daf4a383d9 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -47,7 +47,7 @@ "@xterm/xterm": "^5.5.0", "akamai-cds-react-components": "0.1.0", "algoliasearch": "^4.14.3", - "axios": "~1.12.0", + "axios": "~1.13.5", "braintree-web": "^3.92.2", "chart.js": "~2.9.4", "copy-to-clipboard": "^3.0.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d86446c627a..a5a58cecc54 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -94,8 +94,8 @@ importers: specifier: workspace:* version: link:../validation axios: - specifier: ~1.12.0 - version: 1.12.0 + specifier: ~1.13.5 + version: 1.13.5 ipaddr.js: specifier: ^2.0.0 version: 2.2.0 @@ -111,7 +111,7 @@ importers: version: 22.18.1 axios-mock-adapter: specifier: ^1.22.0 - version: 1.22.0(axios@1.12.0) + version: 1.22.0(axios@1.13.5) concurrently: specifier: ^9.0.1 version: 9.1.0 @@ -221,8 +221,8 @@ importers: specifier: ^4.14.3 version: 4.24.0 axios: - specifier: ~1.12.0 - version: 1.12.0 + specifier: ~1.13.5 + version: 1.13.5 braintree-web: specifier: ^3.92.2 version: 3.112.1 @@ -361,7 +361,7 @@ importers: version: 9.1.17(@types/react@19.1.6)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))) '@storybook/react-vite': specifier: ^9.1.17 - version: 9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.53.5)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@swc/core': specifier: ^1.10.9 version: 1.10.11 @@ -445,7 +445,7 @@ importers: version: 4.0.1(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@vitest/coverage-v8': specifier: ^3.2.4 - version: 3.2.4(vitest@4.0.16(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 3.2.4(vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@vueless/storybook-dark-mode': specifier: ^9.0.5 version: 9.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -523,7 +523,7 @@ importers: version: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) vite-plugin-svgr: specifier: ^4.5.0 - version: 4.5.0(rollup@4.53.5)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) packages/queries: dependencies: @@ -607,7 +607,7 @@ importers: version: link:../tsconfig '@storybook/react-vite': specifier: ^9.0.12 - version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.53.5)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@testing-library/dom': specifier: ^10.1.0 version: 10.4.0 @@ -628,10 +628,10 @@ importers: version: 19.1.6(@types/react@19.1.6) storybook: specifier: ^9.1.17 - version: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) vite-plugin-svgr: specifier: ^4.5.0 - version: 4.5.0(rollup@4.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) packages/tsconfig: {} @@ -676,7 +676,7 @@ importers: version: link:../tsconfig '@storybook/react-vite': specifier: ^9.0.12 - version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.53.5)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@testing-library/dom': specifier: ^10.1.0 version: 10.4.0 @@ -700,10 +700,10 @@ importers: version: 19.1.6(@types/react@19.1.6) storybook: specifier: ^9.1.17 - version: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) vite-plugin-svgr: specifier: ^4.5.0 - version: 4.5.0(rollup@4.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) packages/utilities: dependencies: @@ -1074,8 +1074,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -1092,8 +1092,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -1110,8 +1110,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -1128,8 +1128,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -1146,8 +1146,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -1164,8 +1164,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -1182,8 +1182,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -1200,8 +1200,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -1218,8 +1218,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -1236,8 +1236,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -1254,8 +1254,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -1272,8 +1272,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -1290,8 +1290,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -1308,8 +1308,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -1326,8 +1326,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -1344,8 +1344,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -1362,8 +1362,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -1380,8 +1380,8 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -1398,8 +1398,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -1416,8 +1416,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -1434,8 +1434,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -1446,8 +1446,8 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -1464,8 +1464,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -1482,8 +1482,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -1500,8 +1500,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1518,8 +1518,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -2120,8 +2120,8 @@ packages: cpu: [arm] os: [android] - '@rollup/rollup-android-arm-eabi@4.53.5': - resolution: {integrity: sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==} + '@rollup/rollup-android-arm-eabi@4.57.1': + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} cpu: [arm] os: [android] @@ -2135,8 +2135,8 @@ packages: cpu: [arm64] os: [android] - '@rollup/rollup-android-arm64@4.53.5': - resolution: {integrity: sha512-wrSAViWvZHBMMlWk6EJhvg8/rjxzyEhEdgfMMjREHEq11EtJ6IP6yfcCH57YAEca2Oe3FNCE9DSTgU70EIGmVw==} + '@rollup/rollup-android-arm64@4.57.1': + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} cpu: [arm64] os: [android] @@ -2150,8 +2150,8 @@ packages: cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-arm64@4.53.5': - resolution: {integrity: sha512-S87zZPBmRO6u1YXQLwpveZm4JfPpAa6oHBX7/ghSiGH3rz/KDgAu1rKdGutV+WUI6tKDMbaBJomhnT30Y2t4VQ==} + '@rollup/rollup-darwin-arm64@4.57.1': + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} cpu: [arm64] os: [darwin] @@ -2165,8 +2165,8 @@ packages: cpu: [x64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.5': - resolution: {integrity: sha512-YTbnsAaHo6VrAczISxgpTva8EkfQus0VPEVJCEaboHtZRIb6h6j0BNxRBOwnDciFTZLDPW5r+ZBmhL/+YpTZgA==} + '@rollup/rollup-darwin-x64@4.57.1': + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} cpu: [x64] os: [darwin] @@ -2180,8 +2180,8 @@ packages: cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-arm64@4.53.5': - resolution: {integrity: sha512-1T8eY2J8rKJWzaznV7zedfdhD1BqVs1iqILhmHDq/bqCUZsrMt+j8VCTHhP0vdfbHK3e1IQ7VYx3jlKqwlf+vw==} + '@rollup/rollup-freebsd-arm64@4.57.1': + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} cpu: [arm64] os: [freebsd] @@ -2195,8 +2195,8 @@ packages: cpu: [x64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.5': - resolution: {integrity: sha512-sHTiuXyBJApxRn+VFMaw1U+Qsz4kcNlxQ742snICYPrY+DDL8/ZbaC4DVIB7vgZmp3jiDaKA0WpBdP0aqPJoBQ==} + '@rollup/rollup-freebsd-x64@4.57.1': + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} cpu: [x64] os: [freebsd] @@ -2210,8 +2210,8 @@ packages: cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-gnueabihf@4.53.5': - resolution: {integrity: sha512-dV3T9MyAf0w8zPVLVBptVlzaXxka6xg1f16VAQmjg+4KMSTWDvhimI/Y6mp8oHwNrmnmVl9XxJ/w/mO4uIQONA==} + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} cpu: [arm] os: [linux] @@ -2225,8 +2225,8 @@ packages: cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.5': - resolution: {integrity: sha512-wIGYC1x/hyjP+KAu9+ewDI+fi5XSNiUi9Bvg6KGAh2TsNMA3tSEs+Sh6jJ/r4BV/bx/CyWu2ue9kDnIdRyafcQ==} + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} cpu: [arm] os: [linux] @@ -2240,8 +2240,8 @@ packages: cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.5': - resolution: {integrity: sha512-Y+qVA0D9d0y2FRNiG9oM3Hut/DgODZbU9I8pLLPwAsU0tUKZ49cyV1tzmB/qRbSzGvY8lpgGkJuMyuhH7Ma+Vg==} + '@rollup/rollup-linux-arm64-gnu@4.57.1': + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} cpu: [arm64] os: [linux] @@ -2255,8 +2255,8 @@ packages: cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.5': - resolution: {integrity: sha512-juaC4bEgJsyFVfqhtGLz8mbopaWD+WeSOYr5E16y+1of6KQjc0BpwZLuxkClqY1i8sco+MdyoXPNiCkQou09+g==} + '@rollup/rollup-linux-arm64-musl@4.57.1': + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} cpu: [arm64] os: [linux] @@ -2265,8 +2265,13 @@ packages: cpu: [loong64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.5': - resolution: {integrity: sha512-rIEC0hZ17A42iXtHX+EPJVL/CakHo+tT7W0pbzdAGuWOt2jxDFh7A/lRhsNHBcqL4T36+UiAgwO8pbmn3dE8wA==} + '@rollup/rollup-linux-loong64-gnu@4.57.1': + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.57.1': + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} cpu: [loong64] os: [linux] @@ -2285,8 +2290,13 @@ packages: cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.5': - resolution: {integrity: sha512-T7l409NhUE552RcAOcmJHj3xyZ2h7vMWzcwQI0hvn5tqHh3oSoclf9WgTl+0QqffWFG8MEVZZP1/OBglKZx52Q==} + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] @@ -2300,8 +2310,8 @@ packages: cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.5': - resolution: {integrity: sha512-7OK5/GhxbnrMcxIFoYfhV/TkknarkYC1hqUw1wU2xUN3TVRLNT5FmBv4KkheSG2xZ6IEbRAhTooTV2+R5Tk0lQ==} + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} cpu: [riscv64] os: [linux] @@ -2315,8 +2325,8 @@ packages: cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.5': - resolution: {integrity: sha512-GwuDBE/PsXaTa76lO5eLJTyr2k8QkPipAyOrs4V/KJufHCZBJ495VCGJol35grx9xryk4V+2zd3Ri+3v7NPh+w==} + '@rollup/rollup-linux-riscv64-musl@4.57.1': + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} cpu: [riscv64] os: [linux] @@ -2330,8 +2340,8 @@ packages: cpu: [s390x] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.5': - resolution: {integrity: sha512-IAE1Ziyr1qNfnmiQLHBURAD+eh/zH1pIeJjeShleII7Vj8kyEm2PF77o+lf3WTHDpNJcu4IXJxNO0Zluro8bOw==} + '@rollup/rollup-linux-s390x-gnu@4.57.1': + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} cpu: [s390x] os: [linux] @@ -2345,8 +2355,8 @@ packages: cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.5': - resolution: {integrity: sha512-Pg6E+oP7GvZ4XwgRJBuSXZjcqpIW3yCBhK4BcsANvb47qMvAbCjR6E+1a/U2WXz1JJxp9/4Dno3/iSJLcm5auw==} + '@rollup/rollup-linux-x64-gnu@4.57.1': + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} cpu: [x64] os: [linux] @@ -2360,18 +2370,23 @@ packages: cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.5': - resolution: {integrity: sha512-txGtluxDKTxaMDzUduGP0wdfng24y1rygUMnmlUJ88fzCCULCLn7oE5kb2+tRB+MWq1QDZT6ObT5RrR8HFRKqg==} + '@rollup/rollup-linux-x64-musl@4.57.1': + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} cpu: [x64] os: [linux] + '@rollup/rollup-openbsd-x64@4.57.1': + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + cpu: [x64] + os: [openbsd] + '@rollup/rollup-openharmony-arm64@4.53.3': resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-openharmony-arm64@4.53.5': - resolution: {integrity: sha512-3DFiLPnTxiOQV993fMc+KO8zXHTcIjgaInrqlG8zDp1TlhYl6WgrOHuJkJQ6M8zHEcntSJsUp1XFZSY8C1DYbg==} + '@rollup/rollup-openharmony-arm64@4.57.1': + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} cpu: [arm64] os: [openharmony] @@ -2385,8 +2400,8 @@ packages: cpu: [arm64] os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.53.5': - resolution: {integrity: sha512-nggc/wPpNTgjGg75hu+Q/3i32R00Lq1B6N1DO7MCU340MRKL3WZJMjA9U4K4gzy3dkZPXm9E1Nc81FItBVGRlA==} + '@rollup/rollup-win32-arm64-msvc@4.57.1': + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} cpu: [arm64] os: [win32] @@ -2400,8 +2415,8 @@ packages: cpu: [ia32] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.5': - resolution: {integrity: sha512-U/54pTbdQpPLBdEzCT6NBCFAfSZMvmjr0twhnD9f4EIvlm9wy3jjQ38yQj1AGznrNO65EWQMgm/QUjuIVrYF9w==} + '@rollup/rollup-win32-ia32-msvc@4.57.1': + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} cpu: [ia32] os: [win32] @@ -2410,8 +2425,8 @@ packages: cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.5': - resolution: {integrity: sha512-2NqKgZSuLH9SXBBV2dWNRCZmocgSOx8OJSdpRaEcRlIfX8YrKxUT6z0F1NpvDVhOsl190UFTRh2F2WDWWCYp3A==} + '@rollup/rollup-win32-x64-gnu@4.57.1': + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} cpu: [x64] os: [win32] @@ -2425,8 +2440,8 @@ packages: cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.5': - resolution: {integrity: sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ==} + '@rollup/rollup-win32-x64-msvc@4.57.1': + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} cpu: [x64] os: [win32] @@ -3227,8 +3242,8 @@ packages: '@vitest/expect@4.0.10': resolution: {integrity: sha512-3QkTX/lK39FBNwARCQRSQr0TP9+ywSdxSX+LgbJ2M1WmveXP72anTbnp2yl5fH+dU6SUmBzNMrDHs80G8G2DZg==} - '@vitest/expect@4.0.16': - resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==} + '@vitest/expect@4.0.18': + resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} '@vitest/mocker@3.2.4': resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} @@ -3252,8 +3267,8 @@ packages: vite: optional: true - '@vitest/mocker@4.0.16': - resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==} + '@vitest/mocker@4.0.18': + resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0-0 @@ -3269,20 +3284,20 @@ packages: '@vitest/pretty-format@4.0.10': resolution: {integrity: sha512-99EQbpa/zuDnvVjthwz5bH9o8iPefoQZ63WV8+bsRJZNw3qQSvSltfut8yu1Jc9mqOYi7pEbsKxYTi/rjaq6PA==} - '@vitest/pretty-format@4.0.16': - resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==} + '@vitest/pretty-format@4.0.18': + resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} '@vitest/runner@4.0.10': resolution: {integrity: sha512-EXU2iSkKvNwtlL8L8doCpkyclw0mc/t4t9SeOnfOFPyqLmQwuceMPA4zJBa6jw0MKsZYbw7kAn+gl7HxrlB8UQ==} - '@vitest/runner@4.0.16': - resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==} + '@vitest/runner@4.0.18': + resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} '@vitest/snapshot@4.0.10': resolution: {integrity: sha512-2N4X2ZZl7kZw0qeGdQ41H0KND96L3qX1RgwuCfy6oUsF2ISGD/HpSbmms+CkIOsQmg2kulwfhJ4CI0asnZlvkg==} - '@vitest/snapshot@4.0.16': - resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==} + '@vitest/snapshot@4.0.18': + resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} '@vitest/spy@3.2.4': resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} @@ -3290,8 +3305,8 @@ packages: '@vitest/spy@4.0.10': resolution: {integrity: sha512-AsY6sVS8OLb96GV5RoG8B6I35GAbNrC49AO+jNRF9YVGb/g9t+hzNm1H6kD0NDp8tt7VJLs6hb7YMkDXqu03iw==} - '@vitest/spy@4.0.16': - resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==} + '@vitest/spy@4.0.18': + resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} '@vitest/ui@4.0.10': resolution: {integrity: sha512-oWtNM89Np+YsQO3ttT5i1Aer/0xbzQzp66NzuJn/U16bB7MnvSzdLKXgk1kkMLYyKSSzA2ajzqMkYheaE9opuQ==} @@ -3304,8 +3319,8 @@ packages: '@vitest/utils@4.0.10': resolution: {integrity: sha512-kOuqWnEwZNtQxMKg3WmPK1vmhZu9WcoX69iwWjVz+jvKTsF1emzsv3eoPcDr6ykA3qP2bsCQE7CwqfNtAVzsmg==} - '@vitest/utils@4.0.16': - resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} + '@vitest/utils@4.0.18': + resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} '@vueless/storybook-dark-mode@9.0.5': resolution: {integrity: sha512-JU0bQe+KHvmg04k2yprzVkM0d8xdKwqFaFuQmO7afIUm//ttroDpfHfPzwLZuTDW9coB5bt2+qMSHZOBbt0w4g==} @@ -3489,8 +3504,8 @@ packages: peerDependencies: axios: '>= 0.17.0' - axios@1.12.0: - resolution: {integrity: sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==} + axios@1.13.5: + resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -4070,6 +4085,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + diff@5.2.2: + resolution: {integrity: sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==} + engines: {node: '>=0.3.1'} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -4193,8 +4212,8 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} engines: {node: '>=18'} hasBin: true @@ -4508,6 +4527,10 @@ packages: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + formik@2.1.7: resolution: {integrity: sha512-n1wviIh0JsvHqj9PufNvOV+fS7mFwh9FfMxxTMnTrKR/uVYMS06DKaivXBlJdDF0qEwTcPHxSmIQ3deFHL3Hsg==} peerDependencies: @@ -6027,8 +6050,8 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rollup@4.53.5: - resolution: {integrity: sha512-iTNAbFSlRpcHeeWu73ywU/8KuU/LZmNCSxp6fjQkJBD3ivUb8tpDrXhIxEzA05HlYMEwmtaUnb3RP+YNv162OQ==} + rollup@4.57.1: + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -6755,8 +6778,8 @@ packages: yaml: optional: true - vite@7.3.0: - resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==} + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -6829,18 +6852,18 @@ packages: jsdom: optional: true - vitest@4.0.16: - resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==} + vitest@4.0.18: + resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.16 - '@vitest/browser-preview': 4.0.16 - '@vitest/browser-webdriverio': 4.0.16 - '@vitest/ui': 4.0.16 + '@vitest/browser-playwright': 4.0.18 + '@vitest/browser-preview': 4.0.18 + '@vitest/browser-webdriverio': 4.0.18 + '@vitest/ui': 4.0.18 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -7297,7 +7320,7 @@ snapshots: combined-stream: 1.0.8 extend: 3.0.2 forever-agent: 0.6.1 - form-data: 4.0.4 + form-data: 4.0.5 http-signature: 1.4.0 is-typedarray: 1.0.0 isstream: 0.1.2 @@ -7431,7 +7454,7 @@ snapshots: '@esbuild/aix-ppc64@0.25.3': optional: true - '@esbuild/aix-ppc64@0.27.2': + '@esbuild/aix-ppc64@0.27.3': optional: true '@esbuild/android-arm64@0.25.12': @@ -7440,7 +7463,7 @@ snapshots: '@esbuild/android-arm64@0.25.3': optional: true - '@esbuild/android-arm64@0.27.2': + '@esbuild/android-arm64@0.27.3': optional: true '@esbuild/android-arm@0.25.12': @@ -7449,7 +7472,7 @@ snapshots: '@esbuild/android-arm@0.25.3': optional: true - '@esbuild/android-arm@0.27.2': + '@esbuild/android-arm@0.27.3': optional: true '@esbuild/android-x64@0.25.12': @@ -7458,7 +7481,7 @@ snapshots: '@esbuild/android-x64@0.25.3': optional: true - '@esbuild/android-x64@0.27.2': + '@esbuild/android-x64@0.27.3': optional: true '@esbuild/darwin-arm64@0.25.12': @@ -7467,7 +7490,7 @@ snapshots: '@esbuild/darwin-arm64@0.25.3': optional: true - '@esbuild/darwin-arm64@0.27.2': + '@esbuild/darwin-arm64@0.27.3': optional: true '@esbuild/darwin-x64@0.25.12': @@ -7476,7 +7499,7 @@ snapshots: '@esbuild/darwin-x64@0.25.3': optional: true - '@esbuild/darwin-x64@0.27.2': + '@esbuild/darwin-x64@0.27.3': optional: true '@esbuild/freebsd-arm64@0.25.12': @@ -7485,7 +7508,7 @@ snapshots: '@esbuild/freebsd-arm64@0.25.3': optional: true - '@esbuild/freebsd-arm64@0.27.2': + '@esbuild/freebsd-arm64@0.27.3': optional: true '@esbuild/freebsd-x64@0.25.12': @@ -7494,7 +7517,7 @@ snapshots: '@esbuild/freebsd-x64@0.25.3': optional: true - '@esbuild/freebsd-x64@0.27.2': + '@esbuild/freebsd-x64@0.27.3': optional: true '@esbuild/linux-arm64@0.25.12': @@ -7503,7 +7526,7 @@ snapshots: '@esbuild/linux-arm64@0.25.3': optional: true - '@esbuild/linux-arm64@0.27.2': + '@esbuild/linux-arm64@0.27.3': optional: true '@esbuild/linux-arm@0.25.12': @@ -7512,7 +7535,7 @@ snapshots: '@esbuild/linux-arm@0.25.3': optional: true - '@esbuild/linux-arm@0.27.2': + '@esbuild/linux-arm@0.27.3': optional: true '@esbuild/linux-ia32@0.25.12': @@ -7521,7 +7544,7 @@ snapshots: '@esbuild/linux-ia32@0.25.3': optional: true - '@esbuild/linux-ia32@0.27.2': + '@esbuild/linux-ia32@0.27.3': optional: true '@esbuild/linux-loong64@0.25.12': @@ -7530,7 +7553,7 @@ snapshots: '@esbuild/linux-loong64@0.25.3': optional: true - '@esbuild/linux-loong64@0.27.2': + '@esbuild/linux-loong64@0.27.3': optional: true '@esbuild/linux-mips64el@0.25.12': @@ -7539,7 +7562,7 @@ snapshots: '@esbuild/linux-mips64el@0.25.3': optional: true - '@esbuild/linux-mips64el@0.27.2': + '@esbuild/linux-mips64el@0.27.3': optional: true '@esbuild/linux-ppc64@0.25.12': @@ -7548,7 +7571,7 @@ snapshots: '@esbuild/linux-ppc64@0.25.3': optional: true - '@esbuild/linux-ppc64@0.27.2': + '@esbuild/linux-ppc64@0.27.3': optional: true '@esbuild/linux-riscv64@0.25.12': @@ -7557,7 +7580,7 @@ snapshots: '@esbuild/linux-riscv64@0.25.3': optional: true - '@esbuild/linux-riscv64@0.27.2': + '@esbuild/linux-riscv64@0.27.3': optional: true '@esbuild/linux-s390x@0.25.12': @@ -7566,7 +7589,7 @@ snapshots: '@esbuild/linux-s390x@0.25.3': optional: true - '@esbuild/linux-s390x@0.27.2': + '@esbuild/linux-s390x@0.27.3': optional: true '@esbuild/linux-x64@0.25.12': @@ -7575,7 +7598,7 @@ snapshots: '@esbuild/linux-x64@0.25.3': optional: true - '@esbuild/linux-x64@0.27.2': + '@esbuild/linux-x64@0.27.3': optional: true '@esbuild/netbsd-arm64@0.25.12': @@ -7584,7 +7607,7 @@ snapshots: '@esbuild/netbsd-arm64@0.25.3': optional: true - '@esbuild/netbsd-arm64@0.27.2': + '@esbuild/netbsd-arm64@0.27.3': optional: true '@esbuild/netbsd-x64@0.25.12': @@ -7593,7 +7616,7 @@ snapshots: '@esbuild/netbsd-x64@0.25.3': optional: true - '@esbuild/netbsd-x64@0.27.2': + '@esbuild/netbsd-x64@0.27.3': optional: true '@esbuild/openbsd-arm64@0.25.12': @@ -7602,7 +7625,7 @@ snapshots: '@esbuild/openbsd-arm64@0.25.3': optional: true - '@esbuild/openbsd-arm64@0.27.2': + '@esbuild/openbsd-arm64@0.27.3': optional: true '@esbuild/openbsd-x64@0.25.12': @@ -7611,13 +7634,13 @@ snapshots: '@esbuild/openbsd-x64@0.25.3': optional: true - '@esbuild/openbsd-x64@0.27.2': + '@esbuild/openbsd-x64@0.27.3': optional: true '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.27.2': + '@esbuild/openharmony-arm64@0.27.3': optional: true '@esbuild/sunos-x64@0.25.12': @@ -7626,7 +7649,7 @@ snapshots: '@esbuild/sunos-x64@0.25.3': optional: true - '@esbuild/sunos-x64@0.27.2': + '@esbuild/sunos-x64@0.27.3': optional: true '@esbuild/win32-arm64@0.25.12': @@ -7635,7 +7658,7 @@ snapshots: '@esbuild/win32-arm64@0.25.3': optional: true - '@esbuild/win32-arm64@0.27.2': + '@esbuild/win32-arm64@0.27.3': optional: true '@esbuild/win32-ia32@0.25.12': @@ -7644,7 +7667,7 @@ snapshots: '@esbuild/win32-ia32@0.25.3': optional: true - '@esbuild/win32-ia32@0.27.2': + '@esbuild/win32-ia32@0.27.3': optional: true '@esbuild/win32-x64@0.25.12': @@ -7653,7 +7676,7 @@ snapshots: '@esbuild/win32-x64@0.25.3': optional: true - '@esbuild/win32-x64@0.27.2': + '@esbuild/win32-x64@0.27.3': optional: true '@eslint-community/eslint-utils@4.4.1(eslint@9.31.0(jiti@2.4.2))': @@ -7888,12 +7911,12 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@joshwooding/vite-plugin-react-docgen-typescript@0.6.0(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: glob: 10.5.0 magic-string: 0.30.17 react-docgen-typescript: 2.2.2(typescript@5.9.3) - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) optionalDependencies: typescript: 5.9.3 @@ -8211,21 +8234,21 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.32': {} - '@rollup/pluginutils@5.1.3(rollup@4.53.5)': + '@rollup/pluginutils@5.1.3(rollup@4.57.1)': dependencies: '@types/estree': 1.0.7 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.53.5 + rollup: 4.57.1 - '@rollup/pluginutils@5.2.0(rollup@4.53.5)': + '@rollup/pluginutils@5.2.0(rollup@4.57.1)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.53.5 + rollup: 4.57.1 '@rollup/rollup-android-arm-eabi@4.40.1': optional: true @@ -8233,7 +8256,7 @@ snapshots: '@rollup/rollup-android-arm-eabi@4.53.3': optional: true - '@rollup/rollup-android-arm-eabi@4.53.5': + '@rollup/rollup-android-arm-eabi@4.57.1': optional: true '@rollup/rollup-android-arm64@4.40.1': @@ -8242,7 +8265,7 @@ snapshots: '@rollup/rollup-android-arm64@4.53.3': optional: true - '@rollup/rollup-android-arm64@4.53.5': + '@rollup/rollup-android-arm64@4.57.1': optional: true '@rollup/rollup-darwin-arm64@4.40.1': @@ -8251,7 +8274,7 @@ snapshots: '@rollup/rollup-darwin-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-arm64@4.53.5': + '@rollup/rollup-darwin-arm64@4.57.1': optional: true '@rollup/rollup-darwin-x64@4.40.1': @@ -8260,7 +8283,7 @@ snapshots: '@rollup/rollup-darwin-x64@4.53.3': optional: true - '@rollup/rollup-darwin-x64@4.53.5': + '@rollup/rollup-darwin-x64@4.57.1': optional: true '@rollup/rollup-freebsd-arm64@4.40.1': @@ -8269,7 +8292,7 @@ snapshots: '@rollup/rollup-freebsd-arm64@4.53.3': optional: true - '@rollup/rollup-freebsd-arm64@4.53.5': + '@rollup/rollup-freebsd-arm64@4.57.1': optional: true '@rollup/rollup-freebsd-x64@4.40.1': @@ -8278,7 +8301,7 @@ snapshots: '@rollup/rollup-freebsd-x64@4.53.3': optional: true - '@rollup/rollup-freebsd-x64@4.53.5': + '@rollup/rollup-freebsd-x64@4.57.1': optional: true '@rollup/rollup-linux-arm-gnueabihf@4.40.1': @@ -8287,7 +8310,7 @@ snapshots: '@rollup/rollup-linux-arm-gnueabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.5': + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': optional: true '@rollup/rollup-linux-arm-musleabihf@4.40.1': @@ -8296,7 +8319,7 @@ snapshots: '@rollup/rollup-linux-arm-musleabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.5': + '@rollup/rollup-linux-arm-musleabihf@4.57.1': optional: true '@rollup/rollup-linux-arm64-gnu@4.40.1': @@ -8305,7 +8328,7 @@ snapshots: '@rollup/rollup-linux-arm64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.5': + '@rollup/rollup-linux-arm64-gnu@4.57.1': optional: true '@rollup/rollup-linux-arm64-musl@4.40.1': @@ -8314,13 +8337,16 @@ snapshots: '@rollup/rollup-linux-arm64-musl@4.53.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.5': + '@rollup/rollup-linux-arm64-musl@4.57.1': optional: true '@rollup/rollup-linux-loong64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.5': + '@rollup/rollup-linux-loong64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.57.1': optional: true '@rollup/rollup-linux-loongarch64-gnu@4.40.1': @@ -8332,7 +8358,10 @@ snapshots: '@rollup/rollup-linux-ppc64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.5': + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.57.1': optional: true '@rollup/rollup-linux-riscv64-gnu@4.40.1': @@ -8341,7 +8370,7 @@ snapshots: '@rollup/rollup-linux-riscv64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.5': + '@rollup/rollup-linux-riscv64-gnu@4.57.1': optional: true '@rollup/rollup-linux-riscv64-musl@4.40.1': @@ -8350,7 +8379,7 @@ snapshots: '@rollup/rollup-linux-riscv64-musl@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.5': + '@rollup/rollup-linux-riscv64-musl@4.57.1': optional: true '@rollup/rollup-linux-s390x-gnu@4.40.1': @@ -8359,7 +8388,7 @@ snapshots: '@rollup/rollup-linux-s390x-gnu@4.53.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.5': + '@rollup/rollup-linux-s390x-gnu@4.57.1': optional: true '@rollup/rollup-linux-x64-gnu@4.40.1': @@ -8368,7 +8397,7 @@ snapshots: '@rollup/rollup-linux-x64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.5': + '@rollup/rollup-linux-x64-gnu@4.57.1': optional: true '@rollup/rollup-linux-x64-musl@4.40.1': @@ -8377,13 +8406,16 @@ snapshots: '@rollup/rollup-linux-x64-musl@4.53.3': optional: true - '@rollup/rollup-linux-x64-musl@4.53.5': + '@rollup/rollup-linux-x64-musl@4.57.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.57.1': optional: true '@rollup/rollup-openharmony-arm64@4.53.3': optional: true - '@rollup/rollup-openharmony-arm64@4.53.5': + '@rollup/rollup-openharmony-arm64@4.57.1': optional: true '@rollup/rollup-win32-arm64-msvc@4.40.1': @@ -8392,7 +8424,7 @@ snapshots: '@rollup/rollup-win32-arm64-msvc@4.53.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.5': + '@rollup/rollup-win32-arm64-msvc@4.57.1': optional: true '@rollup/rollup-win32-ia32-msvc@4.40.1': @@ -8401,13 +8433,13 @@ snapshots: '@rollup/rollup-win32-ia32-msvc@4.53.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.5': + '@rollup/rollup-win32-ia32-msvc@4.57.1': optional: true '@rollup/rollup-win32-x64-gnu@4.53.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.5': + '@rollup/rollup-win32-x64-gnu@4.57.1': optional: true '@rollup/rollup-win32-x64-msvc@4.40.1': @@ -8416,7 +8448,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.5': + '@rollup/rollup-win32-x64-msvc@4.57.1': optional: true '@sentry-internal/browser-utils@9.19.0': @@ -8510,12 +8542,12 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@storybook/builder-vite@9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@storybook/builder-vite@9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: - '@storybook/csf-plugin': 9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))) - storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + '@storybook/csf-plugin': 9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))) + storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) ts-dedent: 2.2.0 - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) '@storybook/builder-vite@9.1.17(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: @@ -8524,9 +8556,9 @@ snapshots: ts-dedent: 2.2.0 vite: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) - '@storybook/csf-plugin@9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))': + '@storybook/csf-plugin@9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))': dependencies: - storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) unplugin: 1.16.0 '@storybook/csf-plugin@9.1.17(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))': @@ -8541,11 +8573,11 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - '@storybook/react-dom-shim@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))': + '@storybook/react-dom-shim@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))': dependencies: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@storybook/react-dom-shim@9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))': dependencies: @@ -8553,30 +8585,30 @@ snapshots: react-dom: 19.1.0(react@19.1.0) storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@storybook/react-vite@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.53.5)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@storybook/react-vite@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.0(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@rollup/pluginutils': 5.1.3(rollup@4.53.5) - '@storybook/builder-vite': 9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@storybook/react': 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + '@rollup/pluginutils': 5.1.3(rollup@4.57.1) + '@storybook/builder-vite': 9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + '@storybook/react': 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3) find-up: 7.0.0 magic-string: 0.30.17 react: 19.1.0 react-docgen: 8.0.0 react-dom: 19.1.0(react@19.1.0) resolve: 1.22.8 - storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) tsconfig-paths: 4.2.0 - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) transitivePeerDependencies: - rollup - supports-color - typescript - '@storybook/react-vite@9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.53.5)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@storybook/react-vite@9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@rollup/pluginutils': 5.2.0(rollup@4.53.5) + '@rollup/pluginutils': 5.2.0(rollup@4.57.1) '@storybook/builder-vite': 9.1.17(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@storybook/react': 9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3) find-up: 7.0.0 @@ -8593,13 +8625,13 @@ snapshots: - supports-color - typescript - '@storybook/react@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)': + '@storybook/react@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)': dependencies: '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))) + '@storybook/react-dom-shim': 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) optionalDependencies: typescript: 5.9.3 @@ -9275,7 +9307,7 @@ snapshots: transitivePeerDependencies: - '@swc/helpers' - '@vitest/coverage-v8@3.2.4(vitest@4.0.16(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@vitest/coverage-v8@3.2.4(vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -9290,7 +9322,7 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 4.0.16(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vitest: 4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -9311,12 +9343,12 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/expect@4.0.16': + '@vitest/expect@4.0.18': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.0.16 - '@vitest/utils': 4.0.16 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 chai: 6.2.1 tinyrainbow: 3.0.3 @@ -9329,14 +9361,14 @@ snapshots: msw: 2.6.5(@types/node@22.18.1)(typescript@5.9.3) vite: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) - '@vitest/mocker@3.2.4(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@vitest/mocker@3.2.4(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.6.5(@types/node@22.18.1)(typescript@5.9.3) - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) '@vitest/mocker@4.0.10(msw@2.6.5(@types/node@22.18.1)(typescript@5.7.3))(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: @@ -9347,14 +9379,14 @@ snapshots: msw: 2.6.5(@types/node@22.18.1)(typescript@5.7.3) vite: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) - '@vitest/mocker@4.0.16(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@vitest/mocker@4.0.18(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: - '@vitest/spy': 4.0.16 + '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.6.5(@types/node@22.18.1)(typescript@5.9.3) - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -9364,7 +9396,7 @@ snapshots: dependencies: tinyrainbow: 3.0.3 - '@vitest/pretty-format@4.0.16': + '@vitest/pretty-format@4.0.18': dependencies: tinyrainbow: 3.0.3 @@ -9373,9 +9405,9 @@ snapshots: '@vitest/utils': 4.0.10 pathe: 2.0.3 - '@vitest/runner@4.0.16': + '@vitest/runner@4.0.18': dependencies: - '@vitest/utils': 4.0.16 + '@vitest/utils': 4.0.18 pathe: 2.0.3 '@vitest/snapshot@4.0.10': @@ -9384,9 +9416,9 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/snapshot@4.0.16': + '@vitest/snapshot@4.0.18': dependencies: - '@vitest/pretty-format': 4.0.16 + '@vitest/pretty-format': 4.0.18 magic-string: 0.30.21 pathe: 2.0.3 @@ -9396,7 +9428,7 @@ snapshots: '@vitest/spy@4.0.10': {} - '@vitest/spy@4.0.16': {} + '@vitest/spy@4.0.18': {} '@vitest/ui@4.0.10(vitest@4.0.10)': dependencies: @@ -9420,9 +9452,9 @@ snapshots: '@vitest/pretty-format': 4.0.10 tinyrainbow: 3.0.3 - '@vitest/utils@4.0.16': + '@vitest/utils@4.0.18': dependencies: - '@vitest/pretty-format': 4.0.16 + '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 '@vueless/storybook-dark-mode@9.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': @@ -9628,16 +9660,16 @@ snapshots: axe-core@4.10.2: {} - axios-mock-adapter@1.22.0(axios@1.12.0): + axios-mock-adapter@1.22.0(axios@1.13.5): dependencies: - axios: 1.12.0 + axios: 1.13.5 fast-deep-equal: 3.1.3 is-buffer: 2.0.5 - axios@1.12.0: + axios@1.13.5: dependencies: follow-redirects: 1.15.11 - form-data: 4.0.4 + form-data: 4.0.5 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug @@ -10240,6 +10272,8 @@ snapshots: diff@5.2.0: {} + diff@5.2.2: {} + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -10477,34 +10511,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.3 '@esbuild/win32-x64': 0.25.3 - esbuild@0.27.2: + esbuild@0.27.3: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 escalade@3.2.0: {} @@ -10866,6 +10900,14 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + formik@2.1.7(react@19.1.0): dependencies: deepmerge: 2.2.1 @@ -11802,7 +11844,7 @@ snapshots: browser-stdout: 1.3.1 chokidar: 3.6.0 debug: 4.4.3(supports-color@8.1.1) - diff: 5.2.0 + diff: 5.2.2 escape-string-regexp: 4.0.0 find-up: 5.0.0 glob: 8.1.0 @@ -12533,32 +12575,35 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 - rollup@4.53.5: + rollup@4.57.1: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.5 - '@rollup/rollup-android-arm64': 4.53.5 - '@rollup/rollup-darwin-arm64': 4.53.5 - '@rollup/rollup-darwin-x64': 4.53.5 - '@rollup/rollup-freebsd-arm64': 4.53.5 - '@rollup/rollup-freebsd-x64': 4.53.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.5 - '@rollup/rollup-linux-arm-musleabihf': 4.53.5 - '@rollup/rollup-linux-arm64-gnu': 4.53.5 - '@rollup/rollup-linux-arm64-musl': 4.53.5 - '@rollup/rollup-linux-loong64-gnu': 4.53.5 - '@rollup/rollup-linux-ppc64-gnu': 4.53.5 - '@rollup/rollup-linux-riscv64-gnu': 4.53.5 - '@rollup/rollup-linux-riscv64-musl': 4.53.5 - '@rollup/rollup-linux-s390x-gnu': 4.53.5 - '@rollup/rollup-linux-x64-gnu': 4.53.5 - '@rollup/rollup-linux-x64-musl': 4.53.5 - '@rollup/rollup-openharmony-arm64': 4.53.5 - '@rollup/rollup-win32-arm64-msvc': 4.53.5 - '@rollup/rollup-win32-ia32-msvc': 4.53.5 - '@rollup/rollup-win32-x64-gnu': 4.53.5 - '@rollup/rollup-win32-x64-msvc': 4.53.5 + '@rollup/rollup-android-arm-eabi': 4.57.1 + '@rollup/rollup-android-arm64': 4.57.1 + '@rollup/rollup-darwin-arm64': 4.57.1 + '@rollup/rollup-darwin-x64': 4.57.1 + '@rollup/rollup-freebsd-arm64': 4.57.1 + '@rollup/rollup-freebsd-x64': 4.57.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 + '@rollup/rollup-linux-arm-musleabihf': 4.57.1 + '@rollup/rollup-linux-arm64-gnu': 4.57.1 + '@rollup/rollup-linux-arm64-musl': 4.57.1 + '@rollup/rollup-linux-loong64-gnu': 4.57.1 + '@rollup/rollup-linux-loong64-musl': 4.57.1 + '@rollup/rollup-linux-ppc64-gnu': 4.57.1 + '@rollup/rollup-linux-ppc64-musl': 4.57.1 + '@rollup/rollup-linux-riscv64-gnu': 4.57.1 + '@rollup/rollup-linux-riscv64-musl': 4.57.1 + '@rollup/rollup-linux-s390x-gnu': 4.57.1 + '@rollup/rollup-linux-x64-gnu': 4.57.1 + '@rollup/rollup-linux-x64-musl': 4.57.1 + '@rollup/rollup-openbsd-x64': 4.57.1 + '@rollup/rollup-openharmony-arm64': 4.57.1 + '@rollup/rollup-win32-arm64-msvc': 4.57.1 + '@rollup/rollup-win32-ia32-msvc': 4.57.1 + '@rollup/rollup-win32-x64-gnu': 4.57.1 + '@rollup/rollup-win32-x64-msvc': 4.57.1 fsevents: 2.3.3 rrweb-cssom@0.7.1: {} @@ -12817,13 +12862,13 @@ snapshots: - utf-8-validate - vite - storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): + storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): dependencies: '@storybook/global': 5.0.0 '@testing-library/jest-dom': 6.9.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + '@vitest/mocker': 3.2.4(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@vitest/spy': 3.2.4 better-opn: 3.0.2 esbuild: 0.25.12 @@ -13338,9 +13383,9 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-svgr@4.5.0(rollup@4.53.5)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): + vite-plugin-svgr@4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.53.5) + '@rollup/pluginutils': 5.2.0(rollup@4.57.1) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) vite: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) @@ -13349,12 +13394,12 @@ snapshots: - supports-color - typescript - vite-plugin-svgr@4.5.0(rollup@4.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): + vite-plugin-svgr@4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.53.5) + '@rollup/pluginutils': 5.2.0(rollup@4.57.1) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) transitivePeerDependencies: - rollup - supports-color @@ -13376,13 +13421,13 @@ snapshots: tsx: 4.19.3 yaml: 2.6.1 - vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1): + vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1): dependencies: - esbuild: 0.27.2 + esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.53.5 + rollup: 4.57.1 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.18.1 @@ -13433,15 +13478,15 @@ snapshots: - tsx - yaml - vitest@4.0.16(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1): + vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1): dependencies: - '@vitest/expect': 4.0.16 - '@vitest/mocker': 4.0.16(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@vitest/pretty-format': 4.0.16 - '@vitest/runner': 4.0.16 - '@vitest/snapshot': 4.0.16 - '@vitest/spy': 4.0.16 - '@vitest/utils': 4.0.16 + '@vitest/expect': 4.0.18 + '@vitest/mocker': 4.0.18(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + '@vitest/pretty-format': 4.0.18 + '@vitest/runner': 4.0.18 + '@vitest/snapshot': 4.0.18 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 es-module-lexer: 1.7.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -13453,7 +13498,7 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.0(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.18.1 From 78654f1a11cce7450238bc9b2af79db7470d5a22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 14:25:16 -0500 Subject: [PATCH 10/56] chore(deps): Bump jspdf from 4.0.0 to 4.2.0 (#13426) Bumps [jspdf](https://github.com/parallax/jsPDF) from 4.0.0 to 4.2.0. - [Release notes](https://github.com/parallax/jsPDF/releases) - [Changelog](https://github.com/parallax/jsPDF/blob/master/RELEASE.md) - [Commits](https://github.com/parallax/jsPDF/compare/v4.0.0...v4.2.0) --- updated-dependencies: - dependency-name: jspdf dependency-version: 4.2.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Co-authored-by: Banks Nussman --- packages/manager/package.json | 2 +- pnpm-lock.yaml | 344 ++++++++++++++++++---------------- 2 files changed, 184 insertions(+), 162 deletions(-) diff --git a/packages/manager/package.json b/packages/manager/package.json index 8daf4a383d9..36bf6439e81 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -59,7 +59,7 @@ "he": "^1.2.0", "immer": "^9.0.6", "ipaddr.js": "^1.9.1", - "jspdf": "^4.0.0", + "jspdf": "^4.2.0", "jspdf-autotable": "^5.0.2", "launchdarkly-react-client-sdk": "3.0.10", "libphonenumber-js": "^1.10.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5a58cecc54..219dcb7701f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -257,11 +257,11 @@ importers: specifier: ^1.9.1 version: 1.9.1 jspdf: - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^4.2.0 + version: 4.2.0 jspdf-autotable: specifier: ^5.0.2 - version: 5.0.2(jspdf@4.0.0) + version: 5.0.2(jspdf@4.2.0) launchdarkly-react-client-sdk: specifier: 3.0.10 version: 3.0.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -361,7 +361,7 @@ importers: version: 9.1.17(@types/react@19.1.6)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))) '@storybook/react-vite': specifier: ^9.1.17 - version: 9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.58.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@swc/core': specifier: ^1.10.9 version: 1.10.11 @@ -445,7 +445,7 @@ importers: version: 4.0.1(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@vitest/coverage-v8': specifier: ^3.2.4 - version: 3.2.4(vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 3.2.4(vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10(vitest@4.0.10))(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@vueless/storybook-dark-mode': specifier: ^9.0.5 version: 9.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -523,7 +523,7 @@ importers: version: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) vite-plugin-svgr: specifier: ^4.5.0 - version: 4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 4.5.0(rollup@4.58.0)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) packages/queries: dependencies: @@ -607,7 +607,7 @@ importers: version: link:../tsconfig '@storybook/react-vite': specifier: ^9.0.12 - version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.58.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@testing-library/dom': specifier: ^10.1.0 version: 10.4.0 @@ -631,7 +631,7 @@ importers: version: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) vite-plugin-svgr: specifier: ^4.5.0 - version: 4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 4.5.0(rollup@4.58.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) packages/tsconfig: {} @@ -676,7 +676,7 @@ importers: version: link:../tsconfig '@storybook/react-vite': specifier: ^9.0.12 - version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.58.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@testing-library/dom': specifier: ^10.1.0 version: 10.4.0 @@ -703,7 +703,7 @@ importers: version: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) vite-plugin-svgr: specifier: ^4.5.0 - version: 4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) + version: 4.5.0(rollup@4.58.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) packages/utilities: dependencies: @@ -918,6 +918,10 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.0': resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} engines: {node: '>=6.9.0'} @@ -2120,8 +2124,8 @@ packages: cpu: [arm] os: [android] - '@rollup/rollup-android-arm-eabi@4.57.1': - resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + '@rollup/rollup-android-arm-eabi@4.58.0': + resolution: {integrity: sha512-mr0tmS/4FoVk1cnaeN244A/wjvGDNItZKR8hRhnmCzygyRXYtKF5jVDSIILR1U97CTzAYmbgIj/Dukg62ggG5w==} cpu: [arm] os: [android] @@ -2135,8 +2139,8 @@ packages: cpu: [arm64] os: [android] - '@rollup/rollup-android-arm64@4.57.1': - resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + '@rollup/rollup-android-arm64@4.58.0': + resolution: {integrity: sha512-+s++dbp+/RTte62mQD9wLSbiMTV+xr/PeRJEc/sFZFSBRlHPNPVaf5FXlzAL77Mr8FtSfQqCN+I598M8U41ccQ==} cpu: [arm64] os: [android] @@ -2150,8 +2154,8 @@ packages: cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-arm64@4.57.1': - resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + '@rollup/rollup-darwin-arm64@4.58.0': + resolution: {integrity: sha512-MFWBwTcYs0jZbINQBXHfSrpSQJq3IUOakcKPzfeSznONop14Pxuqa0Kg19GD0rNBMPQI2tFtu3UzapZpH0Uc1Q==} cpu: [arm64] os: [darwin] @@ -2165,8 +2169,8 @@ packages: cpu: [x64] os: [darwin] - '@rollup/rollup-darwin-x64@4.57.1': - resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + '@rollup/rollup-darwin-x64@4.58.0': + resolution: {integrity: sha512-yiKJY7pj9c9JwzuKYLFaDZw5gma3fI9bkPEIyofvVfsPqjCWPglSHdpdwXpKGvDeYDms3Qal8qGMEHZ1M/4Udg==} cpu: [x64] os: [darwin] @@ -2180,8 +2184,8 @@ packages: cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-arm64@4.57.1': - resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + '@rollup/rollup-freebsd-arm64@4.58.0': + resolution: {integrity: sha512-x97kCoBh5MOevpn/CNK9W1x8BEzO238541BGWBc315uOlN0AD/ifZ1msg+ZQB05Ux+VF6EcYqpiagfLJ8U3LvQ==} cpu: [arm64] os: [freebsd] @@ -2195,8 +2199,8 @@ packages: cpu: [x64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.57.1': - resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + '@rollup/rollup-freebsd-x64@4.58.0': + resolution: {integrity: sha512-Aa8jPoZ6IQAG2eIrcXPpjRcMjROMFxCt1UYPZZtCxRV68WkuSigYtQ/7Zwrcr2IvtNJo7T2JfDXyMLxq5L4Jlg==} cpu: [x64] os: [freebsd] @@ -2210,8 +2214,8 @@ packages: cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': - resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + '@rollup/rollup-linux-arm-gnueabihf@4.58.0': + resolution: {integrity: sha512-Ob8YgT5kD/lSIYW2Rcngs5kNB/44Q2RzBSPz9brf2WEtcGR7/f/E9HeHn1wYaAwKBni+bdXEwgHvUd0x12lQSA==} cpu: [arm] os: [linux] @@ -2225,8 +2229,8 @@ packages: cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.57.1': - resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + '@rollup/rollup-linux-arm-musleabihf@4.58.0': + resolution: {integrity: sha512-K+RI5oP1ceqoadvNt1FecL17Qtw/n9BgRSzxif3rTL2QlIu88ccvY+Y9nnHe/cmT5zbH9+bpiJuG1mGHRVwF4Q==} cpu: [arm] os: [linux] @@ -2240,8 +2244,8 @@ packages: cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.57.1': - resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + '@rollup/rollup-linux-arm64-gnu@4.58.0': + resolution: {integrity: sha512-T+17JAsCKUjmbopcKepJjHWHXSjeW7O5PL7lEFaeQmiVyw4kkc5/lyYKzrv6ElWRX/MrEWfPiJWqbTvfIvjM1Q==} cpu: [arm64] os: [linux] @@ -2255,8 +2259,8 @@ packages: cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.57.1': - resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + '@rollup/rollup-linux-arm64-musl@4.58.0': + resolution: {integrity: sha512-cCePktb9+6R9itIJdeCFF9txPU7pQeEHB5AbHu/MKsfH/k70ZtOeq1k4YAtBv9Z7mmKI5/wOLYjQ+B9QdxR6LA==} cpu: [arm64] os: [linux] @@ -2265,13 +2269,13 @@ packages: cpu: [loong64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.57.1': - resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + '@rollup/rollup-linux-loong64-gnu@4.58.0': + resolution: {integrity: sha512-iekUaLkfliAsDl4/xSdoCJ1gnnIXvoNz85C8U8+ZxknM5pBStfZjeXgB8lXobDQvvPRCN8FPmmuTtH+z95HTmg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-loong64-musl@4.57.1': - resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + '@rollup/rollup-linux-loong64-musl@4.58.0': + resolution: {integrity: sha512-68ofRgJNl/jYJbxFjCKE7IwhbfxOl1muPN4KbIqAIe32lm22KmU7E8OPvyy68HTNkI2iV/c8y2kSPSm2mW/Q9Q==} cpu: [loong64] os: [linux] @@ -2290,13 +2294,13 @@ packages: cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.57.1': - resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + '@rollup/rollup-linux-ppc64-gnu@4.58.0': + resolution: {integrity: sha512-dpz8vT0i+JqUKuSNPCP5SYyIV2Lh0sNL1+FhM7eLC457d5B9/BC3kDPp5BBftMmTNsBarcPcoz5UGSsnCiw4XQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-ppc64-musl@4.57.1': - resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + '@rollup/rollup-linux-ppc64-musl@4.58.0': + resolution: {integrity: sha512-4gdkkf9UJ7tafnweBCR/mk4jf3Jfl0cKX9Np80t5i78kjIH0ZdezUv/JDI2VtruE5lunfACqftJ8dIMGN4oHew==} cpu: [ppc64] os: [linux] @@ -2310,8 +2314,8 @@ packages: cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.57.1': - resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + '@rollup/rollup-linux-riscv64-gnu@4.58.0': + resolution: {integrity: sha512-YFS4vPnOkDTD/JriUeeZurFYoJhPf9GQQEF/v4lltp3mVcBmnsAdjEWhr2cjUCZzZNzxCG0HZOvJU44UGHSdzw==} cpu: [riscv64] os: [linux] @@ -2325,8 +2329,8 @@ packages: cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.57.1': - resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + '@rollup/rollup-linux-riscv64-musl@4.58.0': + resolution: {integrity: sha512-x2xgZlFne+QVNKV8b4wwaCS8pwq3y14zedZ5DqLzjdRITvreBk//4Knbcvm7+lWmms9V9qFp60MtUd0/t/PXPw==} cpu: [riscv64] os: [linux] @@ -2340,8 +2344,8 @@ packages: cpu: [s390x] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.57.1': - resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + '@rollup/rollup-linux-s390x-gnu@4.58.0': + resolution: {integrity: sha512-jIhrujyn4UnWF8S+DHSkAkDEO3hLX0cjzxJZPLF80xFyzyUIYgSMRcYQ3+uqEoyDD2beGq7Dj7edi8OnJcS/hg==} cpu: [s390x] os: [linux] @@ -2355,8 +2359,8 @@ packages: cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.57.1': - resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + '@rollup/rollup-linux-x64-gnu@4.58.0': + resolution: {integrity: sha512-+410Srdoh78MKSJxTQ+hZ/Mx+ajd6RjjPwBPNd0R3J9FtL6ZA0GqiiyNjCO9In0IzZkCNrpGymSfn+kgyPQocg==} cpu: [x64] os: [linux] @@ -2370,13 +2374,13 @@ packages: cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.57.1': - resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + '@rollup/rollup-linux-x64-musl@4.58.0': + resolution: {integrity: sha512-ZjMyby5SICi227y1MTR3VYBpFTdZs823Rs/hpakufleBoufoOIB6jtm9FEoxn/cgO7l6PM2rCEl5Kre5vX0QrQ==} cpu: [x64] os: [linux] - '@rollup/rollup-openbsd-x64@4.57.1': - resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + '@rollup/rollup-openbsd-x64@4.58.0': + resolution: {integrity: sha512-ds4iwfYkSQ0k1nb8LTcyXw//ToHOnNTJtceySpL3fa7tc/AsE+UpUFphW126A6fKBGJD5dhRvg8zw1rvoGFxmw==} cpu: [x64] os: [openbsd] @@ -2385,8 +2389,8 @@ packages: cpu: [arm64] os: [openharmony] - '@rollup/rollup-openharmony-arm64@4.57.1': - resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + '@rollup/rollup-openharmony-arm64@4.58.0': + resolution: {integrity: sha512-fd/zpJniln4ICdPkjWFhZYeY/bpnaN9pGa6ko+5WD38I0tTqk9lXMgXZg09MNdhpARngmxiCg0B0XUamNw/5BQ==} cpu: [arm64] os: [openharmony] @@ -2400,8 +2404,8 @@ packages: cpu: [arm64] os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.57.1': - resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + '@rollup/rollup-win32-arm64-msvc@4.58.0': + resolution: {integrity: sha512-YpG8dUOip7DCz3nr/JUfPbIUo+2d/dy++5bFzgi4ugOGBIox+qMbbqt/JoORwvI/C9Kn2tz6+Bieoqd5+B1CjA==} cpu: [arm64] os: [win32] @@ -2415,8 +2419,8 @@ packages: cpu: [ia32] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.57.1': - resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + '@rollup/rollup-win32-ia32-msvc@4.58.0': + resolution: {integrity: sha512-b9DI8jpFQVh4hIXFr0/+N/TzLdpBIoPzjt0Rt4xJbW3mzguV3mduR9cNgiuFcuL/TeORejJhCWiAXe3E/6PxWA==} cpu: [ia32] os: [win32] @@ -2425,8 +2429,8 @@ packages: cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.57.1': - resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + '@rollup/rollup-win32-x64-gnu@4.58.0': + resolution: {integrity: sha512-CSrVpmoRJFN06LL9xhkitkwUcTZtIotYAF5p6XOR2zW0Zz5mzb3IPpcoPhB02frzMHFNo1reQ9xSF5fFm3hUsQ==} cpu: [x64] os: [win32] @@ -2440,8 +2444,8 @@ packages: cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.57.1': - resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + '@rollup/rollup-win32-x64-msvc@4.58.0': + resolution: {integrity: sha512-QFsBgQNTnh5K0t/sBsjJLq24YVqEIVkGpfN2VHsnN90soZyhaiA9UUHufcctVNL4ypJY0wrwad0wslx2KJQ1/w==} cpu: [x64] os: [win32] @@ -3344,6 +3348,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@7.1.1: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} @@ -3518,9 +3527,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - balanced-match@3.0.1: - resolution: {integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==} - engines: {node: '>= 16'} + balanced-match@4.0.3: + resolution: {integrity: sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==} + engines: {node: 20 || >=22} base64-arraybuffer@1.0.2: resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} @@ -3549,9 +3558,9 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - brace-expansion@4.0.1: - resolution: {integrity: sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==} - engines: {node: '>= 18'} + brace-expansion@5.0.2: + resolution: {integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==} + engines: {node: 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -3830,8 +3839,8 @@ packages: copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} - core-js@3.39.0: - resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} + core-js@3.48.0: + resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==} core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -4109,6 +4118,9 @@ packages: dompurify@3.2.4: resolution: {integrity: sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==} + dompurify@3.3.1: + resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} + dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -5121,8 +5133,8 @@ packages: peerDependencies: jspdf: ^2 || ^3 - jspdf@4.0.0: - resolution: {integrity: sha512-w12U97Z6edKd2tXDn3LzTLg7C7QLJlx0BPfM3ecjK2BckUl9/81vZ+r5gK4/3KQdhAcEZhENUxRhtgYBj75MqQ==} + jspdf@4.2.0: + resolution: {integrity: sha512-hR/hnRevAXXlrjeqU5oahOE+Ln9ORJUB5brLHHqH67A+RBQZuFr5GkbI9XQI8OUFSEezKegsi45QRpc4bGj75Q==} jsprim@2.0.2: resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} @@ -6050,8 +6062,8 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rollup@4.57.1: - resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + rollup@4.58.0: + resolution: {integrity: sha512-wbT0mBmWbIvvq8NeEYWWvevvxnOyhKChir47S66WCxw1SXqhw7ssIYejnQEVt7XYQpsj2y8F9PM+Cr3SNEa0gw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -7250,6 +7262,8 @@ snapshots: '@babel/runtime@7.28.4': {} + '@babel/runtime@7.28.6': {} + '@babel/template@7.27.0': dependencies: '@babel/code-frame': 7.26.2 @@ -8041,7 +8055,7 @@ snapshots: '@mui/private-theming@7.1.0(@types/react@19.1.6)(react@19.1.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/utils': 7.1.0(@types/react@19.1.6)(react@19.1.0) prop-types: 15.8.1 react: 19.1.0 @@ -8050,7 +8064,7 @@ snapshots: '@mui/styled-engine@7.1.0(@emotion/react@11.13.5(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(react@19.1.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@emotion/cache': 11.13.5 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 @@ -8063,7 +8077,7 @@ snapshots: '@mui/system@7.1.0(@emotion/react@11.13.5(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.27.1 '@mui/private-theming': 7.1.0(@types/react@19.1.6)(react@19.1.0) '@mui/styled-engine': 7.1.0(@emotion/react@11.13.5(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(react@19.1.0) '@mui/types': 7.4.2(@types/react@19.1.6) @@ -8079,13 +8093,13 @@ snapshots: '@mui/types@7.4.2(@types/react@19.1.6)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.27.1 optionalDependencies: '@types/react': 19.1.6 '@mui/types@7.4.6(@types/react@19.1.6)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 optionalDependencies: '@types/react': 19.1.6 @@ -8234,21 +8248,21 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.32': {} - '@rollup/pluginutils@5.1.3(rollup@4.57.1)': + '@rollup/pluginutils@5.1.3(rollup@4.58.0)': dependencies: '@types/estree': 1.0.7 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.57.1 + rollup: 4.58.0 - '@rollup/pluginutils@5.2.0(rollup@4.57.1)': + '@rollup/pluginutils@5.2.0(rollup@4.58.0)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.57.1 + rollup: 4.58.0 '@rollup/rollup-android-arm-eabi@4.40.1': optional: true @@ -8256,7 +8270,7 @@ snapshots: '@rollup/rollup-android-arm-eabi@4.53.3': optional: true - '@rollup/rollup-android-arm-eabi@4.57.1': + '@rollup/rollup-android-arm-eabi@4.58.0': optional: true '@rollup/rollup-android-arm64@4.40.1': @@ -8265,7 +8279,7 @@ snapshots: '@rollup/rollup-android-arm64@4.53.3': optional: true - '@rollup/rollup-android-arm64@4.57.1': + '@rollup/rollup-android-arm64@4.58.0': optional: true '@rollup/rollup-darwin-arm64@4.40.1': @@ -8274,7 +8288,7 @@ snapshots: '@rollup/rollup-darwin-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-arm64@4.57.1': + '@rollup/rollup-darwin-arm64@4.58.0': optional: true '@rollup/rollup-darwin-x64@4.40.1': @@ -8283,7 +8297,7 @@ snapshots: '@rollup/rollup-darwin-x64@4.53.3': optional: true - '@rollup/rollup-darwin-x64@4.57.1': + '@rollup/rollup-darwin-x64@4.58.0': optional: true '@rollup/rollup-freebsd-arm64@4.40.1': @@ -8292,7 +8306,7 @@ snapshots: '@rollup/rollup-freebsd-arm64@4.53.3': optional: true - '@rollup/rollup-freebsd-arm64@4.57.1': + '@rollup/rollup-freebsd-arm64@4.58.0': optional: true '@rollup/rollup-freebsd-x64@4.40.1': @@ -8301,7 +8315,7 @@ snapshots: '@rollup/rollup-freebsd-x64@4.53.3': optional: true - '@rollup/rollup-freebsd-x64@4.57.1': + '@rollup/rollup-freebsd-x64@4.58.0': optional: true '@rollup/rollup-linux-arm-gnueabihf@4.40.1': @@ -8310,7 +8324,7 @@ snapshots: '@rollup/rollup-linux-arm-gnueabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + '@rollup/rollup-linux-arm-gnueabihf@4.58.0': optional: true '@rollup/rollup-linux-arm-musleabihf@4.40.1': @@ -8319,7 +8333,7 @@ snapshots: '@rollup/rollup-linux-arm-musleabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.57.1': + '@rollup/rollup-linux-arm-musleabihf@4.58.0': optional: true '@rollup/rollup-linux-arm64-gnu@4.40.1': @@ -8328,7 +8342,7 @@ snapshots: '@rollup/rollup-linux-arm64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.57.1': + '@rollup/rollup-linux-arm64-gnu@4.58.0': optional: true '@rollup/rollup-linux-arm64-musl@4.40.1': @@ -8337,16 +8351,16 @@ snapshots: '@rollup/rollup-linux-arm64-musl@4.53.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.57.1': + '@rollup/rollup-linux-arm64-musl@4.58.0': optional: true '@rollup/rollup-linux-loong64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.57.1': + '@rollup/rollup-linux-loong64-gnu@4.58.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.57.1': + '@rollup/rollup-linux-loong64-musl@4.58.0': optional: true '@rollup/rollup-linux-loongarch64-gnu@4.40.1': @@ -8358,10 +8372,10 @@ snapshots: '@rollup/rollup-linux-ppc64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.57.1': + '@rollup/rollup-linux-ppc64-gnu@4.58.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.57.1': + '@rollup/rollup-linux-ppc64-musl@4.58.0': optional: true '@rollup/rollup-linux-riscv64-gnu@4.40.1': @@ -8370,7 +8384,7 @@ snapshots: '@rollup/rollup-linux-riscv64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.57.1': + '@rollup/rollup-linux-riscv64-gnu@4.58.0': optional: true '@rollup/rollup-linux-riscv64-musl@4.40.1': @@ -8379,7 +8393,7 @@ snapshots: '@rollup/rollup-linux-riscv64-musl@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.57.1': + '@rollup/rollup-linux-riscv64-musl@4.58.0': optional: true '@rollup/rollup-linux-s390x-gnu@4.40.1': @@ -8388,7 +8402,7 @@ snapshots: '@rollup/rollup-linux-s390x-gnu@4.53.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.57.1': + '@rollup/rollup-linux-s390x-gnu@4.58.0': optional: true '@rollup/rollup-linux-x64-gnu@4.40.1': @@ -8397,7 +8411,7 @@ snapshots: '@rollup/rollup-linux-x64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.57.1': + '@rollup/rollup-linux-x64-gnu@4.58.0': optional: true '@rollup/rollup-linux-x64-musl@4.40.1': @@ -8406,16 +8420,16 @@ snapshots: '@rollup/rollup-linux-x64-musl@4.53.3': optional: true - '@rollup/rollup-linux-x64-musl@4.57.1': + '@rollup/rollup-linux-x64-musl@4.58.0': optional: true - '@rollup/rollup-openbsd-x64@4.57.1': + '@rollup/rollup-openbsd-x64@4.58.0': optional: true '@rollup/rollup-openharmony-arm64@4.53.3': optional: true - '@rollup/rollup-openharmony-arm64@4.57.1': + '@rollup/rollup-openharmony-arm64@4.58.0': optional: true '@rollup/rollup-win32-arm64-msvc@4.40.1': @@ -8424,7 +8438,7 @@ snapshots: '@rollup/rollup-win32-arm64-msvc@4.53.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.57.1': + '@rollup/rollup-win32-arm64-msvc@4.58.0': optional: true '@rollup/rollup-win32-ia32-msvc@4.40.1': @@ -8433,13 +8447,13 @@ snapshots: '@rollup/rollup-win32-ia32-msvc@4.53.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.57.1': + '@rollup/rollup-win32-ia32-msvc@4.58.0': optional: true '@rollup/rollup-win32-x64-gnu@4.53.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.57.1': + '@rollup/rollup-win32-x64-gnu@4.58.0': optional: true '@rollup/rollup-win32-x64-msvc@4.40.1': @@ -8448,7 +8462,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.57.1': + '@rollup/rollup-win32-x64-msvc@4.58.0': optional: true '@sentry-internal/browser-utils@9.19.0': @@ -8585,10 +8599,10 @@ snapshots: react-dom: 19.1.0(react@19.1.0) storybook: 9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@storybook/react-vite@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@storybook/react-vite@9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.58.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@rollup/pluginutils': 5.1.3(rollup@4.57.1) + '@rollup/pluginutils': 5.1.3(rollup@4.58.0) '@storybook/builder-vite': 9.0.12(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@storybook/react': 9.0.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3) find-up: 7.0.0 @@ -8605,10 +8619,10 @@ snapshots: - supports-color - typescript - '@storybook/react-vite@9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.57.1)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@storybook/react-vite@9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.58.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) - '@rollup/pluginutils': 5.2.0(rollup@4.57.1) + '@rollup/pluginutils': 5.2.0(rollup@4.58.0) '@storybook/builder-vite': 9.1.17(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) '@storybook/react': 9.1.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.1.17(@testing-library/dom@10.4.0)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(prettier@3.5.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)))(typescript@5.9.3) find-up: 7.0.0 @@ -9307,7 +9321,7 @@ snapshots: transitivePeerDependencies: - '@swc/helpers' - '@vitest/coverage-v8@3.2.4(vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': + '@vitest/coverage-v8@3.2.4(vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10(vitest@4.0.10))(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -9322,7 +9336,7 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) + vitest: 4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10(vitest@4.0.10))(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -9477,6 +9491,9 @@ snapshots: acorn@8.15.0: {} + acorn@8.16.0: + optional: true + agent-base@7.1.1: dependencies: debug: 4.4.0 @@ -9678,13 +9695,13 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 cosmiconfig: 7.1.0 resolve: 1.22.8 balanced-match@1.0.2: {} - balanced-match@3.0.1: {} + balanced-match@4.0.3: {} base64-arraybuffer@1.0.2: optional: true @@ -9709,9 +9726,9 @@ snapshots: dependencies: balanced-match: 1.0.2 - brace-expansion@4.0.1: + brace-expansion@5.0.2: dependencies: - balanced-match: 3.0.1 + balanced-match: 4.0.3 braces@3.0.3: dependencies: @@ -9793,9 +9810,9 @@ snapshots: canvg@3.0.11: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@types/raf': 3.4.3 - core-js: 3.39.0 + core-js: 3.48.0 raf: 3.4.1 regenerator-runtime: 0.13.11 rgbcolor: 1.0.1 @@ -9997,7 +10014,7 @@ snapshots: dependencies: toggle-selection: 1.0.6 - core-js@3.39.0: + core-js@3.48.0: optional: true core-util-is@1.0.2: {} @@ -10288,13 +10305,18 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 csstype: 3.1.3 dompurify@3.2.4: optionalDependencies: '@types/trusted-types': 2.0.7 + dompurify@3.3.1: + optionalDependencies: + '@types/trusted-types': 2.0.7 + optional: true + dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -11502,19 +11524,19 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jspdf-autotable@5.0.2(jspdf@4.0.0): + jspdf-autotable@5.0.2(jspdf@4.2.0): dependencies: - jspdf: 4.0.0 + jspdf: 4.2.0 - jspdf@4.0.0: + jspdf@4.2.0: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 fast-png: 6.4.0 fflate: 0.8.2 optionalDependencies: canvg: 3.0.11 - core-js: 3.39.0 - dompurify: 3.2.4 + core-js: 3.48.0 + dompurify: 3.3.1 html2canvas: 1.4.1 jsprim@2.0.2: @@ -11815,7 +11837,7 @@ snapshots: minimatch@5.1.6: dependencies: - brace-expansion: 4.0.1 + brace-expansion: 5.0.2 minimatch@9.0.5: dependencies: @@ -12353,7 +12375,7 @@ snapshots: react-transition-group@4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.27.1 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -12575,35 +12597,35 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 - rollup@4.57.1: + rollup@4.58.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.57.1 - '@rollup/rollup-android-arm64': 4.57.1 - '@rollup/rollup-darwin-arm64': 4.57.1 - '@rollup/rollup-darwin-x64': 4.57.1 - '@rollup/rollup-freebsd-arm64': 4.57.1 - '@rollup/rollup-freebsd-x64': 4.57.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 - '@rollup/rollup-linux-arm-musleabihf': 4.57.1 - '@rollup/rollup-linux-arm64-gnu': 4.57.1 - '@rollup/rollup-linux-arm64-musl': 4.57.1 - '@rollup/rollup-linux-loong64-gnu': 4.57.1 - '@rollup/rollup-linux-loong64-musl': 4.57.1 - '@rollup/rollup-linux-ppc64-gnu': 4.57.1 - '@rollup/rollup-linux-ppc64-musl': 4.57.1 - '@rollup/rollup-linux-riscv64-gnu': 4.57.1 - '@rollup/rollup-linux-riscv64-musl': 4.57.1 - '@rollup/rollup-linux-s390x-gnu': 4.57.1 - '@rollup/rollup-linux-x64-gnu': 4.57.1 - '@rollup/rollup-linux-x64-musl': 4.57.1 - '@rollup/rollup-openbsd-x64': 4.57.1 - '@rollup/rollup-openharmony-arm64': 4.57.1 - '@rollup/rollup-win32-arm64-msvc': 4.57.1 - '@rollup/rollup-win32-ia32-msvc': 4.57.1 - '@rollup/rollup-win32-x64-gnu': 4.57.1 - '@rollup/rollup-win32-x64-msvc': 4.57.1 + '@rollup/rollup-android-arm-eabi': 4.58.0 + '@rollup/rollup-android-arm64': 4.58.0 + '@rollup/rollup-darwin-arm64': 4.58.0 + '@rollup/rollup-darwin-x64': 4.58.0 + '@rollup/rollup-freebsd-arm64': 4.58.0 + '@rollup/rollup-freebsd-x64': 4.58.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.58.0 + '@rollup/rollup-linux-arm-musleabihf': 4.58.0 + '@rollup/rollup-linux-arm64-gnu': 4.58.0 + '@rollup/rollup-linux-arm64-musl': 4.58.0 + '@rollup/rollup-linux-loong64-gnu': 4.58.0 + '@rollup/rollup-linux-loong64-musl': 4.58.0 + '@rollup/rollup-linux-ppc64-gnu': 4.58.0 + '@rollup/rollup-linux-ppc64-musl': 4.58.0 + '@rollup/rollup-linux-riscv64-gnu': 4.58.0 + '@rollup/rollup-linux-riscv64-musl': 4.58.0 + '@rollup/rollup-linux-s390x-gnu': 4.58.0 + '@rollup/rollup-linux-x64-gnu': 4.58.0 + '@rollup/rollup-linux-x64-musl': 4.58.0 + '@rollup/rollup-openbsd-x64': 4.58.0 + '@rollup/rollup-openharmony-arm64': 4.58.0 + '@rollup/rollup-win32-arm64-msvc': 4.58.0 + '@rollup/rollup-win32-ia32-msvc': 4.58.0 + '@rollup/rollup-win32-x64-gnu': 4.58.0 + '@rollup/rollup-win32-x64-msvc': 4.58.0 fsevents: 2.3.3 rrweb-cssom@0.7.1: {} @@ -13032,7 +13054,7 @@ snapshots: terser@5.36.0: dependencies: '@jridgewell/source-map': 0.3.11 - acorn: 8.15.0 + acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 optional: true @@ -13383,9 +13405,9 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-svgr@4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): + vite-plugin-svgr@4.5.0(rollup@4.58.0)(typescript@5.9.3)(vite@7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.57.1) + '@rollup/pluginutils': 5.2.0(rollup@4.58.0) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) vite: 7.2.2(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) @@ -13394,9 +13416,9 @@ snapshots: - supports-color - typescript - vite-plugin-svgr@4.5.0(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): + vite-plugin-svgr@4.5.0(rollup@4.58.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.57.1) + '@rollup/pluginutils': 5.2.0(rollup@4.58.0) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) vite: 7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) @@ -13427,7 +13449,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.57.1 + rollup: 4.58.0 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.18.1 @@ -13478,7 +13500,7 @@ snapshots: - tsx - yaml - vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1): + vitest@4.0.18(@types/node@22.18.1)(@vitest/ui@4.0.10(vitest@4.0.10))(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1): dependencies: '@vitest/expect': 4.0.18 '@vitest/mocker': 4.0.18(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(vite@7.3.1(@types/node@22.18.1)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1)) From cca81139400ded4ab9a10c8e756dc8904bf3ad94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:26:32 -0500 Subject: [PATCH 11/56] build(deps): Bump markdown-it from 14.1.0 to 14.1.1 (#13401) Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from 14.1.0 to 14.1.1. - [Changelog](https://github.com/markdown-it/markdown-it/blob/master/CHANGELOG.md) - [Commits](https://github.com/markdown-it/markdown-it/compare/14.1.0...14.1.1) --- updated-dependencies: - dependency-name: markdown-it dependency-version: 14.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Co-authored-by: Banks Nussman --- packages/manager/package.json | 2 +- pnpm-lock.yaml | 14 +++++++------- scripts/package.json | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/manager/package.json b/packages/manager/package.json index 36bf6439e81..bb59cc775d4 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -65,7 +65,7 @@ "libphonenumber-js": "^1.10.6", "logic-query-parser": "^0.0.5", "luxon": "3.4.4", - "markdown-it": "^14.1.0", + "markdown-it": "^14.1.1", "md5": "^2.2.1", "notistack": "^3.0.1", "qrcode.react": "^4.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 219dcb7701f..c3be8dba7c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -275,8 +275,8 @@ importers: specifier: 3.4.4 version: 3.4.4 markdown-it: - specifier: ^14.1.0 - version: 14.1.0 + specifier: ^14.1.1 + version: 14.1.1 md5: specifier: ^2.2.1 version: 2.3.0 @@ -788,8 +788,8 @@ importers: specifier: ^3.1.4 version: 3.1.12 markdown-it: - specifier: ^14.1.0 - version: 14.1.0 + specifier: ^14.1.1 + version: 14.1.1 simple-git: specifier: ^3.19.0 version: 3.27.0 @@ -5322,8 +5322,8 @@ packages: map-or-similar@1.5.0: resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} - markdown-it@14.1.0: - resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true math-intrinsics@1.1.0: @@ -11756,7 +11756,7 @@ snapshots: map-or-similar@1.5.0: {} - markdown-it@14.1.0: + markdown-it@14.1.1: dependencies: argparse: 2.0.1 entities: 4.5.0 diff --git a/scripts/package.json b/scripts/package.json index ccc9b8c3884..8a9ec3dd44b 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@types/markdown-it": "^14.1.2", - "markdown-it": "^14.1.0", + "markdown-it": "^14.1.1", "@types/node": "^22.13.14", "chalk": "^5.2.0", "commander": "^6.2.1", From 0635df0621682df2384a46c569d41dfa55e6ad1b Mon Sep 17 00:00:00 2001 From: Hana Xu <115299789+hana-akamai@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:37:36 -0500 Subject: [PATCH 12/56] upcoming: [UIE-10178] - Use new hostname endpoint in Database Summary and Network tab (#13413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description 📝 Update host fields in Database Summary Connection Details and Networking tab to use new `host.endpoints` data instead of constructing the address ourselves ## How to test 🧪 ### Prerequisites (How to setup test environment) - Turn on the legacy MSW ### Verification steps (How to verify changes) - [ ] In the `makeMockDatabase` function in `serverHandlers.ts`, comment/uncomment out some of the values to simulate No VPC (public only), VPC with no public access (private only), VPC with public access (private and public) - [ ] Host fields that display should match the table in the ticket. Similar fields should display with/without the Hostname Endpoints feature flag on ``` pnpm test ConnectionDetailsHostRows2 ``` --- .../pr-13413-changed-1771602214397.md | 5 + packages/api-v4/src/databases/types.ts | 4 +- ...r-13413-upcoming-features-1771602250906.md | 5 + .../manager/src/dev-tools/FeatureFlagTool.tsx | 1 + packages/manager/src/factories/databases.ts | 8 +- packages/manager/src/featureFlags.ts | 1 + .../ConnectionDetailsHostDisplay.tsx | 62 ++++++ .../ConnectionDetailsHostRows.test.tsx | 4 + .../ConnectionDetailsHostRows.tsx | 2 + .../ConnectionDetailsHostRows2.test.tsx | 180 ++++++++++++++++++ .../ConnectionDetailsHostRows2.tsx | 90 +++++++++ .../DatabaseManageNetworking.tsx | 8 +- .../DatabaseSummaryConnectionDetails.tsx | 7 +- .../src/features/Databases/utilities.test.ts | 4 +- packages/manager/src/mocks/serverHandlers.ts | 60 +++++- 15 files changed, 423 insertions(+), 18 deletions(-) create mode 100644 packages/api-v4/.changeset/pr-13413-changed-1771602214397.md create mode 100644 packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md create mode 100644 packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostDisplay.tsx create mode 100644 packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.test.tsx create mode 100644 packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.tsx diff --git a/packages/api-v4/.changeset/pr-13413-changed-1771602214397.md b/packages/api-v4/.changeset/pr-13413-changed-1771602214397.md new file mode 100644 index 00000000000..69bdb6b4dff --- /dev/null +++ b/packages/api-v4/.changeset/pr-13413-changed-1771602214397.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Changed +--- + +Export `HostEndpoint` and rename `private_access` to `public_access` ([#13413](https://github.com/linode/manager/pull/13413)) diff --git a/packages/api-v4/src/databases/types.ts b/packages/api-v4/src/databases/types.ts index 59df60aa1c0..971a59a6869 100644 --- a/packages/api-v4/src/databases/types.ts +++ b/packages/api-v4/src/databases/types.ts @@ -96,10 +96,10 @@ export type HostEndpointRole = | 'standby' | 'standby-connection-pool'; -interface HostEndpoint { +export interface HostEndpoint { address: string; port: number; - private_access: boolean; + public_access: boolean; role: HostEndpointRole; } diff --git a/packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md b/packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md new file mode 100644 index 00000000000..ae8b475f78a --- /dev/null +++ b/packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Use new hostname endpoint in Database Summary and Network tab ([#13413](https://github.com/linode/manager/pull/13413)) diff --git a/packages/manager/src/dev-tools/FeatureFlagTool.tsx b/packages/manager/src/dev-tools/FeatureFlagTool.tsx index 6dbe9d0ab4b..a5cf596c319 100644 --- a/packages/manager/src/dev-tools/FeatureFlagTool.tsx +++ b/packages/manager/src/dev-tools/FeatureFlagTool.tsx @@ -36,6 +36,7 @@ const options: { flag: keyof Flags; label: string }[] = [ }, { flag: 'gecko2', label: 'Gecko' }, { flag: 'generationalPlansv2', label: 'Generational compute plans' }, + { flag: 'hostnameEndpoints', label: 'Hostname Endpoints' }, { flag: 'kubernetesBlackwellPlans', label: 'Kubernetes Blackwell Plans' }, { flag: 'limitsEvolution', label: 'Limits Evolution' }, { flag: 'linodeDiskEncryption', label: 'Linode Disk Encryption (LDE)' }, diff --git a/packages/manager/src/factories/databases.ts b/packages/manager/src/factories/databases.ts index 0c1218b2288..7e57944aede 100644 --- a/packages/manager/src/factories/databases.ts +++ b/packages/manager/src/factories/databases.ts @@ -179,7 +179,7 @@ export const databaseInstanceFactory = { address: 'public-db-mysql-primary-0.b.linodeb.net', role: 'primary', - private_access: false, + public_access: true, port: 3306, }, ], @@ -191,7 +191,7 @@ export const databaseInstanceFactory = { address: 'public-db-mysql-primary-0.b.linodeb.net', role: 'primary', - private_access: false, + public_access: true, port: 3306, }, ], @@ -253,7 +253,7 @@ export const databaseFactory = Factory.Sync.makeFactory({ { address: 'public-db-mysql-primary-0.b.linodeb.net', role: 'primary', - private_access: false, + public_access: true, port: 3306, }, ], @@ -265,7 +265,7 @@ export const databaseFactory = Factory.Sync.makeFactory({ { address: 'public-db-mysql-primary-0.b.linodeb.net', role: 'primary', - private_access: false, + public_access: true, port: 3306, }, ], diff --git a/packages/manager/src/featureFlags.ts b/packages/manager/src/featureFlags.ts index a9a9a394867..8c24c608d0d 100644 --- a/packages/manager/src/featureFlags.ts +++ b/packages/manager/src/featureFlags.ts @@ -242,6 +242,7 @@ export interface Flags { gecko2: GeckoFeatureFlag; generationalPlansv2: GenerationalPlansFlag; gpuv2: GpuV2; + hostnameEndpoints: boolean; iam: BaseFeatureFlag; iamDelegation: BaseFeatureFlag; iamLimitedAvailabilityBadges: boolean; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostDisplay.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostDisplay.tsx new file mode 100644 index 00000000000..533bb3cc6c3 --- /dev/null +++ b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostDisplay.tsx @@ -0,0 +1,62 @@ +import { TooltipIcon } from '@linode/ui'; +import { styled } from '@mui/material/styles'; +import * as React from 'react'; + +import { CopyTooltip } from 'src/components/CopyTooltip/CopyTooltip'; + +import { + SUMMARY_HOST_TOOLTIP_COPY, + SUMMARY_PRIVATE_HOST_COPY, +} from '../constants'; + +import type { HostEndpoint } from '@linode/api-v4/lib/databases/types'; + +interface ConnectionDetailsHostDisplayProps { + host: HostEndpoint; +} + +export const ConnectionDetailsHostDisplay = ( + props: ConnectionDetailsHostDisplayProps +) => { + const { host } = props; + + return ( + <> + {host?.address} + + + + ); +}; + +export const StyledCopyTooltip = styled(CopyTooltip, { + label: 'StyledCopyTooltip', +})(({ theme }) => ({ + '& svg': { + height: theme.spacingFunction(16), + width: theme.spacingFunction(16), + }, + '&:hover': { + backgroundColor: 'transparent', + }, + display: 'inline-flex', + marginLeft: theme.spacingFunction(4), +})); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.test.tsx index 043831e70c9..c46c0fed9fc 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.test.tsx @@ -17,6 +17,10 @@ const PRIVATE_STANDBY = `private-${DEFAULT_STANDBY}`; const LEGACY_PRIMARY = 'db-mysql-legacy-primary.net'; const LEGACY_SECONDARY = 'db-mysql-legacy-secondary.net'; +/** + * @TODO - delete this file after API releases hostname endpoint changes + */ + describe('ConnectionDetailsHostRows', () => { it('should display Host and Read-only Host fields for a default database with no VPC configured', () => { const database = databaseFactory.build({ diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.tsx index 0cc591d1eac..87ec404e099 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows.tsx @@ -26,6 +26,8 @@ interface ConnectionDetailsHostRowsProps { type HostContentMode = 'default' | 'private' | 'public'; /** + * @deprecated Delete this file in favor of ConnectionDetailsHostRows2 after the API releases hostname endpoint changes. + * * This component is responsible for conditionally rendering the Private Host, Public Host, and Read-only Host rows that get displayed in * the Connection Details tables that appear in the Database Summary and Networking tabs */ export const ConnectionDetailsHostRows = ( diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.test.tsx new file mode 100644 index 00000000000..9d894b5b816 --- /dev/null +++ b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.test.tsx @@ -0,0 +1,180 @@ +import { screen } from '@testing-library/react'; +import React from 'react'; + +import { databaseFactory } from 'src/factories/databases'; +import { renderWithTheme } from 'src/utilities/testHelpers'; + +import { ConnectionDetailsHostRows2 } from './ConnectionDetailsHostRows2'; + +const DEFAULT_PRIMARY = 'db-mysql-default-primary.net'; +const DEFAULT_STANDBY = 'db-mysql-default-standby.net'; + +const PRIVATE_PRIMARY = `private-${DEFAULT_PRIMARY}`; +const PRIVATE_STANDBY = `private-${DEFAULT_STANDBY}`; + +describe('ConnectionDetailsHostRows2', () => { + it('should display Host and Read-only Host fields for a default database with no VPC configured', () => { + const database = databaseFactory.build({ + hosts: { + primary: DEFAULT_PRIMARY, + standby: DEFAULT_STANDBY, + endpoints: [ + { + role: 'primary', + address: DEFAULT_PRIMARY, + port: 15847, + public_access: true, + }, + { + role: 'standby', + address: DEFAULT_STANDBY, + port: 15847, + public_access: true, + }, + ], + }, + platform: 'rdbms-default', + private_network: null, // No VPC configured, so Host and Read-only Host fields render + }); + + renderWithTheme(); + + expect(screen.getByText('Host')).toBeVisible(); + expect(screen.getByText(DEFAULT_PRIMARY)).toBeVisible(); + + expect(screen.getByText('Read-only Host')).toBeVisible(); + expect(screen.getByText(DEFAULT_STANDBY)).toBeVisible(); + }); + + it('should display N/A for default DB with blank read-only Host field', () => { + const database = databaseFactory.build({ + hosts: { + primary: DEFAULT_PRIMARY, + standby: undefined, + endpoints: [ + { + role: 'primary', + address: DEFAULT_PRIMARY, + port: 15847, + public_access: true, + }, + ], + }, + platform: 'rdbms-default', + }); + + renderWithTheme(); + + expect(screen.getByText('N/A')).toBeVisible(); + }); + + it('should display provisioning text when hosts are not available', () => { + const database = databaseFactory.build({ + hosts: undefined, + platform: 'rdbms-default', + }); + + const { getByText } = renderWithTheme( + + ); + + const hostNameProvisioningText = getByText( + 'Your hostname will appear here once it is available.' + ); + + expect(hostNameProvisioningText).toBeInTheDocument(); + }); + + it('should display Private variations of Host and Read-only fields when a VPC is configured with public access set to false', () => { + const database = databaseFactory.build({ + hosts: { + primary: PRIVATE_PRIMARY, + standby: PRIVATE_STANDBY, + endpoints: [ + { + role: 'primary', + address: PRIVATE_PRIMARY, + port: 15847, + public_access: false, + }, + { + role: 'standby', + address: PRIVATE_STANDBY, + port: 15847, + public_access: false, + }, + ], + }, + platform: 'rdbms-default', + private_network: { + public_access: false, + subnet_id: 1, + vpc_id: 123, + }, // VPC configuration with public access set to false + }); + + renderWithTheme(); + + expect(screen.getByText('Private Host')).toBeVisible(); + expect(screen.getByText(PRIVATE_PRIMARY)).toBeVisible(); + expect(screen.getByText('Private Read-only Host')).toBeVisible(); + expect(screen.getByText(PRIVATE_STANDBY)).toBeVisible(); + }); + + it('should display Private and Public variations of Host and Read-only Host fields when a VPC is configured with public access set to true', () => { + const database = databaseFactory.build({ + hosts: { + primary: PRIVATE_PRIMARY, + standby: PRIVATE_STANDBY, + endpoints: [ + { + role: 'primary', + address: `public-${DEFAULT_PRIMARY}`, + port: 15847, + public_access: true, + }, + { + role: 'standby', + address: `public-${DEFAULT_STANDBY}`, + port: 15847, + public_access: true, + }, + { + role: 'primary', + address: PRIVATE_PRIMARY, + port: 15847, + public_access: false, + }, + { + role: 'standby', + address: PRIVATE_STANDBY, + port: 15847, + public_access: false, + }, + ], + }, + platform: 'rdbms-default', + private_network: { + public_access: true, + subnet_id: 1, + vpc_id: 123, + }, // VPC configuration with public access set to true + }); + + renderWithTheme(); + + // Verify that Private and Public Host and Readonly-host fields are rendered + expect(screen.getByText('Private Host')).toBeVisible(); + expect(screen.getByText('Public Host')).toBeVisible(); + expect(screen.getByText('Private Read-only Host')).toBeVisible(); + expect(screen.getByText('Public Read-only Host')).toBeVisible(); + + // Verify that the Private and Public hostname is rendered correctly + expect(screen.getByText(PRIVATE_PRIMARY)).toBeVisible(); + expect(screen.getByText(`public-${DEFAULT_PRIMARY}`)).toBeVisible(); + + // Verify that the Private and Public read-only hostname is rendered correctly + expect(screen.getByText(PRIVATE_STANDBY)).toBeVisible(); + expect(screen.getByText(`public-${DEFAULT_STANDBY}`)).toBeVisible(); + }); +}); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.tsx new file mode 100644 index 00000000000..f1adca94a1b --- /dev/null +++ b/packages/manager/src/features/Databases/DatabaseDetail/ConnectionDetailsHostRows2.tsx @@ -0,0 +1,90 @@ +import { Typography } from '@linode/ui'; +import * as React from 'react'; + +import { ConnectionDetailsHostDisplay } from './ConnectionDetailsHostDisplay'; +import { ConnectionDetailsRow } from './ConnectionDetailsRow'; +import { useStyles } from './DatabaseSummary/DatabaseSummaryConnectionDetails.style'; + +import type { Database } from '@linode/api-v4/lib/databases/types'; + +interface ConnectionDetailsHostRowsProps { + database: Database; + isSummaryTab?: boolean; +} + +/** + * This component is responsible for conditionally rendering the Private Host, Public Host, and Read-only Host rows that get displayed in + * the Connection Details tables that appear in the Database Summary and Networking tabs */ +export const ConnectionDetailsHostRows2 = ( + props: ConnectionDetailsHostRowsProps +) => { + const { database, isSummaryTab } = props; + const { classes } = useStyles(); + + const hasVPC = Boolean(database?.private_network?.vpc_id); + const hasPublicVPC = hasVPC && database?.private_network?.public_access; + + const getPrimaryHostContent = (mode?: 'private' | 'public') => { + const isPublic = mode === 'private' ? false : true; + const primaryHost = database.hosts?.endpoints.find( + (endpoint) => + endpoint.role === 'primary' && endpoint.public_access === isPublic + ); + + if (!primaryHost) { + return ( + + + Your hostname will appear here once it is available. + + + ); + } + + return ; + }; + + const getReadOnlyHostContent = (mode?: 'private' | 'public') => { + const isPublic = mode === 'private' ? false : true; + const readOnlyHost = database.hosts?.endpoints.find( + (endpoint) => + endpoint.role === 'standby' && endpoint.public_access === isPublic + ); + + if (!readOnlyHost) { + return 'N/A'; + } + + return ; + }; + + return ( + <> + + {getPrimaryHostContent(hasVPC ? 'private' : 'public')} + + {hasPublicVPC && ( + + {getPrimaryHostContent('public')} + + )} + + {getReadOnlyHostContent(hasVPC ? 'private' : 'public')} + + {hasPublicVPC && ( + + {getReadOnlyHostContent('public')} + + )} + + ); +}; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseManageNetworking.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseManageNetworking.tsx index a441e72e98c..27b0993432b 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseManageNetworking.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseManageNetworking.tsx @@ -15,6 +15,7 @@ import { useFlags } from 'src/hooks/useFlags'; import { MANAGE_NETWORKING_LEARN_MORE_LINK } from '../../constants'; import { makeSettingsItemStyles } from '../../shared.styles'; import { ConnectionDetailsHostRows } from '../ConnectionDetailsHostRows'; +import { ConnectionDetailsHostRows2 } from '../ConnectionDetailsHostRows2'; import { ConnectionDetailsRow } from '../ConnectionDetailsRow'; import { StyledGridContainer } from '../DatabaseSummary/DatabaseSummaryClusterConfiguration.style'; import DatabaseManageNetworkingDrawer from './DatabaseManageNetworkingDrawer'; @@ -122,8 +123,11 @@ export const DatabaseManageNetworking = ({ database }: Props) => { )} - - + {flags.hostnameEndpoints ? ( + + ) : ( + + )} {hasVPCConfigured && ( {database?.private_network?.public_access ? 'Yes' : 'No'} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx index 5329032f66c..378605b6578 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx @@ -10,6 +10,7 @@ import { useFlags } from 'src/hooks/useFlags'; import { isDefaultDatabase } from '../../utilities'; import { ConnectionDetailsHostRows } from '../ConnectionDetailsHostRows'; +import { ConnectionDetailsHostRows2 } from '../ConnectionDetailsHostRows2'; import { ConnectionDetailsRow } from '../ConnectionDetailsRow'; import { ServiceURI } from '../ServiceURI'; import { StyledGridContainer } from './DatabaseSummaryClusterConfiguration.style'; @@ -136,7 +137,11 @@ export const DatabaseSummaryConnectionDetails = (props: Props) => { {isLegacy ? database.engine : 'defaultdb'} - + {flags.hostnameEndpoints ? ( + + ) : ( + + )} {database.port} diff --git a/packages/manager/src/features/Databases/utilities.test.ts b/packages/manager/src/features/Databases/utilities.test.ts index 1f3648fbdd4..dbc95ab1275 100644 --- a/packages/manager/src/features/Databases/utilities.test.ts +++ b/packages/manager/src/features/Databases/utilities.test.ts @@ -545,7 +545,7 @@ describe('getReadOnlyHost', () => { { address: 'public-primary.example.com', role: 'primary' as HostEndpointRole, - private_access: false, + public_access: true, port: 12345, }, ], @@ -565,7 +565,7 @@ describe('getReadOnlyHost', () => { { address: 'public-primary.example.com', role: 'primary' as HostEndpointRole, - private_access: false, + public_access: true, port: 12345, }, ], diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index 30a2a54d24c..2ab6f042881 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -220,26 +220,72 @@ const makeMockDatabase = (params: PathParams): Database => { const database = databaseFactory.build(db); - if (database.platform !== 'rdbms-default') { - delete database.private_network; - } + // Mock a database cluster with a public VPC Configuration + database.private_network = { + public_access: true, + subnet_id: 123, + vpc_id: 10, + }; - if (database.platform === 'rdbms-default' && !!database.private_network) { + if (database.private_network) { // When a database is configured with a VPC, the primary and standby hostnames are prepended with 'private-' in the backend database.hosts = { primary: 'private-db-mysql-primary-0.b.linodeb.net', standby: 'private-db-mysql-standby-0.b.linodeb.net', + /** + * The contents of the hosts.endpoints vary based off whether the VPC has public access or not. + * If private_network public_access is true, the endpoints should return both public and private addresses. + * If private_network public_access is false, the endpoints should only return private addresses. + */ endpoints: [ { - address: 'private-db-mysql-primary-0.b.linodeb.net', role: 'primary', - private_access: true, - port: 12345, + address: 'public-db-mysql-primary-0.b.linodeb.net', + port: 15847, + public_access: true, + }, + { + role: 'primary', + address: 'private-db-mysql-primary-0.b.linodeb.net', + port: 15847, + public_access: false, + }, + { + role: 'standby', + address: 'public-replica-db-mysql-standby-0.b.linodeb.net', + port: 15847, + public_access: true, + }, + { + role: 'standby', + address: 'private-replica-db-mysql-standby-0.b.linodeb.net', + port: 15847, + public_access: false, + }, + { + role: 'primary-connection-pool', + address: 'private-db-mysql-primary-0.b.linodeb.net', + port: 15848, + public_access: false, }, ], }; } + // Uncomment the lines below to mock a database cluster without a VPC configuration + // database.private_network = null; + // database.hosts = { + // primary: 'db-mysql-primary-0.b.linodeb.net', + // endpoints: [ + // { + // role: 'primary', + // address: 'db-mysql-primary-0.b.linodeb.net', + // port: 15847, + // public_access: true, + // }, + // ], + // }; + return database; }; From 0664a55fbdda2692539ce24500be66177ed1267a Mon Sep 17 00:00:00 2001 From: mduda-akamai Date: Wed, 25 Feb 2026 07:30:02 +0100 Subject: [PATCH 13/56] change: [DPS-36721] - Custom HTTPS form - Test Connection sometimes doesn't verify destination (#13425) --- .../manager/.changeset/pr-13425-changed-1771593559752.md | 5 +++++ .../Destinations/DestinationForm/DestinationForm.tsx | 1 + .../Delivery/Shared/DestinationCustomHttpsDetailsForm.tsx | 7 ++++++- .../Streams/StreamForm/Delivery/StreamFormDelivery.tsx | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 packages/manager/.changeset/pr-13425-changed-1771593559752.md diff --git a/packages/manager/.changeset/pr-13425-changed-1771593559752.md b/packages/manager/.changeset/pr-13425-changed-1771593559752.md new file mode 100644 index 00000000000..93a12fae9b4 --- /dev/null +++ b/packages/manager/.changeset/pr-13425-changed-1771593559752.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Delivery Logs - in Custom HTTPS form set authentication.details to undefined when None authentication is selected ([#13425](https://github.com/linode/manager/pull/13425)) diff --git a/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationForm.tsx b/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationForm.tsx index 67e1bba84bf..b7097f784d6 100644 --- a/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationForm.tsx +++ b/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationForm.tsx @@ -36,6 +36,7 @@ interface DestinationFormProps { const customHttpsDetailsControlPaths = { authenticationType: 'details.authentication.type', + authenticationDetails: 'details.authentication.details', basicAuthenticationPassword: 'details.authentication.details.basic_authentication_password', basicAuthenticationUser: diff --git a/packages/manager/src/features/Delivery/Shared/DestinationCustomHttpsDetailsForm.tsx b/packages/manager/src/features/Delivery/Shared/DestinationCustomHttpsDetailsForm.tsx index e9d89bb1be9..68f26825c52 100644 --- a/packages/manager/src/features/Delivery/Shared/DestinationCustomHttpsDetailsForm.tsx +++ b/packages/manager/src/features/Delivery/Shared/DestinationCustomHttpsDetailsForm.tsx @@ -1,3 +1,4 @@ +import { authenticationType } from '@linode/api-v4'; import { Autocomplete, Divider, TextField, Typography } from '@linode/ui'; import { useTheme } from '@mui/material/styles'; import React from 'react'; @@ -18,6 +19,7 @@ import type { FormMode, FormType } from 'src/features/Delivery/Shared/types'; interface DestinationCustomHttpsDetailsFormProps { controlPaths: { + authenticationDetails: string; authenticationType: string; basicAuthenticationPassword: string; basicAuthenticationUser: string; @@ -40,7 +42,7 @@ export const DestinationCustomHttpsDetailsForm = ( const { controlPaths } = props; const theme = useTheme(); - const { control } = useFormContext(); + const { control, setValue } = useFormContext(); const selectedAuthenticationType = useWatch({ control, @@ -59,6 +61,9 @@ export const DestinationCustomHttpsDetailsForm = ( label="Authentication" onBlur={field.onBlur} onChange={(_, { value }) => { + if (value === authenticationType.None) { + setValue(controlPaths.authenticationDetails, undefined); + } field.onChange(value); }} options={authenticationTypeOptions} diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.tsx index 2c7052b1006..3fb88ce8308 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.tsx @@ -57,6 +57,7 @@ const akamaiObjectStorageDetailsControlPaths = { const customHttpsDetailsControlPaths = { authenticationType: 'destination.details.authentication.type', + authenticationDetails: 'destination.details.authentication.details', basicAuthenticationPassword: 'destination.details.authentication.details.basic_authentication_password', basicAuthenticationUser: From badc6f93efce040013cd38c7bfa3aef1213d6bd3 Mon Sep 17 00:00:00 2001 From: Purvesh Makode Date: Thu, 26 Feb 2026 12:19:05 +0530 Subject: [PATCH 14/56] upcoming: [UIE-9502] - Add Reusable ImagesView and Integrate It for the Custom (Owned by Me) Images Tab (v2) (#13418) * Split PR, and add more changes * Added changeset: Private Image Sharing tabs new layout (v2) * Few changes * Update few remaining references * Save progress.. * Update filename * Some refactoring and add reuseable images component * Change custom to owned (query params) * Update sharegroups to share-groups * Add more tests * Update remaining share-groups references * Few updates * More changes * Add ImagesView tests for custom images * Minor changes * Added changeset: Add reusable `ImagesView` and Integrate It for the `Owned by me` Images tab (v2) * Added changeset: Add `shared` to ImageType * Added changeset: Add `ZeroStateSearchNarrowIcon` to UI package * Update changeset * Clean up old query param from ImagesSearchParams * Update custom images desc and move styles to dedicated file * Minor change * Update docsLink (for owned by me images) after latest UX update * Few updates --- ...r-13418-upcoming-features-1771851737264.md | 5 + packages/api-v4/src/images/types.ts | 2 +- ...r-13418-upcoming-features-1771851666095.md | 5 + .../v2/ImageLibrary/ImageLibraryTabs.test.tsx | 219 +++++++++++++++++ .../v2/ImageLibrary/ImageLibraryTabs.tsx | 131 +++++++++- .../v2/ImageLibrary/ImagesTable.styles.ts | 24 ++ .../v2/ImageLibrary/ImagesTable.tsx | 208 ++++++++++++++++ .../v2/ImageLibrary/ImagesView.test.tsx | 224 ++++++++++++++++++ .../v2/ImageLibrary/ImagesView.tsx | 223 +++++++++++++++++ .../v2/ImageLibrary/imageLibraryTabsConfig.ts | 11 - .../ImageLibrary/imageLibraryTabsConfig.tsx | 130 ++++++++++ .../ImagesLanding/v2/ImagesLandingV2.tsx | 1 + .../src/features/Images/utils.test.tsx | 15 ++ packages/manager/src/features/Images/utils.ts | 13 + .../features/Search/useClientSideSearch.ts | 8 +- packages/manager/src/routes/images/index.ts | 32 ++- .../src/store/selectors/getSearchEntities.ts | 46 ++-- ...r-13418-upcoming-features-1771851880267.md | 5 + packages/ui/src/assets/icons/index.ts | 1 + .../assets/icons/zero-state-search-narrow.svg | 10 + 20 files changed, 1275 insertions(+), 38 deletions(-) create mode 100644 packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md create mode 100644 packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx delete mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.ts create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx create mode 100644 packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md create mode 100644 packages/ui/src/assets/icons/zero-state-search-narrow.svg diff --git a/packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md b/packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md new file mode 100644 index 00000000000..170fdf886d5 --- /dev/null +++ b/packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Upcoming Features +--- + +Add `shared` to ImageType ([#13418](https://github.com/linode/manager/pull/13418)) diff --git a/packages/api-v4/src/images/types.ts b/packages/api-v4/src/images/types.ts index 42aa1a4f9e1..c2df6d30d69 100644 --- a/packages/api-v4/src/images/types.ts +++ b/packages/api-v4/src/images/types.ts @@ -2,7 +2,7 @@ export type ImageStatus = 'available' | 'creating' | 'pending_upload'; export type ImageCapabilities = 'cloud-init' | 'distributed-sites'; -type ImageType = 'automatic' | 'manual'; +type ImageType = 'automatic' | 'manual' | 'shared'; type SharegroupMemberStatus = 'active' | 'revoked'; diff --git a/packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md b/packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md new file mode 100644 index 00000000000..7de2513b206 --- /dev/null +++ b/packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add reusable `ImagesView` and `ImagesTable` components, and integrated them for the `Owned by me` Images tab (v2) ([#13418](https://github.com/linode/manager/pull/13418)) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx new file mode 100644 index 00000000000..a59927ee485 --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx @@ -0,0 +1,219 @@ +import { linodeFactory } from '@linode/utilities'; +import { waitForElementToBeRemoved } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; + +import { imageFactory } from 'src/factories'; +import { makeResourcePage } from 'src/mocks/serverHandlers'; +import { http, HttpResponse, server } from 'src/mocks/testServer'; +import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; + +import { ImageLibraryTabs } from './ImageLibraryTabs'; + +const queryMocks = vi.hoisted(() => ({ + useLocation: vi.fn(), + usePermissions: vi.fn().mockReturnValue({ data: { create_image: false } }), + useQueryWithPermissions: vi.fn().mockReturnValue({}), + useLinodesPermissionsCheck: vi.fn().mockReturnValue({}), + useSearch: vi.fn().mockReturnValue({}), +})); + +vi.mock('src/features/IAM/hooks/usePermissions', () => ({ + usePermissions: queryMocks.usePermissions, + useQueryWithPermissions: queryMocks.useQueryWithPermissions, +})); + +vi.mock('@tanstack/react-router', async () => { + const actual = await vi.importActual('@tanstack/react-router'); + return { + ...actual, + useLocation: queryMocks.useLocation, + useSearch: queryMocks.useSearch, + }; +}); + +vi.mock('../utils.ts', async () => { + const actual = await vi.importActual('../utils'); + return { + ...actual, + useLinodesPermissionsCheck: queryMocks.useLinodesPermissionsCheck, + }; +}); + +beforeAll(() => mockMatchMedia()); + +const loadingTestId = 'circle-progress'; + +describe('ImageLibraryTabs', () => { + beforeEach(() => { + queryMocks.usePermissions.mockReturnValue({ + data: { + update_image: true, + delete_image: true, + rebuild_linode: true, + create_linode: true, + replicate_image: true, + }, + }); + + queryMocks.useLocation.mockReturnValue({ + pathname: '/images/image-library', + }); + }); + + // For Custom Images (Owned by me) + describe('For Custom Images (Owned by me)', () => { + it("should render 'Owned by me' tab", async () => { + const { getByText } = renderWithTheme(, { + initialRoute: '/images/image-library/owned-by-me', + }); + + expect(getByText('Owned by me')).toBeVisible(); + }); + + // Test Image action navigations for CUSTOM IMAGES (Owned by me) + it('should allow opening the Edit Image drawer', async () => { + const image = imageFactory.build(); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('manual')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { getByText, findByLabelText, router } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me/', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Edit')); + + expect(router.state.location.pathname).toBe( + `/images/image-library/owned-by-me/${encodeURIComponent(image.id)}/edit` + ); + }); + + it('should allow opening the Restore Image drawer', async () => { + const image = imageFactory.build(); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('manual')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { router, getByText, findByLabelText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me/', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Rebuild an Existing Linode')); + + expect(router.state.location.pathname).toBe( + `/images/image-library/owned-by-me/${encodeURIComponent(image.id)}/rebuild` + ); + }); + + it('should allow deploying to a new Linode', async () => { + const image = imageFactory.build(); + queryMocks.useLinodesPermissionsCheck.mockReturnValue({ + availableLinodes: [linodeFactory.build()], + }); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('manual')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { findByLabelText, getByText, queryAllByTestId, router } = + renderWithTheme(, { + initialRoute: '/images/image-library/owned-by-me/', + }); + + const loadingElement = queryAllByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Deploy to New Linode')); + + expect(router.state.location.pathname).toBe('/linodes/create/images'); + + expect(router.state.location.search).toStrictEqual({ + imageID: image.id, + }); + }); + + it('should allow deleting an image', async () => { + const image = imageFactory.build(); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('manual')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { router, findByLabelText, getByText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me/', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Delete')); + + expect(router.state.location.pathname).toBe( + `/images/image-library/owned-by-me/${encodeURIComponent(image.id)}/delete` + ); + }); + }); + + it('should render Owned (custom), Shared and Recovery tabs under Images Library Tab', async () => { + const { getByText } = renderWithTheme(, { + initialRoute: '/images/image-library', + }); + + expect(getByText('Owned by me', { selector: 'button' })).toBeVisible(); + expect(getByText('Shared with me', { selector: 'button' })).toBeVisible(); + expect(getByText('Recovery images', { selector: 'button' })).toBeVisible(); + }); +}); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx index e9a572c8f35..b4ed02409ee 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx @@ -1,4 +1,5 @@ -import { BetaChip, Notice, Stack } from '@linode/ui'; +import { imageQueries, useImageQuery, useQueryClient } from '@linode/queries'; +import { BetaChip, Drawer, Notice, Stack } from '@linode/ui'; import { useNavigate, useParams } from '@tanstack/react-router'; import * as React from 'react'; @@ -10,17 +11,107 @@ import { TabPanels } from 'src/components/Tabs/TabPanels'; import { Tabs } from 'src/components/Tabs/Tabs'; import { getImageLibrarySubTabIndex } from '../../../utils'; +import { DeleteImageDialog } from '../../DeleteImageDialog'; +import { EditImageDrawer } from '../../EditImageDrawer'; +import { ManageImageReplicasForm } from '../../ImageRegions/ManageImageRegionsForm'; +import { RebuildImageDrawer } from '../../RebuildImageDrawer'; import { imageLibrarySubTabs as subTabs } from './imageLibraryTabsConfig'; +import { ImagesView } from './ImagesView'; + +import type { Handlers as ImageHandlers } from '../../ImagesActionMenu'; +import type { Image } from '@linode/api-v4'; +import type { ImageAction } from 'src/routes/images'; export const ImageLibraryTabs = () => { const navigate = useNavigate(); - const params = useParams({ + const imageActionParams = useParams({ + from: '/images/image-library/$imageType/$imageId/$action', + shouldThrow: false, + }); + + const imageTypeParams = useParams({ from: '/images/image-library/$imageType', shouldThrow: false, }); - const subTabIndex = getImageLibrarySubTabIndex(subTabs, params?.imageType); + const queryClient = useQueryClient(); + + const { + data: selectedImage, + isLoading: isFetchingSelectedImage, + error: selectedImageError, + } = useImageQuery( + imageActionParams?.imageId ?? '', + !!imageActionParams?.imageId + ); + + const actionHandler = (image: Image, action: ImageAction) => { + navigate({ + params: { + action, + imageId: image.id, + imageType: imageTypeParams?.imageType ?? 'owned-by-me', + }, + search: (prev) => prev, + to: '/images/image-library/$imageType/$imageId/$action', + }); + }; + + const handleEdit = (image: Image) => { + actionHandler(image, 'edit'); + }; + + const handleRebuild = (image: Image) => { + actionHandler(image, 'rebuild'); + }; + + const handleDelete = (image: Image) => { + actionHandler(image, 'delete'); + }; + + const handleCloseDialog = () => { + navigate({ + search: (prev) => prev, + to: '/images/image-library/$imageType', + params: { + imageType: imageTypeParams?.imageType ?? 'owned-by-me', + }, + }); + }; + + const handleManageRegions = (image: Image) => { + actionHandler(image, 'manage-replicas'); + }; + + const onCancelFailedClick = () => { + queryClient.invalidateQueries({ + queryKey: imageQueries.paginated._def, + }); + }; + + const handleDeployNewLinode = (imageId: string) => { + navigate({ + to: '/linodes/create/images', + search: { + imageID: imageId, + }, + }); + }; + + const handlers: ImageHandlers = { + onCancelFailed: onCancelFailedClick, + onDelete: handleDelete, + onDeploy: handleDeployNewLinode, + onEdit: handleEdit, + onManageRegions: handleManageRegions, + onRebuild: handleRebuild, + }; + + const subTabIndex = getImageLibrarySubTabIndex( + subTabs, + imageTypeParams?.imageType + ); const onTabChange = (index: number) => { // - Update the "imageType" param. @@ -48,8 +139,7 @@ export const ImageLibraryTabs = () => { {subTabs.map((tab, idx) => ( {tab.type === 'owned-by-me' && ( - // - Custom Images + )} {tab.type === 'shared-with-me' && ( @@ -65,6 +155,37 @@ export const ImageLibraryTabs = () => { + + + + + + ); }; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts new file mode 100644 index 00000000000..b6819eee6e8 --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts @@ -0,0 +1,24 @@ +import { Paper, Typography } from '@linode/ui'; +import { styled } from '@mui/material/styles'; + +export const StyledImageTable = styled(Paper, { label: 'StyledImageTable' })( + ({ theme }) => ({ + marginBottom: theme.spacingFunction(24), + padding: 0, + }) +); + +export const StyledImageTableHeader = styled('div', { + label: 'StyledImageTableHeader', +})(({ theme }) => ({ + border: `1px solid ${theme.tokens.alias.Border.Normal}`, + borderBottom: 0, + padding: theme.spacingFunction(8), + paddingLeft: theme.spacingFunction(12), +})); + +export const StyledImageTableSubheader = styled(Typography, { + label: 'StyledImageTableSubheader', +})(({ theme }) => ({ + marginTop: theme.spacingFunction(8), +})); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx new file mode 100644 index 00000000000..01816368b46 --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx @@ -0,0 +1,208 @@ +import { + Box, + Button, + Hidden, + Typography, + ZeroStateSearchNarrowIcon, +} from '@linode/ui'; +import React from 'react'; + +import { DocsLink } from 'src/components/DocsLink/DocsLink'; +import { PaginationFooter } from 'src/components/PaginationFooter/PaginationFooter'; +import { Table } from 'src/components/Table'; +import { TableBody } from 'src/components/TableBody'; +import { TableCell } from 'src/components/TableCell'; +import { TableHead } from 'src/components/TableHead'; +import { TableRow } from 'src/components/TableRow'; +import { TableRowEmpty } from 'src/components/TableRowEmpty/TableRowEmpty'; +import { TableRowError } from 'src/components/TableRowError/TableRowError'; +import { TableSortCell } from 'src/components/TableSortCell'; + +import { ImageRow } from '../../ImageRow'; +import { + StyledImageTable, + StyledImageTableHeader, + StyledImageTableSubheader, +} from './ImagesTable.styles'; + +import type { Handlers as ImageHandlers } from '../../ImagesActionMenu'; +import type { + ImageConfig, + ImageViewTableColConfig, +} from './imageLibraryTabsConfig'; +import type { APIError, Event, Image } from '@linode/api-v4'; +import type { Order } from 'src/hooks/useOrderV2'; + +interface HeaderProps { + buttonProps?: { + buttonText: string; + disabled?: boolean; + onButtonClick: () => void; + tooltipText?: string; + }; + description?: React.ReactNode; + docsLink?: string; + title: string; +} + +interface ImagesTableProps { + columns: ImageViewTableColConfig[]; + emptyMessage: ImageConfig['emptyMessage']; + error?: APIError[] | null; + eventCategory: string; + events: { + [k: string]: Event | undefined; + }; + handleOrderChange: (newOrderBy: string, newOrder: Order) => void; + handlers: ImageHandlers; + headerProps?: HeaderProps; + images: Image[]; + order: Order; + orderBy: string; + pagination: { + count: number; + handlePageChange: (newPage: number) => void; + handlePageSizeChange: (newSize: number) => void; + page: number; + pageSize: number; + }; + query?: string; +} + +export const ImagesTable = (props: ImagesTableProps) => { + const { + headerProps, + images, + orderBy, + order, + handleOrderChange, + columns, + events, + handlers, + error, + query, + pagination, + eventCategory, + emptyMessage, + } = props; + + return ( + + {headerProps && headerProps.title && ( + + + {headerProps.title} + + {headerProps.docsLink && ( + + )} + {headerProps.buttonProps && ( + + )} + + + {headerProps.description && ( + + {headerProps.description} + + )} + + )} +
+ + + {columns.map((col, idx) => { + const cell = + col.sortable && col.label ? ( + + {col.name} + + ) : ( + {col.name} + ); + + return col.hiddenOn ? ( + + {cell} + + ) : ( + cell + ); + })} + + + + + {!error && images?.length === 0 && ( + ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: theme.spacingFunction(4), + p: `${theme.spacingFunction(24)} ${theme.spacingFunction(32)}`, + })} + > + + {emptyMessage.main} + {!query && ( + + {emptyMessage.instruction} + + )} + + } + /> + )} + {error && query && ( + + )} + {images?.map((image) => ( + + ))} + +
+ + + ); +}; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx new file mode 100644 index 00000000000..75e110724f0 --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx @@ -0,0 +1,224 @@ +import { waitForElementToBeRemoved } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; + +import { imageFactory } from 'src/factories'; +import { makeResourcePage } from 'src/mocks/serverHandlers'; +import { http, HttpResponse, server } from 'src/mocks/testServer'; +import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; + +import { ImagesView } from './ImagesView'; + +const queryMocks = vi.hoisted(() => ({ + useLocation: vi.fn(), + usePermissions: vi.fn().mockReturnValue({ data: { create_image: false } }), + useQueryWithPermissions: vi.fn().mockReturnValue({}), + useLinodesPermissionsCheck: vi.fn().mockReturnValue({}), + useSearch: vi.fn().mockReturnValue({}), +})); + +vi.mock('src/features/IAM/hooks/usePermissions', () => ({ + usePermissions: queryMocks.usePermissions, + useQueryWithPermissions: queryMocks.useQueryWithPermissions, +})); + +vi.mock('@tanstack/react-router', async () => { + const actual = await vi.importActual('@tanstack/react-router'); + return { + ...actual, + useLocation: queryMocks.useLocation, + useSearch: queryMocks.useSearch, + }; +}); + +vi.mock('../utils.ts', async () => { + const actual = await vi.importActual('../utils'); + return { + ...actual, + useLinodesPermissionsCheck: queryMocks.useLinodesPermissionsCheck, + }; +}); + +const mockHandlers = { + onDelete: vi.fn(), + onDeploy: vi.fn(), + onEdit: vi.fn(), + onRebuild: vi.fn(), + onManageReplicas: vi.fn(), +}; + +beforeAll(() => mockMatchMedia()); + +const loadingTestId = 'circle-progress'; + +describe('ImagesView component', () => { + beforeEach(() => { + queryMocks.usePermissions.mockReturnValue({ + data: { + update_image: true, + delete_image: true, + rebuild_linode: true, + create_linode: true, + replicate_image: true, + }, + }); + + queryMocks.useLocation.mockReturnValue({ + pathname: '/images/image-library', + }); + }); + + // For Custom Images (Owned by me) + describe('For Custom Images (Owned by me)', () => { + it("should render 'Owned by me' tab with items", async () => { + server.use( + http.get('*/images', () => { + const images = imageFactory.buildList(3, { + regions: [ + { region: 'us-east', status: 'available' }, + { region: 'us-southeast', status: 'pending' }, + ], + }); + return HttpResponse.json(makeResourcePage(images)); + }) + ); + + const { getByText, queryAllByTestId } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me', + } + ); + + const loadingElement = queryAllByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + + // Custom Images table should render + getByText('Owned by me'); + + // Static text and table column headers + expect(getByText('Image')).toBeVisible(); + expect(getByText('Replicated in')).toBeVisible(); + expect(getByText('Original Image')).toBeVisible(); + expect(getByText('All Replicas')).toBeVisible(); + expect(getByText('Created')).toBeVisible(); + expect(getByText('Image ID')).toBeVisible(); + }); + + it("should render 'Owned by me' (manual) empty state", async () => { + server.use( + http.get('*/images', ({ request }) => { + return HttpResponse.json( + makeResourcePage( + request.headers.get('x-filter')?.includes('automatic') + ? [imageFactory.build({ type: 'automatic' })] + : [] + ) + ); + }) + ); + + const { findByText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me', + } + ); + + expect(await findByText('No custom images to display')).toBeVisible(); + }); + + it('disables the action menu buttons if user does not have permissions to edit images', async () => { + queryMocks.usePermissions.mockReturnValue({ + data: { create_image: false }, + }); + const image = imageFactory.build({ + id: 'private/99999', + label: 'vi-test-image', + }); + queryMocks.useLinodesPermissionsCheck.mockReturnValue({ + availableLinodes: [], + }); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('manual')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { findByLabelText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + + await userEvent.click(actionMenu); + + const disabledEditText = await findByLabelText( + "You don't have permissions to edit this Image. Please contact your account administrator to request the necessary permissions." + ); + const disabledDeleteText = await findByLabelText( + "You don't have permissions to delete this Image. Please contact your account administrator to request the necessary permissions." + ); + const disabledLinodeCreationText = await findByLabelText( + "You don't have permissions to create Linodes. Please contact your account administrator to request the necessary permissions." + ); + + expect(disabledEditText).toBeVisible(); + expect(disabledDeleteText).toBeVisible(); + expect(disabledLinodeCreationText).toBeVisible(); + }); + + it('should disable create button if user lacks create_image permission', async () => { + queryMocks.usePermissions.mockReturnValue({ + data: { create_image: false }, + }); + + const { getByText, queryAllByTestId } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me', + } + ); + + const loadingElement = queryAllByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + + const createButton = getByText('Create Image'); + expect(createButton).toBeDisabled(); + expect(createButton).toHaveAttribute( + 'data-qa-tooltip', + "You don't have permissions to create Images. Please contact your account administrator to request the necessary permissions." + ); + }); + + it('should enable create button if user has create_image permission', async () => { + queryMocks.usePermissions.mockReturnValue({ + data: { create_image: true }, + }); + + const { getByText, queryAllByTestId } = renderWithTheme( + , + { + initialRoute: '/images/image-library/owned-by-me', + } + ); + + const loadingElement = queryAllByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + + const createButton = getByText('Create Image'); + expect(createButton).toBeEnabled(); + }); + }); +}); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx new file mode 100644 index 00000000000..bd3faab59bb --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx @@ -0,0 +1,223 @@ +import { useImagesQuery } from '@linode/queries'; +import { getAPIFilterFromQuery } from '@linode/search'; +import { CircleProgress, ErrorState } from '@linode/ui'; +import { useNavigate, useSearch } from '@tanstack/react-router'; +import * as React from 'react'; + +import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; +import { DocumentTitleSegment } from 'src/components/DocumentTitle'; +import { usePermissions } from 'src/features/IAM/hooks/usePermissions'; +import { useOrderV2 } from 'src/hooks/useOrderV2'; +import { usePaginationV2 } from 'src/hooks/usePaginationV2'; +import { + isEventImageUpload, + isEventInProgressDiskImagize, +} from 'src/queries/events/event.helpers'; +import { useEventsInfiniteQuery } from 'src/queries/events/events'; + +import { getEventsForImages } from '../../../utils'; +import { IMAGES_CONFIG } from './imageLibraryTabsConfig'; +import { ImagesTable } from './ImagesTable'; + +import type { ImageLibraryType } from '../../../utils'; +import type { Handlers as ImageHandlers } from '../../ImagesActionMenu'; +import type { Filter } from '@linode/api-v4'; + +interface Props { + handlers: ImageHandlers; + type: Exclude; +} + +export const ImagesView = (props: Props) => { + const { handlers, type } = props; + + const config = IMAGES_CONFIG[type]; + + const navigate = useNavigate(); + const search = useSearch({ from: '/images' }); + + const { data: permissions } = usePermissions('account', ['create_image']); + const canCreateImage = permissions?.create_image; + + /** + * At the time of writing: `label`, `tags`, `size`, `status`, `region` are filterable. + * + * Some fields like `status` and `region` can't be used in complex filters using '+or' / '+and' + * + * Using `tags` in a '+or' is currently broken. See ARB-5792 + */ + const { error: searchParseError, filter } = getAPIFilterFromQuery( + search.query, + { + // Because Images have an array of region objects, we need to transform + // search queries like "region: us-east" to { regions: { region: "us-east" } } + // rather than the default behavior which is { region: { '+contains': "us-east" } } + filterShapeOverrides: { + '+contains': { + field: 'region', + filter: (value) => ({ regions: { region: value } }), + }, + '+eq': { + field: 'region', + filter: (value) => ({ regions: { region: value } }), + }, + }, + searchableFieldsWithoutOperator: ['label', 'tags'], + } + ); + + const pagination = usePaginationV2({ + currentRoute: '/images/image-library/$imageType', + preferenceKey: config.preferenceKey, + searchParams: (prev) => ({ + ...prev, + query: search.query, + }), + }); + + const { + handleOrderChange: handleImagesOrderChange, + order: imagesOrder, + orderBy: imagesOrderBy, + } = useOrderV2({ + initialRoute: { + defaultOrder: { + order: config.orderDefault, + orderBy: config.orderByDefault, + }, + from: '/images/image-library/$imageType', + }, + preferenceKey: config.preferenceKey, + prefix: config.type, + }); + + const imagesFilter: Filter = { + ['+order']: imagesOrder, + ['+order_by']: imagesOrderBy, + ...filter, + }; + + const { + data: images, + error: imagesError, + isFetching: imagesIsFetching, + isLoading: imagesLoading, + } = useImagesQuery( + { + page: pagination.page, + page_size: pagination.pageSize, + }, + { + ...imagesFilter, + is_public: false, + type: config.type, + }, + { + enabled: config.isEnabled(type), + // Refetch custom (manual) images every 30 seconds. + // We do this because we have no /v4/account/events we can use + // to update Image region statuses. We should make the API + // team and Images team implement events for this. + refetchInterval: config.type === 'manual' ? 30_000 : undefined, + // If we have a search query, disable retries to keep the UI + // snappy if the user inputs an invalid X-Filter. Otherwise, + // pass undefined to use the default retry behavior. + retry: search.query ? false : undefined, + } + ); + + const { events } = useEventsInfiniteQuery(); + + const imageEvents = + events?.filter( + (event) => + isEventInProgressDiskImagize(event) || isEventImageUpload(event) + ) ?? []; + + // Private images with the associated events tied in. + const imagesEvents = getEventsForImages(images?.data ?? [], imageEvents); + + const onSearch = (query: string) => { + navigate({ + search: (prev) => ({ + ...prev, + page: undefined, + query: query || undefined, + }), + to: '/images/image-library/$imageType', + params: { imageType: type }, + }); + }; + + if (imagesLoading) { + return ; + } + + if (!search.query && imagesError) { + return ( + + + + + ); + } + + return ( + <> + + + navigate({ + search: () => ({}), + to: config.buttonProps?.navigateTo ?? '/', + }), + disabled: !canCreateImage, + tooltipText: !canCreateImage + ? config.buttonProps.disabledToolTipText + : undefined, + } + : undefined, + docsLink: config.docsLink, + description: config.description, + }} + images={images?.data ?? []} + order={imagesOrder} + orderBy={imagesOrderBy} + pagination={{ + page: pagination.page, + pageSize: pagination.pageSize, + count: images?.results ?? 0, + handlePageChange: pagination.handlePageChange, + handlePageSizeChange: pagination.handlePageSizeChange, + }} + query={search.query} + /> + + ); +}; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.ts deleted file mode 100644 index b0d22445a0c..00000000000 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { ImageLibrarySubTab } from '../../../utils'; - -export const imageLibrarySubTabs: ImageLibrarySubTab[] = [ - { type: 'owned-by-me', title: 'Owned by me' }, - { - type: 'shared-with-me', - title: 'Shared with me', - isBeta: true, - }, - { type: 'recovery-images', title: 'Recovery images' }, -]; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx new file mode 100644 index 00000000000..6bf1942da1b --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx @@ -0,0 +1,130 @@ +import * as React from 'react'; + +import { Link } from 'src/components/Link'; +import { getRestrictedResourceText } from 'src/features/Account/utils'; + +import { + MANUAL_IMAGES_DEFAULT_ORDER, + MANUAL_IMAGES_DEFAULT_ORDER_BY, + MANUAL_IMAGES_PREFERENCE_KEY, +} from '../../../constants'; + +import type { ImageLibrarySubTab, ImageLibraryType } from '../../../utils'; +import type { Image } from '@linode/api-v4'; +import type { HiddenProps } from '@linode/ui'; + +export interface ImageViewTableColConfig { + /** Breakpoint to hide the column (e.g., 'smDown', 'mdUp', etc) */ + hiddenOn?: Exclude; + + /** Field name for sorting (required if sortable is `true`) */ + label?: string; + + /** Column name */ + name: React.ReactNode | string; + + /** Enable sorting for this column */ + sortable?: boolean; +} + +export interface ImageConfig { + buttonProps?: { + buttonText: string; + disabledToolTipText?: string; + navigateTo?: string; + }; + columns: ImageViewTableColConfig[]; + description: React.ReactNode; + docsLink?: string; + emptyMessage: { + instruction: string; + main: string; + }; + eventCategory: string; + isEnabled: (subType: ImageLibraryType | undefined) => boolean; + orderByDefault: string; + orderDefault: 'asc' | 'desc'; + preferenceKey: string; + title: string; + type: Image['type']; +} + +export const imageLibrarySubTabs: ImageLibrarySubTab[] = [ + { type: 'owned-by-me', title: 'Owned by me' }, + { + type: 'shared-with-me', + title: 'Shared with me', + isBeta: true, + }, + { type: 'recovery-images', title: 'Recovery images' }, +]; + +const CUSTOM_IMAGES_TABLE_COLUMNS: ImageViewTableColConfig[] = [ + { name: 'Image', label: 'label', sortable: true }, + { + name: 'Status', + hiddenOn: 'smDown', + }, + { + name: 'Replicated in', + hiddenOn: 'smDown', + }, + { name: 'Original Image', label: 'size', sortable: true }, + { + name: 'All Replicas', + hiddenOn: 'mdDown', + }, + { + name: 'Created', + label: 'created', + sortable: true, + hiddenOn: 'mdDown', + }, + { + name: 'Image ID', + hiddenOn: 'mdDown', + }, +]; + +export const IMAGES_CONFIG: Omit< + Record, + 'recovery-images' | 'shared-with-me' +> = { + 'owned-by-me': { + title: 'Owned by me', + description: ( + <> + These are{' '} + + encrypted + {' '} + images you manually uploaded or captured from an existing compute + instance disk. You can deploy an image to a compute instance in any + region. If you deploy the instance in a different region from where the + image is stored, you may experience slower linode deployment times. + + ), + type: 'manual', + orderByDefault: MANUAL_IMAGES_DEFAULT_ORDER_BY, + orderDefault: MANUAL_IMAGES_DEFAULT_ORDER, + preferenceKey: MANUAL_IMAGES_PREFERENCE_KEY, + isEnabled: (subType) => subType === 'owned-by-me', + columns: CUSTOM_IMAGES_TABLE_COLUMNS, + buttonProps: { + buttonText: 'Create Image', + navigateTo: '/images/create', + disabledToolTipText: getRestrictedResourceText({ + action: 'create', + isSingular: false, + resourceType: 'Images', + }), + }, + eventCategory: 'Custom Images Table', + emptyMessage: { + main: 'No custom images to display', + instruction: + 'Click \u2018Create Image\u2019 to create your first custom image', + }, + }, + // "shared-with-me", and 'recovery-images' images config will go here... +}; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImagesLandingV2.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImagesLandingV2.tsx index 7170e3d14c8..69bfb3eb266 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImagesLandingV2.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImagesLandingV2.tsx @@ -29,6 +29,7 @@ export const ImagesLandingV2 = () => { pathname: 'Images', removeCrumbX: 1, }} + docsLink="https://techdocs.akamai.com/cloud-computing/docs/images" spacingBottom={16} title="Images" /> diff --git a/packages/manager/src/features/Images/utils.test.tsx b/packages/manager/src/features/Images/utils.test.tsx index 87dcbedb154..0b53914d38b 100644 --- a/packages/manager/src/features/Images/utils.test.tsx +++ b/packages/manager/src/features/Images/utils.test.tsx @@ -8,6 +8,7 @@ import { getEventsForImages, getImageLabelForLinode, getImageLibrarySubTabIndex, + getImageTypeToImageLibraryType, useIsPrivateImageSharingEnabled, } from './utils'; @@ -119,3 +120,17 @@ describe('getImageLibrarySubTabIndex', () => { expect(getImageLibrarySubTabIndex([], 'owned-by-me')).toBe(0); }); }); + +describe('getImageTypeToImageLibraryType', () => { + it('returns "owned-by-me" when image type is "manual"', () => { + expect(getImageTypeToImageLibraryType('manual')).toBe('owned-by-me'); + }); + + it('returns "recovery-images" when image type is "automatic"', () => { + expect(getImageTypeToImageLibraryType('automatic')).toBe('recovery-images'); + }); + + it('returns "shared-with-me" when image type is "shared"', () => { + expect(getImageTypeToImageLibraryType('shared')).toBe('shared-with-me'); + }); +}); diff --git a/packages/manager/src/features/Images/utils.ts b/packages/manager/src/features/Images/utils.ts index 00ebc8402c8..e8fb09d9d84 100644 --- a/packages/manager/src/features/Images/utils.ts +++ b/packages/manager/src/features/Images/utils.ts @@ -98,3 +98,16 @@ export const getImageLibrarySubTabIndex = ( return tabIndex; }; + +export const getImageTypeToImageLibraryType = ( + imageType: Image['type'] +): ImageLibraryType => { + switch (imageType) { + case 'automatic': + return 'recovery-images'; + case 'manual': + return 'owned-by-me'; + default: + return 'shared-with-me'; + } +}; diff --git a/packages/manager/src/features/Search/useClientSideSearch.ts b/packages/manager/src/features/Search/useClientSideSearch.ts index fa885192829..a96a6d99856 100644 --- a/packages/manager/src/features/Search/useClientSideSearch.ts +++ b/packages/manager/src/features/Search/useClientSideSearch.ts @@ -28,6 +28,7 @@ import { volumeToSearchableItem, } from 'src/store/selectors/getSearchEntities'; +import { useIsPrivateImageSharingEnabled } from '../Images/utils'; import { search } from './utils'; import type { SearchableEntityType } from './search.interfaces'; @@ -42,6 +43,8 @@ interface Props { * based on a user's seach query. */ export const useClientSideSearch = ({ enabled, query }: Props) => { + const { isPrivateImageSharingEnabled } = useIsPrivateImageSharingEnabled(); + const { data: domains, error: domainsError, @@ -102,7 +105,10 @@ export const useClientSideSearch = ({ enabled, query }: Props) => { const searchableDomains = domains?.map(domainToSearchableItem) ?? []; const searchableVolumes = volumes?.map(volumeToSearchableItem) ?? []; - const searchableImages = privateImages?.map(imageToSearchableItem) ?? []; + const searchableImages = + privateImages?.map((img) => + imageToSearchableItem(img, isPrivateImageSharingEnabled) + ) ?? []; const searchableNodebalancers = nodebals?.map(nodeBalToSearchableItem) ?? []; const searchableFirewalls = firewalls?.map(firewallToSearchableItem) ?? []; const searchableDatabases = databases?.map(databaseToSearchableItem) ?? []; diff --git a/packages/manager/src/routes/images/index.ts b/packages/manager/src/routes/images/index.ts index 64ea9854b9e..7e1dac37a86 100644 --- a/packages/manager/src/routes/images/index.ts +++ b/packages/manager/src/routes/images/index.ts @@ -198,6 +198,34 @@ const imageLibraryTypeRoute = createRoute({ validateSearch: (search: ImagesSearchParams) => search, }); +const imageActionRouteV2 = createRoute({ + beforeLoad: async ({ params }) => { + if (!(params.action in imageActions)) { + throw redirect({ + search: () => ({}), + to: '/images', + }); + } + }, + getParentRoute: () => imageLibraryTypeRoute, + params: { + parse: ({ action, imageId }: ImageActionRouteParams) => ({ + action, + imageId, + }), + stringify: ({ action, imageId }: ImageActionRouteParams) => ({ + action, + imageId, + }), + }, + path: '$imageId/$action', + validateSearch: (search: ImagesSearchParams) => search, +}).lazy(() => + import('src/features/Images/ImagesLanding/v2/imagesLandingV2LazyRoute').then( + (m) => m.imagesLandingV2LazyRoute + ) +); + // Share Groups tab const shareGroupsLandingRoute = createRoute({ getParentRoute: () => imagesRoute, @@ -229,7 +257,9 @@ const shareGroupsIndexRoute = createRoute({ export const imagesRouteTree = imagesRoute.addChildren([ imagesIndexRoute.addChildren([imageActionRoute]), imageLibraryLandingRoute.addChildren([ - imageLibraryIndexRoute.addChildren([imageLibraryTypeRoute]), + imageLibraryIndexRoute.addChildren([ + imageLibraryTypeRoute.addChildren([imageActionRouteV2]), + ]), ]), shareGroupsLandingRoute.addChildren([shareGroupsIndexRoute]), imagesCreateRoute.addChildren([ diff --git a/packages/manager/src/store/selectors/getSearchEntities.ts b/packages/manager/src/store/selectors/getSearchEntities.ts index 10a92442ca4..2de80d2cad4 100644 --- a/packages/manager/src/store/selectors/getSearchEntities.ts +++ b/packages/manager/src/store/selectors/getSearchEntities.ts @@ -7,6 +7,7 @@ import { getStreamDescription, } from 'src/features/Delivery/deliveryUtils'; import { getFirewallDescription } from 'src/features/Firewalls/shared'; +import { getImageTypeToImageLibraryType } from 'src/features/Images/utils'; import { getDescriptionForCluster } from 'src/features/Kubernetes/kubeUtils'; import type { @@ -74,25 +75,32 @@ export const volumeToSearchableItem = (volume: Volume): SearchableItem => ({ value: volume.id, }); -export const imageToSearchableItem = (image: Image): SearchableItem => ({ - data: { - created: image.created, - description: - image.description && image.description.length > 1 - ? image.description - : `${image.size} MB, Replicated in ${pluralize( - 'region', - 'regions', - image.regions.length - )}`, - icon: 'image', - path: `/images?query="${image.label}"`, - tags: image.tags, - }, - entityType: 'image', - label: image.label, - value: image.id, -}); +export const imageToSearchableItem = ( + image: Image, + isPrivateImageSharingEnabled: boolean +): SearchableItem => { + return { + data: { + created: image.created, + description: + image.description && image.description.length > 1 + ? image.description + : `${image.size} MB, Replicated in ${pluralize( + 'region', + 'regions', + image.regions.length + )}`, + icon: 'image', + path: isPrivateImageSharingEnabled + ? `/images/image-library/${getImageTypeToImageLibraryType(image.type)}?query="${image.label}"` + : `/images?query="${image.label}"`, + tags: image.tags, + }, + entityType: 'image', + label: image.label, + value: image.id, + }; +}; export const domainToSearchableItem = (domain: Domain): SearchableItem => ({ data: { diff --git a/packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md b/packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md new file mode 100644 index 00000000000..d93ad8ea7fe --- /dev/null +++ b/packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md @@ -0,0 +1,5 @@ +--- +"@linode/ui": Upcoming Features +--- + +Add `ZeroStateSearchNarrowIcon` to UI package ([#13418](https://github.com/linode/manager/pull/13418)) diff --git a/packages/ui/src/assets/icons/index.ts b/packages/ui/src/assets/icons/index.ts index de34a548e07..bbbd03d8bac 100644 --- a/packages/ui/src/assets/icons/index.ts +++ b/packages/ui/src/assets/icons/index.ts @@ -31,3 +31,4 @@ export { default as VisibilityHideIcon } from './visibilityHide.svg'; export { default as VisibilityShowIcon } from './visibilityShow.svg'; export { default as WarningOutlinedIcon } from './warning-outlined.svg'; export { default as WarningIcon } from './warning.svg'; +export { default as ZeroStateSearchNarrowIcon } from './zero-state-search-narrow.svg'; diff --git a/packages/ui/src/assets/icons/zero-state-search-narrow.svg b/packages/ui/src/assets/icons/zero-state-search-narrow.svg new file mode 100644 index 00000000000..1d0a68c26d6 --- /dev/null +++ b/packages/ui/src/assets/icons/zero-state-search-narrow.svg @@ -0,0 +1,10 @@ + + + + + + + + + + From 9d3c20538af52f6298c96260773265b30a7dc0ed Mon Sep 17 00:00:00 2001 From: Dmytro Chyrva Date: Thu, 26 Feb 2026 13:31:19 +0100 Subject: [PATCH 15/56] fix: STORIF-239 - Object storage metrics fixed. (#13434) --- .../ObjectStorage/BucketDetail/MetricsTab/MetricsTab.tsx | 6 +++--- .../src/features/ObjectStorage/BucketDetail/index.tsx | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/MetricsTab/MetricsTab.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/MetricsTab/MetricsTab.tsx index bc7076fc263..32c76b1ba19 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/MetricsTab/MetricsTab.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/MetricsTab/MetricsTab.tsx @@ -3,16 +3,16 @@ import * as React from 'react'; import { CloudPulseDashboardWithFilters } from 'src/features/CloudPulse/Dashboard/CloudPulseDashboardWithFilters'; interface Props { - bucketName: string; + hostname: string; region: string; } -export const MetricsTab = ({ bucketName, region }: Props) => { +export const MetricsTab = ({ hostname, region }: Props) => { return ( ); }; diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx index b1110d69e7f..5f1efbf510f 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx @@ -148,7 +148,10 @@ export const BucketDetailLanding = React.memo(() => { {!!metricsTabIndex && ( - + )} From d7a6ceb78ecd272ba54b4e97720412e928bdf949 Mon Sep 17 00:00:00 2001 From: aaleksee-akamai Date: Fri, 27 Feb 2026 10:36:22 +0100 Subject: [PATCH 16/56] feat: [UIE-10309] - IAM: last login text for delegates (#13437) * feat: [UIE-10309] - IAM: last login text for delegates * Added changeset: IAM: update last login field for delegate users --- .../pr-13437-changed-1772019096600.md | 5 ++++ .../IAM/Users/UsersTable/UserRow.test.tsx | 15 ++++++------ .../features/IAM/Users/UsersTable/UserRow.tsx | 24 ++++++++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 packages/manager/.changeset/pr-13437-changed-1772019096600.md diff --git a/packages/manager/.changeset/pr-13437-changed-1772019096600.md b/packages/manager/.changeset/pr-13437-changed-1772019096600.md new file mode 100644 index 00000000000..adfe3719b78 --- /dev/null +++ b/packages/manager/.changeset/pr-13437-changed-1772019096600.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +IAM: update last login field for delegate users ([#13437](https://github.com/linode/manager/pull/13437)) diff --git a/packages/manager/src/features/IAM/Users/UsersTable/UserRow.test.tsx b/packages/manager/src/features/IAM/Users/UsersTable/UserRow.test.tsx index f8beb1d7945..72add097f05 100644 --- a/packages/manager/src/features/IAM/Users/UsersTable/UserRow.test.tsx +++ b/packages/manager/src/features/IAM/Users/UsersTable/UserRow.test.tsx @@ -81,16 +81,17 @@ describe('UserRow', () => { }); }); - it('renders username and user type, and does not render email for a Delegate user when isIAMDelegationEnabled flag is enabled', async () => { + it('renders username and user type, and does not render email and last login for a Delegate user when isIAMDelegationEnabled flag is enabled', async () => { const delegateUser = accountUserFactory.build({ user_type: 'delegate', + last_login: null, }); queryMocks.useProfile.mockReturnValue({ data: profileFactory.build({ user_type: 'child' }), }); - const { getByText, queryByText } = renderWithTheme( + const { getAllByText, getByText, queryByText } = renderWithTheme( wrapWithTableBody(, { flags: { iamDelegation: { enabled: true }, @@ -99,12 +100,10 @@ describe('UserRow', () => { ); expect(getByText(delegateUser.username)).toBeVisible(); - - await waitFor(() => { - expect(queryByText(delegateUser.email)).not.toBeInTheDocument(); - expect(getByText('Not applicable')).toBeVisible(); - expect(getByText('Delegate User')).toBeVisible(); - }); + expect(queryByText(delegateUser.email)).not.toBeInTheDocument(); + expect(queryByText('Never')).not.toBeInTheDocument(); + expect(getAllByText('Not applicable').length).toBe(2); + expect(getByText('Delegate User')).toBeVisible(); }); it('renders "Never" if last_login is null', async () => { diff --git a/packages/manager/src/features/IAM/Users/UsersTable/UserRow.tsx b/packages/manager/src/features/IAM/Users/UsersTable/UserRow.tsx index 9cf72bfee1d..135e1ba791b 100644 --- a/packages/manager/src/features/IAM/Users/UsersTable/UserRow.tsx +++ b/packages/manager/src/features/IAM/Users/UsersTable/UserRow.tsx @@ -118,7 +118,7 @@ export const UserRow = ({ onDelete, user }: Props) => { )} - + @@ -137,11 +137,29 @@ export const UserRow = ({ onDelete, user }: Props) => { * Display information about a Users last login * * - The component renders "Never" if last_login is `null` + * - The component renders "Not applicable" if the user is a delegate user * - The component renders a date if last_login is a success * - The component renders a date and a status if last_login is a failure */ -const LastLogin = (props: Pick) => { - const { last_login } = props; +const LastLogin = (props: Pick) => { + const { last_login, user_type } = props; + + if (user_type === 'delegate') { + return ( + + Not applicable + + + ); + } if (last_login === null) { return Never; From 4e922c0965c1dc0b1061c7cf4fff505db7c68095 Mon Sep 17 00:00:00 2001 From: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:01:28 +0100 Subject: [PATCH 17/56] fix: [M3-10329] - IAM Parent/Child: Use User infinite query in UpdateDelegationDrawer (#13441) * Use user inifinte query in UpdateDelegationDrawer * tests * Added changeset: IAM Parent/Child: Use User infinite query in UpdateDelegationDrawer --- .../pr-13441-fixed-1772114115915.md | 5 + .../Delegations/UpdateDelegationForm.test.tsx | 148 ++++++++++++++++++ .../IAM/Delegations/UpdateDelegationForm.tsx | 60 +++++-- .../UpdateDelegationsDrawer.test.tsx | 116 +------------- .../Delegations/UpdateDelegationsDrawer.tsx | 16 -- 5 files changed, 205 insertions(+), 140 deletions(-) create mode 100644 packages/manager/.changeset/pr-13441-fixed-1772114115915.md create mode 100644 packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.test.tsx diff --git a/packages/manager/.changeset/pr-13441-fixed-1772114115915.md b/packages/manager/.changeset/pr-13441-fixed-1772114115915.md new file mode 100644 index 00000000000..dc650537622 --- /dev/null +++ b/packages/manager/.changeset/pr-13441-fixed-1772114115915.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +IAM Parent/Child: Use User infinite query in UpdateDelegationDrawer ([#13441](https://github.com/linode/manager/pull/13441)) diff --git a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.test.tsx b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.test.tsx new file mode 100644 index 00000000000..0018e06236a --- /dev/null +++ b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.test.tsx @@ -0,0 +1,148 @@ +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { vi } from 'vitest'; + +import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; + +import { UpdateDelegationForm } from './UpdateDelegationForm'; + +import type { ChildAccountWithDelegates, User } from '@linode/api-v4'; + +beforeAll(() => mockMatchMedia()); + +const mocks = vi.hoisted(() => ({ + useAccountUsersInfiniteQuery: vi.fn(), + mockUseUpdateChildAccountDelegatesQuery: vi.fn(), + mockMutateAsync: vi.fn(), +})); + +vi.mock('@linode/queries', async () => { + const actual = await vi.importActual('@linode/queries'); + return { + ...actual, + useAccountUsersInfiniteQuery: mocks.useAccountUsersInfiniteQuery, + useUpdateChildAccountDelegatesQuery: + mocks.mockUseUpdateChildAccountDelegatesQuery, + }; +}); + +const mockUsers: User[] = [ + { + email: 'user1@example.com', + last_login: null, + password_created: null, + restricted: false, + ssh_keys: [], + tfa_enabled: false, + user_type: 'default', + username: 'user1', + verified_phone_number: null, + }, + { + email: 'user2@example.com', + last_login: null, + password_created: null, + restricted: false, + ssh_keys: [], + tfa_enabled: false, + user_type: 'default', + username: 'user2', + verified_phone_number: null, + }, +]; + +const mockChildAccountWithDelegates: ChildAccountWithDelegates = { + company: 'Test Company', + euuid: 'E1234567-89AB-CDEF-0123-456789ABCDEF', + users: ['user1'], +}; + +const defaultProps = { + delegation: mockChildAccountWithDelegates, + formattedCurrentUsers: [ + { label: mockUsers[0].username, value: mockUsers[0].username }, + ], + onClose: vi.fn(), +}; + +describe('UpdateDelegationsDrawer', () => { + beforeEach(() => { + vi.clearAllMocks(); + + mocks.useAccountUsersInfiniteQuery.mockReturnValue({ + data: { pages: [{ data: mockUsers }] }, + isFetching: false, + }); + + mocks.mockUseUpdateChildAccountDelegatesQuery.mockReturnValue({ + mutateAsync: mocks.mockMutateAsync, + }); + + mocks.mockMutateAsync.mockResolvedValue({}); + }); + + it('renders the drawer with current delegates', () => { + renderWithTheme(); + + const companyName = screen.getByText(/test company/i); + expect(companyName).toBeInTheDocument(); + const userName = screen.getByText(/user1/i); + expect(userName).toBeInTheDocument(); + }); + + it('allows adding a new delegate', async () => { + renderWithTheme(); + + const user = userEvent.setup(); + + const autocompleteInput = screen.getByRole('combobox'); + await user.click(autocompleteInput); + + await waitFor(async () => { + screen.getByRole('option', { name: 'user2' }); + }); + + const user2Option = screen.getByRole('option', { name: 'user2' }); + await user.click(user2Option); + + const submitButton = screen.getByRole('button', { name: /save changes/i }); + await user.click(submitButton); + + await waitFor(() => { + expect(mocks.mockMutateAsync).toHaveBeenCalledWith({ + euuid: mockChildAccountWithDelegates.euuid, + users: ['user1', 'user2'], + }); + }); + }); + + it('allows sending an empty payload', async () => { + renderWithTheme(); + + const user = userEvent.setup(); + + // Open the autocomplete and deselect the preselected user (user1) + const autocompleteInput = screen.getByRole('combobox'); + await user.click(autocompleteInput); + + await waitFor(() => { + // Ensure options are rendered + expect(screen.getByRole('option', { name: 'user1' })).toBeInTheDocument(); + }); + + const user1Option = screen.getByRole('option', { name: 'user1' }); + await user.click(user1Option); // toggles off the selected user + + // Submit with no users selected + const submitButton = screen.getByRole('button', { name: /save changes/i }); + await user.click(submitButton); + + await waitFor(() => { + expect(mocks.mockMutateAsync).toHaveBeenCalledWith({ + euuid: mockChildAccountWithDelegates.euuid, + users: [], + }); + }); + }); +}); diff --git a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx index 248519be736..80d2310f186 100644 --- a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx +++ b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx @@ -1,5 +1,9 @@ -import { useUpdateChildAccountDelegatesQuery } from '@linode/queries'; +import { + useAccountUsersInfiniteQuery, + useUpdateChildAccountDelegatesQuery, +} from '@linode/queries'; import { ActionsPanel, Autocomplete, Notice, Typography } from '@linode/ui'; +import { useDebouncedValue } from '@linode/utilities'; import { useTheme } from '@mui/material'; import { enqueueSnackbar } from 'notistack'; import * as React from 'react'; @@ -9,7 +13,11 @@ import { usePermissions } from '../hooks/usePermissions'; import { INTERNAL_ERROR_NO_CHANGES_SAVED } from '../Shared/constants'; import { getPlaceholder } from '../Shared/Entities/utils'; -import type { ChildAccount, ChildAccountWithDelegates } from '@linode/api-v4'; +import type { + ChildAccount, + ChildAccountWithDelegates, + Filter, +} from '@linode/api-v4'; interface UpdateDelegationsFormValues { users: UserOption[]; @@ -23,23 +31,38 @@ interface UserOption { interface DelegationsFormProps { delegation: ChildAccount | ChildAccountWithDelegates; formattedCurrentUsers: UserOption[]; - isLoading: boolean; onClose: () => void; - userOptions: UserOption[]; } + export const UpdateDelegationForm = ({ delegation, formattedCurrentUsers, - isLoading, onClose, - userOptions, }: DelegationsFormProps) => { const theme = useTheme(); + const [inputValue, setInputValue] = React.useState(''); + const debouncedInputValue = useDebouncedValue(inputValue); const { data: permissions } = usePermissions('account', [ 'update_delegate_users', ]); + const apiFilter: Filter = { + user_type: 'parent', + username: { '+contains': debouncedInputValue }, + }; + + const { data, error, fetchNextPage, hasNextPage, isFetching } = + useAccountUsersInfiniteQuery(apiFilter); + + const users = + data?.pages.flatMap((page) => { + return page.data.map((user) => ({ + label: user.username, + value: user.username, + })); + }) ?? []; + const { mutateAsync: updateDelegates } = useUpdateChildAccountDelegatesQuery(); @@ -112,23 +135,40 @@ export const UpdateDelegationForm = ({ render={({ field, fieldState }) => ( option.value === value.value } label={'Delegate Users'} - loading={isLoading} + loading={isFetching} multiple noMarginTop onChange={(_, newValue) => { field.onChange(newValue || []); }} - options={userOptions} + onInputChange={(_, value) => { + setInputValue(value); + }} + options={users} placeholder={getPlaceholder( 'delegates', field.value.length, - userOptions.length + users?.length ?? 0 )} + slotProps={{ + listbox: { + onScroll: (event: React.SyntheticEvent) => { + const listboxNode = event.currentTarget; + if ( + listboxNode.scrollTop + listboxNode.clientHeight >= + listboxNode.scrollHeight && + hasNextPage + ) { + fetchNextPage(); + } + }, + }, + }} textFieldProps={{ hideLabel: true, }} diff --git a/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.test.tsx b/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.test.tsx index c370d8a08a8..3fa42f2b00e 100644 --- a/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.test.tsx +++ b/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.test.tsx @@ -1,5 +1,4 @@ -import { screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { screen } from '@testing-library/react'; import React from 'react'; import { vi } from 'vitest'; @@ -7,51 +6,10 @@ import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; import { UpdateDelegationsDrawer } from './UpdateDelegationsDrawer'; -import type { ChildAccountWithDelegates, User } from '@linode/api-v4'; +import type { ChildAccountWithDelegates } from '@linode/api-v4'; beforeAll(() => mockMatchMedia()); -const mocks = vi.hoisted(() => ({ - mockUseAccountUsers: vi.fn(), - mockUseUpdateChildAccountDelegatesQuery: vi.fn(), - mockMutateAsync: vi.fn(), -})); - -vi.mock('@linode/queries', async () => { - const actual = await vi.importActual('@linode/queries'); - return { - ...actual, - useAccountUsers: mocks.mockUseAccountUsers, - useUpdateChildAccountDelegatesQuery: - mocks.mockUseUpdateChildAccountDelegatesQuery, - }; -}); - -const mockUsers: User[] = [ - { - email: 'user1@example.com', - last_login: null, - password_created: null, - restricted: false, - ssh_keys: [], - tfa_enabled: false, - user_type: 'default', - username: 'user1', - verified_phone_number: null, - }, - { - email: 'user2@example.com', - last_login: null, - password_created: null, - restricted: false, - ssh_keys: [], - tfa_enabled: false, - user_type: 'default', - username: 'user2', - verified_phone_number: null, - }, -]; - const mockChildAccountWithDelegates: ChildAccountWithDelegates = { company: 'Test Company', euuid: 'E1234567-89AB-CDEF-0123-456789ABCDEF', @@ -65,21 +23,6 @@ const defaultProps = { }; describe('UpdateDelegationsDrawer', () => { - beforeEach(() => { - vi.clearAllMocks(); - - mocks.mockUseAccountUsers.mockReturnValue({ - data: { data: mockUsers }, - isLoading: false, - }); - - mocks.mockUseUpdateChildAccountDelegatesQuery.mockReturnValue({ - mutateAsync: mocks.mockMutateAsync, - }); - - mocks.mockMutateAsync.mockResolvedValue({}); - }); - it('renders the drawer with current delegates', () => { renderWithTheme(); @@ -90,59 +33,4 @@ describe('UpdateDelegationsDrawer', () => { const userName = screen.getByText(/user1/i); expect(userName).toBeInTheDocument(); }); - - it('allows adding a new delegate', async () => { - renderWithTheme(); - - const user = userEvent.setup(); - - const autocompleteInput = screen.getByRole('combobox'); - await user.click(autocompleteInput); - - await waitFor(async () => { - screen.getByRole('option', { name: 'user2' }); - }); - - const user2Option = screen.getByRole('option', { name: 'user2' }); - await user.click(user2Option); - - const submitButton = screen.getByRole('button', { name: /save changes/i }); - await user.click(submitButton); - - await waitFor(() => { - expect(mocks.mockMutateAsync).toHaveBeenCalledWith({ - euuid: mockChildAccountWithDelegates.euuid, - users: ['user1', 'user2'], - }); - }); - }); - - it('allows sending an empty payload', async () => { - renderWithTheme(); - - const user = userEvent.setup(); - - // Open the autocomplete and deselect the preselected user (user1) - const autocompleteInput = screen.getByRole('combobox'); - await user.click(autocompleteInput); - - await waitFor(() => { - // Ensure options are rendered - expect(screen.getByRole('option', { name: 'user1' })).toBeInTheDocument(); - }); - - const user1Option = screen.getByRole('option', { name: 'user1' }); - await user.click(user1Option); // toggles off the selected user - - // Submit with no users selected - const submitButton = screen.getByRole('button', { name: /save changes/i }); - await user.click(submitButton); - - await waitFor(() => { - expect(mocks.mockMutateAsync).toHaveBeenCalledWith({ - euuid: mockChildAccountWithDelegates.euuid, - users: [], - }); - }); - }); }); diff --git a/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.tsx b/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.tsx index 3c01e8ce5fa..af44912eafa 100644 --- a/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.tsx +++ b/packages/manager/src/features/IAM/Delegations/UpdateDelegationsDrawer.tsx @@ -1,4 +1,3 @@ -import { useAccountUsers } from '@linode/queries'; import { Drawer } from '@linode/ui'; import React from 'react'; @@ -17,11 +16,6 @@ export const UpdateDelegationsDrawer = ({ onClose, open, }: Props) => { - const { data: allParentAccounts, isLoading } = useAccountUsers({ - enabled: open, - filters: { user_type: 'parent' }, - }); - const formattedCurrentUsers = React.useMemo(() => { if (delegation && 'users' in delegation && delegation.users) { return delegation.users.map((username) => ({ @@ -32,23 +26,13 @@ export const UpdateDelegationsDrawer = ({ return []; }, [delegation]); - const userOptions = React.useMemo(() => { - if (!allParentAccounts?.data) return []; - return allParentAccounts.data.map((user) => ({ - label: user.username, - value: user.username, - })); - }, [allParentAccounts]); - return ( {delegation && ( )} From 6383a6fa9c58da9d44cb6716610f1e5e422a54aa Mon Sep 17 00:00:00 2001 From: Purvesh Makode Date: Mon, 2 Mar 2026 14:44:51 +0530 Subject: [PATCH 18/56] upcoming: [UIE-9502] - Add Recovery Images tab (v2) (#13432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Split PR, and add more changes * Added changeset: Private Image Sharing tabs new layout (v2) * Few changes * Update few remaining references * Save progress.. * Update filename * Some refactoring and add reuseable images component * Change custom to owned (query params) * Update sharegroups to share-groups * Add more tests * Update remaining share-groups references * Few updates * More changes * Add ImagesView tests for custom images * Minor changes * Added changeset: Add reusable `ImagesView` and Integrate It for the `Owned by me` Images tab (v2) * Added changeset: Add `shared` to ImageType * Added changeset: Add `ZeroStateSearchNarrowIcon` to UI package * Update changeset * Clean up old query param from ImagesSearchParams * Update custom images desc and move styles to dedicated file * Add recovery images tab v2 * Minor change * Add tests in ImagesView for Recovery Images * Add unit tests in ImageLibraryTabs for recovery images * Few minor changes to tests * Update docsLink (for owned by me images) after latest UX update * Few changes to emptyMessage.instruction type * Add some changes related to docLink * Few updates * Simplify table col config for sorting * Update Recovery Images to Recovery images * Added changeset:  Add Recovery images tab (v2) * Prevent old action routes when flag is enabled and update table styles per UX --- ...r-13432-upcoming-features-1772094828866.md | 5 + .../v2/ImageLibrary/ImageLibraryTabs.test.tsx | 162 +++++++++++++++++- .../v2/ImageLibrary/ImageLibraryTabs.tsx | 3 +- .../v2/ImageLibrary/ImagesTable.styles.ts | 34 ++-- .../v2/ImageLibrary/ImagesTable.tsx | 158 +++++++++-------- .../v2/ImageLibrary/ImagesView.test.tsx | 106 ++++++++++++ .../v2/ImageLibrary/ImagesView.tsx | 2 +- .../ImageLibrary/imageLibraryTabsConfig.tsx | 73 ++++++-- packages/manager/src/routes/images/index.ts | 16 +- 9 files changed, 451 insertions(+), 108 deletions(-) create mode 100644 packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md diff --git a/packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md b/packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md new file mode 100644 index 00000000000..5dd40f2c799 --- /dev/null +++ b/packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + + Add Recovery images tab (v2) ([#13432](https://github.com/linode/manager/pull/13432)) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx index a59927ee485..36249ee5897 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.test.tsx @@ -16,6 +16,7 @@ const queryMocks = vi.hoisted(() => ({ useQueryWithPermissions: vi.fn().mockReturnValue({}), useLinodesPermissionsCheck: vi.fn().mockReturnValue({}), useSearch: vi.fn().mockReturnValue({}), + useParams: vi.fn(), })); vi.mock('src/features/IAM/hooks/usePermissions', () => ({ @@ -29,6 +30,7 @@ vi.mock('@tanstack/react-router', async () => { ...actual, useLocation: queryMocks.useLocation, useSearch: queryMocks.useSearch, + useParams: queryMocks.useParams, }; }); @@ -61,8 +63,12 @@ describe('ImageLibraryTabs', () => { }); }); - // For Custom Images (Owned by me) - describe('For Custom Images (Owned by me)', () => { + // For Custom images (Owned by me) + describe('For Custom images (Owned by me)', () => { + beforeEach(() => { + queryMocks.useParams.mockReturnValue({ imageType: 'owned-by-me' }); + }); + it("should render 'Owned by me' tab", async () => { const { getByText } = renderWithTheme(, { initialRoute: '/images/image-library/owned-by-me', @@ -71,7 +77,7 @@ describe('ImageLibraryTabs', () => { expect(getByText('Owned by me')).toBeVisible(); }); - // Test Image action navigations for CUSTOM IMAGES (Owned by me) + // Test Image action navigations for CUSTOM images (Owned by me) it('should allow opening the Edit Image drawer', async () => { const image = imageFactory.build(); @@ -207,6 +213,156 @@ describe('ImageLibraryTabs', () => { }); }); + // For Recovery images + describe('For Recovery images', () => { + beforeEach(() => { + queryMocks.useParams.mockReturnValue({ imageType: 'recovery-images' }); + }); + + it("should render 'Recovery images' tab", async () => { + const { getByText } = renderWithTheme(, { + initialRoute: '/images/image-library/recovery-images', + }); + + expect(getByText('Recovery images')).toBeVisible(); + }); + + // Test Images Action navigations for RECOVERY images + it('should allow opening the Edit Image drawer', async () => { + const image = imageFactory.build({ type: 'automatic' }); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('automatic')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { getByText, findByLabelText, router } = renderWithTheme( + , + { + initialRoute: '/images/image-library/recovery-images', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Edit')); + + expect(router.state.location.pathname).toBe( + `/images/image-library/recovery-images/${encodeURIComponent(image.id)}/edit` + ); + }); + + it('should allow opening the Restore Image drawer', async () => { + const image = imageFactory.build(); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('automatic')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { router, getByText, findByLabelText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/recovery-images', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Rebuild an Existing Linode')); + + expect(router.state.location.pathname).toBe( + `/images/image-library/recovery-images/${encodeURIComponent(image.id)}/rebuild` + ); + }); + + it('should allow deploying to a new Linode', async () => { + const image = imageFactory.build(); + queryMocks.useLinodesPermissionsCheck.mockReturnValue({ + availableLinodes: [linodeFactory.build()], + }); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('automatic')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { findByLabelText, getByText, queryAllByTestId, router } = + renderWithTheme(, { + initialRoute: '/images/image-library/recovery-images', + }); + + const loadingElement = queryAllByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Deploy to New Linode')); + + expect(router.state.location.pathname).toBe('/linodes/create/images'); + + expect(router.state.location.search).toStrictEqual({ + imageID: image.id, + }); + }); + + it('should allow deleting an image', async () => { + const image = imageFactory.build(); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('automatic')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { router, findByLabelText, getByText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/recovery-images', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + await userEvent.click(actionMenu); + await userEvent.click(getByText('Delete')); + + expect(router.state.location.pathname).toBe( + `/images/image-library/recovery-images/${encodeURIComponent(image.id)}/delete` + ); + }); + }); + it('should render Owned (custom), Shared and Recovery tabs under Images Library Tab', async () => { const { getByText } = renderWithTheme(, { initialRoute: '/images/image-library', diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx index b4ed02409ee..31ada64c651 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx @@ -147,8 +147,7 @@ export const ImageLibraryTabs = () => {
)} {tab.type === 'recovery-images' && ( - // - Recovery Images + )} ))} diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts index b6819eee6e8..15932720246 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts @@ -1,20 +1,18 @@ -import { Paper, Typography } from '@linode/ui'; +import { Box, Paper, Typography } from '@linode/ui'; import { styled } from '@mui/material/styles'; -export const StyledImageTable = styled(Paper, { label: 'StyledImageTable' })( - ({ theme }) => ({ - marginBottom: theme.spacingFunction(24), - padding: 0, - }) -); +export const StyledImageContainer = styled(Paper, { + label: 'StyledImageContainer', +})(({ theme }) => ({ + border: `1px solid ${theme.tokens.alias.Border.Normal}`, + marginBottom: theme.spacingFunction(24), + padding: 0, +})); -export const StyledImageTableHeader = styled('div', { +export const StyledImageTableHeader = styled(Box, { label: 'StyledImageTableHeader', })(({ theme }) => ({ - border: `1px solid ${theme.tokens.alias.Border.Normal}`, - borderBottom: 0, - padding: theme.spacingFunction(8), - paddingLeft: theme.spacingFunction(12), + padding: `${theme.spacingFunction(16)} ${theme.spacingFunction(24)} 0`, })); export const StyledImageTableSubheader = styled(Typography, { @@ -22,3 +20,15 @@ export const StyledImageTableSubheader = styled(Typography, { })(({ theme }) => ({ marginTop: theme.spacingFunction(8), })); + +export const StyledImageTableContainer = styled(Box, { + label: 'StyledImageTableContainer', +})(({ theme }) => ({ + padding: `${theme.spacingFunction(16)} ${theme.spacingFunction(24)} ${theme.spacingFunction(24)}`, + '& .MuiTable-root': { + border: 'none', + }, + '& [data-qa-table-pagination]': { + border: 'none', + }, +})); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx index 01816368b46..a38d56e0a5b 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.tsx @@ -20,7 +20,8 @@ import { TableSortCell } from 'src/components/TableSortCell'; import { ImageRow } from '../../ImageRow'; import { - StyledImageTable, + StyledImageContainer, + StyledImageTableContainer, StyledImageTableHeader, StyledImageTableSubheader, } from './ImagesTable.styles'; @@ -41,7 +42,7 @@ interface HeaderProps { tooltipText?: string; }; description?: React.ReactNode; - docsLink?: string; + docsLink?: ImageConfig['docsLink']; title: string; } @@ -87,7 +88,7 @@ export const ImagesTable = (props: ImagesTableProps) => { } = props; return ( - + {headerProps && headerProps.title && ( { }} > {headerProps.title} - + {headerProps.docsLink && ( )} {headerProps.buttonProps && ( @@ -124,18 +133,18 @@ export const ImagesTable = (props: ImagesTableProps) => { )} )} - - - - {columns.map((col, idx) => { - const cell = - col.sortable && col.label ? ( + +
+ + + {columns.map((col, idx) => { + const cell = col.sortableProps ? ( {col.name} @@ -143,66 +152,67 @@ export const ImagesTable = (props: ImagesTableProps) => { {col.name} ); - return col.hiddenOn ? ( - - {cell} - - ) : ( - cell - ); - })} - - - - - {!error && images?.length === 0 && ( - ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - gap: theme.spacingFunction(4), - p: `${theme.spacingFunction(24)} ${theme.spacingFunction(32)}`, - })} - > - - {emptyMessage.main} - {!query && ( - - {emptyMessage.instruction} - - )} - - } - /> - )} - {error && query && ( - - )} - {images?.map((image) => ( - - ))} - -
- -
+ return col.hiddenOn ? ( + + {cell} + + ) : ( + cell + ); + })} + + + + + {!error && images?.length === 0 && ( + ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: theme.spacingFunction(4), + p: `${theme.spacingFunction(24)} ${theme.spacingFunction(32)}`, + })} + > + + {emptyMessage.main} + {!query && emptyMessage.instruction && ( + + {emptyMessage.instruction} + + )} +
+ } + /> + )} + {error && query && ( + + )} + {images?.map((image) => ( + + ))} + + + + + ); }; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx index 75e110724f0..fb503342c00 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.test.tsx @@ -221,4 +221,110 @@ describe('ImagesView component', () => { expect(createButton).toBeEnabled(); }); }); + + // For Recovery images + describe('For Recovery images', () => { + it("should render 'Recovery images tab' with items", async () => { + server.use( + http.get('*/images', () => { + const images = imageFactory.buildList(3, { + regions: [ + { region: 'us-east', status: 'available' }, + { region: 'us-southeast', status: 'pending' }, + ], + type: 'automatic', + }); + return HttpResponse.json(makeResourcePage(images)); + }) + ); + + const { getByText, queryAllByTestId } = renderWithTheme( + , + { + initialRoute: '/images/image-library/recovery-images', + } + ); + + const loadingElement = queryAllByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + + // Recovery images table should render + getByText('Recovery images'); + + // Static text and table column headers + expect(getByText('Image')).toBeVisible(); + expect(getByText('Status')).toBeVisible(); + expect(getByText('Size')).toBeVisible(); + expect(getByText('Created')).toBeVisible(); + expect(getByText('Expires')).toBeVisible(); + }); + + it("should render 'Recovery images' (automatic) empty state", async () => { + server.use( + http.get('*/images', () => { + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { findByText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/recovery-images', + } + ); + + expect(await findByText('No recovery images to display')).toBeVisible(); + }); + + it('disables the action menu buttons if user does not have permissions to edit images', async () => { + queryMocks.usePermissions.mockReturnValue({ + data: { create_image: false }, + }); + const image = imageFactory.build({ + id: 'private/99999', + label: 'vi-test-image', + }); + queryMocks.useLinodesPermissionsCheck.mockReturnValue({ + availableLinodes: [], + }); + + server.use( + http.get('*/images', ({ request }) => { + const filter = request.headers.get('x-filter'); + + if (filter?.includes('automatic')) { + return HttpResponse.json(makeResourcePage([image])); + } + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { findByLabelText } = renderWithTheme( + , + { + initialRoute: '/images/image-library/recovery-images', + } + ); + + const actionMenu = await findByLabelText( + `Action menu for Image ${image.label}` + ); + + await userEvent.click(actionMenu); + + const disabledEditText = await findByLabelText( + "You don't have permissions to edit this Image. Please contact your account administrator to request the necessary permissions." + ); + const disabledDeleteText = await findByLabelText( + "You don't have permissions to delete this Image. Please contact your account administrator to request the necessary permissions." + ); + const disabledLinodeCreationText = await findByLabelText( + "You don't have permissions to create Linodes. Please contact your account administrator to request the necessary permissions." + ); + + expect(disabledEditText).toBeVisible(); + expect(disabledDeleteText).toBeVisible(); + expect(disabledLinodeCreationText).toBeVisible(); + }); + }); }); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx index bd3faab59bb..02793595192 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesView.tsx @@ -25,7 +25,7 @@ import type { Filter } from '@linode/api-v4'; interface Props { handlers: ImageHandlers; - type: Exclude; + type: Exclude; } export const ImagesView = (props: Props) => { diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx index 6bf1942da1b..7b789dfa4e7 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx @@ -4,6 +4,9 @@ import { Link } from 'src/components/Link'; import { getRestrictedResourceText } from 'src/features/Account/utils'; import { + AUTOMATIC_IMAGES_DEFAULT_ORDER, + AUTOMATIC_IMAGES_DEFAULT_ORDER_BY, + AUTOMATIC_IMAGES_PREFERENCE_KEY, MANUAL_IMAGES_DEFAULT_ORDER, MANUAL_IMAGES_DEFAULT_ORDER_BY, MANUAL_IMAGES_PREFERENCE_KEY, @@ -17,14 +20,16 @@ export interface ImageViewTableColConfig { /** Breakpoint to hide the column (e.g., 'smDown', 'mdUp', etc) */ hiddenOn?: Exclude; - /** Field name for sorting (required if sortable is `true`) */ - label?: string; - /** Column name */ - name: React.ReactNode | string; + name: string; - /** Enable sorting for this column */ - sortable?: boolean; + /** + * Provide sortableProps to enable sorting for this column. + */ + sortableProps?: { + /** API field used for sorting this column */ + label: string; + }; } export interface ImageConfig { @@ -35,9 +40,9 @@ export interface ImageConfig { }; columns: ImageViewTableColConfig[]; description: React.ReactNode; - docsLink?: string; + docsLink?: { href: string; label?: string }; emptyMessage: { - instruction: string; + instruction?: string; main: string; }; eventCategory: string; @@ -60,7 +65,7 @@ export const imageLibrarySubTabs: ImageLibrarySubTab[] = [ ]; const CUSTOM_IMAGES_TABLE_COLUMNS: ImageViewTableColConfig[] = [ - { name: 'Image', label: 'label', sortable: true }, + { name: 'Image', sortableProps: { label: 'label' } }, { name: 'Status', hiddenOn: 'smDown', @@ -69,15 +74,14 @@ const CUSTOM_IMAGES_TABLE_COLUMNS: ImageViewTableColConfig[] = [ name: 'Replicated in', hiddenOn: 'smDown', }, - { name: 'Original Image', label: 'size', sortable: true }, + { name: 'Original Image', sortableProps: { label: 'size' } }, { name: 'All Replicas', hiddenOn: 'mdDown', }, { name: 'Created', - label: 'created', - sortable: true, + sortableProps: { label: 'created' }, hiddenOn: 'mdDown', }, { @@ -86,9 +90,27 @@ const CUSTOM_IMAGES_TABLE_COLUMNS: ImageViewTableColConfig[] = [ }, ]; +const RECOVERY_IMAGES_TABLE_COLUMNS: ImageViewTableColConfig[] = [ + { name: 'Image', sortableProps: { label: 'label' } }, + { + name: 'Status', + hiddenOn: 'smDown', + }, + { name: 'Size', sortableProps: { label: 'size' } }, + { + name: 'Created', + sortableProps: { label: 'created' }, + hiddenOn: 'smDown', + }, + { + name: 'Expires', + hiddenOn: 'smDown', + }, +]; + export const IMAGES_CONFIG: Omit< Record, - 'recovery-images' | 'shared-with-me' + 'shared-with-me' > = { 'owned-by-me': { title: 'Owned by me', @@ -126,5 +148,28 @@ export const IMAGES_CONFIG: Omit< 'Click \u2018Create Image\u2019 to create your first custom image', }, }, - // "shared-with-me", and 'recovery-images' images config will go here... + 'recovery-images': { + title: 'Recovery images', + description: ( + <> + These are images we automatically capture when Linode disks are deleted. + They will be deleted after the indicated expiration date. + + ), + type: 'automatic', + orderByDefault: AUTOMATIC_IMAGES_DEFAULT_ORDER_BY, + orderDefault: AUTOMATIC_IMAGES_DEFAULT_ORDER, + preferenceKey: AUTOMATIC_IMAGES_PREFERENCE_KEY, + isEnabled: (subType) => subType === 'recovery-images', + columns: RECOVERY_IMAGES_TABLE_COLUMNS, + eventCategory: 'Recovery Images Table', + emptyMessage: { + main: 'No recovery images to display', + }, + docsLink: { + label: 'Recover a deleted Linode', + href: 'https://techdocs.akamai.com/cloud-computing/docs/images#recover-a-deleted', + }, + }, + // "shared-with-me" images config will go here }; diff --git a/packages/manager/src/routes/images/index.ts b/packages/manager/src/routes/images/index.ts index 7e1dac37a86..417214f67d6 100644 --- a/packages/manager/src/routes/images/index.ts +++ b/packages/manager/src/routes/images/index.ts @@ -68,7 +68,14 @@ const imagesIndexRoute = createRoute({ ); const imageActionRoute = createRoute({ - beforeLoad: async ({ params }) => { + beforeLoad: async ({ context, params }) => { + // Prevent access if private image sharing is enabled + if (context.isPrivateImageSharingEnabled) { + throw redirect({ + to: '/images/image-library/$imageType', + params: { imageType: 'owned-by-me' }, + }); + } if (!(params.action in imageActions)) { throw redirect({ search: () => ({}), @@ -154,9 +161,14 @@ const imageLibraryIndexRoute = createRoute({ to: '/images', }); } + + const normalizedPath = location.pathname.endsWith('/') + ? location.pathname.slice(0, -1) + : location.pathname; + if ( context.isPrivateImageSharingEnabled && - location.pathname === '/images/image-library' + normalizedPath === '/images/image-library' ) { throw redirect({ to: '/images/image-library/$imageType', From 8aca15ad6228e4209c462a4aee7370994f1c1ece Mon Sep 17 00:00:00 2001 From: mpolotsk-akamai <157619599+mpolotsk-akamai@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:02:57 +0100 Subject: [PATCH 19/56] fix: [UIE-10253], [UIE-10255], [UIE-10328], [UIE-10360] - IAM Delegate Switch Account company name fix (#13433) * fix: [UIE-10253] - IAM Delegate: company name for users with no permissions * fix: [UIE-10253] - IAM Delegate: clear storage * fix: [UIE-10253] - IAM Delegate: hide company name for users with no permission * test fix * mock delegation feature flag * UIE-10360: Navigate to Linodes landing page after switching back to parent account --- .../parentChild/account-switching.spec.ts | 5 + .../features/Account/SwitchAccountButton.tsx | 7 +- .../features/Account/SwitchAccountDrawer.tsx | 102 +++++++++--------- .../useSwitchToParentAccount.ts | 8 +- .../features/TopMenu/UserMenu/UserMenu.tsx | 7 +- .../TopMenu/UserMenu/UserMenuPopover.tsx | 11 +- 6 files changed, 83 insertions(+), 57 deletions(-) diff --git a/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts b/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts index 3d88c570b0d..768cd7071c4 100644 --- a/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts +++ b/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts @@ -22,6 +22,7 @@ import { mockGetUser, } from 'support/intercepts/account'; import { mockGetEvents, mockGetNotifications } from 'support/intercepts/events'; +import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { mockAllApiRequests } from 'support/intercepts/general'; import { mockGetRolePermissionsError, @@ -151,6 +152,10 @@ const mockAlternateChildAccountToken = appTokenFactory.build({ const mockErrorMessage = 'An unknown error has occurred.'; describe('Parent/Child account switching', () => { + beforeEach(() => { + // Disable IAM delegation to use legacy child accounts flow for all tests + mockAppendFeatureFlags({ iamDelegation: false }); + }); /* * Tests to confirm that Parent account users can switch to Child accounts as expected. */ diff --git a/packages/manager/src/features/Account/SwitchAccountButton.tsx b/packages/manager/src/features/Account/SwitchAccountButton.tsx index ef6ce0568ef..c1f4a07f1b5 100644 --- a/packages/manager/src/features/Account/SwitchAccountButton.tsx +++ b/packages/manager/src/features/Account/SwitchAccountButton.tsx @@ -19,10 +19,15 @@ export const SwitchAccountButton = (props: ButtonProps) => { }, font: theme.tokens.alias.Typography.Label.Semibold.S, marginTop: theme.tokens.spacing.S4, + ...(isDelegateUserType && { + '&.MuiButton-root': { + textTransform: 'none', + }, + }), })} {...props} > - {isDelegateUserType ? 'Switch back to your account' : 'Switch Account'} + {isDelegateUserType ? 'Switch Back to Your Account' : 'Switch Account'} ); }; diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index 37ef1d6dbd4..1699e2aa5e2 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -159,12 +159,18 @@ export const SwitchAccountDrawer = (props: Props) => { userType: isIAMDelegationEnabled ? 'delegate' : 'proxy', }); onClose(event); - location.replace('/linodes'); + + // Only redirect to /linodes for IAM delegate users + if (isIAMDelegationEnabled) { + location.replace('/linodes'); + } else { + location.reload(); + } } catch { // Error is handled by createTokenError. } }, - [createToken, isProxyUserType, updateCurrentToken, revokeToken] + [createToken, updateCurrentToken, revokeToken, isIAMDelegationEnabled] ); const [isSwitchingChildAccounts, setIsSwitchingChildAccounts] = @@ -243,7 +249,7 @@ export const SwitchAccountDrawer = (props: Props) => { . - {hasError && ( + {hasError ? ( Unable to load data. @@ -260,8 +266,7 @@ export const SwitchAccountDrawer = (props: Props) => { Try again - )} - {!hasError && ( + ) : ( <> { No search results )} + + {isIAMDelegationEnabled && ( + + )} + {!isIAMDelegationEnabled && ( + + )} )} - {isIAMDelegationEnabled && ( - - )} - {!isIAMDelegationEnabled && ( - - )} ); }; diff --git a/packages/manager/src/features/Account/SwitchAccounts/useSwitchToParentAccount.ts b/packages/manager/src/features/Account/SwitchAccounts/useSwitchToParentAccount.ts index f9ea6ec5efb..94a98755342 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/useSwitchToParentAccount.ts +++ b/packages/manager/src/features/Account/SwitchAccounts/useSwitchToParentAccount.ts @@ -55,7 +55,13 @@ export const useSwitchToParentAccount = ({ } onClose?.(); - location.reload(); + + // For switch back to parent, always redirect to /linodes for delegate users + if (isDelegateUserType) { + location.replace('/linodes'); + } else { + location.reload(); + } } catch (error) { setSubmitting(false); throw error; diff --git a/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx b/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx index 0b712bc1248..9cae73e0e82 100644 --- a/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx +++ b/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx @@ -83,9 +83,10 @@ export const UserMenu = React.memo(() => { setStorage('is_delegate_user_type', 'true'); } - enqueueSnackbar(`Account switched to ${companyNameOrEmail}.`, { - variant: 'success', - }); + const message = companyNameOrEmail + ? `Account switched to ${companyNameOrEmail}.` + : 'Account switched.'; + enqueueSnackbar(message, { variant: 'success' }); } }, [ isProxyOrDelegateUserType, diff --git a/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx b/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx index 4c159f880f0..d5b6997d94e 100644 --- a/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx +++ b/packages/manager/src/features/TopMenu/UserMenu/UserMenuPopover.tsx @@ -236,8 +236,11 @@ export const UserMenuPopover = (props: UserMenuPopoverProps) => { gap={(theme) => theme.tokens.spacing.S16} minWidth={250} > - theme.tokens.spacing.S8}> - {canSwitchBetweenParentOrProxyAccount && ( + (companyNameOrEmail ? theme.tokens.spacing.S8 : 0)} + > + {canSwitchBetweenParentOrProxyAccount && companyNameOrEmail && ( ({ color: theme.tokens.alias.Content.Text.Primary.Default, @@ -254,8 +257,8 @@ export const UserMenuPopover = (props: UserMenuPopoverProps) => { overflowWrap: 'break-word', })} > - {canSwitchBetweenParentOrProxyAccount && companyNameOrEmail - ? companyNameOrEmail + {canSwitchBetweenParentOrProxyAccount + ? companyNameOrEmail || null : userName} {canSwitchBetweenParentOrProxyAccount && ( From cfdfeb34557249dfa7be27b0f0d3125003fb20ef Mon Sep 17 00:00:00 2001 From: aaleksee-akamai Date: Mon, 2 Mar 2026 15:13:53 +0100 Subject: [PATCH 20/56] feat: [UIE-10284] - IAM: session token refresh (#13430) * feat: [UIE-10284] - IAM: session token refresh * store euuid for non admin users * remove a comment * cleanup * remove logic for keeping euuid --- packages/api-v4/src/iam/delegation.ts | 8 +++++- packages/api-v4/src/iam/delegation.types.ts | 6 +++- .../features/Account/SwitchAccountDrawer.tsx | 4 +-- .../SessionExpirationDialog.tsx | 4 +-- .../useParentChildAuthentication.tsx | 28 +++++++++++-------- packages/manager/src/routes/IAM/index.ts | 4 ++- packages/queries/src/iam/delegation.ts | 12 ++++---- 7 files changed, 39 insertions(+), 27 deletions(-) diff --git a/packages/api-v4/src/iam/delegation.ts b/packages/api-v4/src/iam/delegation.ts index 18f439153d3..219a18f313e 100644 --- a/packages/api-v4/src/iam/delegation.ts +++ b/packages/api-v4/src/iam/delegation.ts @@ -1,6 +1,7 @@ import { BETA_API_ROOT } from '../constants'; import Request, { setData, + setHeaders, setMethod, setParams, setURL, @@ -12,6 +13,7 @@ import type { Token } from '../profile'; import type { ResourcePage as Page } from '../types'; import type { ChildAccount, + ChildAccountTokenPayload, ChildAccountWithDelegates, GetChildAccountDelegatesParams, GetChildAccountsIamParams, @@ -98,12 +100,16 @@ export const getDelegatedChildAccount = ({ euuid }: { euuid: string }) => setMethod('GET'), ); -export const generateChildAccountToken = ({ euuid }: { euuid: string }) => +export const generateChildAccountToken = ({ + euuid, + headers, +}: ChildAccountTokenPayload) => Request( setURL( `${BETA_API_ROOT}/iam/delegation/profile/child-accounts/${encodeURIComponent(euuid)}/token`, ), setMethod('POST'), + setHeaders(headers), setData(euuid), ); diff --git a/packages/api-v4/src/iam/delegation.types.ts b/packages/api-v4/src/iam/delegation.types.ts index 953ca57c467..14791a5b2b7 100644 --- a/packages/api-v4/src/iam/delegation.types.ts +++ b/packages/api-v4/src/iam/delegation.types.ts @@ -1,4 +1,4 @@ -import type { Filter, Params } from 'src/types'; +import type { Filter, Params, RequestOptions } from '../types'; export interface ChildAccount { company: string; @@ -37,3 +37,7 @@ export interface UpdateChildAccountDelegatesParams { euuid: string; users: string[]; } + +export interface ChildAccountTokenPayload extends RequestOptions { + euuid: string; +} diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index 1699e2aa5e2..8faed748301 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -103,7 +103,7 @@ export const SwitchAccountDrawer = (props: Props) => { } : undefined, }, - isIAMDelegationEnabled === false + isIAMDelegationEnabled === false && isParentUserType ); const { @@ -170,7 +170,7 @@ export const SwitchAccountDrawer = (props: Props) => { // Error is handled by createTokenError. } }, - [createToken, updateCurrentToken, revokeToken, isIAMDelegationEnabled] + [createToken, isIAMDelegationEnabled, updateCurrentToken, revokeToken] ); const [isSwitchingChildAccounts, setIsSwitchingChildAccounts] = diff --git a/packages/manager/src/features/Account/SwitchAccounts/SessionExpirationDialog.tsx b/packages/manager/src/features/Account/SwitchAccounts/SessionExpirationDialog.tsx index 383afb8d172..807e681cd02 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/SessionExpirationDialog.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/SessionExpirationDialog.tsx @@ -25,7 +25,6 @@ export const SessionExpirationDialog = React.memo( ); const { isProxyUserType, isDelegateUserType } = useDelegationRole(); const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled(); - const [timeRemaining, setTimeRemaining] = React.useState<{ minutes: number; seconds: number; @@ -121,7 +120,6 @@ export const SessionExpirationDialog = React.memo( setTokenInLocalStorage({ prefix: tokenPrefix, - token: { ...proxyToken, token: `Bearer ${proxyToken.token}`, @@ -145,7 +143,7 @@ export const SessionExpirationDialog = React.memo( */ useEffect(() => { const checkTokenExpiry = () => { - const expiryString = isIAMDelegationEnabled + const expiryString = isProxyUserType ? getStorage('authentication/proxy_token/expire') : getStorage('authentication/delegate_token/expire'); diff --git a/packages/manager/src/features/Account/SwitchAccounts/useParentChildAuthentication.tsx b/packages/manager/src/features/Account/SwitchAccounts/useParentChildAuthentication.tsx index d7866b8eb6e..b43bc169a04 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/useParentChildAuthentication.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/useParentChildAuthentication.tsx @@ -47,18 +47,22 @@ export const useParentChildAuthentication = () => { const createToken = useCallback( async (euuid: string): Promise => { - return isIAMDelegationEnabled - ? generateProxyToken({ euuid }) - : createProxyToken({ - euuid, - headers: { - /** - * Headers are required for proxy or delegate users when obtaining a proxy or delegate token. - * For 'proxy' or 'delegate' userType, use the stored parent token in the request. - */ - Authorization: getStorage('authentication/parent_token/token'), - }, - }); + const tokenParent = getStorage('authentication/parent_token/token'); + + const mutationFn = isIAMDelegationEnabled + ? generateProxyToken + : createProxyToken; + + return mutationFn({ + euuid, + headers: { + /** + * Headers are required for proxy or delegate users when obtaining a proxy or delegate token. + * For 'proxy' or 'delegate' userType, use the stored parent token in the request. + */ + Authorization: tokenParent, + }, + }); }, [createProxyToken, generateProxyToken, isIAMDelegationEnabled] ); diff --git a/packages/manager/src/routes/IAM/index.ts b/packages/manager/src/routes/IAM/index.ts index 54cb093ee29..a13e2dcfaba 100644 --- a/packages/manager/src/routes/IAM/index.ts +++ b/packages/manager/src/routes/IAM/index.ts @@ -178,7 +178,9 @@ const iamDelegationsRoute = createRoute({ } const isChildAccount = profile?.user_type === 'child'; - if (!isDelegationEnabled || isChildAccount) { + const isDelegateAccount = profile?.user_type === 'delegate'; + const isChildOrDelegate = isChildAccount || isDelegateAccount; + if (!isDelegationEnabled || isChildOrDelegate) { throw redirect({ to: '/iam/users', replace: true, diff --git a/packages/queries/src/iam/delegation.ts b/packages/queries/src/iam/delegation.ts index d50d49599ba..36c2bf95f1e 100644 --- a/packages/queries/src/iam/delegation.ts +++ b/packages/queries/src/iam/delegation.ts @@ -21,6 +21,7 @@ import type { Account, APIError, ChildAccount, + ChildAccountTokenPayload, ChildAccountWithDelegates, GetChildAccountDelegatesParams, GetChildAccountsIamParams, @@ -233,13 +234,10 @@ export const useGetChildAccountQuery = ( * - Audience: Clients that need temporary auth to perform actions in the child account. * - Data: Token for `POST /iam/delegation/child-accounts/:euuid/token`. */ -export const useGenerateChildAccountTokenQuery = (): UseMutationResult< - Token, - APIError[], - { euuid: string } -> => { - return useMutation({ - mutationFn: generateChildAccountToken, +export const useGenerateChildAccountTokenQuery = () => { + return useMutation({ + mutationFn: ({ euuid, headers }: ChildAccountTokenPayload) => + generateChildAccountToken({ euuid, headers }), }); }; From 10b05522f4a72d078b0269df502b9846a5e195b1 Mon Sep 17 00:00:00 2001 From: hmorris3293 Date: Mon, 2 Mar 2026 12:11:05 -0500 Subject: [PATCH 21/56] feat: [OCA-1639] - Add Gemma3, Qwen, Milvus, pgvector, and GPT-oss Markeplace apps (#13420) * add marketpalce apps feb * add categories for mern & plex * Added changeset: Add Gemma3, Qwen, Milvus, pgvector, and GPT-oss Markeplace apps --- .../pr-13420-added-1771523317072.md | 5 + packages/manager/public/assets/gemma3.svg | 18 +++ packages/manager/public/assets/gptoss.svg | 20 +++ packages/manager/public/assets/milvus.svg | 32 +++++ packages/manager/public/assets/pgvector.svg | 18 +++ packages/manager/public/assets/qwen.svg | 29 ++++ .../manager/public/assets/white/gemma3.svg | 12 ++ .../manager/public/assets/white/gptoss.svg | 20 +++ .../manager/public/assets/white/milvus.svg | 32 +++++ .../manager/public/assets/white/pgvector.svg | 18 +++ packages/manager/public/assets/white/qwen.svg | 13 ++ .../src/features/OneClickApps/oneClickApps.ts | 134 +++++++++++++++--- 12 files changed, 335 insertions(+), 16 deletions(-) create mode 100644 packages/manager/.changeset/pr-13420-added-1771523317072.md create mode 100644 packages/manager/public/assets/gemma3.svg create mode 100644 packages/manager/public/assets/gptoss.svg create mode 100644 packages/manager/public/assets/milvus.svg create mode 100644 packages/manager/public/assets/pgvector.svg create mode 100644 packages/manager/public/assets/qwen.svg create mode 100644 packages/manager/public/assets/white/gemma3.svg create mode 100644 packages/manager/public/assets/white/gptoss.svg create mode 100644 packages/manager/public/assets/white/milvus.svg create mode 100644 packages/manager/public/assets/white/pgvector.svg create mode 100644 packages/manager/public/assets/white/qwen.svg diff --git a/packages/manager/.changeset/pr-13420-added-1771523317072.md b/packages/manager/.changeset/pr-13420-added-1771523317072.md new file mode 100644 index 00000000000..66f3ce2e9ac --- /dev/null +++ b/packages/manager/.changeset/pr-13420-added-1771523317072.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Added +--- + +Add Gemma3, Qwen, Milvus, pgvector, and GPT-oss Markeplace apps ([#13420](https://github.com/linode/manager/pull/13420)) diff --git a/packages/manager/public/assets/gemma3.svg b/packages/manager/public/assets/gemma3.svg new file mode 100644 index 00000000000..a11483caa3f --- /dev/null +++ b/packages/manager/public/assets/gemma3.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/gptoss.svg b/packages/manager/public/assets/gptoss.svg new file mode 100644 index 00000000000..e9546beda4b --- /dev/null +++ b/packages/manager/public/assets/gptoss.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/milvus.svg b/packages/manager/public/assets/milvus.svg new file mode 100644 index 00000000000..27cc4a9349f --- /dev/null +++ b/packages/manager/public/assets/milvus.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/manager/public/assets/pgvector.svg b/packages/manager/public/assets/pgvector.svg new file mode 100644 index 00000000000..1b0b11c41df --- /dev/null +++ b/packages/manager/public/assets/pgvector.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/qwen.svg b/packages/manager/public/assets/qwen.svg new file mode 100644 index 00000000000..5a6a0516ce1 --- /dev/null +++ b/packages/manager/public/assets/qwen.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/white/gemma3.svg b/packages/manager/public/assets/white/gemma3.svg new file mode 100644 index 00000000000..0c89e9c3989 --- /dev/null +++ b/packages/manager/public/assets/white/gemma3.svg @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/white/gptoss.svg b/packages/manager/public/assets/white/gptoss.svg new file mode 100644 index 00000000000..f33e1102ac9 --- /dev/null +++ b/packages/manager/public/assets/white/gptoss.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/white/milvus.svg b/packages/manager/public/assets/white/milvus.svg new file mode 100644 index 00000000000..1f75afabddf --- /dev/null +++ b/packages/manager/public/assets/white/milvus.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/manager/public/assets/white/pgvector.svg b/packages/manager/public/assets/white/pgvector.svg new file mode 100644 index 00000000000..e6f421e9da9 --- /dev/null +++ b/packages/manager/public/assets/white/pgvector.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/public/assets/white/qwen.svg b/packages/manager/public/assets/white/qwen.svg new file mode 100644 index 00000000000..fd5a7b6ad30 --- /dev/null +++ b/packages/manager/public/assets/white/qwen.svg @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/src/features/OneClickApps/oneClickApps.ts b/packages/manager/src/features/OneClickApps/oneClickApps.ts index 4042bdd713c..0d4ec40f5f2 100644 --- a/packages/manager/src/features/OneClickApps/oneClickApps.ts +++ b/packages/manager/src/features/OneClickApps/oneClickApps.ts @@ -68,7 +68,7 @@ export const oneClickApps: Record = { 401702: { alt_description: 'React and Node.js stack.', alt_name: 'Web stack', - categories: [], + categories: ['Stacks'], colors: { end: '256291', start: '30383a', @@ -479,7 +479,7 @@ export const oneClickApps: Record = { alt_description: 'Video / media library storage and sharing across TVs, phones, computers, and more.', alt_name: 'Media server', - categories: [], + categories: ['Media and Entertainment'], colors: { end: '332c37', start: 'e5a00d', @@ -1831,7 +1831,6 @@ export const oneClickApps: Record = { start: '85A355', }, description: `Distributed, masterless, replicating NoSQL database cluster.`, - isNew: false, logo_url: 'apachecassandra.svg', related_guides: [ { @@ -1891,7 +1890,6 @@ export const oneClickApps: Record = { start: 'AAAAAA', }, description: `High performance, BSD license key/value database.`, - isNew: false, logo_url: 'valkey.svg', related_guides: [ { @@ -1911,7 +1909,6 @@ export const oneClickApps: Record = { start: 'FFBA01', }, description: `OSI approved open source secrets platform.`, - isNew: false, logo_url: 'openbao.svg', related_guides: [ { @@ -1931,7 +1928,6 @@ export const oneClickApps: Record = { start: '9D29FB', }, description: `Time series database supporting native query and visualization.`, - isNew: false, logo_url: 'influxdb.svg', related_guides: [ { @@ -1952,7 +1948,6 @@ export const oneClickApps: Record = { start: '1D678F', }, description: `Fast, open-source unified analytics engine for large-scale data processing.`, - isNew: true, logo_url: 'apachespark.svg', related_guides: [ { @@ -1993,7 +1988,6 @@ export const oneClickApps: Record = { start: '9BF0E1', }, description: `Platform for building developer portals designed to simplify and unify software development processes.`, - isNew: true, logo_url: 'backstage.svg', related_guides: [ { @@ -2014,7 +2008,6 @@ export const oneClickApps: Record = { }, description: 'Netfoundry Edge Router is a software gateway that enables secure, zero-trust, high-performance connectivity between local networks, cloud environments, and applications.', - isNew: true, logo_url: 'netfoundry.svg', related_guides: [ { @@ -2036,7 +2029,6 @@ export const oneClickApps: Record = { }, description: 'ArangoDB is a multi-model database that combines the power of graphs, documents, and key-value pairs in a single engine. It provides ACID transactions, flexible data modeling, and powerful query capabilities with AQL (ArangoDB Query Language). Perfect for applications requiring complex data relationships, real-time analytics, and scalable performance.', - isNew: true, logo_url: 'arangodb.svg', related_guides: [ { @@ -2059,7 +2051,6 @@ export const oneClickApps: Record = { }, description: 'Memgraph is a high-performance, in-memory graph database designed for real-time analytics and streaming data. It uses the Cypher query language and supports powerful graph algorithms out of the box. With built-in support for streaming data, Memgraph makes it easy to build apps that respond instantly to changes in complex connected data.', - isNew: true, logo_url: 'memgraph.svg', related_guides: [ { @@ -2082,7 +2073,6 @@ export const oneClickApps: Record = { }, description: 'Neo4j is a high-performance, open-source property graph database designed to store and query data as a network of connected nodes and relationships. It is optimized for handling complex, interconnected data and supports the Cypher query language for expressive and efficient graph queries.', - isNew: true, logo_url: 'neo4j.svg', related_guides: [ { @@ -2121,7 +2111,6 @@ export const oneClickApps: Record = { start: 'ffffff', }, description: `Cribl Stream is an observability pipeline that helps organizations collect, reduce, enrich, and route telemetry data in real-time. It connects with 80+ sources and destinations, enabling you to handle data from any source to any analytics tool. Cribl Stream helps reduce data volume and optimize log processing to cut costs, enhance data security with encryption and access controls, and transform data using AI-powered tools. The platform scales from small to enterprise-level deployments and acts as a universal data management layer, giving organizations more control and efficiency in handling their telemetry data across various systems.`, - isNew: true, logo_url: 'cribl.svg', related_guides: [ { @@ -2141,7 +2130,6 @@ export const oneClickApps: Record = { start: '648c19', }, description: `Jaeger all-in-one is a complete distributed tracing solution deployed as a single Docker container that includes the Jaeger UI, Collector, Query service, Agent, and in-memory storage. This integrated setup is designed for development, testing, and quick deployment scenarios where you need full tracing capabilities without complex distributed architecture. Jaeger helps developers track request flows across microservices, identify performance bottlenecks, analyze service dependencies, and troubleshoot errors in distributed applications. The all-in-one image supports various tracing protocols including Zipkin and Jaeger's own formats, making it ideal for getting started with distributed tracing.`, - isNew: true, logo_url: 'jaeger.svg', related_guides: [ { @@ -2179,7 +2167,7 @@ export const oneClickApps: Record = { alt_description: 'Weaviate is an open-source vector database designed to store and index both data objects and their vector embeddings.', alt_name: 'Open-source vector database.', - categories: ['Vector Databases'], + categories: ['Databases', 'Vector Databases', 'AI'], colors: { end: 'c4d132', start: '53b83d', @@ -2202,7 +2190,7 @@ export const oneClickApps: Record = { alt_description: 'ChromaDB is an open-source vector database designed for building AI applications. It lets you easily store, index, and query embeddings.', alt_name: 'Open-source vector database.', - categories: ['Vector Databases'], + categories: ['Databases', 'Vector Databases', 'AI'], colors: { end: 'ffde2c', start: '327eff', @@ -2243,4 +2231,118 @@ export const oneClickApps: Record = { summary: 'Open-source AI web and chat interface.', website: 'https://docs.openwebui.com/getting-started/', }, + 1972184: { + alt_description: + 'PostgreSQL extension for vector similarity search and AI embeddings.', + alt_name: 'Open-source vector database extension', + categories: ['Databases', 'Vector Databases', 'AI'], + colors: { + end: '336791', + start: '4ea8de', + }, + description: + 'pgvector is an open-source PostgreSQL extension that enables vector similarity search directly within your database. It allows you to store embeddings and perform efficient nearest neighbor queries, making it ideal for AI applications such as semantic search, recommendation systems, and retrieval-augmented generation (RAG).', + isNew: true, + logo_url: 'pgvector.svg', + related_guides: [ + { + href: 'https://www.linode.com/docs/marketplace-docs/guides/pgvector', + title: 'Deploy pgvector', + }, + ], + summary: + 'PostgreSQL extension for vector similarity search and AI workloads.', + website: 'https://github.com/pgvector/pgvector', + }, + 2011033: { + alt_description: + 'Open-source vector database built for scalable AI similarity search.', + alt_name: 'Open-source vector database', + categories: ['Databases', 'Vector Databases', 'AI'], + colors: { + end: '00bfa6', + start: '1f2937', + }, + description: + 'Milvus is an open-source vector database designed for high-performance similarity search and AI workloads. It enables you to store, index, and search massive embedding datasets efficiently, making it ideal for semantic search, recommendation systems, computer vision, and retrieval-augmented generation (RAG) applications.', + isNew: true, + logo_url: 'milvus.svg', + related_guides: [ + { + href: 'https://www.linode.com/docs/marketplace-docs/guides/milvus', + title: 'Deploy Milvus', + }, + ], + summary: + 'High-performance open-source vector database for AI applications.', + website: 'https://milvus.io/', + }, + 2011885: { + alt_description: + 'Open-source large language model for self-hosted AI inference.', + alt_name: 'Open-source LLM', + categories: ['Chat', 'LLM', 'AI'], + colors: { + end: '111827', + start: '10b981', + }, + description: + 'GPT-OSS is an open-source large language model designed for self-hosted AI inference and application development. It enables organizations to deploy powerful text generation, chat, and reasoning capabilities on their own infrastructure, supporting use cases such as chatbots, code generation, content creation, and AI-powered automation.', + isNew: true, + logo_url: 'gptoss.svg', + related_guides: [ + { + href: 'https://www.linode.com/docs/marketplace-docs/guides/gpt-oss-with-openwebui', + title: 'Deploy GPT-OSS', + }, + ], + summary: 'Open-source large language model for self-hosted AI workloads.', + website: 'https://github.com/open-source-gpt/gpt-oss', + }, + 1997012: { + alt_description: + 'Lightweight open large language model optimized for efficient AI inference.', + alt_name: 'Open large language model', + categories: ['Chat', 'LLM', 'AI'], + colors: { + end: '1a73e8', + start: '34a853', + }, + description: + 'Gemma 3 is an open large language model designed for efficient, high-performance AI inference across a variety of workloads. Optimized for text generation, chat, and reasoning tasks, it enables developers to deploy scalable AI applications such as assistants, code generation tools, and content automation directly on their own infrastructure.', + isNew: true, + logo_url: 'gemma3.svg', + related_guides: [ + { + href: 'https://www.linode.com/docs/marketplace-docs/guides/gemma3', + title: 'Deploy Gemma 3', + }, + ], + summary: + 'Efficient open large language model for self-hosted AI applications.', + website: 'https://ai.google.dev/gemma', + }, + 2015845: { + alt_description: + 'Open large language model series for advanced reasoning, coding, and chat.', + alt_name: 'Open large language model', + categories: ['Chat', 'LLM', 'AI'], + colors: { + end: '1f2937', + start: '7c3aed', + }, + description: + 'Qwen is an open large language model series designed for high-performance text generation, reasoning, and coding tasks. It supports chat-based interactions, instruction following, and advanced AI application development, making it well-suited for assistants, code generation tools, automation workflows, and enterprise AI deployments.', + isNew: true, + logo_url: 'qwen.svg', + related_guides: [ + { + href: 'https://www.linode.com/docs/marketplace-docs/guides/qwen/', + title: 'Deploy Qwen with Open WebUI', + }, + ], + summary: + 'Open large language model for reasoning, coding, and chat applications.', + website: 'https://qwenlm.github.io/', + }, }; From faa6873ecc879af94aa3b704f1fe5b058a109f13 Mon Sep 17 00:00:00 2001 From: Hana Xu <115299789+hana-akamai@users.noreply.github.com> Date: Mon, 2 Mar 2026 15:38:31 -0500 Subject: [PATCH 22/56] upcoming: [UIE-10179] - Use new hostname endpoints in Service URIs (#13439) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description 📝 Use new hosts endpoints field to populate General and PgBouncer Service URIs. If a VPC is public, display both public and private Service URIs ## How to test 🧪 ### Prerequisites (How to setup test environment) - Use the legacy MSW and ensure you have the pgbouncer and hostnamesEndpoint feature flag on ### Verification steps (How to verify changes) - [ ] In the makeMockDatabase function in serverHandlers.ts, comment/uncomment out some of the values to simulate No VPC (public only), VPC with no public access (private only), VPC with public access (private and public) - [ ] Go to a postgres Database cluster's details page - [ ] If there is no VPC, you should see a general and pgbouncer service URI with _public_ addresses - [ ] If there is a VPC with no public access, you should see a general and pgbouncer service URI with _private_ addresses - [ ] If there is a VPC with public access, you should see 2 general and pgbouncer service URIs with _public_ and _private_ addresses along with an info tooltip for the private address - [ ] Test different screen sizes, test mysql database (there should be no pgbouncer service URIs, only general) --- packages/api-v4/src/databases/types.ts | 2 - ...r-13439-upcoming-features-1772132438864.md | 5 + packages/manager/src/factories/databases.ts | 10 +- .../DatabaseConnectionPools.test.tsx | 23 +- .../DatabaseConnectionPools.tsx | 50 +++- .../DatabaseSummary/DatabaseSummary.tsx | 43 ++- .../DatabaseSummaryConnectionDetails.tsx | 19 +- .../DatabaseDetail/ServiceURI.test.tsx | 268 ++++++++++++++++-- .../Databases/DatabaseDetail/ServiceURI.tsx | 98 ++++--- packages/manager/src/mocks/serverHandlers.ts | 26 +- 10 files changed, 454 insertions(+), 90 deletions(-) create mode 100644 packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md diff --git a/packages/api-v4/src/databases/types.ts b/packages/api-v4/src/databases/types.ts index 971a59a6869..9974bd22d08 100644 --- a/packages/api-v4/src/databases/types.ts +++ b/packages/api-v4/src/databases/types.ts @@ -120,8 +120,6 @@ type MemberType = 'failover' | 'primary'; export interface DatabaseInstance { allow_list: string[]; cluster_size: ClusterSize; - /** @Deprecated replaced by `endpoints` property */ - connection_pool_port: null | number; connection_strings: ConnectionStrings[]; created: string; /** @Deprecated used by rdbms-legacy only, rdbms-default always encrypts */ diff --git a/packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md b/packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md new file mode 100644 index 00000000000..8e1c634a320 --- /dev/null +++ b/packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Use new hostname endpoints in Service URIs and display public/private URIs for public VPCs ([#13439](https://github.com/linode/manager/pull/13439)) diff --git a/packages/manager/src/factories/databases.ts b/packages/manager/src/factories/databases.ts index 7e57944aede..6defd0cc837 100644 --- a/packages/manager/src/factories/databases.ts +++ b/packages/manager/src/factories/databases.ts @@ -161,8 +161,6 @@ export const databaseInstanceFactory = ? ([1, 3][i % 2] as ClusterSize) : ([1, 2, 3][i % 3] as ClusterSize) ), - connection_pool_port: - null /** @Deprecated replaced by `endpoints` property */, connection_strings: [], created: '2021-12-09T17:15:12', encrypted: false, @@ -203,9 +201,7 @@ export const databaseInstanceFactory = members: { '2.2.2.2': 'primary', }, - platform: Factory.each((i) => - adb10(i) ? 'rdbms-legacy' : 'rdbms-default' - ), + platform: 'rdbms-default', region: Factory.each((i) => possibleRegions[i % possibleRegions.length]), status: Factory.each((i) => possibleStatuses[i % possibleStatuses.length]), type: Factory.each((i) => possibleTypes[i % possibleTypes.length]), @@ -230,8 +226,6 @@ export const databaseInstanceFactory = export const databaseFactory = Factory.Sync.makeFactory({ allow_list: [...IPv4List], cluster_size: Factory.each(() => pickRandom([1, 3])), - connection_pool_port: - null /** @Deprecated replaced by `endpoints` property */, connection_strings: [ { driver: 'python', @@ -277,7 +271,7 @@ export const databaseFactory = Factory.Sync.makeFactory({ '2.2.2.2': 'primary', }, oldest_restore_time: '2024-09-15T17:15:12', - platform: Factory.each((i) => (adb10(i) ? 'rdbms-legacy' : 'rdbms-default')), + platform: 'rdbms-default', private_network: null, port: 3306, region: 'us-east', diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.test.tsx index d0f617f20e9..0c987570a1e 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.test.tsx @@ -14,6 +14,23 @@ import { DatabaseConnectionPools } from './DatabaseConnectionPools'; const mockDatabase = databaseFactory.build({ platform: 'rdbms-default', private_network: null, + hosts: { + primary: 'db-mysql-primary-0.b.linodeb.net', + endpoints: [ + { + role: 'primary', + address: 'db-mysql-primary-0.b.linodeb.net', + port: 15847, + public_access: true, + }, + { + role: 'primary-connection-pool', + address: 'public-db-mysql-primary-0.b.linodeb.net', + port: 15848, + public_access: true, + }, + ], + }, engine: 'postgresql', id: 1, }); @@ -109,13 +126,15 @@ describe('DatabaseConnectionPools Component', () => { expect(errorStateText).toBeInTheDocument(); }); - it('should render service URI component if there are connection pools', () => { + it('should render service URI component if there are connection pools and hostnameEndpoints flag is true', () => { queryMocks.useDatabaseConnectionPoolsQuery.mockReturnValue({ data: makeResourcePage([mockConnectionPool]), isLoading: false, }); - renderWithTheme(); + renderWithTheme(, { + flags: { hostnameEndpoints: true }, + }); const serviceURIText = screen.getByText('Service URI'); expect(serviceURIText).toBeInTheDocument(); }); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx index e1fb2238719..78893f1bb79 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx @@ -7,6 +7,7 @@ import { Stack, Typography, } from '@linode/ui'; +import Grid from '@mui/material/Grid'; import { useTheme } from '@mui/material/styles'; import { Pagination } from 'akamai-cds-react-components/Pagination'; import { @@ -28,6 +29,12 @@ import { CONNECTION_POOL_LABEL_CELL_STYLES, MANAGE_CONNECTION_POOLS_LEARN_MORE_LINK, } from 'src/features/Databases/constants'; +import { + StyledGridContainer, + StyledLabelTypography, + StyledValueGrid, +} from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style'; +import { useFlags } from 'src/hooks/useFlags'; import { usePaginationV2 } from 'src/hooks/usePaginationV2'; import { makeSettingsItemStyles } from '../../shared.styles'; @@ -47,6 +54,7 @@ interface Props { export const DatabaseConnectionPools = ({ database }: Props) => { const { classes } = makeSettingsItemStyles(); const theme = useTheme(); + const flags = useFlags(); const isDatabaseInactive = database.status !== 'active'; const [deletePoolLabelSelection, setDeletePoolLabelSelection] = @@ -80,6 +88,9 @@ export const DatabaseConnectionPools = ({ database }: Props) => { ); } + const hasVPC = Boolean(database?.private_network?.vpc_id); + const hasPublicVPC = hasVPC && database.private_network?.public_access; + return ( <>
@@ -110,9 +121,42 @@ export const DatabaseConnectionPools = ({ database }: Props) => { Add Pool
- {connectionPools && connectionPools.data.length > 0 && ( - - )} + {flags?.hostnameEndpoints && + connectionPools && + connectionPools.data.length > 0 && ( + + + + {hasPublicVPC ? 'Public Service URI' : 'Service URI'} + + + + + + {hasPublicVPC && ( + <> + + + Private Service URI + + + + + + + )} + + )}
{ connectionPools && connectionPools.data.length > 0; + const hasVPC = Boolean(database?.private_network?.vpc_id); + const hasPublicVPC = hasVPC && database.private_network?.public_access; + return ( @@ -47,7 +55,7 @@ export const DatabaseSummary = () => { > - {showPgBouncerConnectionDetails && ( + {flags.hostnameEndpoints && showPgBouncerConnectionDetails && ( { PgBouncer Connection Details - + + + + {hasPublicVPC ? 'Public Service URI' : 'Service URI'} + + + + + + {hasPublicVPC && ( + <> + + + Private Service URI + + + + + + + )} + )} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx index 378605b6578..4e99bfa1a9b 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx @@ -117,17 +117,32 @@ export const DatabaseSummaryConnectionDetails = (props: Props) => { ); + const hasPublicVPC = hasVPC && database.private_network?.public_access; + const showServiceURIs = flags.hostnameEndpoints && flags.databasePgBouncer; + return ( <> Connection Details - {flags.databasePgBouncer && ( - + {showServiceURIs && ( + )} + {showServiceURIs && hasPublicVPC && ( + + + + )} {username} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.test.tsx index b9379d57746..050d13a2f01 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.test.tsx @@ -8,19 +8,142 @@ import { renderWithTheme } from 'src/utilities/testHelpers'; import { ServiceURI } from './ServiceURI'; -const mockDatabase = databaseFactory.build({ - connection_pool_port: 100, - engine: 'postgresql', - id: 1, - platform: 'rdbms-default', - private_network: null, -}); - const mockCredentials = { password: 'password123', username: 'lnroot', }; +const DEFAULT_PRIMARY = 'db-postgres-default-primary.net'; +const DEFAULT_STANDBY = 'db-postgres-default-standby.net'; + +const PRIVATE_PRIMARY = `private-${DEFAULT_PRIMARY}`; +const PRIVATE_STANDBY = `private-${DEFAULT_STANDBY}`; + +const PRIMARY_PUBLIC_CONNECTION_POOL = + 'public-db-postgres-primary-connection-pool-0.b.linodeb.net'; +const PRIMARY_PRIVATE_CONNECTION_POOL = + 'private-db-postgres-primary-connection-pool-0.b.linodeb.net'; + +const databaseWithNoVPC = databaseFactory.build({ + engine: 'postgresql', + hosts: { + primary: DEFAULT_PRIMARY, + standby: DEFAULT_STANDBY, + endpoints: [ + { + role: 'primary', + address: DEFAULT_PRIMARY, + port: 3306, + public_access: true, + }, + { + role: 'primary-connection-pool', + address: PRIMARY_PUBLIC_CONNECTION_POOL, + port: 15848, + public_access: true, + }, + { + role: 'standby-connection-pool', + address: + 'public-replica-db-postgres-standby-connection-pool-0.b.linodeb.net', + port: 15848, + public_access: true, + }, + ], + }, + platform: 'rdbms-default', + private_network: null, // No VPC configured +}); + +const databaseWithPrivateVPC = databaseFactory.build({ + engine: 'postgresql', + hosts: { + primary: PRIVATE_PRIMARY, + standby: PRIVATE_STANDBY, + endpoints: [ + { + role: 'primary', + address: PRIVATE_PRIMARY, + port: 3306, + public_access: false, + }, + { + role: 'primary-connection-pool', + address: PRIMARY_PRIVATE_CONNECTION_POOL, + port: 15848, + public_access: false, + }, + { + role: 'standby-connection-pool', + address: + 'private-replica-db-postgres-standby-connection-pool-0.b.linodeb.net', + port: 15848, + public_access: false, + }, + ], + }, + platform: 'rdbms-default', + private_network: { + public_access: false, + subnet_id: 1, + vpc_id: 123, + }, +}); + +const databaseWithPublicVPC = databaseFactory.build({ + engine: 'postgresql', + hosts: { + primary: PRIVATE_PRIMARY, + standby: PRIVATE_STANDBY, + endpoints: [ + { + role: 'primary', + address: PRIVATE_PRIMARY, + port: 3306, + public_access: false, + }, + { + role: 'primary-connection-pool', + address: PRIMARY_PRIVATE_CONNECTION_POOL, + port: 15848, + public_access: false, + }, + { + role: 'standby-connection-pool', + address: + 'private-replica-db-postgres-standby-connection-pool-0.b.linodeb.net', + port: 15848, + public_access: false, + }, + { + role: 'primary', + address: DEFAULT_PRIMARY, + port: 3306, + public_access: true, + }, + { + role: 'primary-connection-pool', + address: PRIMARY_PUBLIC_CONNECTION_POOL, + port: 15848, + public_access: true, + }, + { + role: 'standby-connection-pool', + address: + 'public-replica-db-postgres-standby-connection-pool-0.b.linodeb.net', + port: 15848, + public_access: true, + }, + ], + }, + platform: 'rdbms-default', + private_network: { + public_access: true, + subnet_id: 1, + vpc_id: 123, + }, +}); + // Hoist query mocks const queryMocks = vi.hoisted(() => { return { @@ -41,8 +164,9 @@ describe('ServiceURI', () => { queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ data: mockCredentials, }); + const { container } = renderWithTheme( - + ); const revealPasswordBtn = screen.getByRole('button', { @@ -52,7 +176,7 @@ describe('ServiceURI', () => { expect(revealPasswordBtn).toBeInTheDocument(); expect(serviceURIText).toBe( - `postgres://{click to reveal password}@db-mysql-primary-0.b.linodeb.net:100/{connection pool label}?sslmode=require` + `postgres://{click to reveal password}@${PRIMARY_PUBLIC_CONNECTION_POOL}:15848/{connection pool label}?sslmode=require` ); // eslint-disable-next-line testing-library/no-container @@ -65,7 +189,8 @@ describe('ServiceURI', () => { data: mockCredentials, refetch: vi.fn(), }); - renderWithTheme(); + + renderWithTheme(); const revealPasswordBtn = screen.getByRole('button', { name: '{click to reveal password}', @@ -75,7 +200,7 @@ describe('ServiceURI', () => { const serviceURIText = screen.getByTestId('service-uri').textContent; expect(revealPasswordBtn).not.toBeInTheDocument(); expect(serviceURIText).toBe( - `postgres://lnroot:password123@db-mysql-primary-0.b.linodeb.net:100/{connection pool label}?sslmode=require` + `postgres://lnroot:password123@${PRIMARY_PUBLIC_CONNECTION_POOL}:15848/{connection pool label}?sslmode=require` ); }); @@ -84,7 +209,7 @@ describe('ServiceURI', () => { error: new Error('Failed to fetch credentials'), }); - renderWithTheme(); + renderWithTheme(); const errorRetryBtn = screen.getByRole('button', { name: '{error. click to retry}', @@ -96,8 +221,9 @@ describe('ServiceURI', () => { queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ data: mockCredentials, }); - const { container } = renderWithTheme( - + + renderWithTheme( + ); const revealPasswordBtn = screen.getByRole('button', { @@ -107,12 +233,8 @@ describe('ServiceURI', () => { expect(revealPasswordBtn).toBeInTheDocument(); expect(serviceURIText).toBe( - `postgres://{click to reveal password}@db-mysql-primary-0.b.linodeb.net:3306/defaultdb?sslmode=require` + `postgres://{click to reveal password}@${DEFAULT_PRIMARY}:3306/defaultdb?sslmode=require` ); - - // eslint-disable-next-line testing-library/no-container - const copyButton = container.querySelector('[data-qa-copy-btn]'); - expect(copyButton).toBeInTheDocument(); }); it('should reveal general service URI password after clicking reveal button', async () => { @@ -120,7 +242,9 @@ describe('ServiceURI', () => { data: mockCredentials, refetch: vi.fn(), }); - renderWithTheme(); + renderWithTheme( + + ); const revealPasswordBtn = screen.getByRole('button', { name: '{click to reveal password}', @@ -130,7 +254,107 @@ describe('ServiceURI', () => { const serviceURIText = screen.getByTestId('service-uri').textContent; expect(revealPasswordBtn).not.toBeInTheDocument(); expect(serviceURIText).toBe( - `postgres://password123@db-mysql-primary-0.b.linodeb.net:3306/defaultdb?sslmode=require` + `postgres://password123@${DEFAULT_PRIMARY}:3306/defaultdb?sslmode=require` + ); + }); + + it('should render private service URI component if there is a private-only VPC', async () => { + queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ + data: mockCredentials, + }); + + renderWithTheme(); + + const revealPasswordBtn = screen.getByRole('button', { + name: '{click to reveal password}', + }); + const serviceURIText = screen.getByTestId('service-uri').textContent; + + expect(revealPasswordBtn).toBeInTheDocument(); + expect(serviceURIText).toBe( + `postgres://{click to reveal password}@${PRIMARY_PRIVATE_CONNECTION_POOL}:15848/{connection pool label}?sslmode=require` + ); + }); + + it('should render private general service URI component if there is a private-only VPC', async () => { + queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ + data: mockCredentials, + }); + + renderWithTheme( + + ); + + const revealPasswordBtn = screen.getByRole('button', { + name: '{click to reveal password}', + }); + const serviceURIText = screen.getByTestId('service-uri').textContent; + + expect(revealPasswordBtn).toBeInTheDocument(); + expect(serviceURIText).toBe( + `postgres://{click to reveal password}@${PRIVATE_PRIMARY}:3306/defaultdb?sslmode=require` + ); + }); + + it('should render public service URI component if there is a VPC with public access', async () => { + queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ + data: mockCredentials, + }); + + renderWithTheme(); + + const revealPasswordBtn = screen.getByRole('button', { + name: '{click to reveal password}', + }); + const serviceURIText = screen.getByTestId('service-uri').textContent; + + expect(revealPasswordBtn).toBeInTheDocument(); + expect(serviceURIText).toBe( + `postgres://{click to reveal password}@${PRIMARY_PUBLIC_CONNECTION_POOL}:15848/{connection pool label}?sslmode=require` + ); + }); + + it('should render private service URI component if there is a VPC with public access and showPrivateVPC is true', async () => { + queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ + data: mockCredentials, + }); + + renderWithTheme( + + ); + + const revealPasswordBtn = screen.getByRole('button', { + name: '{click to reveal password}', + }); + const serviceURIText = screen.getByTestId('service-uri').textContent; + + expect(revealPasswordBtn).toBeInTheDocument(); + expect(serviceURIText).toBe( + `postgres://{click to reveal password}@${PRIMARY_PRIVATE_CONNECTION_POOL}:15848/{connection pool label}?sslmode=require` + ); + }); + + it('should render general private service URI if there is a VPC with public access, isGeneralServiceURI is true, and showPrivateVPC is true', () => { + queryMocks.useDatabaseCredentialsQuery.mockReturnValue({ + data: mockCredentials, + }); + + renderWithTheme( + + ); + + const revealPasswordBtn = screen.getByRole('button', { + name: '{click to reveal password}', + }); + const serviceURIText = screen.getByTestId('service-uri').textContent; + + expect(revealPasswordBtn).toBeInTheDocument(); + expect(serviceURIText).toBe( + `postgres://{click to reveal password}@${PRIVATE_PRIMARY}:3306/defaultdb?sslmode=require` ); }); }); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.tsx b/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.tsx index 0cfe994211d..d417979e572 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/ServiceURI.tsx @@ -1,5 +1,5 @@ import { useDatabaseCredentialsQuery } from '@linode/queries'; -import { Button } from '@linode/ui'; +import { Button, TooltipIcon } from '@linode/ui'; import { Grid, styled } from '@mui/material'; import copy from 'copy-to-clipboard'; import { enqueueSnackbar } from 'notistack'; @@ -7,21 +7,22 @@ import React, { useState } from 'react'; import { Code } from 'src/components/Code/Code'; import { CopyTooltip } from 'src/components/CopyTooltip/CopyTooltip'; -import { - StyledGridContainer, - StyledLabelTypography, - StyledValueGrid, -} from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style'; +import { StyledValueGrid } from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style'; import type { Database, DatabaseCredentials } from '@linode/api-v4'; interface ServiceURIProps { database: Database; isGeneralServiceURI?: boolean; + showPrivateVPC?: boolean; } export const ServiceURI = (props: ServiceURIProps) => { - const { database, isGeneralServiceURI = false } = props; + const { + database, + isGeneralServiceURI = false, + showPrivateVPC = false, + } = props; const [hidePassword, setHidePassword] = useState(true); const [isCopying, setIsCopying] = useState(false); @@ -36,6 +37,26 @@ export const ServiceURI = (props: ServiceURIProps) => { refetch: getDatabaseCredentials, } = useDatabaseCredentialsQuery(database.engine, database.id, !hidePassword); + const hasVPC = Boolean(database?.private_network?.vpc_id); + const hasPublicVPC = hasVPC && database.private_network?.public_access; + // If there is a VPC, use VPC public access unless we want to explicitly show private access, otherwise default to public + const publicAccess = + hasPublicVPC && showPrivateVPC + ? false + : hasVPC + ? database.private_network?.public_access + : true; + + const primaryHost = database.hosts?.endpoints.find( + (endpoint) => + endpoint.role === 'primary' && endpoint.public_access === publicAccess + ); + const primaryConnectionPoolHost = database.hosts?.endpoints.find( + (endpoint) => + endpoint.role === 'primary-connection-pool' && + endpoint.public_access === publicAccess + ); + const handleCopy = async () => { if (!credentials) { try { @@ -43,7 +64,7 @@ export const ServiceURI = (props: ServiceURIProps) => { const { data } = await getDatabaseCredentials(); if (data) { // copy with revealed credentials - copy(getServiceURIText(isGeneralServiceURI, data)); + copy(getServiceURIText(data, isGeneralServiceURI)); } else { enqueueSnackbar( 'There was an error retrieving cluster credentials. Please try again.', @@ -62,13 +83,13 @@ export const ServiceURI = (props: ServiceURIProps) => { }; const getServiceURIText = ( - isGeneralServiceURI: boolean, - credentials: DatabaseCredentials | undefined + credentials: DatabaseCredentials | undefined, + isGeneralServiceURI?: boolean ) => { if (isGeneralServiceURI) { - return `${engine}://${credentials?.password}@${database.hosts?.primary}:${database.port}/defaultdb?sslmode=require`; + return `${engine}://${credentials?.password}@${primaryHost?.address}:${primaryHost?.port}/defaultdb?sslmode=require`; } - return `postgres://${credentials?.username}:${credentials?.password}@${database.hosts?.primary}:${database.connection_pool_port}/{connection pool label}?sslmode=require`; + return `postgres://${credentials?.username}:${credentials?.password}@${primaryConnectionPoolHost?.address}:${primaryConnectionPoolHost?.port}/{connection pool label}?sslmode=require`; }; const getCredentials = (isGeneralServiceURI: boolean) => { @@ -110,7 +131,7 @@ export const ServiceURI = (props: ServiceURIProps) => { ); - const ServiceURIJSX = (isGeneralServiceURI: boolean) => ( + return ( { sx={{ overflowX: 'auto', overflowY: 'hidden', - p: isGeneralServiceURI ? '0' : null, + p: '0', }} whiteSpace="pre" > @@ -128,16 +149,17 @@ export const ServiceURI = (props: ServiceURIProps) => { : hidePassword || (!credentialsError && !credentials) ? RevealPasswordButton : getCredentials(isGeneralServiceURI)} - {!isGeneralServiceURI ? ( + {isGeneralServiceURI ? ( <> - @{database.hosts?.primary}:{database.connection_pool_port}/ - {'{connection pool label}'} - ?sslmode=require + @{primaryHost?.address}: + {`${primaryHost?.port}/defaultdb?sslmode=require`} ) : ( <> - @{database.hosts?.primary}: - {`${database.port}/defaultdb?sslmode=require`} + @{primaryConnectionPoolHost?.address}: + {primaryConnectionPoolHost?.port}/ + {'{connection pool label}'} + ?sslmode=require )} @@ -149,33 +171,29 @@ export const ServiceURI = (props: ServiceURIProps) => { + + )} + {hasPublicVPC && showPrivateVPC && ( + + )} ); - - if (isGeneralServiceURI) { - return ServiceURIJSX(isGeneralServiceURI); - } - - return ( - - - Service URI - - {ServiceURIJSX(isGeneralServiceURI)} - - ); }; -const StyledCode = styled(Code, { +export const StyledCode = styled(Code, { label: 'StyledCode', })(() => ({ margin: 0, diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index 2ab6f042881..253f679434f 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -214,10 +214,6 @@ const makeMockDatabase = (params: PathParams): Database => { db.ssl_connection = true; } - if (db.engine === 'postgresql') { - db.connection_pool_port = 100; /** @Deprecated replaced by `endpoints` property */ - } - const database = databaseFactory.build(db); // Mock a database cluster with a public VPC Configuration @@ -241,27 +237,33 @@ const makeMockDatabase = (params: PathParams): Database => { { role: 'primary', address: 'public-db-mysql-primary-0.b.linodeb.net', - port: 15847, + port: 3306, public_access: true, }, { role: 'primary', address: 'private-db-mysql-primary-0.b.linodeb.net', - port: 15847, + port: 3306, public_access: false, }, { role: 'standby', address: 'public-replica-db-mysql-standby-0.b.linodeb.net', - port: 15847, + port: 3306, public_access: true, }, { role: 'standby', address: 'private-replica-db-mysql-standby-0.b.linodeb.net', - port: 15847, + port: 3306, public_access: false, }, + { + role: 'primary-connection-pool', + address: 'public-db-mysql-primary-0.b.linodeb.net', + port: 15848, + public_access: true, + }, { role: 'primary-connection-pool', address: 'private-db-mysql-primary-0.b.linodeb.net', @@ -280,7 +282,13 @@ const makeMockDatabase = (params: PathParams): Database => { // { // role: 'primary', // address: 'db-mysql-primary-0.b.linodeb.net', - // port: 15847, + // port: 3306, + // public_access: true, + // }, + // { + // role: 'primary-connection-pool', + // address: 'public-db-mysql-primary-0.b.linodeb.net', + // port: 15848, // public_access: true, // }, // ], From a66dd2f5bd1e8bd01689d49cd1115e64c5ee5993 Mon Sep 17 00:00:00 2001 From: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:35:07 +0100 Subject: [PATCH 23/56] fix: [UIE-10329] - UpdateDelegationDrawer Follow up (#13446) * handle select all * feedback * feedback --- .../IAM/Delegations/UpdateDelegationForm.tsx | 66 ++++++++++++++++--- .../components/Autocomplete/Autocomplete.tsx | 20 +++++- 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx index 80d2310f186..a5d6b9c347b 100644 --- a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx +++ b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx @@ -1,5 +1,6 @@ import { useAccountUsersInfiniteQuery, + useAllAccountUsersQuery, useUpdateChildAccountDelegatesQuery, } from '@linode/queries'; import { ActionsPanel, Autocomplete, Notice, Typography } from '@linode/ui'; @@ -41,6 +42,7 @@ export const UpdateDelegationForm = ({ }: DelegationsFormProps) => { const theme = useTheme(); const [inputValue, setInputValue] = React.useState(''); + const [allUserSelected, setAllUserSelected] = React.useState(false); const debouncedInputValue = useDebouncedValue(inputValue); const { data: permissions } = usePermissions('account', [ @@ -55,13 +57,35 @@ export const UpdateDelegationForm = ({ const { data, error, fetchNextPage, hasNextPage, isFetching } = useAccountUsersInfiniteQuery(apiFilter); + const { + data: allUsers, + isFetching: isFetchingAllUsers, + refetch: refetchAllUsers, + } = useAllAccountUsersQuery(allUserSelected, { + user_type: 'parent', + }); + const users = - data?.pages.flatMap((page) => { - return page.data.map((user) => ({ - label: user.username, - value: user.username, - })); - }) ?? []; + allUserSelected && allUsers + ? allUsers.map((user) => ({ + label: user.username, + value: user.username, + })) + : (data?.pages.flatMap((page) => { + return page.data.map((user) => ({ + label: user.username, + value: user.username, + })); + }) ?? []); + + const isSearching = + inputValue.length > 0 && debouncedInputValue !== inputValue; + + const isLoadingOptions = isFetching || isFetchingAllUsers; + + const showNoOptionsText = !isLoadingOptions && !isSearching; + + const isSelectAllFetching = allUserSelected && isFetchingAllUsers; const { mutateAsync: updateDelegates } = useUpdateChildAccountDelegatesQuery(); @@ -78,6 +102,7 @@ export const UpdateDelegationForm = ({ handleSubmit, reset, setError, + setValue, } = form; const onSubmit = async (values: UpdateDelegationsFormValues) => { @@ -99,9 +124,21 @@ export const UpdateDelegationForm = ({ } }; + const onSelectAllClick = async () => { + setAllUserSelected(true); + const { data } = await refetchAllUsers(); + if (data) { + setValue( + 'users', + data.map((user) => ({ label: user.username, value: user.username })) + ); + } + }; + const handleClose = () => { reset(); onClose(); + setAllUserSelected(false); }; return ( @@ -135,20 +172,27 @@ export const UpdateDelegationForm = ({ render={({ field, fieldState }) => ( option.value === value.value } - label={'Delegate Users'} - loading={isFetching} + label="Delegate Users" + loading={isFetching || isFetchingAllUsers} multiple noMarginTop + noOptionsText={showNoOptionsText ? 'No users found' : ' '} onChange={(_, newValue) => { field.onChange(newValue || []); }} onInputChange={(_, value) => { setInputValue(value); }} + onSelectAllClick={(isSelectAllActive) => { + if (isSelectAllActive && !allUserSelected) { + onSelectAllClick(); + } + }} options={users} placeholder={getPlaceholder( 'delegates', @@ -171,6 +215,12 @@ export const UpdateDelegationForm = ({ }} textFieldProps={{ hideLabel: true, + helperText: isSelectAllFetching + ? 'Fetching all users...' + : undefined, + InputProps: isSelectAllFetching + ? { startAdornment: null } + : undefined, }} value={field.value} /> diff --git a/packages/ui/src/components/Autocomplete/Autocomplete.tsx b/packages/ui/src/components/Autocomplete/Autocomplete.tsx index 2dd35db0ca3..060b7888848 100644 --- a/packages/ui/src/components/Autocomplete/Autocomplete.tsx +++ b/packages/ui/src/components/Autocomplete/Autocomplete.tsx @@ -48,6 +48,10 @@ export interface EnhancedAutocompleteProps< noMarginTop?: boolean; /** Element to show when the Autocomplete search yields no results. */ noOptionsText?: JSX.Element | string; + /** Handler called when the Select All option is clicked. */ + onSelectAllClick?: ( + event: React.MouseEvent, + ) => void; placeholder?: string; renderInput?: (_params: AutocompleteRenderInputParams) => React.ReactNode; /** Label for the "select all" option. */ @@ -96,6 +100,7 @@ export const Autocomplete = < keepSearchEnabledOnMobile = false, onBlur, onChange, + onSelectAllClick, options, placeholder, renderInput, @@ -191,6 +196,18 @@ export const Autocomplete = < const isSelectAllOption = option === selectAllOption; const ListItem = isSelectAllOption ? StyledListItem : 'li'; + // If this is the Select All option, add a click handler + const handleClick = ( + event: React.MouseEvent, + ) => { + if (isSelectAllOption && onSelectAllClick) { + onSelectAllClick(event); + } + if (props.onClick) { + props.onClick(event); + } + }; + return renderOption ? ( renderOption(props, option, state, ownerState) ) : ( @@ -198,9 +215,10 @@ export const Autocomplete = < {...props} data-pendo-id={ rest.getOptionLabel ? rest.getOptionLabel(option) : option.label - } // Adding data-pendo-id for better tracking in Pendo analytics, using the option label as the identifier for the option element. + } data-qa-option key={props.key} + onClick={isSelectAllOption ? handleClick : props.onClick} > <> Date: Tue, 3 Mar 2026 19:04:24 +0530 Subject: [PATCH 24/56] upcoming: [DI-29907] - Logs service Alerts Integration (#13445) * upcoming: [DI-29907] - Logs service Alerts Integration * add mocks for easier testing * add changesets * fix lint issues * fix for failing cypress test: adding scrollIntoView to the clickable component --- ...r-13445-upcoming-features-1772199727781.md | 5 ++ packages/api-v4/src/cloudpulse/types.ts | 2 + ...r-13445-upcoming-features-1772199672997.md | 5 ++ ...ification-channel-permission-tests.spec.ts | 9 ++- .../src/factories/cloudpulse/alerts.ts | 65 ++++++++++++++++ .../AlertsResources/AlertsResources.tsx | 13 ++-- .../Alerts/AlertsResources/constants.ts | 8 ++ .../DimensionFilterValue/ValueSchemas.ts | 75 +++++++++++++++++++ .../DimensionFilterValue/constants.ts | 32 ++++++++ .../features/CloudPulse/Alerts/constants.ts | 32 +++----- .../src/features/CloudPulse/Utils/models.ts | 2 + packages/manager/src/mocks/serverHandlers.ts | 35 +++++++++ .../manager/src/queries/cloudpulse/queries.ts | 3 + 13 files changed, 257 insertions(+), 29 deletions(-) create mode 100644 packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md create mode 100644 packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md diff --git a/packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md b/packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md new file mode 100644 index 00000000000..13779090c25 --- /dev/null +++ b/packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Upcoming Features +--- + +Add logs to `CloudPulseServiceType` and `capabilityServiceTypeMapping` ([#13445](https://github.com/linode/manager/pull/13445)) diff --git a/packages/api-v4/src/cloudpulse/types.ts b/packages/api-v4/src/cloudpulse/types.ts index 89e798853d5..e72bef9d0a7 100644 --- a/packages/api-v4/src/cloudpulse/types.ts +++ b/packages/api-v4/src/cloudpulse/types.ts @@ -9,6 +9,7 @@ export type CloudPulseServiceType = | 'firewall' | 'linode' | 'lke' + | 'logs' | 'netloadbalancer' | 'nodebalancer' | 'objectstorage'; @@ -429,6 +430,7 @@ export const capabilityServiceTypeMapping: Record< blockstorage: 'Block Storage', lke: 'Kubernetes', netloadbalancer: 'Network LoadBalancer', + logs: 'Akamai Cloud Pulse Logs', }; /** diff --git a/packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md b/packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md new file mode 100644 index 00000000000..12637196e19 --- /dev/null +++ b/packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Integrate aclp-logs service to alerts with custom validation schemas, error texts ([#13445](https://github.com/linode/manager/pull/13445)) diff --git a/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts b/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts index ad08eabc340..e90e7524412 100644 --- a/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts +++ b/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts @@ -37,7 +37,10 @@ describe('Notification Channel Listing Page — Access Control', () => { mockAppendFeatureFlags(flags); cy.visitWithLogin('/linodes'); - ui.nav.findItemByTitle('Alerts').should('be.visible').click(); + ui.nav.findItemByTitle('Alerts').as('alertsNav'); + cy.get('@alertsNav').scrollIntoView(); + cy.get('@alertsNav').should('be.visible').click(); + ui.tabList .findTabByTitle('Notification Channels') .should('be.visible') @@ -62,7 +65,9 @@ describe('Notification Channel Listing Page — Access Control', () => { mockAppendFeatureFlags(flags); cy.visitWithLogin('/linodes'); - ui.nav.findItemByTitle('Alerts').should('be.visible').click(); + ui.nav.findItemByTitle('Alerts').as('alertsNav'); + cy.get('@alertsNav').scrollIntoView(); + cy.get('@alertsNav').should('be.visible').click(); // Tab should not render at all ui.tabList.findTabByTitle('Notification Channels').should('not.exist'); diff --git a/packages/manager/src/factories/cloudpulse/alerts.ts b/packages/manager/src/factories/cloudpulse/alerts.ts index 9f7a9881211..92af2ac38e2 100644 --- a/packages/manager/src/factories/cloudpulse/alerts.ts +++ b/packages/manager/src/factories/cloudpulse/alerts.ts @@ -731,3 +731,68 @@ export const networkLoadBalancerMetricCriteria: MetricDefinition[] = [ ], }, ]; + +const logsDimensions: Dimension[] = [ + { + label: 'Status Code', + dimension_label: 'status_code', + values: [], + }, +]; + +export const logsMetricCriteria: MetricDefinition[] = [ + { + label: 'Successful Upload Count', + metric: 'success_upload_count', + unit: 'Count', + scrape_interval: '300s', + metric_type: 'gauge', + is_alertable: true, + available_aggregate_functions: ['sum'], + dimensions: logsDimensions, + }, + { + label: 'Error Upload Count', + metric: 'error_upload_count', + unit: 'Count', + scrape_interval: '300s', + metric_type: 'gauge', + is_alertable: true, + available_aggregate_functions: ['sum'], + dimensions: logsDimensions, + }, + { + label: 'Error Upload Rate', + metric: 'error_upload_rate', + unit: 'Percent', + scrape_interval: '300s', + metric_type: 'gauge', + is_alertable: true, + available_aggregate_functions: ['avg'], + dimensions: logsDimensions, + }, +]; + +export const logsAlertMetricCriteria = + Factory.Sync.makeFactory({ + label: 'Successful Upload Count', + metric: 'success_upload_count', + unit: 'Count', + aggregate_function: 'sum', + operator: 'eq', + threshold: 1500, + dimension_filters: [ + { + label: 'Status Code', + dimension_label: 'status_code', + operator: 'in', + value: '203,402', + }, + { + label: 'Status Code', + dimension_label: 'status_code', + operator: 'eq', + value: '503', + }, + ], + }); diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/AlertsResources.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/AlertsResources.tsx index 6207bf3eb6d..f2a7443d523 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/AlertsResources.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/AlertsResources.tsx @@ -179,8 +179,8 @@ export const AlertResources = React.memo((props: AlertResourcesProp) => { const filteredTypes = alertClass === 'shared' ? Object.keys(databaseTypeClassMap).filter( - (type) => type !== 'dedicated' - ) + (type) => type !== 'dedicated' + ) : [alertClass]; // Apply type filter only for DBaaS user alerts with a valid alertClass based on above filtered types @@ -205,7 +205,10 @@ export const AlertResources = React.memo((props: AlertResourcesProp) => { isLoading: isResourcesLoading, } = useResourcesQuery( Boolean( - serviceType && (serviceType === 'firewall' || supportedRegionIds?.length) + serviceType && + (serviceType === 'firewall' || + serviceType === 'logs' || + supportedRegionIds?.length) ), // Enable query only if serviceType and supportedRegionIds are available, in case of firewall only serviceType is needed serviceType, {}, @@ -468,8 +471,8 @@ export const AlertResources = React.memo((props: AlertResourcesProp) => { new Set( regionFilteredResources ? regionFilteredResources.flatMap( - ({ tags }) => tags ?? [] - ) + ({ tags }) => tags ?? [] + ) : [] ) ), diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/constants.ts index 57a793cc4b2..b5254d736a3 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/constants.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsResources/constants.ts @@ -116,6 +116,13 @@ export const serviceTypeBasedColumns: ServiceColumns = { sortingKey: 'region', }, ], + logs: [ + { + accessor: ({ label }) => label, + label: 'Entity', + sortingKey: 'label', + }, + ], }; export const serviceToFiltersMap: Partial< @@ -138,6 +145,7 @@ export const serviceToFiltersMap: Partial< { component: AlertsEndpointFilter, filterKey: 'endpoint' }, ], blockstorage: [{ component: AlertsRegionFilter, filterKey: 'region' }], + logs: [], }; export const applicableAdditionalFilterKeys: AlertAdditionalFilterKey[] = [ 'engineType', // Extendable in future for filter keys like 'tags', 'plan', etc. diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts index 89e705be80b..c3e9dd3ed2a 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts @@ -19,6 +19,9 @@ import { INTERFACE_ID_ERROR_MESSAGE, PORT_HELPER_TEXT, PORTS_TRAILING_COMMA_ERROR_MESSAGE, + STATUS_CODE_ERROR_MESSAGE, + STATUS_CODES_ERROR_MESSAGE, + STATUS_CODES_HELPER_TEXT, } from '../../../constants'; const LENGTH_ERROR_MESSAGE = 'Value must be 100 characters or less.'; @@ -240,6 +243,73 @@ const multipleInterfacesSchema = string() } ); +const singleStatusCodeSchema = string() + .max(100, LENGTH_ERROR_MESSAGE) + .test( + 'validate-single-status-code-schema', + STATUS_CODE_ERROR_MESSAGE, + function (value) { + if (!value || typeof value !== 'string') { + return this.createError({ message: fieldErrorMessage }); + } + + if (!CONFIG_NUMBER_REGEX.test(value)) { + return this.createError({ message: STATUS_CODE_ERROR_MESSAGE }); + } + + return true; + } + ); + +const multipleStatusCodeSchema = string() + .max(100, LENGTH_ERROR_MESSAGE) + .test( + 'validate-multi-status-code-schema', + STATUS_CODES_ERROR_MESSAGE, + function (value) { + if (!value || typeof value !== 'string') { + return this.createError({ message: fieldErrorMessage }); + } + if (value.includes(' ')) { + return this.createError({ message: STATUS_CODES_ERROR_MESSAGE }); + } + + if (value.trim().endsWith(',')) { + return this.createError({ + message: PORTS_TRAILING_COMMA_ERROR_MESSAGE, + }); + } + + if (value.trim().startsWith(',')) { + return this.createError({ message: PORTS_LEADING_COMMA_ERROR_MESSAGE }); + } + + if (value.trim().includes(',,')) { + return this.createError({ + message: CONFIG_IDS_CONSECUTIVE_COMMAS_ERROR_MESSAGE, + }); + } + if (value.includes('.')) { + return this.createError({ message: STATUS_CODES_HELPER_TEXT }); + } + + const rawSegments = value.split(','); + // Check for empty segments + if (rawSegments.some((segment) => segment.trim() === '')) { + return this.createError({ + message: CONFIG_IDS_CONSECUTIVE_COMMAS_ERROR_MESSAGE, + }); + } + for (const configId of rawSegments) { + const trimmedConfigId = configId.trim(); + + if (!CONFIG_NUMBER_REGEX.test(trimmedConfigId)) { + return this.createError({ message: STATUS_CODE_ERROR_MESSAGE }); + } + } + return true; + } + ); const baseValueSchema = string() .nullable() .required(fieldErrorMessage) @@ -269,6 +339,11 @@ export const getDimensionFilterValueSchema = ({ operator === 'in' ? multipleInterfacesSchema : singleInterfaceSchema; return interfaceSchema.concat(baseValueSchema); } + if (dimensionLabel === 'status_code') { + const statusCodeSchema = + operator === 'in' ? multipleStatusCodeSchema : singleStatusCodeSchema; + return statusCodeSchema.concat(baseValueSchema); + } if (['endswith', 'startswith'].includes(operator)) { return string().max(100, LENGTH_ERROR_MESSAGE).concat(baseValueSchema); } diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts index e44366b03f2..8eedc70ace5 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts @@ -15,6 +15,10 @@ import { PORT_HELPER_TEXT, PORT_PLACEHOLDER_TEXT, PORTS_PLACEHOLDER_TEXT, + STATUS_CODE_HELPER_TEXT, + STATUS_CODE_PLACEHOLDER_TEXT, + STATUS_CODES_HELPER_TEXT, + STATUS_CODES_PLACEHOLDER_TEXT, VIP_HELPER_TEXT, VIP_PLACEHOLDER_TEXT, } from '../../../constants'; @@ -366,6 +370,34 @@ export const valueFieldConfig: ValueFieldConfigMap = { inputType: 'text', }, }, + status_code: { + eq_neq: { + type: 'textfield', + inputType: 'number', + min: 0, + max: Number.MAX_SAFE_INTEGER, + placeholder: STATUS_CODE_PLACEHOLDER_TEXT, + helperText: STATUS_CODE_HELPER_TEXT, + }, + startswith_endswith: { + type: 'textfield', + inputType: 'number', + min: 0, + max: Number.MAX_SAFE_INTEGER, + placeholder: STATUS_CODE_PLACEHOLDER_TEXT, + helperText: STATUS_CODE_HELPER_TEXT, + }, + in: { + type: 'textfield', + inputType: 'text', + placeholder: STATUS_CODES_PLACEHOLDER_TEXT, + helperText: STATUS_CODES_HELPER_TEXT, + }, + '*': { + type: 'textfield', + inputType: 'number', + }, + }, emptyValue: { eq_neq: { type: 'textfield', diff --git a/packages/manager/src/features/CloudPulse/Alerts/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/constants.ts index 4a8876f5407..7ac7d64f669 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/constants.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/constants.ts @@ -1,7 +1,5 @@ import type { FieldPath } from 'react-hook-form'; -import { PORTS_HELPER_TEXT } from '../Utils/constants'; - import type { CreateAlertDefinitionForm } from './CreateAlert/types'; import type { AlertDefinitionScope, @@ -277,27 +275,17 @@ export const CONFIGS_ID_PLACEHOLDER_TEXT = 'e.g., 1234,5678'; export const INTERFACE_ID_ERROR_MESSAGE = 'Enter a valid interface ID number.'; export const INTERFACE_ID_HELPER_TEXT = 'Enter an interface ID number.'; -export const PLACEHOLDER_TEXT_MAP: Record> = { - port: { - in: PORTS_PLACEHOLDER_TEXT, - default: PORT_PLACEHOLDER_TEXT, - }, - config_id: { - in: CONFIGS_ID_PLACEHOLDER_TEXT, - default: CONFIG_ID_PLACEHOLDER_TEXT, - }, -}; -export const HELPER_TEXT_MAP: Record> = { - port: { - in: PORTS_HELPER_TEXT, - default: PORT_HELPER_TEXT, - }, - config_id: { - in: CONFIGS_HELPER_TEXT, - default: CONFIG_ERROR_MESSAGE, - }, -}; +export const STATUS_CODE_PLACEHOLDER_TEXT = 'e.g., 200'; +export const STATUS_CODES_PLACEHOLDER_TEXT = 'e.g., 200,403,500'; + +export const STATUS_CODE_HELPER_TEXT = 'Enter a status code number.'; +export const STATUS_CODES_HELPER_TEXT = + 'Enter one or more status codes separated by commas.'; + +export const STATUS_CODE_ERROR_MESSAGE = 'Enter a valid status code number.'; +export const STATUS_CODES_ERROR_MESSAGE = + 'Enter valid status codes as integers separated by commas.'; export const entityLabelMap = { linode: 'Linode', diff --git a/packages/manager/src/features/CloudPulse/Utils/models.ts b/packages/manager/src/features/CloudPulse/Utils/models.ts index 4252612aff5..5743e1f0ea2 100644 --- a/packages/manager/src/features/CloudPulse/Utils/models.ts +++ b/packages/manager/src/features/CloudPulse/Utils/models.ts @@ -12,6 +12,7 @@ import type { NetworkLoadBalancer, NodeBalancer, ObjectStorageBucket, + Stream, Volume, } from '@linode/api-v4'; import type { QueryFunction, QueryKey } from '@tanstack/react-query'; @@ -68,6 +69,7 @@ export type QueryFunctionType = | NetworkLoadBalancer[] | NodeBalancer[] | ObjectStorageBucket[] + | Stream[] | Volume[]; /** * The non array types of QueryFunctionType like DatabaseEngine|DatabaseType diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index 253f679434f..82752725b3c 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -85,6 +85,8 @@ import { lkeEnterpriseTypeFactory, lkeHighAvailabilityTypeFactory, lkeStandardAvailabilityTypeFactory, + logsAlertMetricCriteria, + logsMetricCriteria, longviewActivePlanFactory, longviewClientFactory, longviewSubscriptionFactory, @@ -124,6 +126,7 @@ import { serviceTypesFactory, stackScriptFactory, staticObjects, + streamFactory, subnetFactory, supportReplyFactory, supportTicketFactory, @@ -3521,6 +3524,12 @@ export const handlers = [ rules: [firewallMetricRulesFactory.build()], }, }), + alertFactory.build({ + id: 494, + label: 'Logs-alert', + service_type: 'logs', + type: 'user', + }), ...alertFactory.buildList(3, { status: 'enabling', type: 'user' }), ...alertFactory.buildList(3, { status: 'disabling', type: 'user' }), ...alertFactory.buildList(3, { status: 'provisioning', type: 'user' }), @@ -3623,6 +3632,19 @@ export const handlers = [ }) ); } + if (params.id === '494' && params.serviceType === 'logs') { + return HttpResponse.json( + alertFactory.build({ + id: 494, + label: 'Logs-alert', + service_type: 'logs', + type: 'user', + rule_criteria: { + rules: [logsAlertMetricCriteria.build()], + }, + }) + ); + } if (params.id !== undefined) { return HttpResponse.json( alertFactory.build({ @@ -3894,6 +3916,12 @@ export const handlers = [ regions: 'us-iad,us-east,eu-west', alert: serviceAlertFactory.build({ scope: ['entity'] }), }), + serviceTypesFactory.build({ + label: 'Logs', + service_type: 'logs', + regions: undefined, + alert: serviceAlertFactory.build({ scope: ['entity'] }), + }), ], }; @@ -3910,6 +3938,7 @@ export const handlers = [ blockstorage: 'Volumes', lke: 'LKE Enterprise', netloadbalancer: 'Network Load Balancers', + logs: 'Logs', }; const response = serviceTypesFactory.build({ service_type: `${serviceType}`, @@ -4314,6 +4343,9 @@ export const handlers = [ if (params.serviceType === 'netloadbalancer') { return HttpResponse.json({ data: networkLoadBalancerMetricCriteria }); } + if (params.serviceType === 'logs') { + return HttpResponse.json({ data: logsMetricCriteria }); + } return HttpResponse.json(response); } ), @@ -4717,6 +4749,9 @@ export const handlers = [ }, }); }), + http.get('*/monitor/streams', () => { + return HttpResponse.json(makeResourcePage(streamFactory.buildList(10))); + }), ...entityTransfers, ...statusPage, ...databases, diff --git a/packages/manager/src/queries/cloudpulse/queries.ts b/packages/manager/src/queries/cloudpulse/queries.ts index 0b8c56e05ec..7ac0ca73537 100644 --- a/packages/manager/src/queries/cloudpulse/queries.ts +++ b/packages/manager/src/queries/cloudpulse/queries.ts @@ -10,6 +10,7 @@ import { } from '@linode/api-v4'; import { databaseQueries, + deliveryQueries, firewallQueries, getAllLinodesRequest, networkLoadBalancerQueries, @@ -142,6 +143,8 @@ export const queryFactory = createQueryKeys(key, { }; case 'lke': return kubernetesQueries.lists._ctx.all; + case 'logs': + return deliveryQueries.streams._ctx.all(params, filters); case 'netloadbalancer': return networkLoadBalancerQueries.netloadbalancers._ctx.all( params, From 66ef4b0537f92e5fe3e155571f5eeaba69bb09cb Mon Sep 17 00:00:00 2001 From: skulpok-akamai Date: Tue, 3 Mar 2026 16:14:44 +0100 Subject: [PATCH 25/56] bug: [STORIF-221] - corrected a bug where an empty bucket list was displayed (#13388) * bug: [STORIF-221] - corrected a bug where an empty bucket list was displayed * bug: [STORIF-221] - code review changes, eslint error corrected --- packages/api-v4/src/object-storage/buckets.ts | 19 -- .../enable-object-storage.spec.ts | 29 -- .../object-storage.smoke.spec.ts | 12 +- .../ObjectsTab/ObjectDetailsDrawer.tsx | 4 +- .../ObjectStorage/BucketDetail/index.tsx | 4 +- .../BucketDetailsDrawer.test.tsx | 20 +- .../BucketLanding/BucketLanding.test.tsx | 258 --------------- .../BucketLanding/BucketLanding.tsx | 307 ------------------ .../ObjectStorage/ObjectStorageLanding.tsx | 15 +- .../src/queries/object-storage/queries.ts | 74 ++--- .../src/queries/object-storage/requests.ts | 44 +-- packages/queries/src/regions/regions.ts | 3 +- 12 files changed, 56 insertions(+), 733 deletions(-) delete mode 100644 packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.test.tsx delete mode 100644 packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx diff --git a/packages/api-v4/src/object-storage/buckets.ts b/packages/api-v4/src/object-storage/buckets.ts index f4b3e09b681..20e71533d77 100644 --- a/packages/api-v4/src/object-storage/buckets.ts +++ b/packages/api-v4/src/object-storage/buckets.ts @@ -60,25 +60,6 @@ export const getBuckets = (params?: Params, filters?: Filter) => setURL(`${API_ROOT}/object-storage/buckets`), ); -/** - * getBucketsInCluster - * - * Gets a list of a user's Object Storage Buckets in the specified cluster. - */ -export const getBucketsInCluster = ( - clusterId: string, - params?: Params, - filters?: Filter, -) => - Request>( - setMethod('GET'), - setParams(params), - setXFilter(filters), - setURL( - `${API_ROOT}/object-storage/buckets/${encodeURIComponent(clusterId)}`, - ), - ); - /** * getBucketsInRegion * diff --git a/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts index 708b19561b8..3ebde174bd5 100644 --- a/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts @@ -5,7 +5,6 @@ import { profileFactory, regionFactory } from '@linode/utilities'; import { accountFactory, accountSettingsFactory, - objectStorageClusterFactory, objectStorageKeyFactory, } from '@src/factories'; import { @@ -19,7 +18,6 @@ import { mockCreateAccessKey, mockGetAccessKeys, mockGetBuckets, - mockGetClusters, mockGetObjectStorageTypes, } from 'support/intercepts/object-storage'; import { mockGetProfile } from 'support/intercepts/profile'; @@ -29,8 +27,6 @@ import { randomLabel } from 'support/util/random'; import type { AccountSettings, - ObjectStorageCluster, - ObjectStorageClusterID, PriceType, Region, } from '@linode/api-v4'; @@ -101,29 +97,6 @@ describe('Object Storage enrollment', () => { }), ]; - // Clusters with special pricing are currently hardcoded rather than - // retrieved via API, so we have to mock the cluster API request to correspond - // with that hardcoded data. - // - // Because the IDs used in the mocks don't correspond with any actual clusters, - // we have to cast them as `ObjectStorageClusterID` to satisfy TypeScript. - const mockClusters: ObjectStorageCluster[] = [ - // Regions with special pricing. - objectStorageClusterFactory.build({ - id: 'br-gru-0' as ObjectStorageClusterID, - region: 'br-gru', - }), - objectStorageClusterFactory.build({ - id: 'id-cgk-1' as ObjectStorageClusterID, - region: 'id-cgk', - }), - // A region that does not have special pricing. - objectStorageClusterFactory.build({ - id: 'us-east-1', - region: 'us-east', - }), - ]; - const mockPrices: PriceType[] = [ { id: 'distributed_network_transfer', @@ -209,7 +182,6 @@ describe('Object Storage enrollment', () => { 'getObjectStorageTypes' ); mockGetAccountSettings(mockAccountSettings).as('getAccountSettings'); - mockGetClusters(mockClusters).as('getClusters'); mockGetBuckets([]).as('getBuckets'); mockGetRegions(mockRegions).as('getRegions'); mockGetAccessKeys([]); @@ -217,7 +189,6 @@ describe('Object Storage enrollment', () => { cy.visitWithLogin('/object-storage/buckets'); cy.wait([ '@getAccountSettings', - '@getClusters', '@getBuckets', '@getRegions', ]); diff --git a/packages/manager/cypress/e2e/core/objectStorage/object-storage.smoke.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/object-storage.smoke.spec.ts index 9d36a170faf..c11d6fd890f 100644 --- a/packages/manager/cypress/e2e/core/objectStorage/object-storage.smoke.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorage/object-storage.smoke.spec.ts @@ -42,7 +42,7 @@ describe('object storage smoke tests', () => { mockGetAccount(accountFactory.build({ capabilities: ['Object Storage'] })); mockAppendFeatureFlags({ gecko2: false, - objMultiCluster: false, + objMultiCluster: true, objectStorageGen2: { enabled: false }, }).as('getFeatureFlags'); @@ -179,22 +179,22 @@ describe('object storage smoke tests', () => { */ it('can delete object storage bucket - smoke', () => { const bucketLabel = randomLabel(); - const bucketCluster = 'us-southeast-1'; + const region = 'us-southeast'; const bucketMock = objectStorageBucketFactory.build({ - cluster: bucketCluster, - hostname: `${bucketLabel}.${bucketCluster}.linodeobjects.com`, + region: region, + hostname: `${bucketLabel}.${region}.linodeobjects.com`, label: bucketLabel, objects: 0, }); mockGetAccount(accountFactory.build({ capabilities: ['Object Storage'] })); mockAppendFeatureFlags({ - objMultiCluster: false, + objMultiCluster: true, objectStorageGen2: { enabled: false }, }); mockGetBuckets([bucketMock]).as('getBuckets'); - mockDeleteBucket(bucketLabel, bucketCluster).as('deleteBucket'); + mockDeleteBucket(bucketLabel, region).as('deleteBucket'); cy.visitWithLogin('/object-storage/buckets'); cy.wait('@getBuckets'); diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/ObjectsTab/ObjectDetailsDrawer.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/ObjectsTab/ObjectDetailsDrawer.tsx index 88d566f93ac..09e39c87f89 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/ObjectsTab/ObjectDetailsDrawer.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/ObjectsTab/ObjectDetailsDrawer.tsx @@ -6,7 +6,6 @@ import * as React from 'react'; import { CopyTooltip } from 'src/components/CopyTooltip/CopyTooltip'; import { Link } from 'src/components/Link'; -import { useIsObjectStorageGen2Enabled } from 'src/features/ObjectStorage/hooks/useIsObjectStorageGen2Enabled'; import { useObjectStorageBuckets } from 'src/queries/object-storage/queries'; import { formatDate } from 'src/utilities/formatDate'; @@ -40,9 +39,8 @@ export const ObjectDetailsDrawer = React.memo( let formattedLastModified; const { data: profile } = useProfile(); - const { isObjectStorageGen2Enabled } = useIsObjectStorageGen2Enabled(); const { data: bucketsData, isLoading: isLoadingEndpointData } = - useObjectStorageBuckets(isObjectStorageGen2Enabled); + useObjectStorageBuckets(); const isLoadingEndpoint = isLoadingEndpointData || !bucketsData; diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx index 5f1efbf510f..7320121a1ed 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx @@ -9,7 +9,6 @@ import { SafeTabPanel } from 'src/components/Tabs/SafeTabPanel'; import { TabPanels } from 'src/components/Tabs/TabPanels'; import { Tabs } from 'src/components/Tabs/Tabs'; import { TanStackTabLinkList } from 'src/components/Tabs/TanStackTabLinkList'; -import { useIsObjectStorageGen2Enabled } from 'src/features/ObjectStorage/hooks/useIsObjectStorageGen2Enabled'; import { useFlags } from 'src/hooks/useFlags'; import { useTabs } from 'src/hooks/useTabs'; import { useCloudPulseServiceByServiceType } from 'src/queries/cloudpulse/services'; @@ -48,7 +47,6 @@ export const BucketDetailLanding = React.memo(() => { }); const { aclpServices, objectStorageContextualMetrics } = useFlags(); - const { isObjectStorageGen2Enabled } = useIsObjectStorageGen2Enabled(); const { isError: aclpServiceError, isLoading: aclServiceLoading } = useCloudPulseServiceByServiceType('objectstorage', true); @@ -57,7 +55,7 @@ export const BucketDetailLanding = React.memo(() => { isLoading, error, isPending, - } = useObjectStorageBuckets(isObjectStorageGen2Enabled); + } = useObjectStorageBuckets(); const bucket = bucketsData?.buckets.find(({ label }) => label === bucketName); diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.test.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.test.tsx index 88486866dba..26ac6c68455 100644 --- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.test.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.test.tsx @@ -98,9 +98,6 @@ describe('BucketDetailsDrawer: Legacy UI', () => { selectedBucket={bucket} /> ), - options: { - flags: { objMultiCluster: false }, - }, }); expect(screen.getByText(bucket.label)).toBeInTheDocument(); @@ -122,9 +119,6 @@ describe('BucketDetailsDrawer: Legacy UI', () => { selectedBucket={bucket} /> ), - options: { - flags: { objMultiCluster: false }, - }, }); expect(screen.queryByText(bucket.label)).not.toBeInTheDocument(); @@ -139,9 +133,6 @@ describe('BucketDetailsDrawer: Legacy UI', () => { selectedBucket={bucket} /> ), - options: { - flags: { objMultiCluster: false }, - }, }); expect(screen.getByTestId('cluster')).toHaveTextContent(region.id); @@ -156,9 +147,6 @@ describe('BucketDetailsDrawer: Legacy UI', () => { selectedBucket={undefined} /> ), - options: { - flags: { objMultiCluster: false }, - }, }); expect(screen.getByText('Bucket Detail')).toBeInTheDocument(); @@ -176,7 +164,7 @@ describe('BucketDetailsDrawer: Legacy UI', () => { /> ), options: { - flags: { objMultiCluster: false }, + flags: { objectStorageGen2: { enabled: true } }, }, }); @@ -198,7 +186,7 @@ describe('BucketDetailsDrawer: Legacy UI', () => { /> ), options: { - flags: { objMultiCluster: false }, + flags: { objectStorageGen2: { enabled: true } }, }, }); @@ -227,7 +215,7 @@ describe('BucketDetailDrawer: Gen2 UI', () => { /> ), options: { - flags: { objMultiCluster: false, objectStorageGen2: { enabled: true } }, + flags: { objectStorageGen2: { enabled: true } }, }, }); @@ -254,7 +242,7 @@ describe('BucketDetailDrawer: Gen2 UI', () => { /> ), options: { - flags: { objMultiCluster: false, objectStorageGen2: { enabled: true } }, + flags: { objectStorageGen2: { enabled: true } }, }, }); diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.test.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.test.tsx deleted file mode 100644 index 2db84b05ae7..00000000000 --- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.test.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import { screen, waitFor } from '@testing-library/react'; -import * as React from 'react'; - -import { - objectStorageBucketFactory, - objectStorageClusterFactory, -} from 'src/factories/objectStorage'; -import { makeResourcePage } from 'src/mocks/serverHandlers'; -import { http, HttpResponse, server } from 'src/mocks/testServer'; -import { renderWithTheme } from 'src/utilities/testHelpers'; - -import { BucketLanding } from './BucketLanding'; - -const queryMocks = vi.hoisted(() => ({ - useNavigate: vi.fn(() => vi.fn()), - useOrderV2: vi.fn().mockReturnValue({}), - useSearch: vi.fn(), -})); - -vi.mock('@tanstack/react-router', async () => { - const actual = await vi.importActual('@tanstack/react-router'); - return { - ...actual, - useNavigate: queryMocks.useNavigate, - useSearch: queryMocks.useSearch, - }; -}); - -vi.mock('src/hooks/useOrderV2', async () => { - const actual = await vi.importActual('src/hooks/useOrderV2'); - return { - ...actual, - useOrderV2: queryMocks.useOrderV2, - }; -}); - -describe('ObjectStorageLanding', () => { - beforeAll(() => { - server.listen(); - queryMocks.useSearch.mockReturnValue({ - order: 'asc', - orderBy: 'label', - }); - }); - afterEach(() => server.resetHandlers()); - afterAll(() => server.close()); - - it('renders a loading state', () => { - // Mock Buckets - server.use( - http.get('*/object-storage/buckets', () => { - return HttpResponse.json(makeResourcePage([])); - }) - ); - - renderWithTheme(); - - screen.getByTestId('circle-progress'); - }); - - it('renders an empty state', async () => { - // Mock Clusters - server.use( - http.get('*/object-storage/clusters', () => { - const clusters = objectStorageClusterFactory.buildList(4); - return HttpResponse.json(makeResourcePage(clusters)); - }) - ); - - // Mock Buckets - server.use( - http.get('*/object-storage/buckets/*', () => { - return HttpResponse.json(makeResourcePage([])); - }) - ); - - renderWithTheme(); - - await screen.findByTestId('placeholder-button'); - }); - - it('renders per-cluster errors', async () => { - objectStorageBucketFactory.resetSequenceNumber(); - objectStorageClusterFactory.resetSequenceNumber(); - - const downCluster = objectStorageClusterFactory.build({ - region: 'us-west', - }); - - // Mock Clusters - server.use( - http.get('*/object-storage/clusters', () => { - const upClusters = objectStorageClusterFactory.buildList(1, { - region: 'ap-south-1', - }); - return HttpResponse.json( - makeResourcePage([downCluster, ...upClusters]) - ); - }) - ); - - // Mock Buckets - server.use( - http.get( - '*/object-storage/buckets/cluster-1', - () => { - return HttpResponse.json([{ reason: 'Cluster offline!' }], { - status: 500, - }); - }, - { - once: true, - } - ), - http.get('*/object-storage/buckets/*', () => { - return HttpResponse.json( - makeResourcePage( - objectStorageBucketFactory.buildList(2, { cluster: 'ap-south-1' }) - ) - ); - }) - ); - - renderWithTheme(); - - await screen.findByText( - /^There was an error loading buckets in US, Fremont, CA/ - ); - }); - - it('renders general error state', async () => { - // Mock Clusters - server.use( - http.get('*/object-storage/clusters', () => { - const clusters = objectStorageClusterFactory.buildList(1); - return HttpResponse.json(makeResourcePage(clusters)); - }) - ); - - // Mock Buckets - server.use( - http.get('*/object-storage/buckets/*', () => { - return HttpResponse.json([{ reason: 'Cluster offline!' }], { - status: 500, - }); - }) - ); - renderWithTheme(); - - await screen.findByText(/^There was an error retrieving your buckets/); - }); - - it('renders rows for each Bucket', async () => { - const buckets = objectStorageBucketFactory.buildList(2); - queryMocks.useOrderV2.mockReturnValue({ - order: 'asc', - orderBy: 'label', - sortedData: buckets, - }); - - // Mock Clusters - server.use( - http.get('*/object-storage/clusters', () => { - const clusters = objectStorageClusterFactory.buildList(1); - return HttpResponse.json(makeResourcePage(clusters)); - }) - ); - - // Mock Buckets - server.use( - http.get('*/object-storage/buckets/*', () => { - return HttpResponse.json(makeResourcePage(buckets)); - }) - ); - - renderWithTheme(); - - await screen.findByText(buckets[0].label); - await screen.findByText(buckets[1].label); - }); - - it('renders a "Total usage" section using base2 calculations if there is more than one Bucket', async () => { - const buckets = objectStorageBucketFactory.buildList(2, { - size: 1024 * 1024 * 1024 * 5, // 5 GB in base2 (5 GiB) - }); - - // Mock Clusters - server.use( - http.get('*/object-storage/clusters', () => { - const clusters = objectStorageClusterFactory.buildList(1); - return HttpResponse.json(makeResourcePage(clusters)); - }) - ); - - // Mock Buckets - server.use( - http.get('*/object-storage/buckets/*', () => { - return HttpResponse.json(makeResourcePage(buckets)); - }) - ); - - renderWithTheme(); - - await screen.findByText(/Total storage used: 10 GB/); - }); - - it('renders error notice for multiple regions', async () => { - objectStorageBucketFactory.resetSequenceNumber(); - objectStorageClusterFactory.resetSequenceNumber(); - - // Create multiple down clusters in different regions - const downClusters = [ - objectStorageClusterFactory.build({ region: 'us-west' }), - objectStorageClusterFactory.build({ region: 'ap-south' }), - objectStorageClusterFactory.build({ region: 'eu-west' }), - ]; - - // Mock Clusters - server.use( - http.get('*/object-storage/clusters', () => { - const upCluster = objectStorageClusterFactory.build({ - region: 'us-east', - }); - return HttpResponse.json( - makeResourcePage([...downClusters, upCluster]) - ); - }) - ); - - // Mock bucket errors for each down cluster - server.use( - ...downClusters.map((cluster) => - http.get(`*/object-storage/buckets/${cluster.id}`, () => { - return HttpResponse.json([{ reason: 'Cluster offline!' }], { - status: 500, - }); - }) - ), - // Mock successful response for up cluster - http.get('*/object-storage/buckets/*', () => { - return HttpResponse.json( - makeResourcePage( - objectStorageBucketFactory.buildList(1, { cluster: 'us-east' }) - ) - ); - }) - ); - - renderWithTheme(); - - await waitFor(() => { - const errorRegions = ['US, Fremont, CA', 'SG, Singapore', 'GB, London']; - for (const region of errorRegions) { - expect(screen.queryByText(region)).toBeInTheDocument(); - } - }); - }); -}); diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx deleted file mode 100644 index 3bfbb0c81ae..00000000000 --- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx +++ /dev/null @@ -1,307 +0,0 @@ -import { useProfile, useRegionsQuery } from '@linode/queries'; -import { CircleProgress, ErrorState, Notice, Typography } from '@linode/ui'; -import { readableBytes, useOpenClose } from '@linode/utilities'; -import Grid from '@mui/material/Grid'; -import * as React from 'react'; -import { makeStyles } from 'tss-react/mui'; - -import { DocumentTitleSegment } from 'src/components/DocumentTitle'; -import { Link } from 'src/components/Link'; -import { TransferDisplay } from 'src/components/TransferDisplay/TransferDisplay'; -import { TypeToConfirmDialog } from 'src/components/TypeToConfirmDialog/TypeToConfirmDialog'; -import { useOrderV2 } from 'src/hooks/useOrderV2'; -import { - useDeleteBucketMutation, - useObjectStorageBuckets, -} from 'src/queries/object-storage/queries'; -import { isBucketError } from 'src/queries/object-storage/requests'; -import { - sendDeleteBucketEvent, - sendDeleteBucketFailedEvent, -} from 'src/utilities/analytics/customEventAnalytics'; - -import { CancelNotice } from '../CancelNotice'; -import { BucketDetailsDrawer } from './BucketDetailsDrawer'; -import { BucketLandingEmptyState } from './BucketLandingEmptyState'; -import { BucketTable } from './BucketTable'; - -import type { - APIError, - ObjectStorageBucket, - ObjectStorageCluster, - ObjectStorageEndpoint, -} from '@linode/api-v4'; -import type { Theme } from '@mui/material/styles'; - -interface Props { - isCreateBucketDrawerOpen?: boolean; -} - -const useStyles = makeStyles()((theme: Theme) => ({ - copy: { - marginTop: theme.spacing(), - }, -})); - -export const BucketLanding = (props: Props) => { - const { isCreateBucketDrawerOpen } = props; - const { data: profile } = useProfile(); - - const isRestrictedUser = profile?.restricted; - - const { - data: objectStorageBucketsResponse, - error: bucketsErrors, - isLoading: areBucketsLoading, - } = useObjectStorageBuckets(); - - const { mutateAsync: deleteBucket } = useDeleteBucketMutation(); - - const { classes } = useStyles(); - - const removeBucketConfirmationDialog = useOpenClose(); - const [isLoading, setIsLoading] = React.useState(false); - const [error, setError] = React.useState(undefined); - const [bucketDetailDrawerOpen, setBucketDetailDrawerOpen] = - React.useState(false); - const [selectedBucket, setSelectedBucket] = React.useState< - ObjectStorageBucket | undefined - >(undefined); - - const handleClickDetails = (bucket: ObjectStorageBucket) => { - setBucketDetailDrawerOpen(true); - setSelectedBucket(bucket); - }; - - const closeBucketDetailDrawer = () => { - setBucketDetailDrawerOpen(false); - }; - - const handleClickRemove = (bucket: ObjectStorageBucket) => { - setSelectedBucket(bucket); - setError(undefined); - removeBucketConfirmationDialog.open(); - }; - - const removeBucket = () => { - // This shouldn't happen, but just in case (and to get TS to quit complaining...) - if (!selectedBucket) { - return; - } - - setError(undefined); - setIsLoading(true); - - const { cluster, label } = selectedBucket; - - deleteBucket({ cluster, label }) - .then(() => { - removeBucketConfirmationDialog.close(); - setIsLoading(false); - - // @analytics - sendDeleteBucketEvent(cluster); - }) - .catch((e) => { - // @analytics - sendDeleteBucketFailedEvent(cluster); - - setIsLoading(false); - setError(e); - }); - }; - - const { - handleOrderChange, - order, - orderBy, - sortedData: orderedData, - } = useOrderV2({ - data: objectStorageBucketsResponse?.buckets, - initialRoute: { - defaultOrder: { - order: 'asc', - orderBy: 'label', - }, - from: '/object-storage/buckets', - }, - preferenceKey: 'object-storage-buckets', - }); - - const closeRemoveBucketConfirmationDialog = React.useCallback(() => { - removeBucketConfirmationDialog.close(); - }, [removeBucketConfirmationDialog]); - - const unavailableClusters = - objectStorageBucketsResponse?.errors.map((error) => - isBucketError(error) ? error.cluster : error.endpoint - ) || []; - - if (isRestrictedUser) { - return ; - } - - if (bucketsErrors) { - return ( - - ); - } - - if (areBucketsLoading || objectStorageBucketsResponse === undefined) { - return ; - } - - if (objectStorageBucketsResponse?.buckets.length === 0) { - return ( - <> - {unavailableClusters.length > 0 && ( - - )} - - - ); - } - - const totalUsage = sumBucketUsage(objectStorageBucketsResponse.buckets); - const bucketLabel = selectedBucket ? selectedBucket.label : ''; - - return ( - - - {unavailableClusters.length > 0 && ( - - )} - - - {/* If there's more than one Bucket, display the total usage. */} - {objectStorageBucketsResponse.buckets.length > 1 ? ( - - Total storage used: {readableBytes(totalUsage).formatted} - - ) : null} - 1 ? 8 : 18} - /> - - - - - Warning: Deleting a bucket is permanent and - can’t be undone. - - - - A bucket must be empty before deleting it. Please{' '} - - delete all objects - - , or use{' '} - - another tool - {' '} - to force deletion. - - {/* If the user is attempting to delete their last Bucket, remind them - that they will still be billed unless they cancel Object Storage in - Account Settings. */} - {objectStorageBucketsResponse?.buckets.length === 1 && ( - - )} - - - - ); -}; - -const RenderEmpty = () => { - return ; -}; - -interface UnavailableClustersDisplayProps { - unavailableClusters: (ObjectStorageCluster | ObjectStorageEndpoint)[]; -} - -const UnavailableClustersDisplay = React.memo( - ({ unavailableClusters }: UnavailableClustersDisplayProps) => { - const { data: regions } = useRegionsQuery(); - - const regionsAffected = unavailableClusters.map( - (cluster) => - regions?.find((region) => region.id === cluster.region)?.label ?? - cluster.region - ); - - return ; - } -); - -interface BannerProps { - regionsAffected: string[]; -} - -const Banner = React.memo(({ regionsAffected }: BannerProps) => { - const moreThanOneRegionAffected = regionsAffected.length > 1; - - return ( - - - There was an error loading buckets in{' '} - {moreThanOneRegionAffected - ? 'the following regions:' - : `${regionsAffected[0]}.`} -
    - {moreThanOneRegionAffected && - regionsAffected.map((thisRegion) => ( -
  • {thisRegion}
  • - ))} -
- If you have buckets in{' '} - {moreThanOneRegionAffected ? 'these regions' : regionsAffected[0]}, you - may not see them listed below. -
-
- ); -}); - -export const sumBucketUsage = (buckets: ObjectStorageBucket[]) => { - return buckets.reduce((acc, thisBucket) => { - acc += thisBucket.size; - return acc; - }, 0); -}; diff --git a/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx b/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx index e54bd60784a..00dd326b68f 100644 --- a/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx +++ b/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx @@ -30,11 +30,6 @@ const SummaryLanding = React.lazy(() => default: module.SummaryLanding, })) ); -const BucketLanding = React.lazy(() => - import('./BucketLanding/BucketLanding').then((module) => ({ - default: module.BucketLanding, - })) -); const AccessKeyLanding = React.lazy(() => import('./AccessKeyLanding/AccessKeyLanding').then((module) => ({ default: module.AccessKeyLanding, @@ -179,13 +174,9 @@ export const ObjectStorageLanding = () => { )} - {isObjMultiClusterEnabled ? ( - - ) : ( - - )} + enabled, }); -export const useObjectStorageBuckets = (enabled = true) => { +export const useObjectStorageBuckets = (enabled: boolean = true) => { const flags = useFlags(); - const { data: account } = useAccount(); - const { data: allRegions } = useRegionsQuery(); - - const isObjMultiClusterEnabled = isFeatureEnabledV2( - 'Object Storage Access Key Regions', - Boolean(flags.objMultiCluster), - account?.capabilities ?? [] + const { data: account, isLoading: accountIsLoading } = useAccount(enabled); + + // TODO: always use regions query once dynamic Object Storage capability resolution is enabled + const isObjectStorageGen2Enabled = + account === undefined + ? undefined + : isFeatureEnabledV2( + 'Object Storage Endpoint Types', + Boolean(flags.objectStorageGen2?.enabled), + account.capabilities ?? [] + ); + const endpointsQueryEnabled = enabled && isObjectStorageGen2Enabled === true; + const regionsQueryEnabled = enabled && isObjectStorageGen2Enabled === false; + + const { data: allRegions, isLoading: regionsAreLoading } = + useRegionsQuery(regionsQueryEnabled); + const objRegions = allRegions?.filter((r) => + r.capabilities.includes('Object Storage') ); - const isObjectStorageGen2Enabled = isFeatureEnabledV2( - 'Object Storage Endpoint Types', - Boolean(flags.objectStorageGen2?.enabled), - account?.capabilities ?? [] - ); - - const endpointsQueryEnabled = enabled && isObjectStorageGen2Enabled; - const clustersQueryEnabled = enabled && !isObjMultiClusterEnabled; - // Endpoints contain all the regions that support Object Storage. - const { data: endpoints } = useObjectStorageEndpoints(endpointsQueryEnabled); - const { data: clusters } = useObjectStorageClusters(clustersQueryEnabled); - - const regions = - isObjMultiClusterEnabled && !isObjectStorageGen2Enabled - ? allRegions?.filter((r) => r.capabilities.includes('Object Storage')) - : undefined; - - const queryEnabled = - enabled && - ((isObjectStorageGen2Enabled && Boolean(endpoints)) || - (isObjMultiClusterEnabled && Boolean(regions)) || - Boolean(clusters)); + const { data: endpoints, isLoading: endpointsAreLoading } = + useObjectStorageEndpoints(endpointsQueryEnabled); - const queryFn = isObjectStorageGen2Enabled + const bucketsQueryEnabled = + (endpointsQueryEnabled && Boolean(endpoints)) || + (regionsQueryEnabled && Boolean(objRegions)); + const queryFn = endpointsQueryEnabled ? () => getAllBucketsFromEndpoints(endpoints) - : isObjMultiClusterEnabled - ? () => getAllBucketsFromRegions(regions) - : () => getAllBucketsFromClusters(clusters); + : () => getAllBucketsFromRegions(objRegions); - return useQuery>({ - enabled: queryEnabled, + const dependencyIsLoading = + accountIsLoading || regionsAreLoading || endpointsAreLoading; + + const bucketsQuery = useQuery< + BucketsResponseType + >({ + enabled: bucketsQueryEnabled, queryFn, queryKey: objectStorageQueries.buckets.queryKey, retry: false, }); + return { + ...bucketsQuery, + isLoading: bucketsQuery.isLoading || dependencyIsLoading, + }; }; export const useObjectStorageAccessKeys = (params: Params) => diff --git a/packages/manager/src/queries/object-storage/requests.ts b/packages/manager/src/queries/object-storage/requests.ts index fe5074fb622..4d9170f4c9c 100644 --- a/packages/manager/src/queries/object-storage/requests.ts +++ b/packages/manager/src/queries/object-storage/requests.ts @@ -1,6 +1,5 @@ import { getBuckets, - getBucketsInCluster, getBucketsInRegion, getClusters, getObjectStorageEndpoints, @@ -40,9 +39,8 @@ export const getAllObjectStorageEndpoints = () => * @deprecated This type will be deprecated and removed when OBJ Gen2 is in GA. */ export interface BucketError { - cluster: ObjectStorageCluster; error: APIError[]; - region?: Region; + region: Region; } /** @@ -74,47 +72,9 @@ export type BucketsResponseType = T extends true export function isBucketError( error: BucketError | BucketErrorGen2 ): error is BucketError { - return (error as BucketError).cluster !== undefined; + return (error as BucketError).region !== undefined; } -/** - * @deprecated This function is deprecated and will be removed in the future. - */ -export const getAllBucketsFromClusters = async ( - clusters: ObjectStorageCluster[] | undefined -) => { - if (clusters === undefined) { - return { buckets: [], errors: [] } as BucketsResponse; - } - - const promises = clusters.map((cluster) => - getAll((params) => - getBucketsInCluster(cluster.id, params) - )() - .then((data) => data.data) - .catch((error) => ({ - cluster, - error, - })) - ); - - const data = await Promise.all(promises); - - const bucketsPerCluster = data.filter((item) => - Array.isArray(item) - ) as ObjectStorageBucket[][]; - - const buckets = bucketsPerCluster.reduce((acc, val) => acc.concat(val), []); - - const errors = data.filter((item) => !Array.isArray(item)) as BucketError[]; - - if (errors.length === clusters.length) { - throw new Error('Unable to get Object Storage buckets.'); - } - - return { buckets, errors } as BucketsResponse; -}; - /** * @deprecated This function is deprecated and will be removed in the future. */ diff --git a/packages/queries/src/regions/regions.ts b/packages/queries/src/regions/regions.ts index 0a735b36aaf..2752869ef11 100644 --- a/packages/queries/src/regions/regions.ts +++ b/packages/queries/src/regions/regions.ts @@ -76,10 +76,11 @@ export const useRegionQuery = (regionId: string) => { }); }; -export const useRegionsQuery = () => +export const useRegionsQuery = (enabled: boolean = true) => useQuery({ ...regionQueries.regions, ...queryPresets.longLived, + enabled, select: (regions: Region[]) => regions.map((region) => ({ ...region, From 7b504a747e41e3f82ce8dd74bf12fc14e2a80e5d Mon Sep 17 00:00:00 2001 From: Sakshi Tayal <167911487+stayal712@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:00:38 -0500 Subject: [PATCH 26/56] test: [DBAAS1-1497] Fix cypress test failing for hostname endpoint changes (#13457) * test: [DBAAS1-1497] Fix update database tests for failing hostname changes * Added changeset: Fix cypress test failing for hostname endpoint changes --- .../manager/.changeset/pr-13457-tests-1772559220854.md | 5 +++++ .../cypress/e2e/core/databases/update-database.spec.ts | 10 ---------- 2 files changed, 5 insertions(+), 10 deletions(-) create mode 100644 packages/manager/.changeset/pr-13457-tests-1772559220854.md diff --git a/packages/manager/.changeset/pr-13457-tests-1772559220854.md b/packages/manager/.changeset/pr-13457-tests-1772559220854.md new file mode 100644 index 00000000000..1922b893a27 --- /dev/null +++ b/packages/manager/.changeset/pr-13457-tests-1772559220854.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Fix cypress test failing for hostname endpoint changes ([#13457](https://github.com/linode/manager/pull/13457)) diff --git a/packages/manager/cypress/e2e/core/databases/update-database.spec.ts b/packages/manager/cypress/e2e/core/databases/update-database.spec.ts index 0e274db8967..0bc3ddea940 100644 --- a/packages/manager/cypress/e2e/core/databases/update-database.spec.ts +++ b/packages/manager/cypress/e2e/core/databases/update-database.spec.ts @@ -237,7 +237,6 @@ const suspendCluster = (label: string) => { * @param initialLabel - cluster name * @param updateAttemptLabel - cluster updated name * @param errorMessage - error thrown for updating a suspended/resuming cluster - * @param hostnameRegex - connection settings hostname * @param allowedIp - ip for manage access actions */ @@ -247,7 +246,6 @@ const validateSuspendResume = ( initialLabel: string, updateAttemptLabel: string, errorMessage: string, - hostnameRegex: RegExp, allowedIp: string ) => { cy.visit(`/databases/${engine}/${id}`); @@ -263,8 +261,6 @@ const validateSuspendResume = ( .click(); cy.findByText('Connection Details'); - // DBaaS hostnames are not available when database/cluster is suspended or resuming. - cy.findByText(hostnameRegex).should('be.visible'); // DBaaS passwords cannot be revealed when database/cluster is suspended or resuming. ui.cdsButton.findButtonByTitle('Show').should('be.enabled'); @@ -647,8 +643,6 @@ describe('Update database clusters', () => { const errorMessage = 'Your database is suspended; please wait until it becomes active to perform this operation.'; - const hostnameRegex = - /your hostnames? will appear here once (it is|they are) available./i; mockGetAccount(accountFactory.build()).as('getAccount'); mockGetDatabase(database).as('getDatabase'); @@ -719,7 +713,6 @@ describe('Update database clusters', () => { initialLabel, updateAttemptLabel, errorMessage, - hostnameRegex, allowedIp ); }); @@ -756,8 +749,6 @@ describe('Update database clusters', () => { }); const errorMessage = `Your database is ${action}; please wait until it becomes active to perform this operation.`; - const hostnameRegex = - /your hostnames? will appear here once (it is|they are) available./i; mockGetAccount(accountFactory.build()).as('getAccount'); mockGetDatabases([database]).as('getDatabases'); @@ -846,7 +837,6 @@ describe('Update database clusters', () => { initialLabel, updateAttemptLabel, errorMessage, - hostnameRegex, allowedIp ); }); From 71f5bbbc1a8bb34ed4d1565a379a3efd21dbabc0 Mon Sep 17 00:00:00 2001 From: jdamore-linode <97627410+jdamore-linode@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:24:54 -0500 Subject: [PATCH 27/56] test: [UIE-10347] - Fix Cypress test failures following 1.159.0 release (#13438) * Fix Cypress test failures following 1.159.0 release * Added changeset: Fix Cypress test failures following v1.159.0 release --------- Co-authored-by: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> --- .../pr-13438-tests-1772047855280.md | 5 +++ ...ification-channel-permission-tests.spec.ts | 11 ++--- .../smoke-linode-landing-table.spec.ts | 40 +++++++++++-------- .../enable-object-storage.spec.ts | 12 +----- 4 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 packages/manager/.changeset/pr-13438-tests-1772047855280.md diff --git a/packages/manager/.changeset/pr-13438-tests-1772047855280.md b/packages/manager/.changeset/pr-13438-tests-1772047855280.md new file mode 100644 index 00000000000..af35fa64ad0 --- /dev/null +++ b/packages/manager/.changeset/pr-13438-tests-1772047855280.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Fix Cypress test failures following v1.159.0 release ([#13438](https://github.com/linode/manager/pull/13438)) diff --git a/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts b/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts index e90e7524412..55e2978c839 100644 --- a/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts +++ b/packages/manager/cypress/e2e/core/cloudpulse/alerting-notification-channel-permission-tests.spec.ts @@ -37,10 +37,8 @@ describe('Notification Channel Listing Page — Access Control', () => { mockAppendFeatureFlags(flags); cy.visitWithLogin('/linodes'); - ui.nav.findItemByTitle('Alerts').as('alertsNav'); - cy.get('@alertsNav').scrollIntoView(); - cy.get('@alertsNav').should('be.visible').click(); - + ui.nav.findItemByTitle('Alerts').scrollIntoView(); + ui.nav.findItemByTitle('Alerts').should('be.visible').click(); ui.tabList .findTabByTitle('Notification Channels') .should('be.visible') @@ -65,9 +63,8 @@ describe('Notification Channel Listing Page — Access Control', () => { mockAppendFeatureFlags(flags); cy.visitWithLogin('/linodes'); - ui.nav.findItemByTitle('Alerts').as('alertsNav'); - cy.get('@alertsNav').scrollIntoView(); - cy.get('@alertsNav').should('be.visible').click(); + ui.nav.findItemByTitle('Alerts').scrollIntoView(); + ui.nav.findItemByTitle('Alerts').should('be.visible').click(); // Tab should not render at all ui.tabList.findTabByTitle('Notification Channels').should('not.exist'); diff --git a/packages/manager/cypress/e2e/core/linodes/smoke-linode-landing-table.spec.ts b/packages/manager/cypress/e2e/core/linodes/smoke-linode-landing-table.spec.ts index efaa1174406..f4c1a1ba98f 100644 --- a/packages/manager/cypress/e2e/core/linodes/smoke-linode-landing-table.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/smoke-linode-landing-table.spec.ts @@ -93,21 +93,29 @@ describe('linode landing checks', () => { it('checks the landing page side menu items', () => { cy.findByTitle('Akamai - Cloud Manager').should('be.visible'); - cy.findByTestId('menu-item-Linodes').should('be.visible'); - cy.findByTestId('menu-item-Volumes').should('be.visible'); - cy.findByTestId('menu-item-NodeBalancers').should('be.visible'); - cy.findByTestId('menu-item-Firewalls').should('be.visible'); - cy.findByTestId('menu-item-StackScripts').should('be.visible'); - cy.findByTestId('menu-item-Images').should('be.visible'); - cy.findByTestId('menu-item-Domains').should('be.visible'); - cy.findByTestId('menu-item-Kubernetes').should('be.visible'); - cy.findByTestId('menu-item-Object Storage').should('be.visible'); - cy.findByTestId('menu-item-Longview').should('be.visible'); - cy.findByTestId('menu-item-Marketplace').should('be.visible'); - cy.findByTestId('menu-item-Billing').scrollIntoView(); - cy.findByTestId('menu-item-Billing').should('be.visible'); - cy.findByTestId('menu-item-Account Settings').should('be.visible'); - cy.findByTestId('menu-item-Help & Support').should('be.visible'); + + const expectedNavItems = [ + 'Linodes', + 'Volumes', + 'NodeBalancers', + 'Firewalls', + 'StackScripts', + 'Images', + 'Domains', + 'Kubernetes', + 'Object Storage', + 'Longview', + 'Quick Deploy Apps', + 'Partner Referrals', + 'Billing', + 'Account Settings', + 'Help & Support', + ]; + + expectedNavItems.forEach((navItem) => { + ui.nav.findItemByTitle(navItem).scrollIntoView(); + ui.nav.findItemByTitle(navItem).should('be.visible'); + }); }); it('checks the landing top menu items', () => { @@ -271,7 +279,7 @@ describe('linode landing checks', () => { cy.get(commonLocators.topMenuCreateItemsLocator.marketplaceOneClickLink) .should('be.visible') .within(() => { - cy.findByText('Marketplace').should('be.visible'); + cy.findByText('Quick Deploy Apps').should('be.visible'); cy.findByText('Deploy applications with ease').should('be.visible'); }); }); diff --git a/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts index 3ebde174bd5..ce5a8e16584 100644 --- a/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts @@ -25,11 +25,7 @@ import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { randomLabel } from 'support/util/random'; -import type { - AccountSettings, - PriceType, - Region, -} from '@linode/api-v4'; +import type { AccountSettings, PriceType, Region } from '@linode/api-v4'; // Various messages, notes, and warnings that may be shown when enabling Object Storage // under different circumstances. @@ -187,11 +183,7 @@ describe('Object Storage enrollment', () => { mockGetAccessKeys([]); cy.visitWithLogin('/object-storage/buckets'); - cy.wait([ - '@getAccountSettings', - '@getBuckets', - '@getRegions', - ]); + cy.wait(['@getAccountSettings', '@getBuckets', '@getRegions']); // Confirm that empty-state message is shown before proceeding. cy.findByText('S3-compatible storage solution').should('be.visible'); From f08cf11afbf9af4876a2c2b3ec1d17a0ae2425de Mon Sep 17 00:00:00 2001 From: Hana Xu <115299789+hana-akamai@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:29:33 -0500 Subject: [PATCH 28/56] fix: [UIE-10244] - Connection Pools table page size (#13448) Remove Infinity option from the Database Connection Pools table page size dropdown --- .../manager/.changeset/pr-13448-fixed-1772228313479.md | 5 +++++ .../DatabaseNetworking/DatabaseConnectionPools.tsx | 8 +++----- .../Databases/DatabaseLanding/DatabaseLandingTable.tsx | 6 +++--- packages/manager/src/features/Databases/constants.ts | 2 ++ 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 packages/manager/.changeset/pr-13448-fixed-1772228313479.md diff --git a/packages/manager/.changeset/pr-13448-fixed-1772228313479.md b/packages/manager/.changeset/pr-13448-fixed-1772228313479.md new file mode 100644 index 00000000000..8b60e9f805d --- /dev/null +++ b/packages/manager/.changeset/pr-13448-fixed-1772228313479.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Database Connection Pools table page size ([#13448](https://github.com/linode/manager/pull/13448)) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx index 78893f1bb79..a71ee633ee9 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx @@ -21,10 +21,8 @@ import { import React from 'react'; import { Link } from 'src/components/Link'; -import { - MIN_PAGE_SIZE, - PAGE_SIZES, -} from 'src/components/PaginationFooter/PaginationFooter.constants'; +import { MIN_PAGE_SIZE } from 'src/components/PaginationFooter/PaginationFooter.constants'; +import { DEFAULT_PAGE_SIZES } from 'src/features/Databases/constants'; import { CONNECTION_POOL_LABEL_CELL_STYLES, MANAGE_CONNECTION_POOLS_LEARN_MORE_LINK, @@ -227,7 +225,7 @@ export const DatabaseConnectionPools = ({ database }: Props) => { ) => pagination.handlePageSizeChange(Number(e.detail.pageSize))} page={pagination.page} pageSize={pagination.pageSize} - pageSizes={PAGE_SIZES} + pageSizes={DEFAULT_PAGE_SIZES} style={{ borderLeft: `1px solid ${theme.tokens.alias.Border.Normal}`, borderRight: `1px solid ${theme.tokens.alias.Border.Normal}`, diff --git a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx index 9bb985eed80..3eaeba8e5e9 100644 --- a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx +++ b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx @@ -10,7 +10,9 @@ import { } from 'akamai-cds-react-components/Table'; import React from 'react'; +import { MIN_PAGE_SIZE } from 'src/components/PaginationFooter/PaginationFooter.constants'; import { TableRowEmpty } from 'src/components/TableRowEmpty/TableRowEmpty'; +import { DEFAULT_PAGE_SIZES } from 'src/features/Databases/constants'; import { DatabaseSettingsDeleteClusterDialog } from 'src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog'; import DatabaseSettingsResetPasswordDialog from 'src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsResetPasswordDialog'; import { ManageAccessControlDrawer } from 'src/features/Databases/DatabaseDetail/ManageAccessControlDrawer'; @@ -54,8 +56,6 @@ const DatabaseLandingTable = ({ preferenceKey, queryParamsPrefix: dbPlatformType, }); - const PAGE_SIZES = [25, 50, 75, 100]; - const MIN_PAGE_SIZE = 25; const [selectedDatabase, setSelectedDatabase] = React.useState({} as DatabaseInstance); @@ -245,7 +245,7 @@ const DatabaseLandingTable = ({ ) => pagination.handlePageSizeChange(Number(e.detail.pageSize))} page={pagination.page} pageSize={pagination.pageSize} - pageSizes={PAGE_SIZES} + pageSizes={DEFAULT_PAGE_SIZES} style={{ borderLeft: `1px solid ${theme.tokens.alias.Border.Normal}`, borderRight: `1px solid ${theme.tokens.alias.Border.Normal}`, diff --git a/packages/manager/src/features/Databases/constants.ts b/packages/manager/src/features/Databases/constants.ts index 2f5572989d5..7dd4ac4f34a 100644 --- a/packages/manager/src/features/Databases/constants.ts +++ b/packages/manager/src/features/Databases/constants.ts @@ -92,3 +92,5 @@ export const usernameOptions = [ { label: defaultUsername, value: defaultUsername }, { label: 'akmadmin', value: 'akmadmin' }, ]; // Currently the only options for the username field + +export const DEFAULT_PAGE_SIZES = [25, 50, 75, 100]; From 5d25e6eb25454aeb8c38427a7857c1d32f6c6c3b Mon Sep 17 00:00:00 2001 From: mduda-akamai Date: Wed, 4 Mar 2026 07:47:00 +0100 Subject: [PATCH 29/56] upcoming: [DPS-36578] - Custom HTTPS form - additional validation (#13392) --- .../pr-13392-changed-1770898290092.md | 5 + packages/validation/src/delivery.schema.ts | 110 +++++++++++++----- 2 files changed, 85 insertions(+), 30 deletions(-) create mode 100644 packages/validation/.changeset/pr-13392-changed-1770898290092.md diff --git a/packages/validation/.changeset/pr-13392-changed-1770898290092.md b/packages/validation/.changeset/pr-13392-changed-1770898290092.md new file mode 100644 index 00000000000..320bf3b88b9 --- /dev/null +++ b/packages/validation/.changeset/pr-13392-changed-1770898290092.md @@ -0,0 +1,5 @@ +--- +"@linode/validation": Changed +--- + +Delivery Logs - additional validation in Endpoint URL and Custom Header Name fields ([#13392](https://github.com/linode/manager/pull/13392)) diff --git a/packages/validation/src/delivery.schema.ts b/packages/validation/src/delivery.schema.ts index 8bc1b35011c..cdd66ff8449 100644 --- a/packages/validation/src/delivery.schema.ts +++ b/packages/validation/src/delivery.schema.ts @@ -56,20 +56,15 @@ const clientCertificateDetailsSchema = object({ }).test( 'all-or-nothing-cert-details', 'If any certificate detail is provided, all are required.', - function (value, context) { + function (value) { if (!value) { return true; } - const { - client_ca_certificate, - client_certificate, - client_private_key, - tls_hostname, - } = value; + const { client_ca_certificate, client_certificate, client_private_key } = + value; const fields = [ - tls_hostname, client_ca_certificate, client_certificate, client_private_key, @@ -82,39 +77,30 @@ const clientCertificateDetailsSchema = object({ } const errors: ValidationError[] = []; - if (!hasValue(tls_hostname)) { - errors.push( - context.createError({ - path: `${this.path}.tls_hostname`, - message: - 'TLS Hostname is required when other Client Certificate details are provided.', - }), - ); - } if (!hasValue(client_ca_certificate)) { errors.push( - context.createError({ + this.createError({ path: `${this.path}.client_ca_certificate`, message: - 'CA Certificate is required when other Client Certificate details are provided.', + 'CA Certificate is required when other client certificate details are provided.', }), ); } if (!hasValue(client_certificate)) { errors.push( - context.createError({ + this.createError({ path: `${this.path}.client_certificate`, message: - 'Client Certificate is required when other Client Certificate details are provided.', + 'Client Certificate is required when other client certificate details are provided.', }), ); } if (!hasValue(client_private_key)) { errors.push( - context.createError({ + this.createError({ path: `${this.path}.client_private_key`, message: - 'Client Key is required when other Client Certificate details are provided.', + 'Client Key is required when other client certificate details are provided.', }), ); } @@ -123,15 +109,41 @@ const clientCertificateDetailsSchema = object({ }, ); +const forbiddenCustomHeaderNames = [ + 'content-type', + 'encoding', + 'authorization', + 'host', + 'akamai', +]; + const customHeaderSchema = object({ name: string() .max(maxLength, maxLengthMessage) - .required('Custom Header Name is required.'), + .required('Custom Header Name is required.') + .test( + 'non-empty-name', + 'Custom Header Name cannot be empty or whitespace only.', + (value) => hasValue(value), + ) + .test( + 'forbidden-custom-header-name', + 'This header name is not allowed.', + (value) => + !forbiddenCustomHeaderNames.includes(value.trim().toLowerCase()), + ), value: string() .max(maxLength, maxLengthMessage) - .required('Custom Header Value is required'), + .required('Custom Header Value is required.') + .test( + 'non-empty-value', + 'Custom Header Value cannot be empty or whitespace only.', + (value) => hasValue(value), + ), }); +const urlRgx = /^(https?:\/\/)?(www\.)?[a-zA-Z0-9-]+(\.[a-zA-Z]+)+(\/\S*)?$/; + const customHTTPSDetailsSchema = object({ authentication: authenticationSchema.required(), client_certificate_details: clientCertificateDetailsSchema.optional(), @@ -139,11 +151,49 @@ const customHTTPSDetailsSchema = object({ .oneOf(['application/json', 'application/json; charset=utf-8']) .nullable() .optional(), - custom_headers: array().of(customHeaderSchema).min(1).optional(), + custom_headers: array() + .of(customHeaderSchema) + .min(1) + .optional() + .test( + 'unique-header-names', + 'Custom Header Names must be unique.', + function (headers) { + if (!headers || headers.length === 0) { + return true; + } + + const seenNames = new Set(); + const errors: ValidationError[] = []; + + headers.forEach((header, index) => { + const trimmedName = header?.name?.trim().toLowerCase(); + if (!trimmedName) { + return; + } + + if (seenNames.has(trimmedName)) { + errors.push( + this.createError({ + path: `${this.path}[${index}].name`, + message: 'Custom Header Name must be unique.', + }), + ); + } else { + seenNames.add(trimmedName); + } + }); + + return errors.length === 0 || new ValidationError(errors); + }, + ), data_compression: string().oneOf(['gzip', 'None']).required(), endpoint_url: string() .max(maxLength, maxLengthMessage) - .required('Endpoint URL is required.'), + .required('Endpoint URL is required.') + .test('is-valid-url', 'Endpoint URL must be a valid URL.', (value) => + urlRgx.test(value), + ), }); const hostRgx = @@ -298,7 +348,7 @@ const detailsShouldNotExistOrBeNull = (schema: MixedSchema) => const streamSchemaBase = object({ label: string() - .min(3, 'Stream name must have at least 3 characters') + .min(3, 'Stream name must have at least 3 characters.') .max(maxLength, maxLengthMessage) .required('Stream name is required.'), status: mixed<'active' | 'inactive' | 'provisioning'>().oneOf([ @@ -338,7 +388,7 @@ export const updateStreamSchema = streamSchemaBase return detailsShouldNotExistOrBeNull(mixed()); }), }) - .noUnknown('Object contains unknown fields'); + .noUnknown('Object contains unknown fields.'); export const streamAndDestinationFormSchema = object({ stream: streamSchemaBase.shape({ @@ -349,7 +399,7 @@ export const streamAndDestinationFormSchema = object({ otherwise: (schema) => schema .nullable() - .equals([null], 'Details must be null for audit_logs type'), + .equals([null], 'Details must be null for audit_logs type.'), }) as Schema | null>, }), destination: destinationFormSchema.defined().when('stream.destinations', { From c49c99c1a1d949124ce14520b084021925d1a7ea Mon Sep 17 00:00:00 2001 From: Dmytro Chyrva Date: Wed, 4 Mar 2026 10:09:03 +0100 Subject: [PATCH 30/56] new: STORIF-274 - Detach volume before resizing notice added. (#13453) --- .../Volumes/VolumeDrawers/ResizeVolumeDrawer.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/manager/src/features/Volumes/VolumeDrawers/ResizeVolumeDrawer.tsx b/packages/manager/src/features/Volumes/VolumeDrawers/ResizeVolumeDrawer.tsx index 165b4a7e742..d82b04445fa 100644 --- a/packages/manager/src/features/Volumes/VolumeDrawers/ResizeVolumeDrawer.tsx +++ b/packages/manager/src/features/Volumes/VolumeDrawers/ResizeVolumeDrawer.tsx @@ -5,6 +5,7 @@ import { useFormik } from 'formik'; import { useSnackbar } from 'notistack'; import React from 'react'; +import { Link } from 'src/components/Link'; import { usePermissions } from 'src/features/IAM/hooks/usePermissions'; import { useEventsPollingActions } from 'src/queries/events/events'; import { @@ -35,6 +36,7 @@ export const ResizeVolumeDrawer = (props: Props) => { volume?.id ); const canResizeVolume = permissions?.resize_volume; + const isVolumeAttached = volume?.linode_id || volume?.linode_label; const { mutateAsync: resizeVolume } = useResizeVolumeMutation(); @@ -123,6 +125,20 @@ export const ResizeVolumeDrawer = (props: Props) => { regionId={volume?.region ?? ''} value={values.size ?? -1} /> + + {isVolumeAttached && ( + + Detach this volume from a Linode before resizing to prevent data + loss. For maximum safety, power off the Linode first.{' '} + + Learn more about volume resizing. + + + )} + Date: Wed, 4 Mar 2026 12:43:57 +0100 Subject: [PATCH 31/56] fix: [UIE-10326] - IAM / Entities pagination on page refresh (#13451) * fix * cleanup * changeset --- .../manager/.changeset/pr-13451-fixed-1772457963491.md | 5 +++++ packages/manager/src/hooks/usePaginationV2.test.ts | 8 ++++---- packages/manager/src/hooks/usePaginationV2.ts | 9 +++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 packages/manager/.changeset/pr-13451-fixed-1772457963491.md diff --git a/packages/manager/.changeset/pr-13451-fixed-1772457963491.md b/packages/manager/.changeset/pr-13451-fixed-1772457963491.md new file mode 100644 index 00000000000..16cedfd4ef6 --- /dev/null +++ b/packages/manager/.changeset/pr-13451-fixed-1772457963491.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +IAM / Entities & Roles client-side pagination on page refresh ([#13451](https://github.com/linode/manager/pull/13451)) diff --git a/packages/manager/src/hooks/usePaginationV2.test.ts b/packages/manager/src/hooks/usePaginationV2.test.ts index 67dde099a4d..03df3a581fc 100644 --- a/packages/manager/src/hooks/usePaginationV2.test.ts +++ b/packages/manager/src/hooks/usePaginationV2.test.ts @@ -804,7 +804,7 @@ describe('usePaginationV2', () => { expect(mockNavigate).not.toHaveBeenCalled(); }); - it('should handle page clamping to 1 for empty data', async () => { + it('should not reset page when data is empty (e.g. still loading) to preserve URL on reload', async () => { queryClient.setQueryData(['profile', 'preferences'], { pageSizes: { 'test-key': 25 }, }); @@ -826,9 +826,9 @@ describe('usePaginationV2', () => { expect(result.current.page).toBe(1); }); - await waitFor(() => { - expect(mockNavigate).toHaveBeenCalled(); - }); + // Should not trigger navigation when totalCount is 0 so that page from URL + // is preserved on reload while data is still loading + expect(mockNavigate).not.toHaveBeenCalled(); }); it('should auto-reset page when data changes and current page becomes invalid', async () => { diff --git a/packages/manager/src/hooks/usePaginationV2.ts b/packages/manager/src/hooks/usePaginationV2.ts index 09b224a0617..ae794ad1214 100644 --- a/packages/manager/src/hooks/usePaginationV2.ts +++ b/packages/manager/src/hooks/usePaginationV2.ts @@ -143,10 +143,15 @@ export const usePaginationV2 = ({ }, [clientSidePaginationData, clampedPage, pageSize]); React.useEffect(() => { - if (paginatedData !== undefined && clampedPage !== page) { + if ( + paginatedData !== undefined && + totalCount !== undefined && + totalCount > 0 && + clampedPage !== page + ) { setPage(clampedPage); } - }, [clampedPage, page, paginatedData, setPage]); + }, [clampedPage, page, paginatedData, setPage, totalCount]); return { handlePageChange: setPage, From ca6f063bf521bbee841c7f4b335d96a84d525187 Mon Sep 17 00:00:00 2001 From: Hana Xu <115299789+hana-akamai@users.noreply.github.com> Date: Wed, 4 Mar 2026 09:55:32 -0500 Subject: [PATCH 32/56] change: [UIE-10196] - Remove `New` chip from Database Networking Tab and Access banner from Settings (#13454) Remove New chip from Database Networking Tab and Manage Access banner in Settings tab --- .../pr-13454-removed-1772484449775.md | 5 ++++ .../Databases/DatabaseDetail/index.tsx | 27 ++----------------- 2 files changed, 7 insertions(+), 25 deletions(-) create mode 100644 packages/manager/.changeset/pr-13454-removed-1772484449775.md diff --git a/packages/manager/.changeset/pr-13454-removed-1772484449775.md b/packages/manager/.changeset/pr-13454-removed-1772484449775.md new file mode 100644 index 00000000000..e6a3cb4946d --- /dev/null +++ b/packages/manager/.changeset/pr-13454-removed-1772484449775.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Removed +--- + +Remove New chip from Database Networking Tab and Access banner from Settings ([#13454](https://github.com/linode/manager/pull/13454)) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/index.tsx b/packages/manager/src/features/Databases/DatabaseDetail/index.tsx index 420abc5e2c6..989f7684524 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/index.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/index.tsx @@ -3,14 +3,7 @@ import { useDatabaseQuery, useDatabaseTypesQuery, } from '@linode/queries'; -import { - BetaChip, - CircleProgress, - ErrorState, - NewFeatureChip, - Notice, - Typography, -} from '@linode/ui'; +import { BetaChip, CircleProgress, ErrorState, Notice } from '@linode/ui'; import { useEditableLabelState } from '@linode/utilities'; import { Outlet, @@ -20,7 +13,6 @@ import { } from '@tanstack/react-router'; import * as React from 'react'; -import { DismissibleBanner } from 'src/components/DismissibleBanner/DismissibleBanner'; import { DocumentTitleSegment } from 'src/components/DocumentTitle'; import { LandingHeader } from 'src/components/LandingHeader'; import { TabPanels } from 'src/components/Tabs/TabPanels'; @@ -69,7 +61,7 @@ export const DatabaseDetail = () => { const settingsTabPath = `/databases/$engine/$databaseId/settings`; - const { tabs, tabIndex, handleTabChange, getTabIndex } = useTabs([ + const { tabs, tabIndex, handleTabChange } = useTabs([ { to: `/databases/$engine/$databaseId/summary`, title: 'Summary', @@ -84,7 +76,6 @@ export const DatabaseDetail = () => { to: `/databases/$engine/$databaseId/networking`, title: 'Networking', hide: !isVPCEnabled, - chip: , }, { to: `/databases/$engine/$databaseId/backups`, @@ -153,8 +144,6 @@ export const DatabaseDetail = () => { }); }; - const onSettingsTab = tabIndex === getTabIndex(settingsTabPath); - return ( { variant="warning" /> )} - {isVPCEnabled && onSettingsTab && ( - - - The Manage Access settings were moved and are now available in the - Networking tab. - - - )} - From ad72df2bc8304d87e2540e6476fb99dc5c090e4d Mon Sep 17 00:00:00 2001 From: venkatmano-akamai Date: Wed, 4 Mar 2026 21:20:13 +0530 Subject: [PATCH 33/56] upcoming: [DI-29904] - Changes for logs integration with metrics (#13460) * upcoming: [DI-29904] - Changes for logs integration with metrics * upcoming: [DI-29904] - Changeset * upcoming: [DI-29904] - Some quick refactorings * upcoming: [DI-29904] - Revert changes in dashboard select --- ...r-13460-upcoming-features-1772610973355.md | 5 +++ .../features/CloudPulse/Utils/FilterConfig.ts | 41 +++++++++++++++++ .../features/CloudPulse/Utils/constants.ts | 18 ++++++++ .../src/features/CloudPulse/Utils/utils.ts | 31 +++++++++++++ .../shared/CloudPulseComponentRenderer.tsx | 1 + .../CloudPulseDashboardFilterBuilder.tsx | 4 +- packages/manager/src/mocks/serverHandlers.ts | 45 +++++++++++++++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md diff --git a/packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md b/packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md new file mode 100644 index 00000000000..d7cda247dc2 --- /dev/null +++ b/packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Logs service integration changes for onboarding with `CloudPulse Metrics` ([#13460](https://github.com/linode/manager/pull/13460)) diff --git a/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts b/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts index ef456d70de2..68c495dea83 100644 --- a/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts +++ b/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts @@ -9,6 +9,7 @@ import { PARENT_ENTITY_REGION, REGION, RESOURCE_ID, + STATUS_CODE_PLACEHOLDER_TEXT, } from './constants'; import { CloudPulseAvailableViews, CloudPulseSelectTypes } from './models'; import { filterKubernetesClusters, getValidSortedEndpoints } from './utils'; @@ -657,6 +658,45 @@ export const NETLOADBALANCER_CONFIG: Readonly = ], serviceType: 'netloadbalancer', }; + +export const LOGS_CONFIG: Readonly = { + capability: capabilityServiceTypeMapping['logs'], + filters: [ + { + configuration: { + filterKey: 'resource_id', + filterType: 'string', + isFilterable: true, + isMetricsFilter: true, + isMultiSelect: true, + name: 'Stream Names', + neededInViews: [CloudPulseAvailableViews.central], + placeholder: 'Select Stream Names', + priority: 2, + }, + name: 'Stream Names', + }, + { + configuration: { + filterKey: 'status_code', + filterType: 'string', + isFilterable: true, + isMetricsFilter: false, + name: 'Status Code', + dimensionKey: 'status_code', + neededInViews: [ + CloudPulseAvailableViews.central, + CloudPulseAvailableViews.service, + ], + isOptional: true, + placeholder: STATUS_CODE_PLACEHOLDER_TEXT, + priority: 2, + }, + name: 'Status Code', + }, + ], + serviceType: 'logs', +}; export const FILTER_CONFIG: Readonly< Map > = new Map([ @@ -670,6 +710,7 @@ export const FILTER_CONFIG: Readonly< [8, FIREWALL_NODEBALANCER_CONFIG], [9, LKE_CONFIG], [10, ENDPOINT_DASHBOARD_CONFIG], + [11, LOGS_CONFIG], ]); /** diff --git a/packages/manager/src/features/CloudPulse/Utils/constants.ts b/packages/manager/src/features/CloudPulse/Utils/constants.ts index c0f95fff64c..738ab4fafe1 100644 --- a/packages/manager/src/features/CloudPulse/Utils/constants.ts +++ b/packages/manager/src/features/CloudPulse/Utils/constants.ts @@ -51,6 +51,8 @@ export const INTERFACE_ID = 'interface_id'; export const FIREWALL = 'Firewall'; +export const STATUS_CODE = 'status_code'; + export const PORTS_HELPER_TEXT = 'Enter one or more port numbers (1-65535) separated by commas.'; @@ -72,6 +74,22 @@ export const PORTS_LEADING_COMMA_ERROR_MESSAGE = export const PORTS_LIMIT_ERROR_MESSAGE = 'Port list must be 100 characters or less.'; +export const STATUS_CODE_HELPER_TEXT = + 'Enter one or more Status Codes separated by commas.'; + +export const STATUS_CODE_ERROR_MESSAGE = + 'Enter valid status codes as integers separated by commas without spaces.'; + +export const STATUS_CODE_CONSECUTIVE_COMMAS_ERROR_MESSAGE = + 'Use a single comma to separate status codes.'; +export const STATUS_CODE_LEADING_COMMA_ERROR_MESSAGE = + 'First character must be an integer.'; + +export const STATUS_CODE_LIMIT_ERROR_MESSAGE = + 'Status code list must be 100 characters or less.'; + +export const STATUS_CODE_PLACEHOLDER_TEXT = 'e.g., 200,400'; + export const PORTS_PLACEHOLDER_TEXT = 'e.g., 80,443,3000'; export const INTERFACE_IDS_HELPER_TEXT = diff --git a/packages/manager/src/features/CloudPulse/Utils/utils.ts b/packages/manager/src/features/CloudPulse/Utils/utils.ts index 54e32ba7f59..e172d74127c 100644 --- a/packages/manager/src/features/CloudPulse/Utils/utils.ts +++ b/packages/manager/src/features/CloudPulse/Utils/utils.ts @@ -20,6 +20,11 @@ import { PORTS_LEADING_ZERO_ERROR_MESSAGE, PORTS_LIMIT_ERROR_MESSAGE, PORTS_RANGE_ERROR_MESSAGE, + STATUS_CODE, + STATUS_CODE_CONSECUTIVE_COMMAS_ERROR_MESSAGE, + STATUS_CODE_ERROR_MESSAGE, + STATUS_CODE_LEADING_COMMA_ERROR_MESSAGE, + STATUS_CODE_LIMIT_ERROR_MESSAGE, } from './constants'; import type { FetchOptions } from '../Alerts/CreateAlert/Criteria/DimensionFilterValue/constants'; @@ -391,6 +396,31 @@ export const areValidInterfaceIds = ( return undefined; }; +export const areValidStatusCodes = ( + statusCodes: string +): string | undefined => { + if (statusCodes === '') { + return undefined; + } + + if (statusCodes.length > 100) { + return STATUS_CODE_LIMIT_ERROR_MESSAGE; + } + if (statusCodes.startsWith(',')) { + return STATUS_CODE_LEADING_COMMA_ERROR_MESSAGE; + } + + if (statusCodes.includes(',,')) { + return STATUS_CODE_CONSECUTIVE_COMMAS_ERROR_MESSAGE; + } + + if (!/^[\d,]+$/.test(statusCodes)) { + return STATUS_CODE_ERROR_MESSAGE; + } + + return undefined; +}; + /** * @param filterKey * @returns validation function for the filter key @@ -401,6 +431,7 @@ export const validationFunction: Record< > = { [PORT]: arePortsValid, [INTERFACE_ID]: areValidInterfaceIds, + [STATUS_CODE]: areValidStatusCodes, }; /** diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.tsx index 0a90f3801d4..daa4287d10d 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.tsx @@ -64,6 +64,7 @@ const Components: { associated_entity_region: CloudPulseRegionSelect, endpoint: CloudPulseEndpointsSelect, nodebalancer_id: CloudPulseFirewallNodebalancersSelect, + status_code: CloudPulseTextFilter, }; const buildComponent = (props: CloudPulseComponentRendererProps) => { diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx index f8c7ec342ae..cfb02502aa5 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx @@ -20,6 +20,7 @@ import { REGION, RESOURCE_ID, RESOURCES, + STATUS_CODE, TAGS, } from '../Utils/constants'; import { @@ -379,7 +380,8 @@ export const CloudPulseDashboardFilterBuilder = React.memo( ); } else if ( config.configuration.filterKey === PORT || - config.configuration.filterKey === INTERFACE_ID + config.configuration.filterKey === INTERFACE_ID || + config.configuration.filterKey === STATUS_CODE ) { return getTextFilterProperties( { diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index 82752725b3c..fb44b19121c 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -4072,6 +4072,16 @@ export const handlers = [ ); } + if (params.serviceType === 'logs') { + response.data.push( + dashboardFactory.build({ + id: 11, + service_type: 'logs', + label: 'Log Delivery Status', + }) + ); + } + return HttpResponse.json(response); }), http.get( @@ -4528,6 +4538,41 @@ export const handlers = [ ]; serviceType = 'netloadbalancer'; dashboardLabel = 'Network Load Balancer'; + } else if (id === '11') { + serviceType = 'logs'; + dashboardLabel = 'Log Delivery Status'; + widgets = [ + { + metric: 'success_upload_count', + unit: 'Count', + label: 'Success Upload', + color: 'default', + size: 6, + chart_type: 'area', + y_label: 'success_upload_count', + aggregate_function: 'sum', + }, + { + metric: 'error_upload_count', + unit: 'Count', + label: 'Error Upload', + color: 'default', + size: 6, + chart_type: 'area', + y_label: 'error_upload_count', + aggregate_function: 'sum', + }, + { + metric: 'error_upload_rate', + unit: '%', + label: 'Error Rate', + color: 'default', + size: 12, + chart_type: 'area', + y_label: 'error_upload_rate', + aggregate_function: 'avg', + }, + ]; } else { serviceType = 'linode'; dashboardLabel = 'Linode Service I/O Statistics'; From 4070969d2f8340eac0fc25fdb351a5ac722e942a Mon Sep 17 00:00:00 2001 From: Dmytro Chyrva Date: Thu, 5 Mar 2026 09:32:45 +0100 Subject: [PATCH 34/56] fix: STORIF-304 - Throughput quota limit conversion fixed. (#13463) * fix: STORIF-304 - Throughput quota limit conversion fixed. * Added changeset: Throughtput quota conversion logic --- .../pr-13463-fixed-1772640311940.md | 5 ++ .../Quotas/QuotasTable/QuotasTable.test.tsx | 55 +++++++++++++++++++ .../src/features/Account/Quotas/utils.ts | 2 +- 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 packages/manager/.changeset/pr-13463-fixed-1772640311940.md diff --git a/packages/manager/.changeset/pr-13463-fixed-1772640311940.md b/packages/manager/.changeset/pr-13463-fixed-1772640311940.md new file mode 100644 index 00000000000..d0a3846b468 --- /dev/null +++ b/packages/manager/.changeset/pr-13463-fixed-1772640311940.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Throughtput quota conversion logic ([#13463](https://github.com/linode/manager/pull/13463)) diff --git a/packages/manager/src/features/Account/Quotas/QuotasTable/QuotasTable.test.tsx b/packages/manager/src/features/Account/Quotas/QuotasTable/QuotasTable.test.tsx index 8c65e44c0bb..85b5c7da24f 100644 --- a/packages/manager/src/features/Account/Quotas/QuotasTable/QuotasTable.test.tsx +++ b/packages/manager/src/features/Account/Quotas/QuotasTable/QuotasTable.test.tsx @@ -121,4 +121,59 @@ describe('QuotasTable', () => { ).toBeInTheDocument(); }); }); + + it('should display object storage thoughput quotas correctly', async () => { + queryMocks.useAllQuotasQuery.mockReturnValue({ + data: [ + quotaFactory.build({ + quota_name: 'Ingress Throughput (per endpoint)', + description: + 'Current total ingress bandwidth per account, per endpoint', + quota_limit: 1250000000, + quota_type: 'obj-total-ingress-throughput', + resource_metric: 'byte_per_second', + has_usage: false, + }), + ], + isFetching: false, + }); + + queryMocks.useQueries.mockReturnValue([ + { + data: quotaUsageFactory.build({ + quota_limit: 1250000000, + usage: 10, + }), + isLoading: false, + }, + ]); + + const { getByLabelText, getByText } = renderWithTheme( + + ); + + await waitFor(() => { + expect(getByText('Ingress Throughput')).toBeInTheDocument(); + expect(getByText(`10 Gbps`)).toBeInTheDocument(); + expect( + getByLabelText( + 'Current total ingress bandwidth per account, per endpoint' + ) + ).toBeInTheDocument(); + expect(getByText('Not applicable')).toBeInTheDocument(); + expect( + getByLabelText('Action menu for quota Ingress Throughput') + ).toBeInTheDocument(); + }); + }); }); diff --git a/packages/manager/src/features/Account/Quotas/utils.ts b/packages/manager/src/features/Account/Quotas/utils.ts index ad5ec6b0f13..4c926cfbabe 100644 --- a/packages/manager/src/features/Account/Quotas/utils.ts +++ b/packages/manager/src/features/Account/Quotas/utils.ts @@ -249,7 +249,7 @@ export const convertResourceMetric = ({ return { convertedUsage: 0, convertedResourceMetric: 'Gbps', - convertedLimit: readableBytes(initialLimit, { + convertedLimit: readableBytes(initialLimit * 8, { unit: 'GB', base10: true, }).value, From 13836a7b615453d18470caea491db62822221b74 Mon Sep 17 00:00:00 2001 From: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:37:25 +0100 Subject: [PATCH 35/56] fix: [UIE-10396] - Await permissions to show error on User Detail (#13462) * await permission check * Added changeset: Await permissions to show error on User Detail --- .../.changeset/pr-13462-fixed-1772624564447.md | 5 +++++ .../IAM/Users/UserDetails/UserProfile.tsx | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 packages/manager/.changeset/pr-13462-fixed-1772624564447.md diff --git a/packages/manager/.changeset/pr-13462-fixed-1772624564447.md b/packages/manager/.changeset/pr-13462-fixed-1772624564447.md new file mode 100644 index 00000000000..190daf63ab7 --- /dev/null +++ b/packages/manager/.changeset/pr-13462-fixed-1772624564447.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Await permissions to show error on User Detail ([#13462](https://github.com/linode/manager/pull/13462)) diff --git a/packages/manager/src/features/IAM/Users/UserDetails/UserProfile.tsx b/packages/manager/src/features/IAM/Users/UserDetails/UserProfile.tsx index 824b54d6568..53b843d9933 100644 --- a/packages/manager/src/features/IAM/Users/UserDetails/UserProfile.tsx +++ b/packages/manager/src/features/IAM/Users/UserDetails/UserProfile.tsx @@ -19,12 +19,10 @@ import { UsernamePanel } from './UsernamePanel'; export const UserProfile = () => { const { username } = useParams({ from: '/iam/users/$username' }); - const { data: permissions } = usePermissions('account', [ - 'view_user', - 'update_user', - 'delete_user', - 'list_user_permissions', - ]); + const { data: permissions, isLoading: isLoadingPermissions } = usePermissions( + 'account', + ['view_user', 'update_user', 'delete_user', 'list_user_permissions'] + ); const { data: user, @@ -40,7 +38,10 @@ export const UserProfile = () => { return ; } - if (!permissions?.view_user || !permissions?.list_user_permissions) { + if ( + (!permissions?.view_user || !permissions?.list_user_permissions) && + !isLoadingPermissions + ) { return ( You do not have permission to view this user's details. From a1a54db3c70205311b3307faecbef5b7338b4a9a Mon Sep 17 00:00:00 2001 From: Dmytro Chyrva Date: Thu, 5 Mar 2026 10:47:02 +0100 Subject: [PATCH 36/56] new: STORIF-295 - Condition for showing Volume Metrcis tab updated. (#13452) * new: STORIF-295 - Condition for showing Volume Metrcis tab updated. * Added changeset: New condition for displaying volume metrics tab --- .../pr-13452-added-1772466320530.md | 5 +++ .../Volumes/VolumeDetails/VolumeDetails.tsx | 37 ++++++++++++++----- .../manager/src/features/Volumes/constants.ts | 1 + 3 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 packages/manager/.changeset/pr-13452-added-1772466320530.md diff --git a/packages/manager/.changeset/pr-13452-added-1772466320530.md b/packages/manager/.changeset/pr-13452-added-1772466320530.md new file mode 100644 index 00000000000..0259d1e8b92 --- /dev/null +++ b/packages/manager/.changeset/pr-13452-added-1772466320530.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Added +--- + +New condition for displaying volume metrics tab ([#13452](https://github.com/linode/manager/pull/13452)) diff --git a/packages/manager/src/features/Volumes/VolumeDetails/VolumeDetails.tsx b/packages/manager/src/features/Volumes/VolumeDetails/VolumeDetails.tsx index e82a3613aa7..da45e6c1ad2 100644 --- a/packages/manager/src/features/Volumes/VolumeDetails/VolumeDetails.tsx +++ b/packages/manager/src/features/Volumes/VolumeDetails/VolumeDetails.tsx @@ -1,4 +1,4 @@ -import { useVolumeQuery } from '@linode/queries'; +import { useRegionQuery, useVolumeQuery } from '@linode/queries'; import { BetaChip, CircleProgress, ErrorState } from '@linode/ui'; import { Outlet, useNavigate, useParams } from '@tanstack/react-router'; import * as React from 'react'; @@ -11,6 +11,7 @@ import { useFlags } from 'src/hooks/useFlags'; import { useTabs } from 'src/hooks/useTabs'; import { useCloudPulseServiceByServiceType } from 'src/queries/cloudpulse/services'; +import { BLOCK_STORAGE_METRICS_KEY } from '../constants'; import { VolumeDrawers } from '../VolumeDrawers/VolumeDrawers'; import { VolumeDetailsHeader } from './VolumeDetailsHeader'; @@ -23,7 +24,28 @@ export const VolumeDetails = () => { useCloudPulseServiceByServiceType('blockstorage', true); const { volumeId } = useParams({ from: '/volumes/$volumeId' }); - const { data: volume, isLoading, error } = useVolumeQuery(volumeId); + const { + data: volume, + isLoading: volumeLoading, + error: volumeError, + } = useVolumeQuery(volumeId); + const { + data: region, + isLoading: regionLoading, + error: regionError, + } = useRegionQuery(volume?.region || ''); + + const regionSupportsMetrics = region?.monitors?.metrics?.includes( + BLOCK_STORAGE_METRICS_KEY + ); + + const isVolumeMetricsTabHidden = + aclpServiceError || + !blockStorageContextualMetrics || + !aclpServices?.blockstorage?.metrics?.enabled || + !regionSupportsMetrics || + !!regionError; + const { tabs, handleTabChange, tabIndex } = useTabs([ { to: '/volumes/$volumeId/summary', @@ -32,19 +54,16 @@ export const VolumeDetails = () => { { to: '/volumes/$volumeId/metrics', title: 'Metrics', - hide: - aclpServiceError || - !blockStorageContextualMetrics || - !aclpServices?.blockstorage?.metrics?.enabled, + hide: isVolumeMetricsTabHidden, chip: aclpServices?.blockstorage?.metrics?.beta ? : null, }, ]); - if (!volumeSummaryPage || error) { - return ; + if (!volumeSummaryPage || volumeError) { + return ; } - if (isLoading || aclServiceLoading || !volume) { + if (volumeLoading || regionLoading || aclServiceLoading || !volume) { return ; } diff --git a/packages/manager/src/features/Volumes/constants.ts b/packages/manager/src/features/Volumes/constants.ts index d165b54e603..23f153f6978 100644 --- a/packages/manager/src/features/Volumes/constants.ts +++ b/packages/manager/src/features/Volumes/constants.ts @@ -1 +1,2 @@ export const SIZE_FIELD_WIDTH = 160; +export const BLOCK_STORAGE_METRICS_KEY = 'Block Storage'; From 573ad616715c428e9af74ba421ae7cb4466fc353 Mon Sep 17 00:00:00 2001 From: grevanak-akamai <145482092+grevanak-akamai@users.noreply.github.com> Date: Thu, 5 Mar 2026 18:42:08 +0530 Subject: [PATCH 37/56] change: [UIE-10132] - Make firewall selection mandatory while creating linode and its interfaces (#13410) --- .../pr-13410-changed-1772435694557.md | 5 + .../e2e/core/general/gdpr-agreement.spec.ts | 16 +- .../open-support-ticket.spec.ts | 9 + .../images/create-linode-from-image.spec.ts | 15 +- .../e2e/core/linodes/alerts-create.spec.ts | 31 ++- .../e2e/core/linodes/clone-linode.spec.ts | 10 + .../linodes/create-linode-blackwell.spec.ts | 15 ++ .../create-linode-in-core-region.spec.ts | 14 ++ ...reate-linode-in-distributed-region.spec.ts | 16 +- .../core/linodes/create-linode-mobile.spec.ts | 14 +- .../create-linode-view-code-snippet.spec.ts | 12 +- .../create-linode-vm-host-maintenance.spec.ts | 12 +- .../create-linode-with-add-ons.spec.ts | 21 ++ ...create-linode-with-disk-encryption.spec.ts | 16 +- .../create-linode-with-firewall.spec.ts | 199 ++++++++++++++---- .../create-linode-with-ssh-key.spec.ts | 19 +- .../create-linode-with-user-data.spec.ts | 13 +- .../linodes/create-linode-with-vlan.spec.ts | 38 ++++ .../linodes/create-linode-with-vpc.spec.ts | 61 ++++++ .../e2e/core/linodes/create-linode.spec.ts | 30 ++- .../core/oneClickApps/one-click-apps.spec.ts | 17 +- ...reate-linode-with-placement-groups.spec.ts | 19 +- .../stackscripts/create-stackscripts.spec.ts | 26 ++- .../smoke-community-stackscripts.spec.ts | 7 + .../support/ui/pages/linode-create-page.ts | 26 +++ .../manager/cypress/support/util/linodes.ts | 2 +- .../src/features/Account/DefaultFirewalls.tsx | 4 + .../components/FirewallSelect.test.tsx | 75 +++++++ .../Firewalls/components/FirewallSelect.tsx | 113 +++++++--- .../Kubernetes/NodePoolFirewallSelect.tsx | 1 + .../Linodes/LinodeCreate/Firewall.tsx | 6 +- .../LinodeCreate/Networking/Firewall.tsx | 7 +- .../Networking/InterfaceFirewall.tsx | 6 +- .../Networking/InterfaceGeneration.tsx | 8 +- .../LinodeCreate/Networking/InterfaceType.tsx | 8 +- .../Linodes/LinodeCreate/Summary/Summary.tsx | 2 +- .../Linodes/LinodeCreate/resolvers.ts | 18 ++ .../features/Linodes/LinodeCreate/schemas.ts | 7 + .../Linodes/LinodeCreate/utilities.test.tsx | 4 + .../AddInterfaceDrawer/AddInterfaceForm.tsx | 4 +- .../AddInterfaceDrawer/InterfaceFirewall.tsx | 4 +- .../AddInterfaceDrawer/InterfaceType.tsx | 4 +- .../AddInterfaceDrawer/utilities.ts | 3 + .../EditInterfaceFirewall.tsx | 1 + .../manager/src/features/Linodes/constants.ts | 3 + .../VPCDetail/SubnetAssignLinodesDrawer.tsx | 4 + 46 files changed, 826 insertions(+), 119 deletions(-) create mode 100644 packages/manager/.changeset/pr-13410-changed-1772435694557.md diff --git a/packages/manager/.changeset/pr-13410-changed-1772435694557.md b/packages/manager/.changeset/pr-13410-changed-1772435694557.md new file mode 100644 index 00000000000..dcd3b8c1141 --- /dev/null +++ b/packages/manager/.changeset/pr-13410-changed-1772435694557.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Make firewall selection mandatory while creating linode and its interfaces ([#13410](https://github.com/linode/manager/pull/13410)) diff --git a/packages/manager/cypress/e2e/core/general/gdpr-agreement.spec.ts b/packages/manager/cypress/e2e/core/general/gdpr-agreement.spec.ts index c89c6cbc6c9..9aaa67132c6 100644 --- a/packages/manager/cypress/e2e/core/general/gdpr-agreement.spec.ts +++ b/packages/manager/cypress/e2e/core/general/gdpr-agreement.spec.ts @@ -1,9 +1,12 @@ import { linodeFactory, regionFactory } from '@linode/utilities'; +import { firewallFactory } from '@src/factories'; import { mockGetAccountAgreements } from 'support/intercepts/account'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; -import { randomLabel, randomString } from 'support/util/random'; +import { linodeCreatePage } from 'support/ui/pages'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; import type { Region } from '@linode/api-v4'; @@ -100,6 +103,11 @@ describe('GDPR agreement', () => { }); it('needs the agreement checked to submit the form', () => { + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockGetRegions(mockRegions).as('getRegions'); mockGetAccountAgreements({ billing_agreement: false, @@ -127,6 +135,12 @@ describe('GDPR agreement', () => { cy.findByLabelText('Root Password').type(rootpass); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); + cy.get('[data-testid="eu-agreement-checkbox"]') .as('euAgreement') .scrollIntoView(); diff --git a/packages/manager/cypress/e2e/core/helpAndSupport/open-support-ticket.spec.ts b/packages/manager/cypress/e2e/core/helpAndSupport/open-support-ticket.spec.ts index f979b0cd28a..b41149900de 100644 --- a/packages/manager/cypress/e2e/core/helpAndSupport/open-support-ticket.spec.ts +++ b/packages/manager/cypress/e2e/core/helpAndSupport/open-support-ticket.spec.ts @@ -6,6 +6,7 @@ import 'cypress-file-upload'; import { mockGetAccount } from 'support/intercepts/account'; import { mockGetDomains } from 'support/intercepts/domains'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinodeAccountLimitError, mockGetLinodeDetails, @@ -31,6 +32,7 @@ import { } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; +import { firewallFactory } from 'src/factories'; import { accountFactory, domainFactory, @@ -378,6 +380,10 @@ describe('open support tickets', () => { planLabel: 'Nanode 1 GB', planId: 'g6-nanode-1', }; + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); const mockLinode = linodeFactory.build(); @@ -393,6 +399,7 @@ describe('open support tickets', () => { mockGetSupportTicket(mockAccountLimitTicket); mockGetSupportTicketReplies(mockAccountLimitTicket.id, []); mockGetLinodes([mockLinode]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); @@ -401,6 +408,8 @@ describe('open support tickets', () => { linodeCreatePage.selectRegionById(mockRegion.id); linodeCreatePage.selectPlan(mockPlan.planType, mockPlan.planLabel); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // Attempt to create Linode and confirm mocked account limit error with support link is present. ui.button diff --git a/packages/manager/cypress/e2e/core/images/create-linode-from-image.spec.ts b/packages/manager/cypress/e2e/core/images/create-linode-from-image.spec.ts index 40aef7bf9ed..3206e9ed69e 100644 --- a/packages/manager/cypress/e2e/core/images/create-linode-from-image.spec.ts +++ b/packages/manager/cypress/e2e/core/images/create-linode-from-image.spec.ts @@ -1,7 +1,9 @@ import { linodeFactory } from '@linode/utilities'; -import { imageFactory } from '@src/factories'; +import { firewallFactory, imageFactory } from '@src/factories'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockGetAllImages } from 'support/intercepts/images'; import { ui } from 'support/ui'; +import { linodeCreatePage } from 'support/ui/pages'; import { apiMatcher } from 'support/util/intercepts'; import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; @@ -20,8 +22,14 @@ const mockImage = imageFactory.build({ label: randomLabel(), }); +const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), +}); + const createLinodeWithImageMock = (url: string, preselectedImage: boolean) => { mockGetAllImages([mockImage]).as('mockImage'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.intercept('POST', apiMatcher('linode/instances'), (req) => { req.reply({ @@ -52,6 +60,11 @@ const createLinodeWithImageMock = (url: string, preselectedImage: boolean) => { cy.findByText('Shared CPU').click(); cy.get('[id="g6-nanode-1"][type="radio"]').click(); cy.get('[id="root-password"]').type(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); ui.button .findByTitle('Create Linode') diff --git a/packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts b/packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts index 43325319275..329debdf69c 100644 --- a/packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts @@ -2,15 +2,21 @@ import { regionAvailabilityFactory, regionFactory } from '@linode/utilities'; import { mockGetAccountSettings } from 'support/intercepts/account'; import { mockGetAlertDefinition } from 'support/intercepts/cloudpulse'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { interceptCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegionAvailability, mockGetRegions, } from 'support/intercepts/regions'; import { ui } from 'support/ui'; -import { randomLabel, randomString } from 'support/util/random'; +import { linodeCreatePage } from 'support/ui/pages'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; -import { accountSettingsFactory, alertFactory } from 'src/factories'; +import { + accountSettingsFactory, + alertFactory, + firewallFactory, +} from 'src/factories'; import { ALERTS_BETA_MODE_BANNER_TEXT, ALERTS_BETA_MODE_BUTTON_TEXT, @@ -18,6 +24,11 @@ import { ALERTS_LEGACY_MODE_BUTTON_TEXT, } from 'src/features/Linodes/constants'; +const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), +}); + describe('Create flow when beta alerts enabled by region and feature flag', function () { beforeEach(() => { const mockEnabledRegion = regionFactory.build({ @@ -54,6 +65,7 @@ describe('Create flow when beta alerts enabled by region and feature flag', func interfaces_for_new_linodes: 'legacy_config_default_but_linode_allowed', }); mockGetAccountSettings(mockInitialAccountSettings).as('getSettings'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); }); it('Alerts panel becomes visible after switching to region w/ alerts enabled', function () { @@ -88,6 +100,11 @@ describe('Create flow when beta alerts enabled by region and feature flag', func const enabledRegion = this.mockRegions[0]; mockGetRegionAvailability(enabledRegion.id, []).as('getRegionAvailability'); ui.regionSelect.find().type(`${enabledRegion.label}{enter}`); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // legacy alerts panel appears cy.wait('@getRegionAvailability'); @@ -208,6 +225,11 @@ describe('Create flow when beta alerts enabled by region and feature flag', func const enabledRegion = this.mockRegions[0]; mockGetRegionAvailability(enabledRegion.id, []).as('getRegionAvailability'); ui.regionSelect.find().type(`${enabledRegion.label}{enter}`); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // legacy alerts panel appears cy.wait('@getRegionAvailability'); @@ -437,6 +459,11 @@ describe('Create flow when beta alerts enabled by region and feature flag', func 'getRegionAvailability' ); ui.regionSelect.find().type(`${disabledRegion.label}{enter}`); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); cy.wait('@getRegionAvailability'); // enter plan and password form fields to enable "View Code Snippets" button diff --git a/packages/manager/cypress/e2e/core/linodes/clone-linode.spec.ts b/packages/manager/cypress/e2e/core/linodes/clone-linode.spec.ts index 434d839b5ef..c611bfd31d7 100644 --- a/packages/manager/cypress/e2e/core/linodes/clone-linode.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/clone-linode.spec.ts @@ -20,6 +20,7 @@ import { LINODE_CREATE_TIMEOUT } from 'support/constants/linodes'; import { mockGetLinodeConfigs } from 'support/intercepts/configs'; import { interceptEvents } from 'support/intercepts/events'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { interceptCloneLinode, mockCloneLinode, @@ -44,6 +45,8 @@ import { } from 'support/util/random'; import { chooseRegion, extendRegion } from 'support/util/regions'; +import { firewallFactory } from 'src/factories'; + import type { Linode } from '@linode/api-v4'; /** @@ -195,8 +198,13 @@ describe('clone linode', () => { id: mockLinode.id + 1, label: newLinodeLabel, }; + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); mockGetVLANs([mockVlan]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); mockGetLinodeVolumes(clonedLinode.id, [mockVolume]).as('getLinodeVolumes'); @@ -229,6 +237,8 @@ describe('clone linode', () => { .type(mockVlan.cidr_block); }); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // Confirm that VLAN attachment is listed in summary, then create Linode. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-blackwell.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-blackwell.spec.ts index 93e7ef5fc69..035c51d9169 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-blackwell.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-blackwell.spec.ts @@ -5,6 +5,7 @@ import { regionFactory, } from '@linode/utilities'; import { LINODE_CREATE_TIMEOUT } from 'support/constants/linodes'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode, mockGetLinodeTypes, @@ -14,7 +15,11 @@ import { mockGetRegions, } from 'support/intercepts/regions'; import { ui } from 'support/ui'; +import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomString } from 'support/util/random'; +import { randomNumber } from 'support/util/random'; + +import { firewallFactory } from 'src/factories'; const mockEnabledRegion = regionFactory.build({ id: 'us-east', @@ -37,10 +42,15 @@ const mockBlackwellLinodeTypes = new Array(4).fill(null).map((_, index) => const selectedBlackwell = mockBlackwellLinodeTypes[0]; describe('smoketest for Nvidia blackwell GPUs in linodes/create page', () => { + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); beforeEach(() => { mockGetRegions([mockEnabledRegion, mockDisabledRegion]).as('getRegions'); mockGetLinodeTypes(mockBlackwellLinodeTypes).as('getLinodeTypes'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); }); /* @@ -120,6 +130,11 @@ describe('smoketest for Nvidia blackwell GPUs in linodes/create page', () => { cy.findByLabelText('Linode Label').type(newLinodeLabel); cy.get('[type="password"]').should('be.visible').scrollIntoView(); cy.get('[id="root-password"]').type(randomString(12)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); cy.scrollTo('bottom'); const mockLinode = linodeFactory.build({ label: randomLabel(), diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-in-core-region.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-in-core-region.spec.ts index df59f00ebe3..77d3236aaca 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-in-core-region.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-in-core-region.spec.ts @@ -1,5 +1,6 @@ import { linodeFactory, regionFactory } from '@linode/utilities'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegionAvailability, @@ -8,6 +9,9 @@ import { import { ui } from 'support/ui'; import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomString } from 'support/util/random'; +import { randomNumber } from 'support/util/random'; + +import { firewallFactory } from 'src/factories'; describe('Create Linode in a Core Region', () => { /* @@ -30,6 +34,10 @@ describe('Create Linode in a Core Region', () => { region: mockRegion1.id, }); const rootPass = randomString(32); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); mockAppendFeatureFlags({ gecko2: { @@ -39,6 +47,7 @@ describe('Create Linode in a Core Region', () => { }).as('getFeatureFlags'); mockGetRegions(mockRegions).as('getRegions'); mockGetRegionAvailability(mockRegion1.id, []).as('getRegionAvailability'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -55,6 +64,11 @@ describe('Create Linode in a Core Region', () => { linodeCreatePage.selectImage('Debian 11'); linodeCreatePage.setRootPassword(rootPass); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); ui.button .findByTitle('Create Linode') diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-in-distributed-region.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-in-distributed-region.spec.ts index 8f1ccfd6833..be42ffc1206 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-in-distributed-region.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-in-distributed-region.spec.ts @@ -4,6 +4,7 @@ import { regionFactory, } from '@linode/utilities'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode, mockGetLinodeTypes, @@ -14,9 +15,11 @@ import { } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { linodeCreatePage } from 'support/ui/pages'; -import { randomLabel, randomString } from 'support/util/random'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { extendRegion } from 'support/util/regions'; +import { firewallFactory } from 'src/factories'; + import type { Region } from '@linode/api-v4'; describe('Create Linode in Distributed Region', () => { @@ -42,6 +45,10 @@ describe('Create Linode in Distributed Region', () => { label: randomLabel(), region: mockRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); const rootPass = randomString(32); mockAppendFeatureFlags({ @@ -51,6 +58,7 @@ describe('Create Linode in Distributed Region', () => { }, }).as('getFeatureFlags'); mockGetRegions([mockRegion]).as('getRegions'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockGetLinodeTypes(mockLinodeTypes).as('getLinodeTypes'); mockGetRegionAvailability(mockRegion.id, []).as('getRegionAvailability'); mockCreateLinode(mockLinode).as('createLinode'); @@ -75,6 +83,12 @@ describe('Create Linode in Distributed Region', () => { .click(); }); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); + ui.button .findByTitle('Create Linode') .should('be.visible') diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-mobile.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-mobile.spec.ts index ffc2939ce95..c12df22e5e3 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-mobile.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-mobile.spec.ts @@ -4,12 +4,15 @@ import { linodeFactory } from '@linode/utilities'; import { MOBILE_VIEWPORTS } from 'support/constants/environment'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { ui } from 'support/ui'; import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; +import { firewallFactory } from 'src/factories'; + describe('Linode create mobile smoke', () => { MOBILE_VIEWPORTS.forEach((viewport) => { /* @@ -23,7 +26,11 @@ describe('Linode create mobile smoke', () => { label: randomLabel(), region: mockLinodeRegion.id, }); - + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.viewport(viewport.width, viewport.height); @@ -34,6 +41,11 @@ describe('Linode create mobile smoke', () => { linodeCreatePage.selectPlanCard('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setLabel(mockLinode.label); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-view-code-snippet.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-view-code-snippet.spec.ts index b74046af2fc..358c01392a1 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-view-code-snippet.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-view-code-snippet.spec.ts @@ -3,11 +3,14 @@ */ import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { ui } from 'support/ui'; import { linodeCreatePage } from 'support/ui/pages'; -import { randomLabel, randomString } from 'support/util/random'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; +import { firewallFactory } from 'src/factories'; + describe('Create Linode flow to validate code snippet modal', () => { beforeEach(() => { mockAppendFeatureFlags({ @@ -24,6 +27,11 @@ describe('Create Linode flow to validate code snippet modal', () => { const mockLinodeRegion = chooseRegion({ capabilities: ['Linodes'], }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); // Set Linode label, distribution, plan type, password, etc. @@ -32,6 +40,8 @@ describe('Create Linode flow to validate code snippet modal', () => { linodeCreatePage.selectRegionById(mockLinodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(rootPass); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // View Code Snippets and confirm it's provisioned as expected. ui.button diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts index 7f0e8989401..256aecd29e3 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts @@ -1,13 +1,14 @@ import { linodeFactory, regionFactory } from '@linode/utilities'; import { mockGetAccountSettings } from 'support/intercepts/account'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { linodeCreatePage } from 'support/ui/pages'; -import { randomLabel, randomString } from 'support/util/random'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; -import { accountSettingsFactory } from 'src/factories'; +import { accountSettingsFactory, firewallFactory } from 'src/factories'; const mockEnabledRegion = regionFactory.build({ capabilities: ['Linodes', 'Maintenance Policy'], }); @@ -35,7 +36,12 @@ describe('vmHostMaintenance feature flag', () => { label: randomLabel(), region: mockEnabledRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); mockCreateLinode(mockLinode).as('createLinode'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); cy.wait(['@getAccountSettings', '@getFeatureFlags', '@getRegions']); @@ -82,6 +88,8 @@ describe('vmHostMaintenance feature flag', () => { planLabel: 'Nanode 1 GB', }; linodeCreatePage.selectPlan(mockPlan.planType, mockPlan.planLabel); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); cy.scrollTo('bottom'); ui.button .findByTitle('View Code Snippets') diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-add-ons.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-add-ons.spec.ts index 3dbdf20a47f..c5ec7562dd2 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-add-ons.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-add-ons.spec.ts @@ -1,4 +1,5 @@ import { linodeFactory } from '@linode/utilities'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode, mockGetLinodeDetails, @@ -8,7 +9,13 @@ import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; +import { firewallFactory } from 'src/factories'; + describe('Create Linode with Add-ons', () => { + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); /* * - Confirms UI flow to create a Linode with backups using mock API data. * - Confirms that backups is reflected in create summary section. @@ -25,6 +32,7 @@ describe('Create Linode with Add-ons', () => { mockCreateLinode(mockLinode).as('createLinode'); mockGetLinodeDetails(mockLinode.id, mockLinode); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); @@ -33,6 +41,11 @@ describe('Create Linode with Add-ons', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); linodeCreatePage.checkBackups(); linodeCreatePage.checkEUAgreements(); @@ -78,6 +91,7 @@ describe('Create Linode with Add-ons', () => { mockCreateLinode(mockLinode).as('createLinode'); mockGetLinodeDetails(mockLinode.id, mockLinode); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); @@ -86,8 +100,15 @@ describe('Create Linode with Add-ons', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); linodeCreatePage.checkEUAgreements(); linodeCreatePage.selectInterfaceGeneration('legacy_config'); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); linodeCreatePage.checkPrivateIPs(); // Confirm Private IP assignment indicator is shown in Linode summary. diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-disk-encryption.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-disk-encryption.spec.ts index 093b89bd120..351d0e56400 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-disk-encryption.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-disk-encryption.spec.ts @@ -3,9 +3,10 @@ import { linodeTypeFactory, regionFactory, } from '@linode/utilities'; -import { accountFactory } from '@src/factories'; +import { accountFactory, firewallFactory } from '@src/factories'; import { mockGetAccount } from 'support/intercepts/account'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode, mockGetLinodeTypes, @@ -17,7 +18,7 @@ import { import { ui } from 'support/ui'; import { linodeCreatePage } from 'support/ui/pages'; import { makeFeatureFlagData } from 'support/util/feature-flags'; -import { randomLabel, randomString } from 'support/util/random'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { extendRegion } from 'support/util/regions'; import { @@ -156,6 +157,10 @@ describe('Create Linode with Disk Encryption', () => { label: randomLabel(), region: distributedRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); mockAppendFeatureFlags({ gecko2: { @@ -167,6 +172,7 @@ describe('Create Linode with Disk Encryption', () => { mockGetLinodeTypes([mockLinodeType]); mockGetRegionAvailability(distributedRegion.id, []); mockCreateLinode(mockLinode).as('createLinode'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); cy.get('[data-qa-linode-region]').within(() => { @@ -185,7 +191,11 @@ describe('Create Linode with Disk Encryption', () => { linodeCreatePage.setLabel(mockLinode.label); linodeCreatePage.setRootPassword(randomString(32)); - + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // Select mock Nanode plan type. cy.get('[data-qa-plan-row="Nanode 1 GB"]').click(); diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-firewall.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-firewall.spec.ts index b87f8dea920..c1ff82e4451 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-firewall.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-firewall.spec.ts @@ -424,17 +424,8 @@ describe('Create Linode with Firewall (Linode Interfaces)', () => { // Switch to legacy Config Interfaces linodeCreatePage.selectLegacyConfigInterfacesType(); - // Confirm that mocked Firewall is shown in the Autocomplete, and then select it. - cy.findByLabelText('Firewall').should('be.visible'); - cy.get('[data-qa-autocomplete="Firewall"]').within(() => { - cy.get('[data-testid="textfield-input"]').click(); - cy.focused().type(`${mockFirewall.label}`); - }); - - ui.autocompletePopper - .findByTitle(mockFirewall.label) - .should('be.visible') - .click(); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); // Confirm Firewall assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); @@ -494,17 +485,10 @@ describe('Create Linode with Firewall (Linode Interfaces)', () => { // Confirm the Linode Interfaces section is shown. assertNewLinodeInterfacesIsAvailable(); - // Confirm that mocked Firewall is shown in the Autocomplete, and then select it. - cy.findByLabelText('Public Interface Firewall').should('be.visible'); - cy.get('[data-qa-autocomplete="Public Interface Firewall"]').within(() => { - cy.get('[data-testid="textfield-input"]').click(); - cy.focused().type(`${mockFirewall.label}`); - }); - - ui.autocompletePopper - .findByTitle(mockFirewall.label) - .should('be.visible') - .click(); + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // Confirm Firewall assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); @@ -593,17 +577,7 @@ describe('Create Linode with Firewall (Linode Interfaces)', () => { `Firewall ${mockFirewall.label} successfully created` ); - // Confirm that mocked Firewall is shown in the Autocomplete, and then select it. - cy.findByLabelText('Firewall').should('be.visible'); - cy.get('[data-qa-autocomplete="Firewall"]').within(() => { - cy.get('[data-testid="textfield-input"]').click(); - cy.focused().type(`${mockFirewall.label}`); - }); - - ui.autocompletePopper - .findByTitle(mockFirewall.label) - .should('be.visible') - .click(); + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); // Confirm Firewall assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); @@ -688,17 +662,10 @@ describe('Create Linode with Firewall (Linode Interfaces)', () => { `Firewall ${mockFirewall.label} successfully created` ); - // Confirm that mocked Firewall is shown in the Autocomplete, and then select it. - cy.findByLabelText('Public Interface Firewall').should('be.visible'); - cy.get('[data-qa-autocomplete="Public Interface Firewall"]').within(() => { - cy.get('[data-testid="textfield-input"]').click(); - cy.focused().type(`${mockFirewall.label}`); - }); - - ui.autocompletePopper - .findByTitle(mockFirewall.label) - .should('be.visible') - .click(); + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // Confirm Firewall assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); @@ -936,6 +903,150 @@ describe('Create Linode with Firewall (Linode Interfaces)', () => { ui.toast.assertMessage(`Your Linode ${mockLinode.label} is being created.`); }); + /* + * Legacy Configuration Profile Interfaces + * - Confirms UI flow to create a Linode with "No firewall" option. + * - Confirms that no firewall is reflected in create summary section. + * - Confirms that outgoing Linode Create API request specifies no Firewall to be attached. + */ + it('can assign "No firewall" option during Linode Create flow (legacy)', () => { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: linodeRegion.id, + }); + + mockCreateLinode(mockLinode).as('createLinode'); + mockGetLinodeDetails(mockLinode.id, mockLinode); + + cy.visitWithLogin('/linodes/create'); + + linodeCreatePage.setLabel(mockLinode.label); + linodeCreatePage.selectImage('Debian 12'); + linodeCreatePage.selectRegionById(linodeRegion.id); + linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); + linodeCreatePage.setRootPassword(randomString(32)); + + // Confirm the Linode Interfaces section is shown. + assertNewLinodeInterfacesIsAvailable(); + + // Switch to legacy Config Interfaces + linodeCreatePage.selectLegacyConfigInterfacesType(); + + // Select a firewall + linodeCreatePage.selectFirewall( + 'No firewall - traffic is unprotected (not recommended)', + 'Firewall' + ); + + // Create Linode and confirm contents of outgoing API request payload. + ui.button + .findByTitle('Create Linode') + .should('be.visible') + .should('be.enabled') + .click(); + + cy.wait('@createLinode').then((xhr) => { + const requestPayload = xhr.request.body; + const firewallId = requestPayload['firewall_id']; + expect(firewallId).to.equal(-1); + }); + + // Confirm redirect to new Linode. + cy.url().should('endWith', `/linodes/${mockLinode.id}`); + // Confirm toast notification should appear on Linode create. + ui.toast.assertMessage(`Your Linode ${mockLinode.label} is being created.`); + }); + + /* + * Linode Interfaces + * - Confirms UI flow to create a Linode with "No firewall" option. + * - Confirms that no firewall is reflected in create summary section. + * - Confirms that outgoing Linode Create API request specifies no Firewall to be attached. + */ + it('can assign "No firewall" option during Linode Create flow (Linode Interfaces)', () => { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: linodeRegion.id, + }); + + mockCreateLinode(mockLinode).as('createLinode'); + mockGetLinodeDetails(mockLinode.id, mockLinode); + + cy.visitWithLogin('/linodes/create'); + + linodeCreatePage.setLabel(mockLinode.label); + linodeCreatePage.selectImage('Debian 12'); + linodeCreatePage.selectRegionById(linodeRegion.id); + linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); + linodeCreatePage.setRootPassword(randomString(32)); + + // Confirm the Linode Interfaces section is shown. + assertNewLinodeInterfacesIsAvailable(); + + linodeCreatePage.selectFirewall( + 'No firewall - traffic is unprotected (not recommended)', + 'Public Interface Firewall' + ); + + // Create Linode and confirm contents of outgoing API request payload. + ui.button + .findByTitle('Create Linode') + .should('be.visible') + .should('be.enabled') + .click(); + + cy.wait('@createLinode').then((xhr) => { + const requestPayload = xhr.request.body; + const firewallId = requestPayload['interfaces'][0]['firewall_id']; + expect(firewallId).to.equal(-1); + }); + + // Confirm redirect to new Linode. + cy.url().should('endWith', `/linodes/${mockLinode.id}`); + // Confirm toast notification should appear on Linode create. + ui.toast.assertMessage(`Your Linode ${mockLinode.label} is being created.`); + }); + + /* + * Mocks no selection made in firewall dropdown. + * Confirms that correct validation error message is shown on the page when attempting to create a Linode. + */ + it('displays validation error related to firewall if no selection made in firewall dropdown', () => { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: linodeRegion.id, + }); + + mockCreateLinode(mockLinode).as('createLinode'); + mockGetLinodeDetails(mockLinode.id, mockLinode); + + cy.visitWithLogin('/linodes/create'); + + linodeCreatePage.setLabel(mockLinode.label); + linodeCreatePage.selectImage('Debian 12'); + linodeCreatePage.selectRegionById(linodeRegion.id); + linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); + linodeCreatePage.setRootPassword(randomString(32)); + + // Confirm the Linode Interfaces section is shown. + assertNewLinodeInterfacesIsAvailable(); + + // Create Linode and confirm contents of outgoing API request payload. + ui.button + .findByTitle('Create Linode') + .should('be.visible') + .should('be.enabled') + .click(); + + // Confirm the correct validation error related to firewall show up on the page. + cy.findByText('Select an option or create a new Firewall.').should( + 'be.visible' + ); + }); + /* * - Mocks the internal header to enable the Generate Compliant Firewall banner. * - Mocks an error response to the Create Firewall call. diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-ssh-key.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-ssh-key.spec.ts index fac8dd00c69..b15ecf35878 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-ssh-key.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-ssh-key.spec.ts @@ -1,5 +1,6 @@ import { linodeFactory, sshKeyFactory } from '@linode/utilities'; import { mockGetUser, mockGetUsers } from 'support/intercepts/account'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockCreateSSHKey } from 'support/intercepts/profile'; import { ui } from 'support/ui'; @@ -7,9 +8,13 @@ import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; -import { accountUserFactory } from 'src/factories'; +import { accountUserFactory, firewallFactory } from 'src/factories'; describe('Create Linode with SSH Key', () => { + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); /* * - Confirms UI flow when creating a Linode with an authorized SSH key. * - Confirms that existing SSH keys are listed on page and can be selected. @@ -34,6 +39,7 @@ describe('Create Linode with SSH Key', () => { mockGetUsers([mockUser]); mockGetUser(mockUser); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -43,6 +49,11 @@ describe('Create Linode with SSH Key', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // Confirm that SSH key is listed, then select it. cy.findByText(mockSshKey.label).scrollIntoView(); @@ -101,6 +112,7 @@ describe('Create Linode with SSH Key', () => { mockGetUsers([mockUser]); mockCreateLinode(mockLinode).as('createLinode'); mockCreateSSHKey(mockSshKey).as('createSSHKey'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); @@ -109,6 +121,11 @@ describe('Create Linode with SSH Key', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // Confirm that no SSH keys are listed for the mocked user. cy.findByText(mockUser.username).scrollIntoView(); diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-user-data.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-user-data.spec.ts index 9fb53cba649..8330b471b9d 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-user-data.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-user-data.spec.ts @@ -1,4 +1,5 @@ import { linodeFactory, regionFactory } from '@linode/utilities'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockGetAllImages, mockGetImage } from 'support/intercepts/images'; import { mockCreateLinode, @@ -10,7 +11,7 @@ import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; -import { imageFactory } from 'src/factories'; +import { firewallFactory, imageFactory } from 'src/factories'; describe('Create Linode with user data', () => { /* @@ -26,10 +27,15 @@ describe('Create Linode with user data', () => { label: randomLabel(), region: linodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); const userDataFixturePath = 'user-data/user-data-config-basic.yml'; mockCreateLinode(mockLinode).as('createLinode'); mockGetLinodeDetails(mockLinode.id, mockLinode); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin('/linodes/create'); @@ -40,6 +46,11 @@ describe('Create Linode with user data', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); // Expand "Add User Data" accordion and enter user data config. ui.accordionHeading diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-vlan.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-vlan.spec.ts index 1ed9356b23b..f55e562ee2b 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-vlan.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-vlan.spec.ts @@ -4,6 +4,7 @@ import { mockGetAccountSettings, } from 'support/intercepts/account'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegion, mockGetRegions } from 'support/intercepts/regions'; import { mockGetVLANs } from 'support/intercepts/vlans'; @@ -21,6 +22,7 @@ import { chooseRegion } from 'support/util/regions'; import { accountFactory, accountSettingsFactory, + firewallFactory, VLANFactory, } from 'src/factories'; @@ -56,7 +58,13 @@ describe('Create Linode with VLANs (Legacy)', () => { region: mockLinodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetVLANs([mockVlan]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -89,6 +97,9 @@ describe('Create Linode with VLANs (Legacy)', () => { .type(mockVlan.cidr_block); }); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); + // Confirm that VLAN attachment is listed in summary, then create Linode. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { @@ -146,7 +157,13 @@ describe('Create Linode with VLANs (Legacy)', () => { region: mockLinodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetVLANs([]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -175,6 +192,9 @@ describe('Create Linode with VLANs (Legacy)', () => { .click(); }); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); + // Confirm that VLAN attachment is listed in summary, then create Linode. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { @@ -305,7 +325,13 @@ describe('Create Linode with VLANs (Linode Interfaces)', () => { region: mockLinodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetVLANs([mockVlan]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -338,6 +364,9 @@ describe('Create Linode with VLANs (Linode Interfaces)', () => { .should('be.enabled') .type(mockVlan.cidr_block); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); + // Confirm that VLAN attachment is listed in summary, then create Linode. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { @@ -471,7 +500,13 @@ describe('Create Linode with VLANs (Linode Interfaces)', () => { region: mockLinodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetVLANs([]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -505,6 +540,9 @@ describe('Create Linode with VLANs (Linode Interfaces)', () => { .should('be.enabled') .type(mockVlan.cidr_block); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); + // Confirm that VLAN attachment is listed in summary, then create Linode. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-with-vpc.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-with-vpc.spec.ts index 0f9fa5ab253..b1a97b5da75 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-with-vpc.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-with-vpc.spec.ts @@ -9,6 +9,7 @@ import { } from 'support/intercepts/account'; import { mockGetLinodeConfig } from 'support/intercepts/configs'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode, mockGetLinodeDetails, @@ -36,6 +37,7 @@ import { chooseRegion } from 'support/util/regions'; import { accountFactory, accountSettingsFactory, + firewallFactory, linodeConfigFactory, subnetFactory, vpcFactory, @@ -106,8 +108,14 @@ describe('Create Linode with VPCs (Legacy)', () => { ], }; + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetVPCs([mockVPC]).as('getVPCs'); mockGetVPC(mockVPC).as('getVPC'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); mockGetLinodeDetails(mockLinode.id, mockLinode); @@ -137,6 +145,9 @@ describe('Create Linode with VPCs (Legacy)', () => { `${mockSubnet.label} (${mockSubnet.ipv4})` ); + // Select a firewall for the VPC interface + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); + // Confirm VPC assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { @@ -240,7 +251,13 @@ describe('Create Linode with VPCs (Legacy)', () => { ], }; + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetVPCs([]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -293,6 +310,9 @@ describe('Create Linode with VPCs (Legacy)', () => { cy.findByLabelText('Clear').click(); }); + // Select a firewall for the VPC interface + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); + // Try to submit the form without a subnet selected ui.button .findByTitle('Create Linode') @@ -460,6 +480,11 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { ], }; + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockGetVPCs([mockVPC]).as('getVPCs'); mockGetVPC(mockVPC).as('getVPC'); mockCreateLinode(mockLinode).as('createLinode'); @@ -500,6 +525,9 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { `${mockSubnet.label} (${mockSubnet.ipv4})` ); + // Select a firewall for the VPC interface + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); + // Confirm VPC assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { @@ -572,6 +600,11 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { region: linodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + const mockInterface = linodeConfigInterfaceFactoryWithVPC.build({ active: true, primary: true, @@ -601,6 +634,7 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { mockGetVPCs([mockVPC]).as('getVPCs'); mockGetVPC(mockVPC).as('getVPC'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); mockGetLinodeDetails(mockLinode.id, mockLinode); @@ -636,6 +670,12 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { `${mockSubnet.label} (${mockSubnet.ipv4})` ); + // Select a firewall for the VPC interface + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'VPC Interface Firewall' + ); + // Confirm VPC assignment indicator is shown in Linode summary. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); cy.get('[data-qa-linode-create-summary]').within(() => { @@ -737,6 +777,13 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { ], }; + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + + mockGetFirewalls([mockFirewall]).as('getFirewalls'); + mockGetVPCs([]); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -755,6 +802,8 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { // Select VPC card linodeCreatePage.selectInterface('vpc'); + // Select a firewall for the VPC interface + linodeCreatePage.selectFirewall(mockFirewall.label, 'Firewall'); cy.findByText('Create VPC').should('be.visible').click(); @@ -896,6 +945,11 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { region: linodeRegion.id, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); + const mockInterface = linodeConfigInterfaceFactoryWithVPC.build({ active: true, primary: true, @@ -924,6 +978,7 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { }; mockGetVPCs([]); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -1009,6 +1064,12 @@ describe('Create Linode with VPCs (Linode Interfaces)', () => { .should('be.visible') .click(); + // Select a firewall for the VPC interface + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'VPC Interface Firewall' + ); + // Create Linode and confirm contents of outgoing API request payload. ui.button .findByTitle('Create Linode') diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts index eb6eec87f92..dd43845b810 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts @@ -13,6 +13,7 @@ import { authenticate } from 'support/api/authentication'; import { LINODE_CREATE_TIMEOUT } from 'support/constants/linodes'; import { mockGetAccount, mockGetUser } from 'support/intercepts/account'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { interceptCreateLinode, mockCreateLinode, @@ -31,10 +32,17 @@ import { cleanUp } from 'support/util/cleanup'; import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; -import { accountFactory, accountUserFactory } from 'src/factories'; +import { + accountFactory, + accountUserFactory, + firewallFactory, +} from 'src/factories'; let username: string; - +const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), +}); authenticate(); describe('Create Linode', () => { before(() => { @@ -54,6 +62,12 @@ describe('Create Linode', () => { describe('End-to-end', () => { // Run an end-to-end test to create a basic Linode for each plan type described below. describe('By plan type', () => { + beforeEach(() => { + mockAppendFeatureFlags({ + linodeInterfaces: { enabled: true }, + }); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); + }); [ { planId: 'g6-nanode-1', @@ -81,6 +95,7 @@ describe('Create Linode', () => { const linodeRegion = chooseRegion({ capabilities: ['Linodes', 'Vlans'], }); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); const linodeLabel = randomLabel(); @@ -108,6 +123,11 @@ describe('Create Linode', () => { planConfig.planLabel ); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall( + 'No firewall - traffic is unprotected (not recommended)', + 'Public Interface Firewall' + ); // Confirm information in summary is shown as expected. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); @@ -227,6 +247,7 @@ describe('Create Linode', () => { }).as('getFeatureFlags'); mockGetRegions(mockRegions).as('getRegions'); mockGetLinodeTypes([...mockAcceleratedType]).as('getLinodeTypes'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); @@ -243,6 +264,8 @@ describe('Create Linode', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Accelerated', mockAcceleratedType[0].label); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // Confirm information in summary is shown as expected. cy.get('[data-qa-linode-create-summary]').scrollIntoView(); @@ -297,6 +320,7 @@ describe('Create Linode', () => { const createLinodeErrorMessage = 'An error has occurred during Linode creation flow'; + mockGetFirewalls([mockFirewall]).as('getFirewalls'); mockCreateLinodeError(createLinodeErrorMessage).as('createLinodeError'); cy.visitWithLogin('/linodes/create'); @@ -306,6 +330,8 @@ describe('Create Linode', () => { linodeCreatePage.selectRegionById(linodeRegion.id); linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // Create Linode by clicking the button. ui.button diff --git a/packages/manager/cypress/e2e/core/oneClickApps/one-click-apps.spec.ts b/packages/manager/cypress/e2e/core/oneClickApps/one-click-apps.spec.ts index 8c1e15ab9bd..f1779baa308 100644 --- a/packages/manager/cypress/e2e/core/oneClickApps/one-click-apps.spec.ts +++ b/packages/manager/cypress/e2e/core/oneClickApps/one-click-apps.spec.ts @@ -1,4 +1,5 @@ import { linodeFactory } from '@linode/utilities'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockGetAllImages } from 'support/intercepts/images'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { @@ -7,11 +8,12 @@ import { mockGetStackScripts, } from 'support/intercepts/stackscripts'; import { ui } from 'support/ui'; +import { linodeCreatePage } from 'support/ui/pages'; import { getRandomOCAId } from 'support/util/one-click-apps'; -import { randomLabel, randomString } from 'support/util/random'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; -import { imageFactory } from 'src/factories'; +import { firewallFactory, imageFactory } from 'src/factories'; import { stackScriptFactory } from 'src/factories/stackscripts'; import { getMarketplaceAppLabel } from 'src/features/Linodes/LinodeCreate/Tabs/Marketplace/utilities'; import { oneClickApps } from 'src/features/OneClickApps/oneClickApps'; @@ -166,10 +168,15 @@ describe('OneClick Apps (OCA)', () => { const linode = linodeFactory.build({ label: linodeLabel, }); + const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), + }); mockGetAllImages(images); mockGetStackScripts([stackscript]).as('getStackScripts'); mockGetStackScript(stackscript.id, stackscript); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); cy.visitWithLogin(`/linodes/create/marketplace`); @@ -242,6 +249,12 @@ describe('OneClick Apps (OCA)', () => { // Create the Linode mockCreateLinode(linode).as('createLinode'); + // Select a firewall + linodeCreatePage.selectFirewall( + mockFirewall.label, + 'Public Interface Firewall' + ); + ui.button .findByTitle('Create Linode') .should('be.visible') diff --git a/packages/manager/cypress/e2e/core/placementGroups/create-linode-with-placement-groups.spec.ts b/packages/manager/cypress/e2e/core/placementGroups/create-linode-with-placement-groups.spec.ts index dfd189af374..f592606a2e1 100644 --- a/packages/manager/cypress/e2e/core/placementGroups/create-linode-with-placement-groups.spec.ts +++ b/packages/manager/cypress/e2e/core/placementGroups/create-linode-with-placement-groups.spec.ts @@ -1,5 +1,6 @@ import { linodeFactory, regionFactory } from '@linode/utilities'; import { mockGetAccount } from 'support/intercepts/account'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { mockCreateLinode, mockGetLinodeDetails, @@ -11,10 +12,14 @@ import { import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui/'; import { linodeCreatePage } from 'support/ui/pages'; -import { randomNumber, randomString } from 'support/util/random'; +import { randomLabel, randomNumber, randomString } from 'support/util/random'; import { extendRegion } from 'support/util/regions'; -import { accountFactory, placementGroupFactory } from 'src/factories'; +import { + accountFactory, + firewallFactory, + placementGroupFactory, +} from 'src/factories'; import { CANNOT_CHANGE_PLACEMENT_GROUP_POLICY_MESSAGE } from 'src/features/PlacementGroups/constants'; const mockAccount = accountFactory.build(); @@ -37,12 +42,18 @@ const mockDallasRegion = extendRegion( }) ); +const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), +}); + const mockRegions = [mockNewarkRegion, mockDallasRegion]; describe('Linode create flow with Placement Group', () => { beforeEach(() => { mockGetAccount(mockAccount); mockGetRegions(mockRegions).as('getRegions'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); }); /* @@ -90,6 +101,8 @@ describe('Linode create flow with Placement Group', () => { // Choose plan cy.findByText('Shared CPU').click(); cy.get('[id="g6-nanode-1"]').click(); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // Choose Placement Group // No Placement Group available @@ -241,6 +254,8 @@ describe('Linode create flow with Placement Group', () => { linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB'); linodeCreatePage.setRootPassword(randomString(32)); linodeCreatePage.setLabel(mockLinode.label); + // Select a firewall + linodeCreatePage.selectFirewall(mockFirewall.label, 'Assign Firewall'); // Confirm that mocked Placement Group is shown in the Autocomplete, and then select it. cy.findByText( diff --git a/packages/manager/cypress/e2e/core/stackscripts/create-stackscripts.spec.ts b/packages/manager/cypress/e2e/core/stackscripts/create-stackscripts.spec.ts index 2d793df73f5..903f449da50 100644 --- a/packages/manager/cypress/e2e/core/stackscripts/create-stackscripts.spec.ts +++ b/packages/manager/cypress/e2e/core/stackscripts/create-stackscripts.spec.ts @@ -2,6 +2,7 @@ import { createImage, getLinodeDisks, resizeLinodeDisk } from '@linode/api-v4'; import { createLinodeRequestFactory } from '@linode/utilities'; import { authenticate } from 'support/api/authentication'; import { interceptGetAccountAvailability } from 'support/intercepts/account'; +import { mockGetFirewalls } from 'support/intercepts/firewalls'; import { interceptGetAllImages } from 'support/intercepts/images'; import { interceptCreateLinode } from 'support/intercepts/linodes'; import { @@ -9,6 +10,7 @@ import { interceptGetStackScripts, } from 'support/intercepts/stackscripts'; import { ui } from 'support/ui'; +import { linodeCreatePage } from 'support/ui/pages'; import { SimpleBackoffMethod } from 'support/util/backoff'; import { cleanUp } from 'support/util/cleanup'; import { chooseImage } from 'support/util/images'; @@ -18,10 +20,16 @@ import { pollLinodeDiskSize, pollLinodeStatus, } from 'support/util/polling'; -import { randomLabel, randomPhrase, randomString } from 'support/util/random'; +import { + randomLabel, + randomNumber, + randomPhrase, + randomString, +} from 'support/util/random'; import { chooseRegion, getRegionByLabel } from 'support/util/regions'; import { getFilteredImagesForImageSelect } from 'src/components/ImageSelect/utilities'; +import { firewallFactory } from 'src/factories'; import type { Image } from '@linode/api-v4'; @@ -179,6 +187,11 @@ const createLinodeAndImage = async () => { return image; }; +const mockFirewall = firewallFactory.build({ + id: randomNumber(), + label: randomLabel(), +}); + authenticate(); describe('Create stackscripts', () => { before(() => { @@ -186,6 +199,7 @@ describe('Create stackscripts', () => { }); beforeEach(() => { cy.tag('method:e2e', 'purpose:dcTesting'); + mockGetFirewalls([mockFirewall]).as('getFirewalls'); }); /* @@ -288,6 +302,11 @@ describe('Create stackscripts', () => { cy.findByLabelText('Example Title').should('be.visible').click(); cy.focused().type('{selectall}{backspace}'); cy.focused().type(randomString(12)); + // Select a firewall + linodeCreatePage.selectFirewall( + 'No firewall - traffic is unprotected (not recommended)', + 'Public Interface Firewall' + ); ui.button .findByTitle('Create Linode') @@ -389,6 +408,11 @@ describe('Create stackscripts', () => { cy.findByText(privateImage.label).as('qaPrivateImage').scrollIntoView(); cy.get('@qaPrivateImage').should('be.visible').click(); + // Select a firewall + linodeCreatePage.selectFirewall( + 'No firewall - traffic is unprotected (not recommended)', + 'Public Interface Firewall' + ); interceptCreateLinode().as('createLinode'); fillOutLinodeForm( linodeLabel, diff --git a/packages/manager/cypress/e2e/core/stackscripts/smoke-community-stackscripts.spec.ts b/packages/manager/cypress/e2e/core/stackscripts/smoke-community-stackscripts.spec.ts index 7e137192517..f698d9e4cc0 100644 --- a/packages/manager/cypress/e2e/core/stackscripts/smoke-community-stackscripts.spec.ts +++ b/packages/manager/cypress/e2e/core/stackscripts/smoke-community-stackscripts.spec.ts @@ -8,6 +8,7 @@ import { mockGetStackScripts, } from 'support/intercepts/stackscripts'; import { ui } from 'support/ui'; +import { linodeCreatePage } from 'support/ui/pages'; import { cleanUp } from 'support/util/cleanup'; import { randomLabel, randomString } from 'support/util/random'; import { chooseRegion } from 'support/util/regions'; @@ -392,6 +393,12 @@ describe('Community Stackscripts integration tests', () => { cy.get('[data-qa-radio]').click({ force: true }); }); + // Select a firewall + linodeCreatePage.selectFirewall( + 'No firewall - traffic is unprotected (not recommended)', + 'Public Interface Firewall' + ); + // Input root password // Weak or fair root password cannot rebuild the linode cy.get('[id="root-password"]').clear(); diff --git a/packages/manager/cypress/support/ui/pages/linode-create-page.ts b/packages/manager/cypress/support/ui/pages/linode-create-page.ts index 47e370d7ffd..b3f9741a81f 100644 --- a/packages/manager/cypress/support/ui/pages/linode-create-page.ts +++ b/packages/manager/cypress/support/ui/pages/linode-create-page.ts @@ -157,4 +157,30 @@ export const linodeCreatePage = { selectInterface: (type: 'public' | 'vlan' | 'vpc') => { cy.get(`[data-qa-interface-type-option="${type}"]`).click(); }, + + /** + * Selects a firewall from the firewall dropdown. + * + * @param firewallLabel - Label of the firewall to select. + * @param interfaceType - Optional interface type for the firewall dropdown label (e.g., 'Public Interface Firewall', 'VPC Interface Firewall'). + */ + selectFirewall: ( + firewallLabel: string, + dropdownLabel: + | 'Assign Firewall' + | 'Firewall' + | 'Public Interface Firewall' + | 'VPC Interface Firewall' + ) => { + cy.findByLabelText(dropdownLabel).should('be.visible'); + cy.get(`[data-qa-autocomplete="${dropdownLabel}"]`).within(() => { + cy.get('[data-testid="textfield-input"]').click(); + cy.focused().type(firewallLabel); + }); + + ui.autocompletePopper + .findByTitle(firewallLabel) + .should('be.visible') + .click(); + }, }; diff --git a/packages/manager/cypress/support/util/linodes.ts b/packages/manager/cypress/support/util/linodes.ts index ba990a3c94d..95494c39820 100644 --- a/packages/manager/cypress/support/util/linodes.ts +++ b/packages/manager/cypress/support/util/linodes.ts @@ -135,7 +135,7 @@ export const createTestLinode = async ( const resolvedCreatePayload = { ...createLinodeRequestFactory.build({ interface_generation: 'legacy_config', - firewall_id: null, + firewall_id: -1, booted: false, image: 'linode/ubuntu24.04', label: randomLabel(), diff --git a/packages/manager/src/features/Account/DefaultFirewalls.tsx b/packages/manager/src/features/Account/DefaultFirewalls.tsx index 84af676e298..5197c6d3038 100644 --- a/packages/manager/src/features/Account/DefaultFirewalls.tsx +++ b/packages/manager/src/features/Account/DefaultFirewalls.tsx @@ -126,6 +126,7 @@ export const DefaultFirewalls = () => { label="Configuration Profile Interfaces Firewall" onChange={(e, firewall) => field.onChange(firewall.id)} placeholder={DEFAULT_FIREWALL_PLACEHOLDER} + showNoFirewallOption={false} value={field.value} /> )} @@ -142,6 +143,7 @@ export const DefaultFirewalls = () => { label="Linode Interfaces - Public Interface Firewall" onChange={(e, firewall) => field.onChange(firewall.id)} placeholder={DEFAULT_FIREWALL_PLACEHOLDER} + showNoFirewallOption={false} value={field.value} /> )} @@ -158,6 +160,7 @@ export const DefaultFirewalls = () => { label="Linode Interfaces - VPC Interface Firewall" onChange={(e, firewall) => field.onChange(firewall.id)} placeholder={DEFAULT_FIREWALL_PLACEHOLDER} + showNoFirewallOption={false} value={field.value} /> )} @@ -177,6 +180,7 @@ export const DefaultFirewalls = () => { label="NodeBalancers Firewall" onChange={(e, firewall) => field.onChange(firewall.id)} placeholder={DEFAULT_FIREWALL_PLACEHOLDER} + showNoFirewallOption={false} value={field.value} /> )} diff --git a/packages/manager/src/features/Firewalls/components/FirewallSelect.test.tsx b/packages/manager/src/features/Firewalls/components/FirewallSelect.test.tsx index 5489c7cff9c..3b038dd20b8 100644 --- a/packages/manager/src/features/Firewalls/components/FirewallSelect.test.tsx +++ b/packages/manager/src/features/Firewalls/components/FirewallSelect.test.tsx @@ -8,6 +8,10 @@ import { renderWithTheme } from 'src/utilities/testHelpers'; import { FirewallSelect } from './FirewallSelect'; +const NO_FIREWALL_ID = -1; +const NO_FIREWALL_LABEL = + 'No firewall - traffic is unprotected (not recommended)'; + describe('FirewallSelect', () => { it('renders a default label', () => { const { getByText } = renderWithTheme(); @@ -50,4 +54,75 @@ describe('FirewallSelect', () => { expect(getByText(firewall.label)).toBeVisible(); } }); + + it('renders "No firewall" option in the dropdown by default', async () => { + const firewalls = firewallFactory.buildList(2); + + server.use( + http.get('*/v4/networking/firewalls', () => { + return HttpResponse.json(makeResourcePage(firewalls)); + }) + ); + + const { getByLabelText, getByText } = renderWithTheme( + + ); + + await userEvent.click(getByLabelText('Firewall')); + + expect(getByText(NO_FIREWALL_LABEL)).toBeVisible(); + }); + + it('does not render "No firewall" option when showNoFirewallOption is false', async () => { + const firewalls = firewallFactory.buildList(2); + + server.use( + http.get('*/v4/networking/firewalls', () => { + return HttpResponse.json(makeResourcePage(firewalls)); + }) + ); + + const { getByLabelText, queryByText } = renderWithTheme( + + ); + + await userEvent.click(getByLabelText('Firewall')); + + expect(queryByText(NO_FIREWALL_LABEL)).not.toBeInTheDocument(); + }); + + it('displays warning notice when "No firewall" is selected and warningMessageForNoFirewallOption is provided', () => { + const warningMessage = 'This Linode is not secured with a Cloud Firewall.'; + + const { getByText } = renderWithTheme( + + ); + + expect(getByText(warningMessage)).toBeVisible(); + }); + + it('does not display warning notice when "No firewall" is selected but warningMessageForNoFirewallOption is not provided', () => { + const { queryByRole } = renderWithTheme( + + ); + + expect(queryByRole('alert')).not.toBeInTheDocument(); + }); + + it('shows "No firewall" as selected when value is NO_FIREWALL_ID', async () => { + server.use( + http.get('*/v4/networking/firewalls', () => { + return HttpResponse.json(makeResourcePage([])); + }) + ); + + const { findByDisplayValue } = renderWithTheme( + + ); + + await findByDisplayValue(NO_FIREWALL_LABEL); + }); }); diff --git a/packages/manager/src/features/Firewalls/components/FirewallSelect.tsx b/packages/manager/src/features/Firewalls/components/FirewallSelect.tsx index 0b17aaf6de8..6f25528e252 100644 --- a/packages/manager/src/features/Firewalls/components/FirewallSelect.tsx +++ b/packages/manager/src/features/Firewalls/components/FirewallSelect.tsx @@ -1,5 +1,5 @@ import { useAllFirewallsQuery } from '@linode/queries'; -import { Autocomplete, InputAdornment } from '@linode/ui'; +import { Autocomplete, InputAdornment, Notice, Stack } from '@linode/ui'; import React, { useMemo } from 'react'; import { useDefaultFirewallChipInformation } from 'src/hooks/useDefaultFirewallChipInformation'; @@ -10,6 +10,15 @@ import { FirewallSelectOption } from './FirewallSelectOption'; import type { Firewall } from '@linode/api-v4'; import type { EnhancedAutocompleteProps } from '@linode/ui'; +// -1 is used as the value for the "firewall_id" if user doesn't want to use a firewall. +// If null or undefined were used instead, the API would default to using the default firewall, which is not the intended behavior when a user explicitly selects "No firewall". +const NO_FIREWALL_ID = -1; + +const noFirewallOption = { + label: 'No firewall - traffic is unprotected (not recommended)', + id: NO_FIREWALL_ID, +} as Firewall; + interface Props extends Omit< EnhancedAutocompleteProps, @@ -31,10 +40,18 @@ interface Props * All Firewall will show if this is omitted. */ options?: Firewall[]; + /** + * Show an additional "No firewall (not recommended)" option in the dropdown, which has a value of `-1`. + */ + showNoFirewallOption?: boolean; /** * The ID of the selected Firewall */ value: null | number | undefined; + /** + * Warning notice when no firewall is selected. + */ + warningMessageForNoFirewallOption?: string; } /** @@ -47,50 +64,80 @@ interface Props export const FirewallSelect = ( props: Props ) => { - const { errorText, hideDefaultChips, label, loading, value, ...rest } = props; + const { + errorText, + hideDefaultChips, + label, + loading, + options, + showNoFirewallOption = true, + value, + warningMessageForNoFirewallOption, + ...rest + } = props; const { data: firewalls, error, isLoading } = useAllFirewallsQuery(); const { defaultNumEntities, isDefault, tooltipText } = useDefaultFirewallChipInformation(value, hideDefaultChips); + const firewallOptions = useMemo( + () => [ + ...(options ? options : (firewalls ?? [])), + ...(showNoFirewallOption ? [noFirewallOption] : []), + ], + [firewalls, options, showNoFirewallOption] + ); + const selectedFirewall = useMemo( - () => firewalls?.find((firewall) => firewall.id === value) ?? null, + () => + value === NO_FIREWALL_ID + ? noFirewallOption + : (firewalls?.find((firewall) => firewall.id === value) ?? null), [firewalls, value] ); return ( - - aria-label={label === '' ? 'Firewall' : undefined} - errorText={errorText ?? error?.[0].reason} - label={label ?? 'Firewall'} - loading={isLoading || loading} - noMarginTop - options={firewalls ?? []} - placeholder="None" - renderOption={({ key, ...props }, option, state) => ( - + + aria-label={label === '' ? 'Firewall' : undefined} + errorText={errorText ?? error?.[0].reason} + label={label ?? 'Firewall'} + loading={isLoading || loading} + noMarginTop + options={firewallOptions} + placeholder="Select a Firewall" + renderOption={({ key, ...props }, option, state) => ( + + )} + textFieldProps={{ + InputProps: { + endAdornment: isDefault && !hideDefaultChips && ( + + + + ), + }, + }} + value={selectedFirewall!} + {...rest} + /> + {value === NO_FIREWALL_ID && warningMessageForNoFirewallOption && ( + )} - textFieldProps={{ - InputProps: { - endAdornment: isDefault && !hideDefaultChips && ( - - - - ), - }, - }} - value={selectedFirewall!} - {...rest} - /> + ); }; diff --git a/packages/manager/src/features/Kubernetes/NodePoolFirewallSelect.tsx b/packages/manager/src/features/Kubernetes/NodePoolFirewallSelect.tsx index a272cbebdc8..cc0008e5a50 100644 --- a/packages/manager/src/features/Kubernetes/NodePoolFirewallSelect.tsx +++ b/packages/manager/src/features/Kubernetes/NodePoolFirewallSelect.tsx @@ -137,6 +137,7 @@ export const NodePoolFirewallSelect = (props: NodePoolFirewallSelectProps) => { } }} placeholder="Select firewall" + showNoFirewallOption={false} value={field.value} /> )} diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Firewall.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Firewall.tsx index 93edc25385b..08c40cadcbc 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Firewall.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Firewall.tsx @@ -14,6 +14,7 @@ import { useFlags } from 'src/hooks/useFlags'; import { useSecureVMNoticesEnabled } from 'src/hooks/useSecureVMNoticesEnabled'; import { sendLinodeCreateFormInputEvent } from 'src/utilities/analytics/formEventAnalytics'; +import { WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION } from '../constants'; import { useGetLinodeCreateType } from './Tabs/utils/useGetLinodeCreateType'; import type { CreateLinodeRequest } from '@linode/api-v4'; @@ -108,8 +109,11 @@ export const Firewall = () => { }); } }} - placeholder="None" + placeholder="Select a Firewall" value={field.value} + warningMessageForNoFirewallOption={ + WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION + } /> { @@ -61,8 +63,11 @@ export const Firewall = () => { errorText={fieldState.error?.message} onBlur={field.onBlur} onChange={(e, firewall) => field.onChange(firewall?.id ?? null)} - placeholder="None" + placeholder="Select a Firewall" value={field.value} + warningMessageForNoFirewallOption={ + WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION + } /> { label={`${labelMap[interfaceType ?? 'public']} Interface Firewall`} onBlur={field.onBlur} onChange={(e, firewall) => field.onChange(firewall?.id ?? null)} - placeholder="None" + placeholder="Select a Firewall" value={field.value} + warningMessageForNoFirewallOption={ + WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION + } /> { label={ - ({ font: theme.font.bold })}> - Linode Interfaces (Recommended) - + Linode Interfaces (Recommended) { disabled={disabled} label={ - ({ font: theme.font.bold })}> - Configuration Profile Interfaces (Legacy) - + Configuration Profile Interfaces (Legacy) { field.onChange(value); // VLAN interfaces do not support Firewalls, so set - // the Firewall ID to `null` to be safe and early return. + // the Firewall ID to `-1` to be safe and early return. if (value === 'vlan') { - setValue(`linodeInterfaces.${index}.firewall_id`, null); + setValue(`linodeInterfaces.${index}.firewall_id`, -1); return; } @@ -136,9 +136,7 @@ export const InterfaceType = ({ index }: Props) => { key={interfaceType.purpose} label={ - ({ font: theme.font.bold })}> - {interfaceType.label} - + {interfaceType.label} { const hasFirewall = interfaceGeneration === 'linode' - ? linodeInterfaces.some((i) => i.firewall_id) + ? linodeInterfaces.some((i) => i.firewall_id && i.firewall_id !== -1) : firewallId; const hasBetaAclpAlertsAssigned = diff --git a/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts b/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts index dedae51d7de..dd798b23e45 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts +++ b/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts @@ -38,6 +38,18 @@ export const getLinodeCreateResolver = ( values.linodeInterfaces = values.linodeInterfaces.map( getCleanedLinodeInterfaceValues ); + if ( + values.interface_generation === 'legacy_config' || + tab === 'Clone Linode' + ) { + // firewall_id is required in the form under interfaces object when using linode interfaces, but not when using legacy interfaces. + // If the user selects legacy interfaces, we set firewall_id to -1 to bypass the firewall requirement in the validation schema. + values.linodeInterfaces.forEach((linodeInterface) => { + linodeInterface.firewall_id = -1; + }); + } else { + values.firewall_id = -1; + } } else { values.linodeInterfaces = []; values.interfaces = @@ -52,6 +64,12 @@ export const getLinodeCreateResolver = ( values.metadata = undefined; } + // For the Clone Linode flow, we need not send firewall_id in the payload as API will take care of assigning the firewall_id based on the source Linode's configuration. + if (tab === 'Clone Linode' && !values.firewall_id) { + // The Clone Linode flow does not have the firewall_id field under interfaces object, so we set firewall_id to -1 to bypass the firewall requirement in the validation schema. + values.firewall_id = -1; + } + const { errors } = await yupResolver( schema, {}, diff --git a/packages/manager/src/features/Linodes/LinodeCreate/schemas.ts b/packages/manager/src/features/Linodes/LinodeCreate/schemas.ts index 2bc6cc15084..f51432af0fd 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/schemas.ts +++ b/packages/manager/src/features/Linodes/LinodeCreate/schemas.ts @@ -7,6 +7,7 @@ import { array, boolean, number, object, string } from 'yup'; import { CreateLinodeInterfaceFormSchema } from '../LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/utilities'; import type { LinodeCreateFormValues } from './utilities'; +import type { InterfaceGenerationType } from '@linode/api-v4/lib/linodes/types'; import type { ObjectSchema } from 'yup'; /** @@ -17,6 +18,12 @@ import type { ObjectSchema } from 'yup'; export const CreateLinodeSchema: ObjectSchema = BaseCreateLinodeSchema.concat( object({ + firewall_id: number().when('interface_generation', { + is: (value: InterfaceGenerationType) => value === 'legacy_config', + then: (schema) => + schema.required('Select an option or create a new Firewall.'), + otherwise: (schema) => schema.nullable().notRequired(), + }), firewallOverride: boolean(), hasSignedEUAgreement: boolean(), interfaces: array(ConfigProfileInterfaceSchema).required(), diff --git a/packages/manager/src/features/Linodes/LinodeCreate/utilities.test.tsx b/packages/manager/src/features/Linodes/LinodeCreate/utilities.test.tsx index 10ffa39e821..8dc0a441f17 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/utilities.test.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/utilities.test.tsx @@ -489,6 +489,7 @@ describe('getDoesEmployeeNeedToAssignFirewall', () => { vpc: null, default_route: null, vlan: null, + firewall_id: null, }, ], 'linode' @@ -545,6 +546,7 @@ describe('getDoesEmployeeNeedToAssignFirewall', () => { public: null, default_route: null, vlan: { vlan_label: 'my-vlan-1' }, + firewall_id: null, }, ], 'linode' @@ -565,6 +567,7 @@ describe('getDoesEmployeeNeedToAssignFirewall', () => { vpc: null, vlan: null, default_route: null, + firewall_id: null, }, { vpc: null, @@ -572,6 +575,7 @@ describe('getDoesEmployeeNeedToAssignFirewall', () => { public: null, default_route: null, vlan: { vlan_label: 'my-vlan-1' }, + firewall_id: null, }, ], 'linode' diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/AddInterfaceForm.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/AddInterfaceForm.tsx index 82b2370844e..f71a3fad372 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/AddInterfaceForm.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/AddInterfaceForm.tsx @@ -45,7 +45,7 @@ export const AddInterfaceForm = (props: Props) => { ) ?? []; const form = useForm({ defaultValues: { - firewall_id: null, + firewall_id: undefined, public: {}, vlan: {}, vpc: { @@ -58,7 +58,7 @@ export const AddInterfaceForm = (props: Props) => { async resolver(rawValues, context, options) { const valuesWithOnlySelectedInterface = getCleanedLinodeInterfaceValues( structuredClone(rawValues) - ); + ) as CreateInterfaceFormValues; const { errors, values } = await yupResolver( CreateLinodeInterfaceFormSchema diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceFirewall.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceFirewall.tsx index e697993df09..a1e98f02870 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceFirewall.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceFirewall.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { useController } from 'react-hook-form'; import { FirewallSelect } from 'src/features/Firewalls/components/FirewallSelect'; +import { WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION } from 'src/features/Linodes/constants'; import type { CreateInterfaceFormValues } from './utilities'; @@ -18,8 +19,9 @@ export const InterfaceFirewall = () => { errorText={fieldState.error?.message} onBlur={field.onBlur} onChange={(e, firewall) => field.onChange(firewall?.id ?? null)} - placeholder="None" + placeholder="Select a Firewall" value={field.value} + warningMessageForNoFirewallOption={WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION} /> ); }; diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceType.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceType.tsx index 83465ed7068..d09a81afcbc 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceType.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/InterfaceType.tsx @@ -39,9 +39,9 @@ export const InterfaceType = (props: Props) => { field.onChange(value); // VLAN interfaces do not support Firewalls, so set - // the Firewall ID to `null` to be safe and early return. + // the Firewall ID to `-1` to be safe and early return. if (value === 'vlan') { - setValue('firewall_id', null); + setValue('firewall_id', -1); return; } diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/utilities.ts b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/utilities.ts index 9e3c41835f3..7f464ce0fba 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/utilities.ts +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/utilities.ts @@ -9,6 +9,9 @@ import type { InferType } from 'yup'; export const CreateLinodeInterfaceFormSchema = CreateLinodeInterfaceSchema.concat( object({ + firewall_id: number().required( + 'Select an option or create a new Firewall.' + ), purpose: string() .oneOf(['vpc', 'vlan', 'public']) .required('You must selected an Interface type.'), diff --git a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/EditInterfaceDrawer/EditInterfaceFirewall.tsx b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/EditInterfaceDrawer/EditInterfaceFirewall.tsx index c83e38e881d..0a38715062d 100644 --- a/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/EditInterfaceDrawer/EditInterfaceFirewall.tsx +++ b/packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/EditInterfaceDrawer/EditInterfaceFirewall.tsx @@ -33,6 +33,7 @@ export const EditInterfaceFirewall = ({ showSuccessNotice }: Props) => { field.onChange(firewall?.id ?? null)} + showNoFirewallOption={false} value={field.value} /> )} diff --git a/packages/manager/src/features/Linodes/constants.ts b/packages/manager/src/features/Linodes/constants.ts index b1326b91364..63a2cd6c581 100644 --- a/packages/manager/src/features/Linodes/constants.ts +++ b/packages/manager/src/features/Linodes/constants.ts @@ -51,3 +51,6 @@ export const LINODE_LOCKED_DELETE_INTERFACE_TOOLTIP = export const LINODE_REBUILD_LOCKED_NOTICE_TEXT = 'This Linode is currently locked and cannot be rebuilt. Please remove the lock to proceed.'; + +export const WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION = + 'This Linode, or its Linode interface, is not secured with a Cloud Firewall. Add a firewall to help protect your resources and simplify security management.'; diff --git a/packages/manager/src/features/VPCs/VPCDetail/SubnetAssignLinodesDrawer.tsx b/packages/manager/src/features/VPCs/VPCDetail/SubnetAssignLinodesDrawer.tsx index 89d105ae4c8..6787031e6dc 100644 --- a/packages/manager/src/features/VPCs/VPCDetail/SubnetAssignLinodesDrawer.tsx +++ b/packages/manager/src/features/VPCs/VPCDetail/SubnetAssignLinodesDrawer.tsx @@ -29,6 +29,7 @@ import { Link } from 'src/components/Link'; import { RemovableSelectionsListTable } from 'src/components/RemovableSelectionsList/RemovableSelectionsListTable'; import { FirewallSelect } from 'src/features/Firewalls/components/FirewallSelect'; import { useGetAllUserEntitiesByPermission } from 'src/features/IAM/hooks/useGetAllUserEntitiesByPermission'; +import { WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION } from 'src/features/Linodes/constants'; import { getDefaultFirewallForInterfacePurpose } from 'src/features/Linodes/LinodeCreate/Networking/utilities'; import { REMOVABLE_SELECTIONS_LINODES_TABLE_HEADERS, @@ -753,6 +754,9 @@ export const SubnetAssignLinodesDrawer = ( setFieldValue('selectedFirewall', firewall?.id) } value={values.selectedFirewall} + warningMessageForNoFirewallOption={ + WARNING_MESSAGE_FOR_NO_FIREWALL_OPTION + } /> )} From d64ca6fb7bc0cecdb6c32f111a33c4a1bd8e44a9 Mon Sep 17 00:00:00 2001 From: kagora-akamai Date: Mon, 9 Mar 2026 08:46:09 +0100 Subject: [PATCH 38/56] change: [DPS-41452] Switch Delivery endpoints from beta APIv4 to APIv4 (#13461) --- .../pr-13461-changed-1772617190589.md | 5 +++ packages/api-v4/src/delivery/destinations.ts | 14 ++++---- packages/api-v4/src/delivery/streams.ts | 12 +++---- .../pr-13461-changed-1772617249955.md | 5 +++ .../mocks/presets/crud/handlers/delivery.ts | 34 +++++++++---------- 5 files changed, 40 insertions(+), 30 deletions(-) create mode 100644 packages/api-v4/.changeset/pr-13461-changed-1772617190589.md create mode 100644 packages/manager/.changeset/pr-13461-changed-1772617249955.md diff --git a/packages/api-v4/.changeset/pr-13461-changed-1772617190589.md b/packages/api-v4/.changeset/pr-13461-changed-1772617190589.md new file mode 100644 index 00000000000..80c2a79bfa8 --- /dev/null +++ b/packages/api-v4/.changeset/pr-13461-changed-1772617190589.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Changed +--- + +Switch delivery endpoints from Beta APIv4 to APIv4 ([#13461](https://github.com/linode/manager/pull/13461)) diff --git a/packages/api-v4/src/delivery/destinations.ts b/packages/api-v4/src/delivery/destinations.ts index 1dcd4d6442c..1626a17e4de 100644 --- a/packages/api-v4/src/delivery/destinations.ts +++ b/packages/api-v4/src/delivery/destinations.ts @@ -3,7 +3,7 @@ import { updateDestinationSchema, } from '@linode/validation'; -import { BETA_API_ROOT } from '../constants'; +import { API_ROOT } from '../constants'; import Request, { setData, setMethod, @@ -28,7 +28,7 @@ import type { export const getDestination = (destinationId: number) => Request( setURL( - `${BETA_API_ROOT}/monitor/streams/destinations/${encodeURIComponent(destinationId)}`, + `${API_ROOT}/monitor/streams/destinations/${encodeURIComponent(destinationId)}`, ), setMethod('GET'), ); @@ -39,7 +39,7 @@ export const getDestination = (destinationId: number) => */ export const getDestinations = (params?: Params, filter?: Filter) => Request>( - setURL(`${BETA_API_ROOT}/monitor/streams/destinations`), + setURL(`${API_ROOT}/monitor/streams/destinations`), setMethod('GET'), setParams(params), setXFilter(filter), @@ -53,7 +53,7 @@ export const getDestinations = (params?: Params, filter?: Filter) => export const createDestination = (data: CreateDestinationPayload) => Request( setData(data, createDestinationSchema), - setURL(`${BETA_API_ROOT}/monitor/streams/destinations`), + setURL(`${API_ROOT}/monitor/streams/destinations`), setMethod('POST'), ); @@ -70,7 +70,7 @@ export const updateDestination = ( Request( setData(data, updateDestinationSchema), setURL( - `${BETA_API_ROOT}/monitor/streams/destinations/${encodeURIComponent(destinationId)}`, + `${API_ROOT}/monitor/streams/destinations/${encodeURIComponent(destinationId)}`, ), setMethod('PUT'), ); @@ -83,7 +83,7 @@ export const updateDestination = ( export const deleteDestination = (destinationId: number) => Request<{}>( setURL( - `${BETA_API_ROOT}/monitor/streams/destinations/${encodeURIComponent(destinationId)}`, + `${API_ROOT}/monitor/streams/destinations/${encodeURIComponent(destinationId)}`, ), setMethod('DELETE'), ); @@ -96,6 +96,6 @@ export const deleteDestination = (destinationId: number) => export const verifyDestination = (data: CreateDestinationPayload) => Request( setData(data, createDestinationSchema), - setURL(`${BETA_API_ROOT}/monitor/streams/destinations/verify`), + setURL(`${API_ROOT}/monitor/streams/destinations/verify`), setMethod('POST'), ); diff --git a/packages/api-v4/src/delivery/streams.ts b/packages/api-v4/src/delivery/streams.ts index 621bafa7247..e1a5c41f3f1 100644 --- a/packages/api-v4/src/delivery/streams.ts +++ b/packages/api-v4/src/delivery/streams.ts @@ -1,6 +1,6 @@ import { createStreamSchema, updateStreamSchema } from '@linode/validation'; -import { BETA_API_ROOT } from '../constants'; +import { API_ROOT } from '../constants'; import Request, { setData, setMethod, @@ -20,7 +20,7 @@ import type { CreateStreamPayload, Stream, UpdateStreamPayload } from './types'; */ export const getStream = (streamId: number) => Request( - setURL(`${BETA_API_ROOT}/monitor/streams/${encodeURIComponent(streamId)}`), + setURL(`${API_ROOT}/monitor/streams/${encodeURIComponent(streamId)}`), setMethod('GET'), ); @@ -30,7 +30,7 @@ export const getStream = (streamId: number) => */ export const getStreams = (params?: Params, filter?: Filter) => Request>( - setURL(`${BETA_API_ROOT}/monitor/streams`), + setURL(`${API_ROOT}/monitor/streams`), setMethod('GET'), setParams(params), setXFilter(filter), @@ -44,7 +44,7 @@ export const getStreams = (params?: Params, filter?: Filter) => export const createStream = (data: CreateStreamPayload) => Request( setData(data, createStreamSchema), - setURL(`${BETA_API_ROOT}/monitor/streams`), + setURL(`${API_ROOT}/monitor/streams`), setMethod('POST'), ); @@ -57,7 +57,7 @@ export const createStream = (data: CreateStreamPayload) => export const updateStream = (streamId: number, data: UpdateStreamPayload) => Request( setData(data, updateStreamSchema), - setURL(`${BETA_API_ROOT}/monitor/streams/${encodeURIComponent(streamId)}`), + setURL(`${API_ROOT}/monitor/streams/${encodeURIComponent(streamId)}`), setMethod('PUT'), ); @@ -68,6 +68,6 @@ export const updateStream = (streamId: number, data: UpdateStreamPayload) => */ export const deleteStream = (streamId: number) => Request<{}>( - setURL(`${BETA_API_ROOT}/monitor/streams/${encodeURIComponent(streamId)}`), + setURL(`${API_ROOT}/monitor/streams/${encodeURIComponent(streamId)}`), setMethod('DELETE'), ); diff --git a/packages/manager/.changeset/pr-13461-changed-1772617249955.md b/packages/manager/.changeset/pr-13461-changed-1772617249955.md new file mode 100644 index 00000000000..5de9a12ee9d --- /dev/null +++ b/packages/manager/.changeset/pr-13461-changed-1772617249955.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Delivery CRUD mocks update from Beta APIv4 to APIv4 ([#13461](https://github.com/linode/manager/pull/13461)) diff --git a/packages/manager/src/mocks/presets/crud/handlers/delivery.ts b/packages/manager/src/mocks/presets/crud/handlers/delivery.ts index ec62a6204e3..5b0e39e0a7e 100644 --- a/packages/manager/src/mocks/presets/crud/handlers/delivery.ts +++ b/packages/manager/src/mocks/presets/crud/handlers/delivery.ts @@ -34,7 +34,7 @@ import type { export const getStreams = () => [ http.get( - '*/v4beta/monitor/streams', + '*/v4/monitor/streams', async ({ request, }): Promise< @@ -53,7 +53,7 @@ export const getStreams = () => [ } ), http.get( - '*/v4beta/monitor/streams/:id', + '*/v4/monitor/streams/:id', async ({ params }): Promise> => { const id = Number(params.id); const stream = await mswDB.get('streams', id); @@ -69,7 +69,7 @@ export const getStreams = () => [ export const createStreams = (mockState: MockState) => [ http.post( - '*/v4beta/monitor/streams', + '*/v4/monitor/streams', async ({ request }): Promise> => { const payload = await request.clone().json(); const destinations = await mswDB.getAll('destinations'); @@ -94,7 +94,7 @@ export const createStreams = (mockState: MockState) => [ id: stream.id, label: stream.label, type: 'stream', - url: `/v4beta/delivery/streams`, + url: `/v4/delivery/streams`, }, }, mockState, @@ -108,7 +108,7 @@ export const createStreams = (mockState: MockState) => [ export const updateStream = (mockState: MockState) => [ http.put( - '*/v4beta/monitor/streams/:id', + '*/v4/monitor/streams/:id', async ({ params, request, @@ -140,7 +140,7 @@ export const updateStream = (mockState: MockState) => [ id: stream.id, label: stream.label, type: 'stream', - url: `/v4beta/monitor/streams/${stream.id}`, + url: `/v4/monitor/streams/${stream.id}`, }, }, mockState, @@ -154,7 +154,7 @@ export const updateStream = (mockState: MockState) => [ export const deleteStream = (mockState: MockState) => [ http.delete( - '*/v4beta/monitor/streams/:id', + '*/v4/monitor/streams/:id', async ({ params }): Promise> => { const id = Number(params.id); const stream = await mswDB.get('streams', id); @@ -172,7 +172,7 @@ export const deleteStream = (mockState: MockState) => [ id: stream.id, label: stream.label, type: 'domain', - url: `/v4beta/monitor/streams/${stream.id}`, + url: `/v4/monitor/streams/${stream.id}`, }, }, mockState, @@ -186,7 +186,7 @@ export const deleteStream = (mockState: MockState) => [ export const getDestinations = () => [ http.get( - '*/v4beta/monitor/streams/destinations', + '*/v4/monitor/streams/destinations', async ({ request, }): Promise< @@ -205,7 +205,7 @@ export const getDestinations = () => [ } ), http.get( - '*/v4beta/monitor/streams/destinations/:id', + '*/v4/monitor/streams/destinations/:id', async ({ params, }): Promise> => { @@ -223,7 +223,7 @@ export const getDestinations = () => [ export const createDestinations = (mockState: MockState) => [ http.post( - '*/v4beta/monitor/streams/destinations', + '*/v4/monitor/streams/destinations', async ({ request, }): Promise> => { @@ -278,7 +278,7 @@ export const createDestinations = (mockState: MockState) => [ id: destination.id, label: destination.label, type: 'destination', - url: `/v4beta/delivery/streams/destinations`, + url: `/v4/delivery/streams/destinations`, }, }, mockState, @@ -292,7 +292,7 @@ export const createDestinations = (mockState: MockState) => [ export const updateDestination = (mockState: MockState) => [ http.put( - '*/v4beta/monitor/streams/destinations/:id', + '*/v4/monitor/streams/destinations/:id', async ({ params, request, @@ -322,7 +322,7 @@ export const updateDestination = (mockState: MockState) => [ id: destination.id, label: destination.label, type: 'stream', - url: `/v4beta/monitor/streams/${destination.id}`, + url: `/v4/monitor/streams/${destination.id}`, }, }, mockState, @@ -336,7 +336,7 @@ export const updateDestination = (mockState: MockState) => [ export const deleteDestination = (mockState: MockState) => [ http.delete( - '*/v4beta/monitor/streams/destinations/:id', + '*/v4/monitor/streams/destinations/:id', async ({ params }): Promise> => { const id = Number(params.id); const destination = await mswDB.get('destinations', id); @@ -367,7 +367,7 @@ export const deleteDestination = (mockState: MockState) => [ id: destination.id, label: destination.label, type: 'domain', - url: `/v4beta/monitor/streams/${destination.id}`, + url: `/v4/monitor/streams/${destination.id}`, }, }, mockState, @@ -381,7 +381,7 @@ export const deleteDestination = (mockState: MockState) => [ export const verifyDestination = () => [ http.post( - '*/v4beta/monitor/streams/destinations/verify', + '*/v4/monitor/streams/destinations/verify', async (): Promise> => { return makeResponse({}, 200); } From 7bf9ed9e2192524c01b9553fd05f846f9a8eed8a Mon Sep 17 00:00:00 2001 From: kagora-akamai Date: Mon, 9 Mar 2026 10:00:44 +0100 Subject: [PATCH 39/56] fix: [DPS-41226][CMJPOC-7] - Errors while searching for services in cloud manager (#13459) --- .../.changeset/pr-13459-fixed-1772610765361.md | 5 +++++ .../manager/src/features/Search/useAPISearch.ts | 13 ++++++++++--- .../src/features/Search/useClientSideSearch.ts | 6 ++++-- .../src/store/selectors/getSearchEntities.ts | 2 ++ 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 packages/manager/.changeset/pr-13459-fixed-1772610765361.md diff --git a/packages/manager/.changeset/pr-13459-fixed-1772610765361.md b/packages/manager/.changeset/pr-13459-fixed-1772610765361.md new file mode 100644 index 00000000000..a7ecf54bc4c --- /dev/null +++ b/packages/manager/.changeset/pr-13459-fixed-1772610765361.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Unnecessary API requests for Delivery services while searching when feature access is not present ([#13459](https://github.com/linode/manager/pull/13459)) diff --git a/packages/manager/src/features/Search/useAPISearch.ts b/packages/manager/src/features/Search/useAPISearch.ts index 9c225c188d3..53520e6b928 100644 --- a/packages/manager/src/features/Search/useAPISearch.ts +++ b/packages/manager/src/features/Search/useAPISearch.ts @@ -13,6 +13,7 @@ import { import { getAPIFilterFromQuery } from '@linode/search'; import { useDebouncedValue } from '@linode/utilities'; +import { useIsACLPLogsEnabled } from 'src/features/Delivery/deliveryUtils'; import { useKubernetesClustersInfiniteQuery } from 'src/queries/kubernetes'; import { databaseToSearchableItem, @@ -119,6 +120,7 @@ const entities = [ searchOptions: { searchableFieldsWithoutOperator: ['label'], }, + requireACLPLogsEnabled: true, }, { getSearchableItem: destinationToSearchableItem, @@ -127,6 +129,7 @@ const entities = [ searchOptions: { searchableFieldsWithoutOperator: ['label'], }, + requireACLPLogsEnabled: true, }, ]; @@ -142,11 +145,12 @@ const entities = [ * and do the filtering client-side. */ export const useAPISearch = ({ enabled, query }: Props) => { - const deboundedQuery = useDebouncedValue(query); + const debouncedQuery = useDebouncedValue(query); + const { isACLPLogsEnabled } = useIsACLPLogsEnabled(); const result = entities.map((entity) => { const { error, filter } = getAPIFilterFromQuery( - deboundedQuery, + debouncedQuery, entity.searchOptions ); @@ -155,7 +159,10 @@ export const useAPISearch = ({ enabled, query }: Props) => { parseError: error, ...entity.query( entity.baseFilter ? { ...entity.baseFilter, ...filter } : filter, - enabled && error === null && Boolean(deboundedQuery) + enabled && + error === null && + Boolean(debouncedQuery) && + (!entity.requireACLPLogsEnabled || isACLPLogsEnabled) ), }; }); diff --git a/packages/manager/src/features/Search/useClientSideSearch.ts b/packages/manager/src/features/Search/useClientSideSearch.ts index a96a6d99856..3f86b7584ac 100644 --- a/packages/manager/src/features/Search/useClientSideSearch.ts +++ b/packages/manager/src/features/Search/useClientSideSearch.ts @@ -11,6 +11,7 @@ import { useAllVolumesQuery, } from '@linode/queries'; +import { useIsACLPLogsEnabled } from 'src/features/Delivery/deliveryUtils'; import { useAllKubernetesClustersQuery } from 'src/queries/kubernetes'; import { useObjectStorageBuckets } from 'src/queries/object-storage/queries'; import { @@ -44,6 +45,7 @@ interface Props { */ export const useClientSideSearch = ({ enabled, query }: Props) => { const { isPrivateImageSharingEnabled } = useIsPrivateImageSharingEnabled(); + const { isACLPLogsEnabled } = useIsACLPLogsEnabled(); const { data: domains, @@ -96,12 +98,12 @@ export const useClientSideSearch = ({ enabled, query }: Props) => { data: streams, error: streamsError, isLoading: streamsLoading, - } = useAllStreamsQuery({}, {}, enabled); + } = useAllStreamsQuery({}, {}, enabled && isACLPLogsEnabled); const { data: destinations, error: destinationsError, isLoading: destinationsLoading, - } = useAllDestinationsQuery({}, {}, enabled); + } = useAllDestinationsQuery({}, {}, enabled && isACLPLogsEnabled); const searchableDomains = domains?.map(domainToSearchableItem) ?? []; const searchableVolumes = volumes?.map(volumeToSearchableItem) ?? []; diff --git a/packages/manager/src/store/selectors/getSearchEntities.ts b/packages/manager/src/store/selectors/getSearchEntities.ts index 2de80d2cad4..a6a30f838e8 100644 --- a/packages/manager/src/store/selectors/getSearchEntities.ts +++ b/packages/manager/src/store/selectors/getSearchEntities.ts @@ -215,6 +215,7 @@ export const streamToSearchableItem = (stream: Stream): SearchableItem => ({ description: getStreamDescription(stream), path: `/logs/delivery/streams/${stream.id}/edit`, status: stream.status, + created: stream.created, }, entityType: 'stream', label: stream.label, @@ -227,6 +228,7 @@ export const destinationToSearchableItem = ( data: { description: getDestinationDescription(destination), path: `/logs/delivery/destinations/${destination.id}/edit`, + created: destination.created, }, entityType: 'destination', label: destination.label, From 07a5ee41ad196eaa2ad7d397820de1c77cb5b63b Mon Sep 17 00:00:00 2001 From: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Date: Mon, 9 Mar 2026 10:59:54 +0100 Subject: [PATCH 40/56] fix: [UIE-10308] - IAM Parent/Child - SwitchAccount Drawer: hide search if no child account (#13464) * hide search if no child account * better condition * Added changeset: IAM Parent/Child - SwitchAccount Drawer: hide search if no child account * test fix * feedback --- .../pr-13464-fixed-1772634680494.md | 5 + .../src/assets/icons/no-results-state.svg | 10 + .../Account/SwitchAccountDrawer.test.tsx | 65 ++++- .../features/Account/SwitchAccountDrawer.tsx | 235 ++++++++++-------- .../ChildAccountsTable.test.tsx | 13 - .../SwitchAccounts/ChildAccountsTable.tsx | 19 +- 6 files changed, 207 insertions(+), 140 deletions(-) create mode 100644 packages/manager/.changeset/pr-13464-fixed-1772634680494.md create mode 100644 packages/manager/src/assets/icons/no-results-state.svg diff --git a/packages/manager/.changeset/pr-13464-fixed-1772634680494.md b/packages/manager/.changeset/pr-13464-fixed-1772634680494.md new file mode 100644 index 00000000000..229fecf3f04 --- /dev/null +++ b/packages/manager/.changeset/pr-13464-fixed-1772634680494.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +IAM Parent/Child - SwitchAccount Drawer: hide search if no child account ([#13464](https://github.com/linode/manager/pull/13464)) diff --git a/packages/manager/src/assets/icons/no-results-state.svg b/packages/manager/src/assets/icons/no-results-state.svg new file mode 100644 index 00000000000..e7723054193 --- /dev/null +++ b/packages/manager/src/assets/icons/no-results-state.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx index 36f4e9fcd7b..4ae55c8d34b 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx @@ -9,7 +9,11 @@ import { SwitchAccountDrawer } from './SwitchAccountDrawer'; const queryMocks = vi.hoisted(() => ({ useProfile: vi.fn().mockReturnValue({}), - useGetListMyDelegatedChildAccountsQuery: vi.fn().mockReturnValue({}), + useMyDelegatedChildAccountsQuery: vi.fn().mockReturnValue({}), + useChildAccountsInfiniteQuery: vi.fn().mockReturnValue({}), + useIsIAMDelegationEnabled: vi + .fn() + .mockReturnValue({ isIAMDelegationEnabled: true }), })); vi.mock('@linode/queries', async () => { @@ -17,8 +21,19 @@ vi.mock('@linode/queries', async () => { return { ...actual, useProfile: queryMocks.useProfile, - useGetListMyDelegatedChildAccountsQuery: - queryMocks.useGetListMyDelegatedChildAccountsQuery, + useMyDelegatedChildAccountsQuery: + queryMocks.useMyDelegatedChildAccountsQuery, + useChildAccountsInfiniteQuery: queryMocks.useChildAccountsInfiniteQuery, + }; +}); + +vi.mock('src/features/IAM/hooks/useIsIAMEnabled', async () => { + const actual = await vi.importActual( + 'src/features/IAM/hooks/useIsIAMEnabled' + ); + return { + ...actual, + useIsIAMDelegationEnabled: queryMocks.useIsIAMDelegationEnabled, }; }); @@ -29,16 +44,34 @@ const props = { }; describe('SwitchAccountDrawer', () => { + const accounts = accountFactory.buildList(5, { + company: 'Test Account 1', + }); + beforeEach(() => { queryMocks.useProfile.mockReturnValue({}); - queryMocks.useGetListMyDelegatedChildAccountsQuery.mockReturnValue({ - data: accountFactory.buildList(5, { - company: 'Test Account 1', - euuid: '123', - }), + queryMocks.useIsIAMDelegationEnabled.mockReturnValue({ + isIAMDelegationEnabled: true, + }); + queryMocks.useMyDelegatedChildAccountsQuery.mockReturnValue({ + data: { data: accounts, results: accounts.length, page: 1, pages: 1 }, isLoading: false, isRefetching: false, }); + queryMocks.useChildAccountsInfiniteQuery.mockReturnValue({ + data: { + pages: [ + { data: accounts, results: accounts.length, page: 1, pages: 1 }, + ], + pageParams: [], + }, + isInitialLoading: false, + isRefetching: false, + isFetchingNextPage: false, + hasNextPage: false, + fetchNextPage: vi.fn(), + refetch: vi.fn(), + }); }); it('should have a title', () => { @@ -94,4 +127,20 @@ describe('SwitchAccountDrawer', () => { expect(props.onClose).toHaveBeenCalledTimes(1); }); }); + + it('should display an empty state when no child accounts are found', async () => { + queryMocks.useMyDelegatedChildAccountsQuery.mockReturnValue({ + data: { data: [], results: 0, page: 1, pages: 1 }, + isLoading: false, + isRefetching: false, + }); + const { getByText } = renderWithTheme(); + + expect(getByText('You don’t have access to other accounts.')).toBeVisible(); + expect( + getByText( + 'You must be added to a delegation by an account administrator to have access to other accounts.' + ) + ).toBeVisible(); + }); }); diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index 8faed748301..dea40764784 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -3,6 +3,7 @@ import { useMyDelegatedChildAccountsQuery, } from '@linode/queries'; import { + Box, Button, Drawer, LinkButton, @@ -14,6 +15,7 @@ import { import React, { useMemo, useState } from 'react'; import ErrorStateCloud from 'src/assets/icons/error-state-cloud.svg'; +import NoResultsState from 'src/assets/icons/no-results-state.svg'; import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; import { useParentChildAuthentication } from 'src/features/Account/SwitchAccounts/useParentChildAuthentication'; import { useSwitchToParentAccount } from 'src/features/Account/SwitchAccounts/useSwitchToParentAccount'; @@ -217,6 +219,7 @@ export const SwitchAccountDrawer = (props: Props) => { const hasError = isIAMDelegationEnabled ? delegatedChildAccountsError : childAccountInfiniteError; + return ( {createTokenErrorReason && ( @@ -225,116 +228,144 @@ export const SwitchAccountDrawer = (props: Props) => { {isParentTokenError.length > 0 && ( )} - ({ - margin: `${theme.spacingFunction(24)} 0`, - })} - > - Select an account to view and manage its settings and configurations - {isProxyOrDelegateUserType && ( - <> - {' or '} - { - sendSwitchToParentAccountEvent(); - handleSwitchToParentAccount(); - }} - > - switch back to your account - - - )} - . - - - {hasError ? ( - - - Unable to load data. - - Try again or contact support if the issue persists. + {childAccounts && + childAccounts.length === 0 && + !Object.prototype.hasOwnProperty.call(filter, 'company') ? ( + + + + You don’t have access to other accounts. + + + You must be added to a delegation by an account administrator to + have access to other accounts. - + ) : ( <> - - {searchQuery && - childAccounts && - childAccounts.length === 0 && - !isLoading && ( - - No search results - + ({ + margin: `${theme.spacingFunction(24)} 0`, + })} + > + Select an account to view and manage its settings and configurations + {isProxyOrDelegateUserType && ( + <> + {' or '} + { + sendSwitchToParentAccountEvent(); + handleSwitchToParentAccount(); + }} + > + switch back to your account + + )} + . + - {isIAMDelegationEnabled && ( - - )} - {!isIAMDelegationEnabled && ( - + {hasError ? ( + + + Unable to load data. + + Try again or contact support if the issue persists. + + + + ) : ( + <> + {((childAccounts && childAccounts.length !== 0) || + searchQuery) && ( + + )} + {isIAMDelegationEnabled && + searchQuery && + childAccounts && + childAccounts.length === 0 && + !isLoading && ( + + No search results + + )} + + {isIAMDelegationEnabled && ( + + )} + {!isIAMDelegationEnabled && ( + + )} + )} )} diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx index b7a4ec14655..e226097a2d2 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.test.tsx @@ -28,7 +28,6 @@ const props: ChildAccountsTableProps = { setIsSwitchingChildAccounts: vi.fn(), totalResults: 0, userType: undefined, - filter: {}, isLoading: false, isSwitchingChildAccounts: false, onClose: vi.fn(), @@ -65,16 +64,4 @@ describe('ChildAccountsTable', () => { expect(getByTestId('child-accounts-table-pagination')).toBeVisible(); }); - - it('should display an empty state when no child accounts are found', async () => { - const { getByText } = renderWithTheme( - - ); - - expect( - getByText( - /You don't have access to other accounts. You must be added to a delegation by an account administrator to have access to other accounts./ - ) - ).toBeInTheDocument(); - }); }); diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx index 31cd956fb29..524960b2cb0 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx @@ -1,4 +1,4 @@ -import { Box, CircleProgress, LinkButton, Notice, useTheme } from '@linode/ui'; +import { Box, CircleProgress, LinkButton, useTheme } from '@linode/ui'; import { Pagination } from 'akamai-cds-react-components/Pagination'; import { Table, @@ -10,12 +10,11 @@ import React from 'react'; import { MIN_PAGE_SIZE } from 'src/components/PaginationFooter/PaginationFooter.constants'; -import type { Account, Filter, UserType } from '@linode/api-v4'; +import type { Account, UserType } from '@linode/api-v4'; export interface ChildAccountsTableProps { childAccounts?: Account[]; currentTokenWithBearer?: string; - filter: Filter; isLoading: boolean; isSwitchingChildAccounts: boolean; onClose: () => void; @@ -43,7 +42,6 @@ export interface ChildAccountsTableProps { export const ChildAccountsTable = (props: ChildAccountsTableProps) => { const { - filter, childAccounts, currentTokenWithBearer, isLoading, @@ -76,19 +74,6 @@ export const ChildAccountsTable = (props: ChildAccountsTableProps) => { ); } - if ( - childAccounts && - childAccounts.length === 0 && - !Object.prototype.hasOwnProperty.call(filter, 'company') - ) { - return ( - - You don't have access to other accounts. You must be added to a - delegation by an account administrator to have access to other accounts. - - ); - } - return ( <>
Date: Mon, 9 Mar 2026 09:01:17 -0400 Subject: [PATCH 41/56] test: [UIE-10395 & UIE-10444] - Fix Parent/Child account switching bugs and test failures (#13470) * Fix bug preventing child accounts from being fetched when signed in as a proxy user * Work around debounce issue when searching for child accounts in test * Added changeset: Fix test flakiness in account switching spec --- packages/manager/.changeset/pr-13470-tests-1772743282866.md | 5 +++++ .../cypress/e2e/core/parentChild/account-switching.spec.ts | 4 ++-- .../manager/src/features/Account/SwitchAccountDrawer.tsx | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 packages/manager/.changeset/pr-13470-tests-1772743282866.md diff --git a/packages/manager/.changeset/pr-13470-tests-1772743282866.md b/packages/manager/.changeset/pr-13470-tests-1772743282866.md new file mode 100644 index 00000000000..6a685721520 --- /dev/null +++ b/packages/manager/.changeset/pr-13470-tests-1772743282866.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Fix test flakiness in account switching spec ([#13470](https://github.com/linode/manager/pull/13470)) diff --git a/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts b/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts index 768cd7071c4..0e59a8ba6a4 100644 --- a/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts +++ b/packages/manager/cypress/e2e/core/parentChild/account-switching.spec.ts @@ -366,7 +366,7 @@ describe('Parent/Child account switching', () => { // Confirm no results message. mockGetChildAccounts([]).as('getEmptySearchResults'); cy.findByPlaceholderText('Search').click(); - cy.focused().type('Fake Name'); + cy.focused().type('Fake Name', { delay: 50 }); cy.wait('@getEmptySearchResults'); cy.contains(mockChildAccount.company).should('not.exist'); @@ -378,7 +378,7 @@ describe('Parent/Child account switching', () => { mockGetChildAccounts([mockChildAccount]).as('getSearchResults'); cy.findByPlaceholderText('Search').click(); cy.focused().clear(); - cy.focused().type(mockChildAccount.company); + cy.focused().type(mockChildAccount.company, { delay: 50 }); cy.wait('@getSearchResults'); cy.findByText(mockChildAccount.company).should('be.visible'); diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index dea40764784..0f914e25e6e 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -105,7 +105,7 @@ export const SwitchAccountDrawer = (props: Props) => { } : undefined, }, - isIAMDelegationEnabled === false && isParentUserType + isIAMDelegationEnabled === false && (isParentUserType || isProxyUserType) ); const { From a791f04d4e8371df1b11cdd25afd9a76f7d61fd8 Mon Sep 17 00:00:00 2001 From: Sakshi Tayal <167911487+stayal712@users.noreply.github.com> Date: Mon, 9 Mar 2026 10:41:34 -0400 Subject: [PATCH 42/56] test: [DBAAS1-1403] Cypress tests for Postgresql Synchronous Replication Advanced Configuration (#13440) * test: [DBAAS1-1403] Add cypress test for synchronous replication advanced config, include nested/top level config * test: [DBAAS1-1403] Add negative cypress test for synchronous replication advanced config * test: fix for review comments * test: fix for failing cases * Added changeset: Cypress tests for Postgresql Synchronous Replication Advanced Configuration * test: add a pg advanced config for unit tests --- .../pr-13440-tests-1772556190302.md | 5 + .../databases/advanced-configuration.spec.ts | 235 +++++++++++++----- .../cypress/support/constants/databases.ts | 10 + .../cypress/support/intercepts/databases.ts | 27 ++ packages/manager/src/factories/databases.ts | 8 +- 5 files changed, 221 insertions(+), 64 deletions(-) create mode 100644 packages/manager/.changeset/pr-13440-tests-1772556190302.md diff --git a/packages/manager/.changeset/pr-13440-tests-1772556190302.md b/packages/manager/.changeset/pr-13440-tests-1772556190302.md new file mode 100644 index 00000000000..7ae6571a992 --- /dev/null +++ b/packages/manager/.changeset/pr-13440-tests-1772556190302.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Cypress tests for Postgresql Synchronous Replication Advanced Configuration ([#13440](https://github.com/linode/manager/pull/13440)) diff --git a/packages/manager/cypress/e2e/core/databases/advanced-configuration.spec.ts b/packages/manager/cypress/e2e/core/databases/advanced-configuration.spec.ts index deee96b0079..4f2bedd849e 100644 --- a/packages/manager/cypress/e2e/core/databases/advanced-configuration.spec.ts +++ b/packages/manager/cypress/e2e/core/databases/advanced-configuration.spec.ts @@ -13,6 +13,7 @@ import { mockGetDatabaseEngineConfigs, mockGetDatabaseTypes, mockUpdateDatabase, + mockUpdateDatabaseError, } from 'support/intercepts/databases'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { ui } from 'support/ui'; @@ -40,15 +41,45 @@ import type { DatabaseClusterConfiguration } from 'support/constants/databases'; */ const getFlattenDefaultConfigs = ( engineConfig: Record, - prefix = '' + prefix = '', + includePrefix = true ): string[] => Object.entries(engineConfig).flatMap(([key, value]) => { const fullKey = prefix ? `${prefix}.${key}` : key; return typeof value === 'object' && value !== null && !Array.isArray(value) - ? getFlattenDefaultConfigs(value, fullKey) - : [fullKey]; + ? getFlattenDefaultConfigs( + value, + includePrefix ? fullKey : '', + includePrefix + ) + : [includePrefix ? fullKey : key]; }); +const flattenConfigsEngineLevel = ( + configs: Record +): Record => { + const result: Record = {}; + Object.entries(configs).forEach(([key, value]) => { + if ( + typeof value === 'object' && + value !== null && + // Only flatten if value is a config group (not a config leaf) + Object.values(value).every( + (v) => typeof v === 'object' && v !== null && !Array.isArray(v) + ) + ) { + // Nested group (e.g., pg, mysql) + Object.entries(value).forEach(([subKey, subValue]) => { + result[subKey] = subValue; + }); + } else { + // Top-level config + result[key] = value; + } + }); + return result; +}; + /** * Get list of advanced Configurations available for users to add/modify * @@ -100,9 +131,14 @@ const addConfigsToUI = ( ? false : value.example; + // Get all existing config keys from engine_config (handles nested structures) + const existingConfigKeys = new Set( + getFlattenDefaultConfigs(database.engine_config, '', false) + ); + // Process new configs to be added const newEntries = Object.entries(configsList) - .filter(([key]) => !database.engine_config[engineType][key]) + .filter(([key]) => !existingConfigKeys.has(key)) .slice(0, addSingle ? 1 : undefined); // Limit to 1 if addSingle, otherwise all if (newEntries.length > 0) { @@ -121,8 +157,20 @@ const addConfigsToUI = ( .within(() => { // Confirms configure drawer already renders default configs Object.keys(database.engine_config[engineType]).forEach((key) => { + cy.findByText(`${engineType}.${key}`).scrollIntoView(); cy.findByText(`${engineType}.${key}`).should('be.visible'); }); + Object.keys(database.engine_config) + .filter( + (key) => + key !== 'pg' && + key !== 'mysql' && + typeof database.engine_config[key] !== 'object' + ) + .forEach((key) => { + cy.findByText(key).scrollIntoView(); + cy.findByText(key).should('be.visible'); + }); // Adding configs one at a time from the dropdown cy.get( @@ -140,9 +188,24 @@ const addConfigsToUI = ( // Type value for non-boolean configs if (value.type !== 'boolean') { - cy.get(`[name="${flatKey}"]`).scrollIntoView(); - cy.get(`[name="${flatKey}"]`).should('be.visible').clear(); - cy.get(`[name="${flatKey}"]`).type(additionalConfigs[flatKey]); + if (value.enum) { + cy.findByText(flatKey).scrollIntoView(); + cy.findByText(flatKey) + .parent() + .within(() => { + ui.autocomplete.find().click(); + ui.autocomplete.find().clear(); + ui.autocomplete.find().type(`${additionalConfigs[flatKey]}`); + }); + ui.autocompletePopper + .findByTitle(`${additionalConfigs[flatKey]}`) + .click(); + } else { + cy.get(`[name="${flatKey}"]`).scrollIntoView(); + cy.get(`[name="${flatKey}"]`).should('be.visible'); + cy.get(`[name="${flatKey}"]`).clear(); + cy.get(`[name="${flatKey}"]`).type(additionalConfigs[flatKey]); + } } }); }); @@ -195,7 +258,7 @@ describe('Update database clusters', () => { ); mockGetAccount(accountFactory.build()).as('getAccount'); - mockGetDatabase(database).as('getDatabase').debug(); + mockGetDatabase(database).as('getDatabase'); mockGetDatabaseTypes(mockDatabaseNodeTypes).as('getDatabaseTypes'); mockGetDatabaseEngineConfigs(database.engine, mockConfigs); @@ -215,6 +278,7 @@ describe('Update database clusters', () => { }); // Confirms all the buttons are in the initial state - enabled/disabled + ui.cdsButton.findButtonByTitle('Configure').scrollIntoView(); ui.cdsButton .findButtonByTitle('Configure') .should('be.visible') @@ -226,18 +290,15 @@ describe('Update database clusters', () => { .findButtonByTitle('Add') .should('exist') .should('be.disabled'); - ui.button - .findByTitle('Save') - .scrollIntoView() - .should('be.visible') - .should('be.disabled'); + ui.button.findByTitle('Save').should('exist').should('be.disabled'); ui.button .findByTitle('Cancel') - .scrollIntoView() - .should('be.visible') + .should('exist') .should('be.enabled') - .click(); + .then((btn) => { + btn[0].click(); + }); ui.cdsButton .findButtonByTitle('Configure') @@ -247,9 +308,11 @@ describe('Update database clusters', () => { ui.drawer.findByTitle('Advanced Configuration').should('be.visible'); cy.get('[aria-label="Close drawer"]') - .should('be.visible') + .should('exist') .should('be.enabled') - .click(); + .then((btn) => { + btn[0].click(); + }); }); /* @@ -296,6 +359,7 @@ describe('Update database clusters', () => { cy.wait(['@getDatabase', '@getDatabaseTypes']); // Expand configure drawer to add configs + ui.cdsButton.findButtonByTitle('Configure').scrollIntoView(); ui.cdsButton .findButtonByTitle('Configure') .should('be.visible') @@ -313,31 +377,52 @@ describe('Update database clusters', () => { true ); + const isSyncReplicationQuorum = + singleConfig['synchronous_replication'] === 'quorum'; + const isInvaliClusterSize = + database.cluster_size < 3 && isSyncReplicationQuorum; + // Update advanced configurations with the newly added config - mockUpdateDatabase(database.id, database.engine, { - ...database, - engine_config: { - ...(database.engine_config as ConfigCategoryValues), - [engineType]: { - ...(existingConfig as ConfigCategoryValues), - ...singleConfig, + if (isInvaliClusterSize) { + mockUpdateDatabaseError( + database.id, + database.engine, + 'engine_config.synchronous_replication', + 'synchronous_replication is only supported for clusters with 3 nodes' + ).as('updateAdvancedConfiguration'); + } else { + mockUpdateDatabase(database.id, database.engine, { + ...database, + engine_config: { + ...(database.engine_config as ConfigCategoryValues), + [engineType]: { + ...(existingConfig as ConfigCategoryValues), + ...singleConfig, + }, }, - }, - }).as('updateAdvancedConfiguration'); - + }).as('updateAdvancedConfiguration'); + } // Save or Save and Restart Services as per the config added ui.button .findByTitle(saveRestartButton) - .scrollIntoView() - .should('be.visible') + .should('exist') .should('be.enabled') - .click(); + .then((btn) => { + btn[0].click(); + }); cy.wait('@updateAdvancedConfiguration'); - // Confirms newly added advacned Config on the Configuration tab tableview - cy.findByText(`${engineType}.${Object.keys(singleConfig)[0]}`).should( - 'be.visible' - ); + if (isInvaliClusterSize) { + // Verify error message is displayed for invalid synchronous replication + cy.findByText( + /synchronous_replication is only supported for clusters with 3 nodes/i + ).should('be.visible'); + } else { + // Confirms newly added advanced Config on the Configuration tab tableview + cy.findByText( + `${engineType}.${Object.keys(singleConfig)[0]}` + ).should('be.visible'); + } }); /* @@ -384,48 +469,83 @@ describe('Update database clusters', () => { cy.wait(['@getDatabase', '@getDatabaseTypes']); // Expand configure drawer to add configs + ui.cdsButton.findButtonByTitle('Configure').scrollIntoView(); ui.cdsButton .findButtonByTitle('Configure') .should('be.visible') .should('be.enabled') .click(); + const flatMockConfigs = flattenConfigsEngineLevel(mockConfigs); + // Add configs from the configList to the existing database cluster const { additionalConfigs: allConfig, saveButton: saveRestartButton, - } = addConfigsToUI( - mockConfigs[engineType], - database, - engineType, - false - ); + } = addConfigsToUI(flatMockConfigs, database, engineType, false); + + const nestedConfig: Record = {}; + const topLevelConfig: Record = {}; + // Separate nested engine configs and top-level configs + Object.entries(allConfig).forEach(([key, value]) => { + if (key in mockConfigs[engineType]) { + nestedConfig[key] = value; + } else { + topLevelConfig[key] = value; + } + }); + + const isSyncReplicationQuorum = + allConfig['synchronous_replication'] === 'quorum'; + const isInvalidClusterSize = + database.cluster_size < 3 && isSyncReplicationQuorum; // Update advanced configurations with the newly added config - mockUpdateDatabase(database.id, database.engine, { - ...database, - engine_config: { - ...(database.engine_config as ConfigCategoryValues), - [engineType]: { - ...(existingConfig as ConfigCategoryValues), - ...allConfig, + if (isInvalidClusterSize) { + mockUpdateDatabaseError( + database.id, + database.engine, + 'engine_config.synchronous_replication', + 'synchronous_replication is only supported for clusters with 3 nodes' + ).as('updateAdvancedConfiguration'); + } else { + mockUpdateDatabase(database.id, database.engine, { + ...database, + engine_config: { + ...(database.engine_config as ConfigCategoryValues), + [engineType]: { + ...(existingConfig as ConfigCategoryValues), + ...nestedConfig, + }, + ...topLevelConfig, }, - }, - }).as('updateAdvancedConfiguration'); + }).as('updateAdvancedConfiguration'); + } // Save or Save and Restart Services as per the config added ui.button .findByTitle(saveRestartButton) - .scrollIntoView() - .should('be.visible') + .should('exist') .should('be.enabled') - .click(); + .then((btn) => { + btn[0].click(); + }); cy.wait('@updateAdvancedConfiguration'); - // Confirms newly added advacned Config on the Configuration tab tableview - Object.keys(allConfig).forEach((key) => { - cy.findByText(`${engineType}.${key}`).should('be.visible'); - }); + if (isInvalidClusterSize) { + // Verify error message is displayed for invalid synchronous replication + cy.findByText( + /synchronous_replication is only supported for clusters with 3 nodes/i + ).should('be.visible'); + } else { + // Confirms newly added advanced Config on the Configuration tab tableview + Object.keys(nestedConfig).forEach((key) => { + cy.findByText(`${engineType}.${key}`).should('be.visible'); + }); + Object.keys(topLevelConfig).forEach((key) => { + cy.findByText(`${key}`).should('be.visible'); + }); + } }); /* @@ -469,6 +589,7 @@ describe('Update database clusters', () => { cy.wait(['@getDatabase', '@getDatabaseTypes']); // Expand configure drawer to add configs + ui.cdsButton.findButtonByTitle('Configure').scrollIntoView(); ui.cdsButton .findButtonByTitle('Configure') .should('be.visible') diff --git a/packages/manager/cypress/support/constants/databases.ts b/packages/manager/cypress/support/constants/databases.ts index 048b10e2494..6094ef2e698 100644 --- a/packages/manager/cypress/support/constants/databases.ts +++ b/packages/manager/cypress/support/constants/databases.ts @@ -564,6 +564,16 @@ export const databaseConfigurationsAdvConfig: DatabaseClusterConfiguration[] = [ version: '8', ip: randomIp(), }, + { + clusterSize: 2, + dbType: 'postgresql', + engine: 'PostgreSQL', + label: randomLabel(), + linodeType: 'g6-nanode-1', + region: chooseRegion({ capabilities: ['Managed Databases'] }), + version: '13', + ip: randomIp(), + }, { clusterSize: 3, dbType: 'postgresql', diff --git a/packages/manager/cypress/support/intercepts/databases.ts b/packages/manager/cypress/support/intercepts/databases.ts index 77af59f9fb1..693a636e1d6 100644 --- a/packages/manager/cypress/support/intercepts/databases.ts +++ b/packages/manager/cypress/support/intercepts/databases.ts @@ -240,6 +240,33 @@ export const mockUpdateSuspendResumeDatabase = ( ); }; +/** + * Intercepts PUT request to update database and mocks error with custom field and reason. + * + * @param id - Database ID. + * @param engine - Database engine type. + * @param field - Error field name. + * @param reason - Error reason message. + * + * @returns Cypress chainable. + */ +export const mockUpdateDatabaseError = ( + id: number, + engine: string, + field: string, + reason: string +): Cypress.Chainable => { + const error = makeErrorResponse({ + field, + reason, + }); + return cy.intercept( + 'PUT', + apiMatcher(`databases/${engine}/instances/${id}`), + error + ); +}; + /** * Intercepts POST request to reset an active database's password and mocks response. * diff --git a/packages/manager/src/factories/databases.ts b/packages/manager/src/factories/databases.ts index 6defd0cc837..a22cceee850 100644 --- a/packages/manager/src/factories/databases.ts +++ b/packages/manager/src/factories/databases.ts @@ -412,13 +412,6 @@ export const mysqlConfigResponse = { type: 'boolean', }, }, - service_log: { - description: - 'Store logs for the service so that they are available in the HTTP API and console.', - example: true, - requires_restart: false, - type: ['boolean', 'null'], - }, }; export const postgresConfigResponse = { @@ -493,6 +486,7 @@ export const postgresConfigResponse = { description: 'Synchronous replication type. Note that the service plan also needs to support synchronous replication.', enum: ['quorum', 'off'], + example: 'quorum', requires_restart: false, default: 'off', type: 'string', From 9a6298214ac9e98c11da2703a4d423c7ca6c5cfe Mon Sep 17 00:00:00 2001 From: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:36:58 -0400 Subject: [PATCH 43/56] =?UTF-8?q?upcoming:=20[UIE-9420]=20=E2=80=94=20Impl?= =?UTF-8?q?ement=20new=20Image=20selection=20UI=20on=20the=20Linode=20Crea?= =?UTF-8?q?te=20page=20(#13435)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...r-13435-upcoming-features-1772580889092.md | 5 + .../ImageSelect/ImageSelectTable.tsx | 336 ++++++++++++++++++ .../ImageSelect/ImageSelectTableRow.tsx | 160 +++++++++ .../src/components/ImageSelect/constants.ts | 15 + .../manager/src/features/Images/constants.ts | 3 + .../Linodes/LinodeCreate/Tabs/Images.test.tsx | 67 +++- .../Linodes/LinodeCreate/Tabs/Images.tsx | 35 +- 7 files changed, 611 insertions(+), 10 deletions(-) create mode 100644 packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md create mode 100644 packages/manager/src/components/ImageSelect/ImageSelectTable.tsx create mode 100644 packages/manager/src/components/ImageSelect/ImageSelectTableRow.tsx create mode 100644 packages/manager/src/components/ImageSelect/constants.ts diff --git a/packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md b/packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md new file mode 100644 index 00000000000..105a8c6351a --- /dev/null +++ b/packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add new Image Select table and use it in Linode Create > Images tab ([#13435](https://github.com/linode/manager/pull/13435)) diff --git a/packages/manager/src/components/ImageSelect/ImageSelectTable.tsx b/packages/manager/src/components/ImageSelect/ImageSelectTable.tsx new file mode 100644 index 00000000000..0e27105f5c1 --- /dev/null +++ b/packages/manager/src/components/ImageSelect/ImageSelectTable.tsx @@ -0,0 +1,336 @@ +import { + useAllImagesQuery, + useAllTagsQuery, + useProfile, + useRegionsQuery, +} from '@linode/queries'; +import { getAPIFilterFromQuery } from '@linode/search'; +import { + Autocomplete, + Box, + CircleProgress, + ErrorState, + Hidden, + Notice, + Stack, + TooltipIcon, + useTheme, +} from '@linode/ui'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import { Pagination } from 'akamai-cds-react-components/Pagination'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeaderCell, + TableRow, +} from 'akamai-cds-react-components/Table'; +import React, { useState } from 'react'; + +import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; +import { SHARE_GROUP_COLUMN_HEADER_TOOLTIP } from 'src/features/Images/constants'; +import { usePaginationV2 } from 'src/hooks/usePaginationV2'; + +import { + DEFAULT_CLIENT_SIDE_PAGE_SIZE, + IMAGE_SELECT_TABLE_PREFERENCE_KEY, + TABLE_CELL_BASE_STYLE, +} from './constants'; +import { ImageSelectTableRow } from './ImageSelectTableRow'; + +import type { IMAGE_SELECT_TABLE_PENDO_IDS } from './constants'; +import type { Filter, Image } from '@linode/api-v4'; +import type { LinkProps } from '@tanstack/react-router'; + +interface Props { + /** + * The route this table is rendered on. Used to persist pagination and + * sort state in the URL. + */ + currentRoute: LinkProps['to']; + /** + * Error message to display above the table, e.g. from form validation. + */ + errorText?: string; + /** + * Callback fired when the user selects an image row. + */ + onSelect: (image: Image) => void; + /** + * An object containing Pendo IDs for elements in this component. + */ + pendoIDs: typeof IMAGE_SELECT_TABLE_PENDO_IDS; + /** + * The ID of the currently selected image. + */ + selectedImageId?: null | string; +} + +type OptionType = { label: string; value: string }; + +export const ImageSelectTable = (props: Props) => { + const { currentRoute, errorText, onSelect, pendoIDs, selectedImageId } = + props; + + const theme = useTheme(); + const [query, setQuery] = useState(''); + const [selectedTag, setSelectedTag] = useState(null); + const [selectedRegion, setSelectedRegion] = useState(null); + const matchesSmDown = useMediaQuery(theme.breakpoints.down('md')); + + const { data: profile } = useProfile(); + const { data: tags } = useAllTagsQuery(); + const { data: regions } = useRegionsQuery(); + + const { filter: searchFilter, error: filterError } = getAPIFilterFromQuery( + query, + { + filterShapeOverrides: { + '+contains': { + field: 'region', + filter: (value) => ({ regions: { region: value } }), + }, + '+eq': { + field: 'region', + filter: (value) => ({ regions: { region: value } }), + }, + }, + searchableFieldsWithoutOperator: ['label', 'tags'], + } + ); + + const combinedFilter = buildImageFilter({ + searchFilter, + selectedRegion, + selectedTag, + }); + + const { + data: imagesData, + error: imagesError, + isFetching, + isLoading, + } = useAllImagesQuery( + {}, + { + ...combinedFilter, + is_public: false, + type: 'manual', + } + ); + + const pagination = usePaginationV2({ + clientSidePaginationData: imagesData, + currentRoute, + defaultPageSize: DEFAULT_CLIENT_SIDE_PAGE_SIZE, + initialPage: 1, + preferenceKey: IMAGE_SELECT_TABLE_PREFERENCE_KEY, + }); + + const tagOptions = + tags?.map((tag) => ({ label: tag.label, value: tag.label })) ?? []; + + const regionOptions = + regions?.map((r) => ({ label: r.label, value: r.id })) ?? []; + + const selectedTagOption = + tagOptions.find((t) => t.value === selectedTag) ?? null; + + const selectedRegionOption = + regionOptions.find((r) => r.value === selectedRegion) ?? null; + + const handlePageChange = (event: CustomEvent<{ page: number }>) => { + pagination.handlePageChange(Number(event.detail)); + }; + + const handlePageSizeChange = (event: CustomEvent<{ pageSize: number }>) => { + const newSize = event.detail.pageSize; + pagination.handlePageSizeChange(newSize); + }; + + return ( + + {errorText && } + + + { + setQuery(q); + pagination.handlePageChange(1); + }} + placeholder="Search images" + value={query} + /> + + + { + setSelectedTag((value as null | OptionType)?.value ?? null); + pagination.handlePageChange(1); + }} + options={tagOptions} + placeholder="Filter by tag" + textFieldProps={{ + hideLabel: true, + }} + value={selectedTagOption} + /> + + + { + setSelectedRegion((value as null | OptionType)?.value ?? null); + pagination.handlePageChange(1); + }} + options={regionOptions} + placeholder="Filter by region" + textFieldProps={{ + hideLabel: true, + }} + value={selectedRegionOption} + /> + + + +
+ + + + Image + + + Replicated in + + + + + Share Group + + + + + + + Size + + + + Created + + + Image ID + + + + + {isLoading && } + {imagesError && ( + + )} + {!isLoading && !imagesError && imagesData?.length === 0 && ( + + + No items to display. + + + )} + {!isLoading && + !imagesError && + pagination.paginatedData.map((image) => ( + onSelect(image)} + pendoIDs={pendoIDs} + regions={regions ?? []} + selected={image.id === selectedImageId} + timezone={profile?.timezone} + /> + ))} + +
+ + + + ); +}; + +interface BuildImageFilterParams { + searchFilter: Filter; + selectedRegion: null | string; + selectedTag: null | string; +} + +/** + * Merges the search filter with optional tag and region dropdown filters + * into a single API filter object. + */ +const buildImageFilter = ({ + searchFilter, + selectedRegion, + selectedTag, +}: BuildImageFilterParams) => { + return { + ...searchFilter, + ...(selectedTag ? { tags: { '+contains': selectedTag } } : {}), + ...(selectedRegion ? { regions: { region: selectedRegion } } : {}), + }; +}; diff --git a/packages/manager/src/components/ImageSelect/ImageSelectTableRow.tsx b/packages/manager/src/components/ImageSelect/ImageSelectTableRow.tsx new file mode 100644 index 00000000000..c77f5e7b140 --- /dev/null +++ b/packages/manager/src/components/ImageSelect/ImageSelectTableRow.tsx @@ -0,0 +1,160 @@ +import { + FormControlLabel, + Hidden, + ListItem, + Radio, + TooltipIcon, +} from '@linode/ui'; +import { convertStorageUnit, pluralize } from '@linode/utilities'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import { TableCell, TableRow } from 'akamai-cds-react-components/Table'; +import React from 'react'; + +import CloudInitIcon from 'src/assets/icons/cloud-init.svg'; +import { + PlanTextTooltip, + StyledFormattedRegionList, +} from 'src/features/components/PlansPanel/PlansAvailabilityNotice.styles'; +import { formatDate } from 'src/utilities/formatDate'; + +import { + IMAGE_SELECT_TABLE_PENDO_IDS, + TABLE_CELL_BASE_STYLE, +} from './constants'; + +import type { Image, ImageRegion, Region } from '@linode/api-v4'; +import type { Theme } from '@linode/ui'; + +interface Props { + image: Image; + onSelect: () => void; + pendoIDs: typeof IMAGE_SELECT_TABLE_PENDO_IDS; + regions: Region[]; + selected: boolean; + timezone?: string; +} + +export const ImageSelectTableRow = (props: Props) => { + const { image, onSelect, pendoIDs, regions, selected, timezone } = props; + + const { + capabilities, + created, + id, + image_sharing, + label, + regions: imageRegions, + size, + status, + type, + } = image; + + const matchesLgDown = useMediaQuery((theme: Theme) => + theme.breakpoints.down('lg') + ); + + const getSizeDisplay = () => { + if (status === 'available') { + const sizeInGB = convertStorageUnit('MB', size, 'GB'); + const formatted = Intl.NumberFormat('en-US', { + maximumFractionDigits: 2, + minimumFractionDigits: 0, + }).format(sizeInGB); + return `${formatted} GB`; + } + return 'Pending'; + }; + + const getShareGroupDisplay = () => { + if (image_sharing?.shared_by?.sharegroup_label) { + return image_sharing.shared_by.sharegroup_label; + } + + return '—'; + }; + + const getRegionListItem = (imageRegion: ImageRegion) => { + const matchingRegion = regions.find((r) => r.id === imageRegion.region); + + return matchingRegion + ? `${matchingRegion.label} (${imageRegion.region})` + : imageRegion.region; + }; + + const FormattedRegionList = () => ( + + {imageRegions.map((region: ImageRegion, idx) => { + return ( + + {getRegionListItem(region)} + + ); + })} + + ); + + return ( + + + } + label={label} + onChange={onSelect} + sx={{ gap: 2 }} + /> + {type === 'manual' && capabilities.includes('cloud-init') && ( + } + sxTooltipIcon={{ + padding: 0, + }} + text="This image supports our Metadata service via cloud-init." + /> + )} + + + + 0 + ? pluralize('Region', 'Regions', imageRegions.length) + : '—' + } + tooltipText={} + /> + + + + + {getShareGroupDisplay()} + + + + + {getSizeDisplay()} + + + + {formatDate(created, { timezone })} + + + {id} + + + ); +}; diff --git a/packages/manager/src/components/ImageSelect/constants.ts b/packages/manager/src/components/ImageSelect/constants.ts new file mode 100644 index 00000000000..473fac3ef6b --- /dev/null +++ b/packages/manager/src/components/ImageSelect/constants.ts @@ -0,0 +1,15 @@ +export const TABLE_CELL_BASE_STYLE = { + boxSizing: 'border-box' as const, +}; + +export const IMAGE_SELECT_TABLE_PREFERENCE_KEY = 'image-select-table'; +export const DEFAULT_CLIENT_SIDE_PAGE_SIZE = 10; + +export const IMAGE_SELECT_TABLE_PENDO_IDS = { + searchImagesBar: 'Linodes Create Images-Search click', + tagFilterSelect: 'Linodes Create Images-Filter by Tag click', + regionFilterSelect: 'Linodes Create Images-Filter by Region click', + metadataSupportedIcon: 'Linodes Create Images-Metadata Supported icon', + replicatedRegionPopover: 'Linodes Create Images-Replicated in', + shareGroupInfoIcon: 'Linodes Create Images-Share Group info icon', +}; diff --git a/packages/manager/src/features/Images/constants.ts b/packages/manager/src/features/Images/constants.ts index ac206464950..88ae9abc38a 100644 --- a/packages/manager/src/features/Images/constants.ts +++ b/packages/manager/src/features/Images/constants.ts @@ -6,3 +6,6 @@ export const MANUAL_IMAGES_DEFAULT_ORDER = 'asc'; export const MANUAL_IMAGES_DEFAULT_ORDER_BY = 'label'; export const AUTOMATIC_IMAGES_DEFAULT_ORDER = 'asc'; export const AUTOMATIC_IMAGES_DEFAULT_ORDER_BY = 'label'; + +export const SHARE_GROUP_COLUMN_HEADER_TOOLTIP = + "Displays the share group for images shared with you; your custom images don't display a group name."; diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.test.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.test.tsx index e3d3f068610..569a9f1b4db 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.test.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.test.tsx @@ -1,10 +1,16 @@ import React from 'react'; -import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers'; +import { + renderWithThemeAndHookFormContext, + resizeScreenSize, +} from 'src/utilities/testHelpers'; import { Images } from './Images'; const queryMocks = vi.hoisted(() => ({ + useIsPrivateImageSharingEnabled: vi.fn(() => ({ + isPrivateImageSharingEnabled: false, + })), useNavigate: vi.fn(), useParams: vi.fn(), useSearch: vi.fn(), @@ -29,11 +35,22 @@ vi.mock('src/features/IAM/hooks/usePermissions', () => ({ usePermissions: queryMocks.userPermissions, })); +vi.mock('src/features/Images/utils', async () => { + const actual = await vi.importActual('src/features/Images/utils'); + return { + ...actual, + useIsPrivateImageSharingEnabled: queryMocks.useIsPrivateImageSharingEnabled, + }; +}); + describe('Images', () => { beforeEach(() => { queryMocks.useNavigate.mockReturnValue(vi.fn()); queryMocks.useSearch.mockReturnValue({}); queryMocks.useParams.mockReturnValue({}); + queryMocks.useIsPrivateImageSharingEnabled.mockReturnValue({ + isPrivateImageSharingEnabled: false, + }); }); it('renders a header', () => { @@ -73,4 +90,52 @@ describe('Images', () => { expect(getByPlaceholderText('Choose an image')).toBeVisible(); expect(getByPlaceholderText('Choose an image')).toBeEnabled(); }); + + describe('when isPrivateImageSharingEnabled is true', () => { + beforeEach(() => { + queryMocks.useIsPrivateImageSharingEnabled.mockReturnValue({ + isPrivateImageSharingEnabled: true, + }); + // Mock matchMedia at a width wider than MUI's `lg` breakpoint (1200px) + // so that columns wrapped in are not hidden. + resizeScreenSize(1280); + }); + + it('renders the search images field', () => { + const { getByPlaceholderText } = renderWithThemeAndHookFormContext({ + component: , + }); + + expect(getByPlaceholderText('Search images')).toBeVisible(); + }); + + it('renders the filter by tag field', () => { + const { getByPlaceholderText } = renderWithThemeAndHookFormContext({ + component: , + }); + + expect(getByPlaceholderText('Filter by tag')).toBeVisible(); + }); + + it('renders the filter by region field', () => { + const { getByPlaceholderText } = renderWithThemeAndHookFormContext({ + component: , + }); + + expect(getByPlaceholderText('Filter by region')).toBeVisible(); + }); + + it('renders the table column headers', () => { + const { getByText } = renderWithThemeAndHookFormContext({ + component: , + }); + + expect(getByText('Image')).toBeVisible(); + expect(getByText('Replicated in')).toBeVisible(); + expect(getByText('Share Group')).toBeVisible(); + expect(getByText('Size')).toBeVisible(); + expect(getByText('Created')).toBeVisible(); + expect(getByText('Image ID')).toBeVisible(); + }); + }); }); diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.tsx index 717cdc85696..9c2836f0547 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Tabs/Images.tsx @@ -5,11 +5,14 @@ import React from 'react'; import { useController, useFormContext, useWatch } from 'react-hook-form'; import ComputeIcon from 'src/assets/icons/entityIcons/compute.svg'; +import { IMAGE_SELECT_TABLE_PENDO_IDS } from 'src/components/ImageSelect/constants'; import { ImageSelect } from 'src/components/ImageSelect/ImageSelect'; +import { ImageSelectTable } from 'src/components/ImageSelect/ImageSelectTable'; import { getAPIFilterForImageSelect } from 'src/components/ImageSelect/utilities'; import { Link } from 'src/components/Link'; import { Placeholder } from 'src/components/Placeholder/Placeholder'; import { usePermissions } from 'src/features/IAM/hooks/usePermissions'; +import { useIsPrivateImageSharingEnabled } from 'src/features/Images/utils'; import { Region } from '../Region'; import { getGeneratedLinodeLabel } from '../utilities'; @@ -26,10 +29,12 @@ export const Images = () => { getValues, setValue, } = useFormContext(); + const { field, fieldState } = useController({ control, name: 'image', }); + const queryClient = useQueryClient(); const { data: permissions } = usePermissions('account', ['create_linode']); @@ -40,6 +45,8 @@ export const Images = () => { const selectedRegion = regions?.find((r) => r.id === regionId); + const { isPrivateImageSharingEnabled } = useIsPrivateImageSharingEnabled(); + const onChange = async (image: Image | null) => { field.onChange(image?.id ?? null); @@ -88,17 +95,27 @@ export const Images = () => { Choose an Image - - - + ) : ( + + + + )} ); From b1c1b74e4c025d34179639511d1a56bcf5bbff7f Mon Sep 17 00:00:00 2001 From: Alban Bailly <130582365+abailly-akamai@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:22:17 +0100 Subject: [PATCH 44/56] feat: [UIE-10361] - Improve UpdateDelegateDrawer & EntitiesSelect UI (#13468) * Update Delegation UI * Entities * test * Added changeset: Improve UpdateDelegateDrawer & EntitiesSelect UI * Address feedback + copy changes * test fix * e2e small fix --- .../pr-13468-changed-1772720184107.md | 5 + .../features/Account/SwitchAccountDrawer.tsx | 1 + .../IAM/Delegations/UpdateDelegationForm.tsx | 149 ++++++++++++++---- .../RolesTable/AssignSelectedRolesDrawer.tsx | 2 +- .../UpdateEntitiesDrawer.test.tsx | 4 + .../IAM/Shared/Entities/EntitiesSelect.tsx | 116 +++++++++----- .../IAM/Shared/Entities/utils.test.ts | 11 +- .../src/features/IAM/Shared/Entities/utils.ts | 18 +-- 8 files changed, 227 insertions(+), 79 deletions(-) create mode 100644 packages/manager/.changeset/pr-13468-changed-1772720184107.md diff --git a/packages/manager/.changeset/pr-13468-changed-1772720184107.md b/packages/manager/.changeset/pr-13468-changed-1772720184107.md new file mode 100644 index 00000000000..4f6cad9389f --- /dev/null +++ b/packages/manager/.changeset/pr-13468-changed-1772720184107.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Improve UpdateDelegateDrawer & EntitiesSelect UI ([#13468](https://github.com/linode/manager/pull/13468)) diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index 0f914e25e6e..f8df9fa34fe 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -230,6 +230,7 @@ export const SwitchAccountDrawer = (props: Props) => { )} {childAccounts && childAccounts.length === 0 && + isIAMDelegationEnabled && !Object.prototype.hasOwnProperty.call(filter, 'company') ? ( diff --git a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx index a5d6b9c347b..e5b0120c081 100644 --- a/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx +++ b/packages/manager/src/features/IAM/Delegations/UpdateDelegationForm.tsx @@ -3,7 +3,16 @@ import { useAllAccountUsersQuery, useUpdateChildAccountDelegatesQuery, } from '@linode/queries'; -import { ActionsPanel, Autocomplete, Notice, Typography } from '@linode/ui'; +import { + ActionsPanel, + Autocomplete, + CloseIcon, + IconButton, + Notice, + Paper, + Stack, + Typography, +} from '@linode/ui'; import { useDebouncedValue } from '@linode/utilities'; import { useTheme } from '@mui/material'; import { enqueueSnackbar } from 'notistack'; @@ -57,6 +66,8 @@ export const UpdateDelegationForm = ({ const { data, error, fetchNextPage, hasNextPage, isFetching } = useAccountUsersInfiniteQuery(apiFilter); + const totalUserCount = data?.pages[0]?.results ?? 0; + const { data: allUsers, isFetching: isFetchingAllUsers, @@ -65,26 +76,6 @@ export const UpdateDelegationForm = ({ user_type: 'parent', }); - const users = - allUserSelected && allUsers - ? allUsers.map((user) => ({ - label: user.username, - value: user.username, - })) - : (data?.pages.flatMap((page) => { - return page.data.map((user) => ({ - label: user.username, - value: user.username, - })); - }) ?? []); - - const isSearching = - inputValue.length > 0 && debouncedInputValue !== inputValue; - - const isLoadingOptions = isFetching || isFetchingAllUsers; - - const showNoOptionsText = !isLoadingOptions && !isSearching; - const isSelectAllFetching = allUserSelected && isFetchingAllUsers; const { mutateAsync: updateDelegates } = @@ -103,8 +94,35 @@ export const UpdateDelegationForm = ({ reset, setError, setValue, + watch, } = form; + const selectedUsers = watch('users'); + + const users = + allUserSelected && allUsers + ? allUsers.map((user) => ({ + label: user.username, + value: user.username, + })) + : !inputValue && + totalUserCount > 0 && + selectedUsers.length >= totalUserCount + ? selectedUsers + : (data?.pages.flatMap((page) => { + return page.data.map((user) => ({ + label: user.username, + value: user.username, + })); + }) ?? []); + + const isSearching = + inputValue.length > 0 && debouncedInputValue !== inputValue; + + const isLoadingOptions = isFetching || isFetchingAllUsers; + + const showNoOptionsText = !isLoadingOptions && !isSearching; + const onSubmit = async (values: UpdateDelegationsFormValues) => { const usersList = values.users.map((user) => user.value); @@ -171,8 +189,11 @@ export const UpdateDelegationForm = ({ name="users" render={({ field, fieldState }) => ( option.value === value.value @@ -188,17 +209,19 @@ export const UpdateDelegationForm = ({ onInputChange={(_, value) => { setInputValue(value); }} - onSelectAllClick={(isSelectAllActive) => { - if (isSelectAllActive && !allUserSelected) { + onSelectAllClick={(_event) => { + const allCurrentOptionsSelected = + totalUserCount > 0 && + selectedUsers.length >= totalUserCount; + if (allCurrentOptionsSelected) { + setValue('users', []); + setAllUserSelected(false); + } else { onSelectAllClick(); } }} options={users} - placeholder={getPlaceholder( - 'delegates', - field.value.length, - users?.length ?? 0 - )} + renderTags={() => null} slotProps={{ listbox: { onScroll: (event: React.SyntheticEvent) => { @@ -221,11 +244,53 @@ export const UpdateDelegationForm = ({ InputProps: isSelectAllFetching ? { startAdornment: null } : undefined, + placeholder: getPlaceholder( + 'delegates', + selectedUsers.length, + totalUserCount + ), }} value={field.value} /> )} /> + + Users in the account delegation + {isFetchingAllUsers ? '' : ` (${selectedUsers.length})`}: + + ({ + backgroundColor: isFetchingAllUsers + ? theme.tokens.alias.Interaction.Background.Disabled + : theme.palette.background.paper, + maxHeight: 370, + overflowY: 'auto', + p: 2, + py: 1, + })} + variant="outlined" + > + + {selectedUsers.length === 0 && ( + + No users selected + + )} + {selectedUsers.map((user) => ( + + setValue( + 'users', + selectedUsers.filter((u) => u.value !== user.value) + ) + } + username={user.label} + /> + ))} + + ); }; + +interface DelegationUserRowProps { + isSubmitting: boolean; + onRemove: () => void; + username: string; +} + +const DelegationUserRow = ({ + onRemove, + username, + isSubmitting, +}: DelegationUserRowProps) => { + return ( + + {username} + + + + + ); +}; diff --git a/packages/manager/src/features/IAM/Roles/RolesTable/AssignSelectedRolesDrawer.tsx b/packages/manager/src/features/IAM/Roles/RolesTable/AssignSelectedRolesDrawer.tsx index 2e593f8a0fd..83b70dbbc67 100644 --- a/packages/manager/src/features/IAM/Roles/RolesTable/AssignSelectedRolesDrawer.tsx +++ b/packages/manager/src/features/IAM/Roles/RolesTable/AssignSelectedRolesDrawer.tsx @@ -167,7 +167,7 @@ export const AssignSelectedRolesDrawer = ({ 1 ? `s` : ``} to Users`} + title={`Assign Selected Role${selectedRoles.length > 1 ? `s` : ``} to a User`} >
diff --git a/packages/manager/src/features/IAM/Shared/AssignedRolesTable/UpdateEntitiesDrawer.test.tsx b/packages/manager/src/features/IAM/Shared/AssignedRolesTable/UpdateEntitiesDrawer.test.tsx index ecbcf169880..f158474ee2f 100644 --- a/packages/manager/src/features/IAM/Shared/AssignedRolesTable/UpdateEntitiesDrawer.test.tsx +++ b/packages/manager/src/features/IAM/Shared/AssignedRolesTable/UpdateEntitiesDrawer.test.tsx @@ -105,6 +105,10 @@ describe('UpdateEntitiesDrawer', () => { }); it('should prefill the form with assigned entities', async () => { + queryMocks.useAllAccountEntities.mockReturnValue({ + data: mockEntities, + isLoading: false, + }); renderWithTheme(); // Verify the prefilled entities diff --git a/packages/manager/src/features/IAM/Shared/Entities/EntitiesSelect.tsx b/packages/manager/src/features/IAM/Shared/Entities/EntitiesSelect.tsx index e1e477892ed..f2bf5ba4f28 100644 --- a/packages/manager/src/features/IAM/Shared/Entities/EntitiesSelect.tsx +++ b/packages/manager/src/features/IAM/Shared/Entities/EntitiesSelect.tsx @@ -1,4 +1,12 @@ -import { Autocomplete, Notice, TextField, Typography } from '@linode/ui'; +import { + Autocomplete, + CloseIcon, + IconButton, + Notice, + Paper, + Stack, + Typography, +} from '@linode/ui'; import { useTheme } from '@mui/material'; import React from 'react'; @@ -101,7 +109,9 @@ export const EntitiesSelect = ({ return ( <> option.label} isOptionEqualToValue={(option, value) => option.value === value.value} label="Entities" @@ -123,26 +133,8 @@ export const EntitiesSelect = ({ setInputValue(value); }} options={visibleOptions} - placeholder={getPlaceholder( - type, - value.length, - filteredEntities.length - )} readOnly={mode === 'change-role'} - renderInput={(params) => ( - - )} + renderTags={() => null} slotProps={{ listbox: { onScroll: (e) => { @@ -155,26 +147,53 @@ export const EntitiesSelect = ({ }, }, }} - sx={{ - marginTop: 0, - '& .MuiChip-root': { - padding: theme.tokens.spacing.S4, - height: 'auto', - }, - '& .MuiInputLabel-root': { - color: theme.tokens.alias.Content.Text.Primary.Default, - }, - '& .MuiChip-labelMedium': { - textWrap: 'auto', - height: 'auto', - }, - '& .MuiAutocomplete-tag': { - wordBreak: 'break-all', - }, + textFieldProps={{ + placeholder: getPlaceholder( + type, + value.length, + filteredEntities.length + ), }} value={value || []} /> - {!memoizedEntities.length && ( + {memoizedEntities.length > 0 && !isLoading && ( + <> + + Selected entities ({value.length}): + + ({ + backgroundColor: isLoading + ? theme.tokens.alias.Interaction.Background.Disabled + : theme.palette.background.paper, + maxHeight: 370, + overflowY: 'auto', + p: 2, + py: 1, + })} + variant="outlined" + > + + {value.length === 0 && ( + + No entities selected + + )} + {value.map((entity) => ( + + onChange(value.filter((v) => v.value !== entity.value)) + } + /> + ))} + + + + )} + {!memoizedEntities.length && !isLoading && ( @@ -188,3 +207,26 @@ export const EntitiesSelect = ({ ); }; + +interface EntityRowProps { + disabled?: boolean; + label: string; + onRemove: () => void; +} + +const EntityRow = ({ disabled, label, onRemove }: EntityRowProps) => { + return ( + + {label} + {!disabled && ( + + + + )} + + ); +}; diff --git a/packages/manager/src/features/IAM/Shared/Entities/utils.test.ts b/packages/manager/src/features/IAM/Shared/Entities/utils.test.ts index e620f21bf65..261b655d19b 100644 --- a/packages/manager/src/features/IAM/Shared/Entities/utils.test.ts +++ b/packages/manager/src/features/IAM/Shared/Entities/utils.test.ts @@ -20,17 +20,22 @@ describe('getCreateLinkForEntityType', () => { }); describe('getPlaceholder', () => { - it('should return a space if currentValueLength is greater than 0', () => { - expect(getPlaceholder('linode', 1, 10)).toBe(' '); + it('should return the placeholder from placeholderMap if some but not all items are selected', () => { + expect(getPlaceholder('linode', 1, 10)).toBe(placeholderMap['linode']); }); it('should return "None" if possibleEntitiesLength is 0', () => { expect(getPlaceholder('linode', 0, 0)).toBe('None'); }); - it('should return the placeholder from placeholderMap if type exists', () => { + it('should return the placeholder from placeholderMap if type exists and nothing is selected', () => { expect(getPlaceholder('linode', 0, 10)).toBe(placeholderMap['linode']); }); + + it('should return "All X selected" when all items are selected', () => { + expect(getPlaceholder('linode', 10, 10)).toBe('All Linodes selected'); + expect(getPlaceholder('delegates', 5, 5)).toBe('All users selected'); + }); }); describe('getEntitiesByType', () => { diff --git a/packages/manager/src/features/IAM/Shared/Entities/utils.ts b/packages/manager/src/features/IAM/Shared/Entities/utils.ts index aab965e3fd6..c3d6ee86d4f 100644 --- a/packages/manager/src/features/IAM/Shared/Entities/utils.ts +++ b/packages/manager/src/features/IAM/Shared/Entities/utils.ts @@ -19,7 +19,7 @@ export const placeholderMap: Record = { stackscript: 'Select Stackscripts', volume: 'Select Volumes', vpc: 'Select VPCs', - delegates: 'Select Users', + delegates: 'Select users', }; export const getCreateLinkForEntityType = (entityType: AccessType): string => { @@ -41,17 +41,17 @@ export const getPlaceholder = ( currentValueLength: number, possibleEntitiesLength: number ): string => { - let placeholder: string; + if (possibleEntitiesLength === 0) { + return 'None'; + } - if (currentValueLength > 0) { - placeholder = ' '; - } else if (possibleEntitiesLength === 0) { - placeholder = 'None'; - } else { - placeholder = placeholderMap[type] || 'Select'; + if (currentValueLength > 0 && currentValueLength >= possibleEntitiesLength) { + const label = placeholderMap[type] || type; + const subject = label.startsWith('Select ') ? label.slice(7) : label; + return `All ${subject} selected`; } - return placeholder; + return placeholderMap[type] || 'Select'; }; export const mapEntitiesToOptions = ( From 9f8f7be245cb39b6807e08ea25f80182f3ec3e85 Mon Sep 17 00:00:00 2001 From: Dmytro Chyrva Date: Tue, 10 Mar 2026 09:36:02 +0100 Subject: [PATCH 45/56] new: STORIF-294 - Condition for showing Bucket Metrcis tab updated. (#13456) * new: STORIF-294 - Condition for showing Bucket Metrcis tab updated. * Added changeset: New condition for displaying bucket metrics tab --- .../pr-13456-added-1772643395780.md | 5 +++ .../ObjectStorage/BucketDetail/index.tsx | 32 ++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 packages/manager/.changeset/pr-13456-added-1772643395780.md diff --git a/packages/manager/.changeset/pr-13456-added-1772643395780.md b/packages/manager/.changeset/pr-13456-added-1772643395780.md new file mode 100644 index 00000000000..da7d049be31 --- /dev/null +++ b/packages/manager/.changeset/pr-13456-added-1772643395780.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Added +--- + +New condition for displaying bucket metrics tab ([#13456](https://github.com/linode/manager/pull/13456)) diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx index 7320121a1ed..3fead4de35e 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx @@ -1,3 +1,4 @@ +import { useRegionQuery } from '@linode/queries'; import { BetaChip, CircleProgress, ErrorState } from '@linode/ui'; import { useParams } from '@tanstack/react-router'; import * as React from 'react'; @@ -40,6 +41,7 @@ const BucketMetrics = React.lazy(() => const BUCKET_DETAILS_URL = '/object-storage/buckets/$clusterId/$bucketName'; const ENDPOINT_TYPES_WITH_NO_METRICS_SUPPORT = ['E0', 'E1']; +const OBJECT_STORAGE_METRICS_KEY = 'Object Storage'; export const BucketDetailLanding = React.memo(() => { const { bucketName, clusterId } = useParams({ @@ -52,17 +54,36 @@ export const BucketDetailLanding = React.memo(() => { const { data: bucketsData, - isLoading, + isLoading: bucketsLoading, error, isPending, } = useObjectStorageBuckets(); const bucket = bucketsData?.buckets.find(({ label }) => label === bucketName); + const { + data: region, + isLoading: regionLoading, + error: regionError, + } = useRegionQuery(bucket?.region || ''); + const { endpoint_type } = bucket ?? {}; const isGen2Endpoint = endpoint_type === 'E2' || endpoint_type === 'E3'; + const regionSupportsMetrics = region?.monitors?.metrics?.includes( + OBJECT_STORAGE_METRICS_KEY + ); + + const isBucketMetricsTabHidden = + !endpoint_type || + ENDPOINT_TYPES_WITH_NO_METRICS_SUPPORT.includes(endpoint_type) || + aclpServiceError || + !aclpServices?.objectstorage?.metrics?.enabled || + !objectStorageContextualMetrics || + !regionSupportsMetrics || + !!regionError; + const { handleTabChange, tabIndex, tabs, getTabIndex } = useTabs([ { title: 'Objects', @@ -80,17 +101,12 @@ export const BucketDetailLanding = React.memo(() => { { title: 'Metrics', to: `${BUCKET_DETAILS_URL}/metrics`, - hide: - !endpoint_type || - ENDPOINT_TYPES_WITH_NO_METRICS_SUPPORT.includes(endpoint_type) || - aclpServiceError || - !aclpServices?.objectstorage?.metrics?.enabled || - !objectStorageContextualMetrics, + hide: isBucketMetricsTabHidden, chip: aclpServices?.objectstorage?.metrics?.beta ? : null, }, ]); - if (isPending || isLoading || aclServiceLoading) { + if (isPending || bucketsLoading || regionLoading || aclServiceLoading) { return ; } From 420685e2d41d88b35a2c537b95da4e3479a08842 Mon Sep 17 00:00:00 2001 From: mduda-akamai Date: Tue, 10 Mar 2026 10:02:00 +0100 Subject: [PATCH 46/56] change: [DPS-36773] - Improvements for bucket selection in Akamai Object Storage form (#13444) Co-authored-by: dmcintyr-akamai --- .../pr-13444-changed-1772188843247.md | 5 + .../core/delivery/create-destination.spec.ts | 66 ++++++- .../core/delivery/edit-destination.spec.ts | 51 +++++ .../support/ui/pages/logs-destination-form.ts | 34 +++- .../DestinationCreate.test.tsx | 171 +++++++++++++++- .../DestinationForm/DestinationEdit.test.tsx | 160 ++++++++++++++- ...tinationAkamaiObjectStorageDetailsForm.tsx | 177 ++++++++++++++--- .../Delivery/StreamFormDelivery.test.tsx | 183 +++++++++++++++++- .../Streams/StreamForm/StreamCreate.test.tsx | 10 +- .../Streams/StreamForm/StreamEdit.test.tsx | 11 +- 10 files changed, 810 insertions(+), 58 deletions(-) create mode 100644 packages/manager/.changeset/pr-13444-changed-1772188843247.md diff --git a/packages/manager/.changeset/pr-13444-changed-1772188843247.md b/packages/manager/.changeset/pr-13444-changed-1772188843247.md new file mode 100644 index 00000000000..8a0e84deaef --- /dev/null +++ b/packages/manager/.changeset/pr-13444-changed-1772188843247.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Improvements for bucket selection in Akamai Object Storage Destination form ([#13444](https://github.com/linode/manager/pull/13444)) diff --git a/packages/manager/cypress/e2e/core/delivery/create-destination.spec.ts b/packages/manager/cypress/e2e/core/delivery/create-destination.spec.ts index 0418ab542b0..c7c257790ad 100644 --- a/packages/manager/cypress/e2e/core/delivery/create-destination.spec.ts +++ b/packages/manager/cypress/e2e/core/delivery/create-destination.spec.ts @@ -8,9 +8,12 @@ import { mockTestConnection, } from 'support/intercepts/delivery'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetBuckets } from 'support/intercepts/object-storage'; import { ui } from 'support/ui'; import { logsDestinationForm } from 'support/ui/pages/logs-destination-form'; +import { objectStorageBucketFactory } from 'src/factories'; + import type { AkamaiObjectStorageDetailsExtended } from '@linode/api-v4'; describe('Create Destination', () => { @@ -22,11 +25,10 @@ describe('Create Destination', () => { bypassAccountCapabilities: true, }, }); + cy.visitWithLogin('/logs/delivery/destinations/create'); }); it('create destination with form', () => { - cy.visitWithLogin('/logs/delivery/destinations/create'); - // Give Destination a label logsDestinationForm.setLabel(mockDestinationPayload.label); @@ -100,4 +102,64 @@ describe('Create Destination', () => { cy.findByText(mockDestination.label).should('be.visible'); }); }); + + describe('Bucket end Endpoint fields', () => { + it('populates Bucket and Endpoint when selecting an existing bucket and manually entering data', () => { + mockGetBuckets([ + objectStorageBucketFactory.build({ + hostname: 'bucket-hostname.us-east-1.linodeobjects.com', + label: 'bucket-with-hostname', + region: 'us-east', + }), + objectStorageBucketFactory.build({ + hostname: 'bucket-s3.eu-central-1.linodeobjects.com', + label: 'bucket-with-s3-endpoint', + region: 'eu-central', + s3_endpoint: 'eu-central-1.linodeobjects.com', + }), + ]); + + // Default radio should be "Select Bucket associated with the account" + cy.findByLabelText('Select Bucket associated with the account').should( + 'be.checked' + ); + + // Endpoint should be disabled in bucket_from_account mode + cy.findByLabelText('Endpoint').should('be.disabled'); + + // Select a bucket without s3_endpoint - should use hostname as Endpoint + logsDestinationForm.selectBucketFromDropdown('bucket-with-hostname'); + cy.findByLabelText('Bucket').should('have.value', 'bucket-with-hostname'); + cy.findByLabelText('Endpoint').should( + 'have.value', + 'bucket-hostname.us-east-1.linodeobjects.com' + ); + + // Select a bucket with s3_endpoint - should use s3_endpoint as Endpoint + logsDestinationForm.selectBucketFromDropdown('bucket-with-s3-endpoint'); + cy.findByLabelText('Bucket').should( + 'have.value', + 'bucket-with-s3-endpoint' + ); + cy.findByLabelText('Endpoint').should( + 'have.value', + 'eu-central-1.linodeobjects.com' + ); + + // Switch to manual mode and fill in values + cy.findByLabelText('Enter Bucket manually').click(); + logsDestinationForm.setBucket('my-manual-bucket'); + logsDestinationForm.setEndpoint('my-endpoint.com'); + + cy.findByLabelText('Bucket').should('have.value', 'my-manual-bucket'); + cy.findByLabelText('Endpoint').should('have.value', 'my-endpoint.com'); + + // Switch back to bucket_from_account + cy.findByLabelText('Select Bucket associated with the account').click(); + + // Both fields should be cleared + cy.findByLabelText('Bucket').should('have.value', ''); + cy.findByLabelText('Endpoint').should('have.value', ''); + }); + }); }); diff --git a/packages/manager/cypress/e2e/core/delivery/edit-destination.spec.ts b/packages/manager/cypress/e2e/core/delivery/edit-destination.spec.ts index 9ae689d23b5..0042fef60c4 100644 --- a/packages/manager/cypress/e2e/core/delivery/edit-destination.spec.ts +++ b/packages/manager/cypress/e2e/core/delivery/edit-destination.spec.ts @@ -10,10 +10,12 @@ import { mockUpdateDestination, } from 'support/intercepts/delivery'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetBuckets } from 'support/intercepts/object-storage'; import { ui } from 'support/ui'; import { logsDestinationForm } from 'support/ui/pages/logs-destination-form'; import { randomLabel } from 'support/util/random'; +import { objectStorageBucketFactory } from 'src/factories'; import { getDestinationTypeOption } from 'src/features/Delivery/deliveryUtils'; import type { AkamaiObjectStorageDetailsExtended } from '@linode/api-v4'; @@ -120,4 +122,53 @@ describe('Edit Destination', () => { cy.findByText(newLabel).should('be.visible'); }); }); + + describe('Bucket end Endpoint fields', () => { + it('populates Bucket and Endpoint when selecting an existing bucket and manually entering data', () => { + mockGetBuckets([ + objectStorageBucketFactory.build({ + hostname: 'bucket-hostname.us-east-1.linodeobjects.com', + label: 'bucket-with-hostname', + region: 'us-east', + }), + objectStorageBucketFactory.build({ + hostname: 'bucket-s3.eu-central-1.linodeobjects.com', + label: 'bucket-with-s3-endpoint', + region: 'eu-central', + s3_endpoint: 'eu-central-1.linodeobjects.com', + }), + ]); + + // Edit mode defaults to manual bucket entry + cy.findByLabelText('Enter Bucket manually').should('be.checked'); + + // Endpoint should be enabled in manual mode + cy.findByLabelText('Endpoint').should('be.enabled'); + + // Switch to bucket_from_account - Bucket and Endpoint should be cleared + cy.findByLabelText('Select Bucket associated with the account').click(); + cy.findByLabelText('Bucket').should('have.value', ''); + cy.findByLabelText('Endpoint').should('have.value', ''); + cy.findByLabelText('Endpoint').should('be.disabled'); + + // Select a bucket without s3_endpoint - should use hostname as Endpoint + logsDestinationForm.selectBucketFromDropdown('bucket-with-hostname'); + cy.findByLabelText('Bucket').should('have.value', 'bucket-with-hostname'); + cy.findByLabelText('Endpoint').should( + 'have.value', + 'bucket-hostname.us-east-1.linodeobjects.com' + ); + + // Select a bucket with s3_endpoint - should use s3_endpoint + logsDestinationForm.selectBucketFromDropdown('bucket-with-s3-endpoint'); + cy.findByLabelText('Bucket').should( + 'have.value', + 'bucket-with-s3-endpoint' + ); + cy.findByLabelText('Endpoint').should( + 'have.value', + 'eu-central-1.linodeobjects.com' + ); + }); + }); }); diff --git a/packages/manager/cypress/support/ui/pages/logs-destination-form.ts b/packages/manager/cypress/support/ui/pages/logs-destination-form.ts index e129c119e41..12e9bc35fdf 100644 --- a/packages/manager/cypress/support/ui/pages/logs-destination-form.ts +++ b/packages/manager/cypress/support/ui/pages/logs-destination-form.ts @@ -4,6 +4,8 @@ * Create/Edit Stream Page */ +import { ui } from 'support/ui'; + import type { AkamaiObjectStorageDetailsExtended } from '@linode/api-v4'; export const logsDestinationForm = { @@ -21,17 +23,30 @@ export const logsDestinationForm = { }, /** - * Sets destination's host + * Selects a bucket from the "Select Bucket associated with the account" Autocomplete dropdown + * + * @param bucketLabel - bucket label to select from the dropdown + */ + selectBucketFromDropdown: (bucketLabel: string) => { + cy.findByLabelText('Bucket') + .should('be.visible') + .should('be.enabled') + .click(); + ui.autocompletePopper.findByTitle(bucketLabel).should('be.visible').click(); + }, + + /** + * Sets destination's endpoint * - * @param host - destination host to set + * @param endpoint - destination endpoint to set */ - setHost: (host: string) => { - cy.findByLabelText('Host') + setEndpoint: (endpoint: string) => { + cy.findByLabelText('Endpoint') .should('be.visible') .should('be.enabled') - .should('have.attr', 'placeholder', 'Host for the destination') + .should('have.attr', 'placeholder', 'Endpoint for the destination') .clear(); - cy.focused().type(host); + cy.focused().type(endpoint); }, /** @@ -79,12 +94,15 @@ export const logsDestinationForm = { * @param data - object with destination details of AkamaiObjectStorageDetails type */ fillDestinationDetailsForm: (data: AkamaiObjectStorageDetailsExtended) => { - // Give Destination a host - logsDestinationForm.setHost(data.host); + // Switch to manual bucket entry + cy.findByLabelText('Enter Bucket manually').click(); // Give Destination a bucket logsDestinationForm.setBucket(data.bucket_name); + // Give Destination an endpoint + logsDestinationForm.setEndpoint(data.host); + // Give the Destination Access Key ID logsDestinationForm.setAccessKeyId(data.access_key_id); diff --git a/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationCreate.test.tsx b/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationCreate.test.tsx index 8bfd950652b..0082a289411 100644 --- a/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationCreate.test.tsx +++ b/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationCreate.test.tsx @@ -5,7 +5,7 @@ import userEvent from '@testing-library/user-event'; import React from 'react'; import { describe, expect, it, vi } from 'vitest'; -import { accountFactory } from 'src/factories'; +import { accountFactory, objectStorageBucketFactory } from 'src/factories'; import { http, HttpResponse, server } from 'src/mocks/testServer'; import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers'; @@ -14,11 +14,49 @@ import { DestinationCreate } from './DestinationCreate'; import type { CreateDestinationPayload } from '@linode/api-v4'; import type { Flags } from 'src/featureFlags'; +const mockBuckets = [ + objectStorageBucketFactory.build({ + hostname: 'bucket-with-hostname.us-east-1.linodeobjects.com', + label: 'bucket-with-hostname', + region: 'us-east', + }), + objectStorageBucketFactory.build({ + hostname: 'bucket-with-s3-endpoint.eu-central-1.linodeobjects.com', + label: 'bucket-with-s3-endpoint', + region: 'eu-central', + s3_endpoint: 'eu-central-1.linodeobjects.com', + }), +]; + +const queryMocks = vi.hoisted(() => ({ + useObjectStorageBuckets: vi.fn().mockReturnValue({ + data: undefined, + error: null, + isPending: true, + }), +})); + +vi.mock('src/queries/object-storage/queries', async () => { + const actual = await vi.importActual('src/queries/object-storage/queries'); + return { + ...actual, + useObjectStorageBuckets: queryMocks.useObjectStorageBuckets, + }; +}); + const testConnectionButtonText = 'Test Connection'; const createDestinationButtonText = 'Create Destination'; const addCustomHeaderButtonText = 'Add Custom Header'; describe('DestinationCreate', () => { + beforeEach(() => { + queryMocks.useObjectStorageBuckets.mockReturnValue({ + data: { buckets: mockBuckets }, + error: null, + isPending: false, + }); + }); + const renderDestinationCreate = ( flags: Partial, defaultValues?: Partial @@ -64,18 +102,31 @@ describe('DestinationCreate', () => { expect(destinationNameInput).toHaveValue('Test Destination'); }); - it('should render Host input and allow to type text', async () => { + it('should render Endpoint input as disabled in bucket_from_account mode', () => { renderDestinationCreate(flags); - const hostInput = screen.getByLabelText('Host'); - await userEvent.type(hostInput, 'test-host.com'); + const endpointInput = screen.getByLabelText('Endpoint'); + expect(endpointInput).toBeDisabled(); + }); - expect(hostInput).toHaveValue('test-host.com'); + it('should render Endpoint input and allow to type text in manual mode', async () => { + renderDestinationCreate(flags); + + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const endpointInput = screen.getByLabelText('Endpoint'); + await userEvent.type(endpointInput, 'test-host.com'); + + expect(endpointInput).toHaveValue('test-host.com'); }); - it('should render Bucket input and allow to type text', async () => { + it('should render Bucket input and allow to type text in manual mode', async () => { renderDestinationCreate(flags); + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + const bucketInput = screen.getByLabelText('Bucket'); await userEvent.type(bucketInput, 'test-bucket'); @@ -155,13 +206,117 @@ describe('DestinationCreate', () => { ); }); + describe('Bucket selection behavior', () => { + it('should default to "Select Bucket associated with the account" radio in create mode', () => { + renderDestinationCreate(flags); + + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + expect(bucketFromAccountRadio).toBeChecked(); + }); + + it('should disable the Endpoint field when "Select Bucket associated with the account" is selected', () => { + renderDestinationCreate(flags); + + const endpointInput = screen.getByLabelText('Endpoint'); + expect(endpointInput).toBeDisabled(); + }); + + it('should enable the Endpoint field when "Enter Bucket manually" is selected', async () => { + renderDestinationCreate(flags); + + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const endpointInput = screen.getByLabelText('Endpoint'); + expect(endpointInput).toBeEnabled(); + }); + + it('should clear Bucket and Endpoint when switching to "Select Bucket associated with the account"', async () => { + renderDestinationCreate(flags); + + // Switch to manual mode and fill in values + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const bucketInput = screen.getByLabelText('Bucket'); + await userEvent.type(bucketInput, 'my-manual-bucket'); + expect(bucketInput).toHaveValue('my-manual-bucket'); + + const endpointInput = screen.getByLabelText('Endpoint'); + await userEvent.type(endpointInput, 'my-endpoint.com'); + expect(endpointInput).toHaveValue('my-endpoint.com'); + + // Switch back to bucket_from_account + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + await userEvent.click(bucketFromAccountRadio); + + // Both fields should be cleared + const bucketAutocomplete = screen.getByLabelText('Bucket'); + expect(bucketAutocomplete).toHaveValue(''); + expect(screen.getByLabelText('Endpoint')).toHaveValue(''); + }); + + it('should set Bucket and Endpoint from hostname when selecting a bucket without s3_endpoint', async () => { + renderDestinationCreate(flags); + + // Open the Bucket Autocomplete and select a bucket with only hostname + const bucketAutocomplete = screen.getByLabelText('Bucket'); + await userEvent.click(bucketAutocomplete); + + const bucketOption = await screen.findByText('bucket-with-hostname'); + await userEvent.click(bucketOption); + + // Bucket should display the selected bucket label + await waitFor(() => { + expect(bucketAutocomplete).toHaveValue('bucket-with-hostname'); + }); + + // Endpoint should be auto-filled with the bucket's hostname + expect(screen.getByLabelText('Endpoint')).toHaveValue( + 'bucket-with-hostname.us-east-1.linodeobjects.com' + ); + }); + + it('should set Bucket and Endpoint from s3_endpoint when selecting a bucket with s3_endpoint', async () => { + renderDestinationCreate(flags); + + // Open the Bucket Autocomplete and select a bucket with s3_endpoint + const bucketAutocomplete = screen.getByLabelText('Bucket'); + await userEvent.click(bucketAutocomplete); + + const bucketOption = await screen.findByText( + 'bucket-with-s3-endpoint' + ); + await userEvent.click(bucketOption); + + // Bucket should display the selected bucket label + await waitFor(() => { + expect(bucketAutocomplete).toHaveValue('bucket-with-s3-endpoint'); + }); + + // Endpoint should be auto-filled with the bucket's s3_endpoint (takes priority over hostname) + expect(screen.getByLabelText('Endpoint')).toHaveValue( + 'eu-central-1.linodeobjects.com' + ); + }); + }); + describe('given Test Connection and Create Destination buttons', () => { const fillOutAkamaiObjectStorageForm = async () => { const destinationNameInput = screen.getByLabelText('Destination Name'); await userEvent.type(destinationNameInput, 'Test'); - const hostInput = screen.getByLabelText('Host'); - await userEvent.type(hostInput, 'test'); + + // Switch to manual bucket entry to allow typing + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const endpointInput = screen.getByLabelText('Endpoint'); + await userEvent.type(endpointInput, 'test'); const bucketInput = screen.getByLabelText('Bucket'); await userEvent.type(bucketInput, 'test'); const accessKeyIDInput = screen.getByLabelText('Access Key ID'); diff --git a/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationEdit.test.tsx b/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationEdit.test.tsx index c65cd49587c..4e24b0946cd 100644 --- a/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationEdit.test.tsx +++ b/packages/manager/src/features/Delivery/Destinations/DestinationForm/DestinationEdit.test.tsx @@ -7,7 +7,10 @@ import userEvent from '@testing-library/user-event'; import React from 'react'; import { describe, expect } from 'vitest'; -import { akamaiObjectStorageDestinationFactory } from 'src/factories'; +import { + akamaiObjectStorageDestinationFactory, + objectStorageBucketFactory, +} from 'src/factories'; import { DestinationEdit } from 'src/features/Delivery/Destinations/DestinationForm/DestinationEdit'; import { http, HttpResponse, server } from 'src/mocks/testServer'; import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers'; @@ -19,6 +22,36 @@ const mockDestination = akamaiObjectStorageDestinationFactory.build({ label: `Destination ${destinationId}`, }); +const mockBuckets = [ + objectStorageBucketFactory.build({ + hostname: 'bucket-with-hostname.us-east-1.linodeobjects.com', + label: 'bucket-with-hostname', + region: 'us-east', + }), + objectStorageBucketFactory.build({ + hostname: 'bucket-with-s3-endpoint.eu-central-1.linodeobjects.com', + label: 'bucket-with-s3-endpoint', + region: 'eu-central', + s3_endpoint: 'eu-central-1.linodeobjects.com', + }), +]; + +const queryMocks = vi.hoisted(() => ({ + useObjectStorageBuckets: vi.fn().mockReturnValue({ + data: undefined, + error: null, + isPending: true, + }), +})); + +vi.mock('src/queries/object-storage/queries', async () => { + const actual = await vi.importActual('src/queries/object-storage/queries'); + return { + ...actual, + useObjectStorageBuckets: queryMocks.useObjectStorageBuckets, + }; +}); + vi.mock('@tanstack/react-router', async () => { const actual = await vi.importActual('@tanstack/react-router'); return { @@ -28,6 +61,13 @@ vi.mock('@tanstack/react-router', async () => { }); describe('DestinationEdit', () => { + beforeEach(() => { + queryMocks.useObjectStorageBuckets.mockReturnValue({ + data: { buckets: mockBuckets }, + error: null, + isPending: false, + }); + }); const assertInputHasValue = (inputLabel: string, inputValue: string) => { expect(screen.getByLabelText(inputLabel)).toHaveValue(inputValue); }; @@ -51,13 +91,129 @@ describe('DestinationEdit', () => { await waitFor(() => { assertInputHasValue('Destination Name', 'Destination 123'); }); - assertInputHasValue('Host', 'destinations-bucket-name.host.com'); + assertInputHasValue('Endpoint', 'destinations-bucket-name.host.com'); assertInputHasValue('Bucket', 'destinations-bucket-name'); assertInputHasValue('Access Key ID', 'Access Id'); assertInputHasValue('Secret Access Key', ''); assertInputHasValue('Log Path Prefix (optional)', 'file'); }); + describe('Bucket selection behavior in edit mode', () => { + const renderEditWithMockDestination = async () => { + server.use( + http.get(`*/monitor/streams/destinations/${destinationId}`, () => { + return HttpResponse.json(mockDestination); + }) + ); + + renderWithThemeAndHookFormContext({ + component: , + }); + + const loadingElement = screen.queryByTestId(loadingTestId); + await waitForElementToBeRemoved(loadingElement); + }; + + it('should default to "Enter Bucket manually" radio in edit mode', async () => { + await renderEditWithMockDestination(); + + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + expect(manualRadio).toBeChecked(); + }); + + it('should enable the Endpoint field in manual mode', async () => { + await renderEditWithMockDestination(); + + await waitFor(() => { + expect(screen.getByLabelText('Endpoint')).toBeEnabled(); + }); + }); + + it('should clear Bucket and Endpoint when switching to "Select Bucket associated with the account"', async () => { + await renderEditWithMockDestination(); + + await waitFor(() => { + assertInputHasValue('Bucket', 'destinations-bucket-name'); + }); + assertInputHasValue('Endpoint', 'destinations-bucket-name.host.com'); + + // Switch to bucket_from_account + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + await userEvent.click(bucketFromAccountRadio); + + // Both fields should be cleared + expect(screen.getByLabelText('Bucket')).toHaveValue(''); + expect(screen.getByLabelText('Endpoint')).toHaveValue(''); + }); + + it('should disable the Endpoint field after switching to "Select Bucket associated with the account"', async () => { + await renderEditWithMockDestination(); + + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + await userEvent.click(bucketFromAccountRadio); + + expect(screen.getByLabelText('Endpoint')).toBeDisabled(); + }); + + it('should set Bucket and Endpoint from hostname when selecting a bucket without s3_endpoint', async () => { + await renderEditWithMockDestination(); + + // Switch to bucket_from_account to show the Autocomplete + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + await userEvent.click(bucketFromAccountRadio); + + // Open the Bucket Autocomplete and select a bucket with only hostname + const bucketAutocomplete = screen.getByLabelText('Bucket'); + await userEvent.click(bucketAutocomplete); + + const bucketOption = await screen.findByText('bucket-with-hostname'); + await userEvent.click(bucketOption); + + // Bucket should display the selected bucket label + await waitFor(() => { + expect(bucketAutocomplete).toHaveValue('bucket-with-hostname'); + }); + + // Endpoint should be auto-filled with the bucket's hostname + expect(screen.getByLabelText('Endpoint')).toHaveValue( + 'bucket-with-hostname.us-east-1.linodeobjects.com' + ); + }); + + it('should set Bucket and Endpoint from s3_endpoint when selecting a bucket with s3_endpoint', async () => { + await renderEditWithMockDestination(); + + // Switch to bucket_from_account to show the Autocomplete + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + await userEvent.click(bucketFromAccountRadio); + + // Open the Bucket Autocomplete and select a bucket with s3_endpoint + const bucketAutocomplete = screen.getByLabelText('Bucket'); + await userEvent.click(bucketAutocomplete); + + const bucketOption = await screen.findByText('bucket-with-s3-endpoint'); + await userEvent.click(bucketOption); + + // Bucket should display the selected bucket label + await waitFor(() => { + expect(bucketAutocomplete).toHaveValue('bucket-with-s3-endpoint'); + }); + + // Endpoint should be auto-filled with the bucket's s3_endpoint + expect(screen.getByLabelText('Endpoint')).toHaveValue( + 'eu-central-1.linodeobjects.com' + ); + }); + }); + describe('given Test Connection and Edit Destination buttons', () => { const testConnectionButtonText = 'Test Connection'; const saveDestinationButtonText = 'Save Changes'; diff --git a/packages/manager/src/features/Delivery/Shared/DestinationAkamaiObjectStorageDetailsForm.tsx b/packages/manager/src/features/Delivery/Shared/DestinationAkamaiObjectStorageDetailsForm.tsx index b5b17fc7f58..673f1b07d4c 100644 --- a/packages/manager/src/features/Delivery/Shared/DestinationAkamaiObjectStorageDetailsForm.tsx +++ b/packages/manager/src/features/Delivery/Shared/DestinationAkamaiObjectStorageDetailsForm.tsx @@ -1,10 +1,23 @@ -import { Box, Divider, TextField, Typography } from '@linode/ui'; -import { capitalize } from '@mui/material'; -import React from 'react'; +import { useRegionsQuery } from '@linode/queries'; +import { useIsGeckoEnabled } from '@linode/shared'; +import { + Autocomplete, + Box, + Divider, + Radio, + RadioGroup, + TextField, + Typography, +} from '@linode/ui'; +import { capitalize, FormControlLabel } from '@mui/material'; +import React, { useState } from 'react'; import { Controller, useFormContext, useWatch } from 'react-hook-form'; import { HideShowText } from 'src/components/PasswordInput/HideShowText'; +import { RegionSelect } from 'src/components/RegionSelect/RegionSelect'; import { PathSample } from 'src/features/Delivery/Shared/PathSample'; +import { useFlags } from 'src/hooks/useFlags'; +import { useObjectStorageBuckets } from 'src/queries/object-storage/queries'; import type { FormMode, FormType } from 'src/features/Delivery/Shared/types'; @@ -33,50 +46,164 @@ export const DestinationAkamaiObjectStorageDetailsForm = ({ entity, mode, }: DestinationLinodeObjectStorageDetailsFormProps) => { - const { control } = useFormContext(); + const { gecko2 } = useFlags(); + const { isGeckoLAEnabled } = useIsGeckoEnabled(gecko2?.enabled, gecko2?.la); + + const { data: regions, isPending: areRegionsLoading } = useRegionsQuery(); + const { data: objectStorageBucketsResponse, isPending: areBucketsLoading } = + useObjectStorageBuckets(); + const objectStorageBuckets = objectStorageBucketsResponse?.buckets || []; + + const { control, setValue } = useFormContext(); + const path = useWatch({ control, name: controlPaths?.path, }); + const pendoPageId = `Logs Delivery ${capitalize(entity)}s ${capitalize(mode)}${entity === 'destination' ? '' : ' New Destination'}-`; + const [selectedBucketConfiguration, setSelectedBucketConfiguration] = + useState( + mode === 'edit' ? 'bucket_entered_manually' : 'bucket_from_account' + ); + const [selectedRegion, setSelectedRegion] = useState(null); + + const getBucketsForRegion = (regionId: null | string) => + regionId + ? objectStorageBuckets.filter(({ region }) => region === regionId) + : objectStorageBuckets; + + const buckets = getBucketsForRegion(selectedRegion); + + const clearBucketFields = () => { + setValue(controlPaths.bucketName, ''); + setValue(controlPaths.host, ''); + }; + + const handleRegionChange = (regionId: string | undefined) => { + const newRegion = regionId || null; + setSelectedRegion(newRegion); + + if (getBucketsForRegion(newRegion).length === 0) { + clearBucketFields(); + } + }; + + const handleBucketConfigurationChange = (value: string) => { + setSelectedBucketConfiguration(value); + if (value === 'bucket_from_account') { + clearBucketFields(); + setSelectedRegion(null); + } + }; + return ( <> - ( - { - field.onChange(value); + + Bucket + + handleBucketConfigurationChange(value)} + sx={{ '&[role="radiogroup"]': { mb: 0 } }} + value={selectedBucketConfiguration} + > + } + label="Select Bucket associated with the account" + value="bucket_from_account" + /> + } + label="Enter Bucket manually" + value="bucket_entered_manually" + /> + + {selectedBucketConfiguration === 'bucket_from_account' ? ( + <> + handleRegionChange(region?.id)} + regionFilter="core" + regions={regions ?? []} + textFieldProps={{ + optional: true, }} - placeholder="Host for the destination" - value={field.value} + value={selectedRegion} /> - )} - /> + ( + { + field.onChange(bucket?.label || ''); + setValue( + controlPaths?.host, + bucket?.s3_endpoint || bucket?.hostname || '' + ); + }} + options={buckets} + textFieldProps={{ + inputProps: { + 'data-pendo-id': `${pendoPageId}Bucket`, + }, + }} + value={ + buckets.find(({ label }) => label === field.value) ?? null + } + /> + )} + /> + + ) : ( + ( + { + field.onChange(value); + }} + value={field.value} + /> + )} + /> + )} ( { field.onChange(value); }} + placeholder="Endpoint for the destination" value={field.value} /> )} diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.test.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.test.tsx index 9218718a04f..ed85f82349a 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.test.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/Delivery/StreamFormDelivery.test.tsx @@ -1,5 +1,9 @@ import { destinationType } from '@linode/api-v4'; -import { screen, waitForElementToBeRemoved } from '@testing-library/react'; +import { + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { beforeEach, describe, expect } from 'vitest'; @@ -7,6 +11,7 @@ import { beforeEach, describe, expect } from 'vitest'; import { akamaiObjectStorageDestinationFactory, customHttpsDestinationFactory, + objectStorageBucketFactory, } from 'src/factories'; import { makeResourcePage } from 'src/mocks/serverHandlers'; import { http, HttpResponse, server } from 'src/mocks/testServer'; @@ -24,10 +29,46 @@ const mockDestinations = [ ...customHttpsDestinationFactory.buildList(2), ]; +const mockBuckets = [ + objectStorageBucketFactory.build({ + hostname: 'bucket-with-hostname.us-east-1.linodeobjects.com', + label: 'bucket-with-hostname', + region: 'us-east', + }), + objectStorageBucketFactory.build({ + hostname: 'bucket-with-s3-endpoint.eu-central-1.linodeobjects.com', + label: 'bucket-with-s3-endpoint', + region: 'eu-central', + s3_endpoint: 'eu-central-1.linodeobjects.com', + }), +]; + +const queryMocks = vi.hoisted(() => ({ + useObjectStorageBuckets: vi.fn().mockReturnValue({ + data: undefined, + error: null, + isPending: true, + }), +})); + +vi.mock('src/queries/object-storage/queries', async () => { + const actual = await vi.importActual('src/queries/object-storage/queries'); + return { + ...actual, + useObjectStorageBuckets: queryMocks.useObjectStorageBuckets, + }; +}); + describe('StreamFormDelivery', () => { const setDisableTestConnection = () => {}; beforeEach(async () => { + queryMocks.useObjectStorageBuckets.mockReturnValue({ + data: { buckets: mockBuckets }, + error: null, + isPending: false, + }); + server.use( http.get('*/monitor/streams/destinations', () => { return HttpResponse.json(makeResourcePage(mockDestinations)); @@ -188,25 +229,36 @@ describe('StreamFormDelivery', () => { }); describe('and new Destination Name is added', () => { - it('should render Host input and allow to type text', async () => { + it('should render Endpoint input as disabled in bucket_from_account mode and allow to type text after switching to manual mode', async () => { await renderComponentAndAddNewDestinationName( destinationType.AkamaiObjectStorage, flags ); - // Type the test value inside the input - const hostInput = screen.getByLabelText('Host'); - await userEvent.type(hostInput, 'Test'); + // Endpoint is disabled when bucket_from_account is selected + const endpointInput = screen.getByLabelText('Endpoint'); + expect(endpointInput).toBeDisabled(); + + // Switch to manual mode + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); - expect(hostInput.getAttribute('value')).toEqual('Test'); + // Now Endpoint should be enabled + expect(endpointInput).toBeEnabled(); + await userEvent.type(endpointInput, 'Test'); + expect(endpointInput.getAttribute('value')).toEqual('Test'); }); - it('should render Bucket input and allow to type text', async () => { + it('should render Bucket input and allow to type text in manual mode', async () => { await renderComponentAndAddNewDestinationName( destinationType.AkamaiObjectStorage, flags ); + // Switch to manual mode + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + // Type the test value inside the input const bucketInput = screen.getByLabelText('Bucket'); await userEvent.type(bucketInput, 'test'); @@ -256,6 +308,123 @@ describe('StreamFormDelivery', () => { expect(logPathPrefixInput.getAttribute('value')).toEqual('Test'); }); }); + + describe('Bucket selection behavior', () => { + it('should default to "Select Bucket associated with the account" radio', async () => { + await renderComponentAndAddNewDestinationName( + destinationType.AkamaiObjectStorage, + flags + ); + + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + expect(bucketFromAccountRadio).toBeChecked(); + }); + + it('should disable the Endpoint field when "Select Bucket associated with the account" is selected', async () => { + await renderComponentAndAddNewDestinationName( + destinationType.AkamaiObjectStorage, + flags + ); + + const endpointInput = screen.getByLabelText('Endpoint'); + expect(endpointInput).toBeDisabled(); + }); + + it('should enable the Endpoint field when "Enter Bucket manually" is selected', async () => { + await renderComponentAndAddNewDestinationName( + destinationType.AkamaiObjectStorage, + flags + ); + + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const endpointInput = screen.getByLabelText('Endpoint'); + expect(endpointInput).toBeEnabled(); + }); + + it('should clear Bucket and Endpoint when switching to "Select Bucket associated with the account"', async () => { + await renderComponentAndAddNewDestinationName( + destinationType.AkamaiObjectStorage, + flags + ); + + // Switch to manual mode and fill in values + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const bucketInput = screen.getByLabelText('Bucket'); + await userEvent.type(bucketInput, 'my-manual-bucket'); + expect(bucketInput).toHaveValue('my-manual-bucket'); + + const endpointInput = screen.getByLabelText('Endpoint'); + await userEvent.type(endpointInput, 'my-endpoint.com'); + expect(endpointInput).toHaveValue('my-endpoint.com'); + + // Switch back to bucket_from_account + const bucketFromAccountRadio = screen.getByLabelText( + 'Select Bucket associated with the account' + ); + await userEvent.click(bucketFromAccountRadio); + + // Both fields should be cleared + const bucketAutocomplete = screen.getByLabelText('Bucket'); + expect(bucketAutocomplete).toHaveValue(''); + expect(screen.getByLabelText('Endpoint')).toHaveValue(''); + }); + + it('should set Bucket and Endpoint from hostname when selecting a bucket without s3_endpoint', async () => { + await renderComponentAndAddNewDestinationName( + destinationType.AkamaiObjectStorage, + flags + ); + + // Open the Bucket Autocomplete and select a bucket with only hostname + const bucketAutocomplete = screen.getByLabelText('Bucket'); + await userEvent.click(bucketAutocomplete); + + const bucketOption = await screen.findByText('bucket-with-hostname'); + await userEvent.click(bucketOption); + + // Bucket should display the selected bucket label + await waitFor(() => { + expect(bucketAutocomplete).toHaveValue('bucket-with-hostname'); + }); + + // Endpoint should be auto-filled with the bucket's hostname + expect(screen.getByLabelText('Endpoint')).toHaveValue( + 'bucket-with-hostname.us-east-1.linodeobjects.com' + ); + }); + + it('should set Bucket and Endpoint from s3_endpoint when selecting a bucket with s3_endpoint', async () => { + await renderComponentAndAddNewDestinationName( + destinationType.AkamaiObjectStorage, + flags + ); + + // Open the Bucket Autocomplete and select a bucket with s3_endpoint + const bucketAutocomplete = screen.getByLabelText('Bucket'); + await userEvent.click(bucketAutocomplete); + + const bucketOption = await screen.findByText( + 'bucket-with-s3-endpoint' + ); + await userEvent.click(bucketOption); + + // Bucket should display the selected bucket label + await waitFor(() => { + expect(bucketAutocomplete).toHaveValue('bucket-with-s3-endpoint'); + }); + + // Endpoint should be auto-filled with the bucket's s3_endpoint + expect(screen.getByLabelText('Endpoint')).toHaveValue( + 'eu-central-1.linodeobjects.com' + ); + }); + }); }); }); diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/StreamCreate.test.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/StreamCreate.test.tsx index 700f766fc9c..49744d734af 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/StreamCreate.test.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/StreamCreate.test.tsx @@ -55,11 +55,15 @@ describe('StreamCreate', () => { { exact: false } ); await userEvent.click(createNewTestDestination); - const hostInput = screen.getByLabelText('Host'); + + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const endpointInput = screen.getByLabelText('Endpoint'); await waitFor(() => { - expect(hostInput).toBeDefined(); + expect(endpointInput).toBeDefined(); }); - await userEvent.type(hostInput, 'test'); + await userEvent.type(endpointInput, 'test'); const bucketInput = screen.getByLabelText('Bucket'); await userEvent.type(bucketInput, 'test'); const accessKeyIDInput = screen.getByLabelText('Access Key ID'); diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/StreamEdit.test.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/StreamEdit.test.tsx index ee51755cfd2..7aa98b387db 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/StreamEdit.test.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/StreamEdit.test.tsx @@ -101,11 +101,16 @@ describe('StreamEdit', () => { { exact: false } ); await userEvent.click(createNewTestDestination); - const hostInput = screen.getByLabelText('Host'); + + // Switch to manual bucket entry mode + const manualRadio = screen.getByLabelText('Enter Bucket manually'); + await userEvent.click(manualRadio); + + const endpointInput = screen.getByLabelText('Endpoint'); await waitFor(() => { - expect(hostInput).toBeDefined(); + expect(endpointInput).toBeDefined(); }); - await userEvent.type(hostInput, 'test'); + await userEvent.type(endpointInput, 'test'); const bucketInput = screen.getByLabelText('Bucket'); await userEvent.type(bucketInput, 'test'); const accessKeyIDInput = screen.getByLabelText('Access Key ID'); From 9dd1d3dc88e191085fa22235b0ac4da45f1d756f Mon Sep 17 00:00:00 2001 From: mduda-akamai Date: Tue, 10 Mar 2026 10:11:59 +0100 Subject: [PATCH 47/56] change: [DPS-36769] - Filter clusters in Stream Form based on region capability (#13467) --- .../pr-13467-added-1772701469134.md | 5 + packages/api-v4/src/regions/types.ts | 1 + .../pr-13467-changed-1772702080743.md | 5 + .../e2e/core/delivery/create-stream.spec.ts | 88 +++++++++++--- .../e2e/core/delivery/edit-stream.spec.ts | 93 +++++++++++--- .../Clusters/StreamFormClusters.test.tsx | 113 ++++++++++++++++-- .../Clusters/StreamFormClusters.tsx | 99 +++++++++------ 7 files changed, 327 insertions(+), 77 deletions(-) create mode 100644 packages/api-v4/.changeset/pr-13467-added-1772701469134.md create mode 100644 packages/manager/.changeset/pr-13467-changed-1772702080743.md diff --git a/packages/api-v4/.changeset/pr-13467-added-1772701469134.md b/packages/api-v4/.changeset/pr-13467-added-1772701469134.md new file mode 100644 index 00000000000..96651c0c718 --- /dev/null +++ b/packages/api-v4/.changeset/pr-13467-added-1772701469134.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Added +--- + +Add `ACLP Logs Datacenter LKE-E` to the Region's `Capability` type ([#13467](https://github.com/linode/manager/pull/13467)) diff --git a/packages/api-v4/src/regions/types.ts b/packages/api-v4/src/regions/types.ts index e4fa034d08a..98abf0a6c56 100644 --- a/packages/api-v4/src/regions/types.ts +++ b/packages/api-v4/src/regions/types.ts @@ -1,6 +1,7 @@ import type { COUNTRY_CODE_TO_CONTINENT_CODE } from './constants'; export type Capabilities = + | 'ACLP Logs Datacenter LKE-E' | 'Backups' | 'Bare Metal' | 'Block Storage' diff --git a/packages/manager/.changeset/pr-13467-changed-1772702080743.md b/packages/manager/.changeset/pr-13467-changed-1772702080743.md new file mode 100644 index 00000000000..06969619357 --- /dev/null +++ b/packages/manager/.changeset/pr-13467-changed-1772702080743.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Stream Create/Edit form: in the Clusters table show only clusters with a region that has "ACLP Logs Datacenter LKE-E" capability ([#13467](https://github.com/linode/manager/pull/13467)) diff --git a/packages/manager/cypress/e2e/core/delivery/create-stream.spec.ts b/packages/manager/cypress/e2e/core/delivery/create-stream.spec.ts index 2bb0b56b2d4..d0bdae727f3 100644 --- a/packages/manager/cypress/e2e/core/delivery/create-stream.spec.ts +++ b/packages/manager/cypress/e2e/core/delivery/create-stream.spec.ts @@ -1,4 +1,5 @@ import { streamType } from '@linode/api-v4'; +import { regionFactory } from '@linode/utilities'; import { mockDestination } from 'support/constants/delivery'; import { mockGetAccount } from 'support/intercepts/account'; import { @@ -9,6 +10,7 @@ import { } from 'support/intercepts/delivery'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { mockGetClusters } from 'support/intercepts/lke'; +import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { logsStreamForm } from 'support/ui/pages/logs-stream-form'; import { randomLabel } from 'support/util/random'; @@ -179,25 +181,55 @@ describe('Create Stream', () => { describe('given Kubernetes API Audit Logs Stream Type', () => { it('selects clusters and creates new stream', () => { + const regionWithCapabilityAndCluster = regionFactory.build({ + id: 'us-southeast', + label: 'Atlanta, GA', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }); + const regionWithCapabilityNoCluster = regionFactory.build({ + id: 'us-chicago', + label: 'Chicago, IL', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }); + const regionNoCapabilityWithCluster = regionFactory.build({ + id: 'us-west', + label: 'Fremont, CA', + capabilities: ['Object Storage'], + }); + + const cluster1 = kubernetesClusterFactory.build({ + id: 1, + label: 'cluster-1', + region: regionWithCapabilityAndCluster.id, + control_plane: { audit_logs_enabled: true }, + }); + const cluster2 = kubernetesClusterFactory.build({ + id: 2, + label: 'cluster-2', + region: regionWithCapabilityAndCluster.id, + control_plane: { audit_logs_enabled: false }, + }); + const cluster3 = kubernetesClusterFactory.build({ + id: 3, + label: 'cluster-3', + region: regionWithCapabilityAndCluster.id, + control_plane: { audit_logs_enabled: true }, + }); + const clusterNoCap = kubernetesClusterFactory.build({ + id: 4, + label: 'cluster-4', + region: regionNoCapabilityWithCluster.id, + control_plane: { audit_logs_enabled: true }, + }); + // Mock API responses mockGetDestinations([mockDestination]); - mockGetClusters([ - kubernetesClusterFactory.build({ - id: 1, - label: 'cluster-1', - control_plane: { audit_logs_enabled: true }, - }), - kubernetesClusterFactory.build({ - id: 2, - label: 'cluster-2', - control_plane: { audit_logs_enabled: false }, - }), - kubernetesClusterFactory.build({ - id: 3, - label: 'cluster-3', - control_plane: { audit_logs_enabled: true }, - }), + mockGetRegions([ + regionWithCapabilityAndCluster, + regionWithCapabilityNoCluster, + regionNoCapabilityWithCluster, ]); + mockGetClusters([cluster1, cluster2, cluster3, clusterNoCap]); // Visit the Create Stream page cy.visitWithLogin('/logs/delivery/streams/create'); @@ -213,9 +245,33 @@ describe('Create Stream', () => { // Select existing destination logsStreamForm.selectExistingDestination(mockDestination.label); + // Expect only 'Atlanta, GA' to be in Region Select (has capability and is in clusters) + ui.regionSelect.find().should('be.visible').click(); + + ui.autocompletePopper + .findByTitle(regionWithCapabilityAndCluster.id, { exact: false }) + .should('be.visible'); + + ui.autocompletePopper + .find() + .should('not.contain', regionWithCapabilityNoCluster.id); + + ui.autocompletePopper + .find() + .should('not.contain', regionNoCapabilityWithCluster.id); + + // Close the dropdown + ui.regionSelect.find().type('{esc}'); + cy.findByText('Clusters').should('be.visible'); cy.get('[data-testid="clusters-table"]').should('exist'); + // Expect only cluster-1, cluster-2, cluster-3 to be in table. + cy.findByText('cluster-1').should('be.visible'); + cy.findByText('cluster-2').should('be.visible'); + cy.findByText('cluster-3').should('be.visible'); + cy.findByText('cluster-4').should('not.exist'); + // Select cluster-1 and cluster-3 individually logsStreamForm.findClusterCheckbox('cluster-1').check(); diff --git a/packages/manager/cypress/e2e/core/delivery/edit-stream.spec.ts b/packages/manager/cypress/e2e/core/delivery/edit-stream.spec.ts index 95942ae99b4..9b5795ae89c 100644 --- a/packages/manager/cypress/e2e/core/delivery/edit-stream.spec.ts +++ b/packages/manager/cypress/e2e/core/delivery/edit-stream.spec.ts @@ -1,3 +1,4 @@ +import { regionFactory } from '@linode/utilities'; import { mockAuditLogsStream, mockAuditLogsStreamPayload, @@ -15,6 +16,7 @@ import { } from 'support/intercepts/delivery'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { mockGetClusters } from 'support/intercepts/lke'; +import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { logsStreamForm } from 'support/ui/pages/logs-stream-form'; import { randomLabel } from 'support/util/random'; @@ -147,28 +149,61 @@ describe('Edit Stream', () => { describe('given Kubernetes API Audit Logs Stream Type', () => { it('edits stream label and clusters and saves', () => { + const regionWithCapabilityAndCluster = regionFactory.build({ + id: 'us-southeast', + label: 'Atlanta, GA', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }); + const regionWithCapabilityNoCluster = regionFactory.build({ + id: 'us-chicago', + label: 'Chicago, IL', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }); + const regionNoCapabilityWithCluster = regionFactory.build({ + id: 'us-west', + label: 'Fremont, CA', + capabilities: ['Object Storage'], + }); + + const cluster1 = kubernetesClusterFactory.build({ + id: 1, + label: 'cluster-1', + region: regionWithCapabilityAndCluster.id, + control_plane: { audit_logs_enabled: true }, + }); + const cluster2 = kubernetesClusterFactory.build({ + id: 2, + label: 'cluster-2', + region: regionWithCapabilityAndCluster.id, + control_plane: { audit_logs_enabled: false }, + }); + const cluster3 = kubernetesClusterFactory.build({ + id: 3, + label: 'cluster-3', + region: regionWithCapabilityAndCluster.id, + control_plane: { audit_logs_enabled: true }, + }); + const cluster4 = kubernetesClusterFactory.build({ + id: 4, + label: 'cluster-no-cap', + region: regionNoCapabilityWithCluster.id, + control_plane: { audit_logs_enabled: true }, + }); + // Mock API responses mockGetDestinations([mockDestination]); mockGetDestination(mockDestination); mockGetStreams([mockLKEAuditLogsStream]); - mockGetStream(mockLKEAuditLogsStream); - mockGetClusters([ - kubernetesClusterFactory.build({ - id: 1, - label: 'cluster-1', - control_plane: { audit_logs_enabled: true }, - }), - kubernetesClusterFactory.build({ - id: 2, - label: 'cluster-2', - control_plane: { audit_logs_enabled: false }, - }), - kubernetesClusterFactory.build({ - id: 3, - label: 'cluster-3', - control_plane: { audit_logs_enabled: true }, - }), + mockGetStream({ + ...mockLKEAuditLogsStream, + details: { cluster_ids: [1, 3] }, + }); + mockGetRegions([ + regionWithCapabilityAndCluster, + regionWithCapabilityNoCluster, + regionNoCapabilityWithCluster, ]); + mockGetClusters([cluster1, cluster2, cluster3, cluster4]); // Visit the Edit Stream page cy.visitWithLogin( @@ -196,10 +231,34 @@ describe('Edit Stream', () => { .should('be.disabled') .should('have.attr', 'value', 'Kubernetes API Audit Logs'); + // Expect only 'Atlanta, GA' to be in Region Select (has capability and is in clusters) + ui.regionSelect.find().should('be.visible').click(); + + ui.autocompletePopper + .findByTitle(regionWithCapabilityAndCluster.id, { exact: false }) + .should('be.visible'); + + ui.autocompletePopper + .find() + .should('not.contain', regionWithCapabilityNoCluster.id); + + ui.autocompletePopper + .find() + .should('not.contain', regionNoCapabilityWithCluster.id); + + // Close the dropdown + ui.regionSelect.find().type('{esc}'); + // Clusters table should be visible cy.findByText('Clusters').should('be.visible'); cy.get('[data-testid="clusters-table"]').should('exist'); + // Verify Clusters Table content + cy.findByText('cluster-1').should('be.visible'); + cy.findByText('cluster-2').should('be.visible'); + cy.findByText('cluster-3').should('be.visible'); + cy.findByText('cluster-4').should('not.exist'); + // Initially selected clusters should be checked logsStreamForm.findClusterCheckbox('cluster-1').should('be.checked'); logsStreamForm.findClusterCheckbox('cluster-3').should('be.checked'); diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.test.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.test.tsx index 156fbc30dba..322bfde465c 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.test.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.test.tsx @@ -1,3 +1,4 @@ +import { regionFactory } from '@linode/utilities'; import { screen, waitFor, @@ -6,7 +7,7 @@ import { } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { describe, expect, it } from 'vitest'; +import { beforeEach, describe, expect, it } from 'vitest'; import { kubernetesClusterFactory } from 'src/factories'; import { makeResourcePage } from 'src/mocks/serverHandlers'; @@ -20,7 +21,7 @@ const testClustersDetails = [ { label: 'gke-prod-europe-west1', id: 1, - region: 'US, Atalanta, GA', + region: 'us-southeast', control_plane: { audit_logs_enabled: false, }, @@ -28,7 +29,7 @@ const testClustersDetails = [ { label: 'metrics-stream-cluster', id: 2, - region: 'US, Chicago, IL', + region: 'us-chicago', control_plane: { audit_logs_enabled: true, }, @@ -36,21 +37,59 @@ const testClustersDetails = [ { label: 'prod-cluster-eu', id: 3, - region: 'NL, Amsterdam', + region: 'nl-ams', + control_plane: { + audit_logs_enabled: true, + }, + }, + { + label: 'cluster-no-capability', + id: 4, + region: 'us-east', control_plane: { audit_logs_enabled: true, }, }, ]; -const clusters = kubernetesClusterFactory.buildList(3).map((cluster, idx) => ({ +const clusters = kubernetesClusterFactory.buildList(4).map((cluster, idx) => ({ ...cluster, ...testClustersDetails[idx], })); +const regions = [ + regionFactory.build({ + id: 'us-southeast', + label: 'Atlanta, GA', + country: 'us', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }), + regionFactory.build({ + id: 'us-chicago', + label: 'Chicago, IL', + country: 'us', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }), + regionFactory.build({ + id: 'nl-ams', + label: 'Amsterdam', + country: 'nl', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }), + regionFactory.build({ + id: 'us-east', + label: 'Newark, NJ', + country: 'us', + capabilities: ['Object Storage'], + }), +]; + const renderComponentWithoutSelectedClusters = async () => { server.use( http.get('*/lke/clusters', () => { return HttpResponse.json(makeResourcePage(clusters)); + }), + http.get('*/regions', () => { + return HttpResponse.json(makeResourcePage(regions)); }) ); @@ -134,12 +173,12 @@ describe('StreamFormClusters', () => { // Type test value inside the search await userEvent.click(input); - await userEvent.type(input, 'US,'); + await userEvent.type(input, 'us-'); await waitFor(() => expect(getColumnsValuesFromTable(2)).toEqual([ - 'US, Atalanta, GA', - 'US, Chicago, IL', + 'US, Atlanta, GA (us-southeast)', + 'US, Chicago, IL (us-chicago)', ]) ); }); @@ -231,6 +270,9 @@ describe('StreamFormClusters', () => { server.use( http.get('*/lke/clusters', () => { return HttpResponse.json(makeResourcePage(clusters)); + }), + http.get('*/regions', () => { + return HttpResponse.json(makeResourcePage(regions)); }) ); @@ -276,6 +318,9 @@ describe('StreamFormClusters', () => { server.use( http.get('*/lke/clusters', () => { return HttpResponse.json(makeResourcePage(modifiedClusters)); + }), + http.get('*/regions', () => { + return HttpResponse.json(makeResourcePage(regions)); }) ); @@ -394,4 +439,56 @@ describe('StreamFormClusters', () => { expect(metricsStreamCheckbox).not.toBeChecked(); expect(prodClusterCheckbox).toBeChecked(); }); + + describe('capability filtering', () => { + describe('given clusters table', () => { + it('should only display clusters in regions with "ACLP Logs Datacenter LKE-E" capability', async () => { + await renderComponentWithoutSelectedClusters(); + + const tableRows = getColumnsValuesFromTable(); + expect(tableRows).toContain('gke-prod-europe-west1'); + expect(tableRows).not.toContain('cluster-no-capability'); + }); + }); + + describe('given regions dropdown', () => { + beforeEach(() => { + const regionWithCapabilityButNoClusters = regionFactory.build({ + id: 'ap-south', + label: 'Singapore', + country: 'sg', + capabilities: ['ACLP Logs Datacenter LKE-E', 'Object Storage'], + }); + + const allRegions = [...regions, regionWithCapabilityButNoClusters]; + + server.use( + http.get('*/lke/clusters', () => { + return HttpResponse.json(makeResourcePage(clusters)); + }), + http.get('*/regions', () => { + return HttpResponse.json(makeResourcePage(allRegions)); + }) + ); + }); + + it('should only display regions that have clusters and the required capability', async () => { + await renderComponentWithoutSelectedClusters(); + + const regionSelect = screen.getByPlaceholderText('Select Region'); + await userEvent.click(regionSelect); + + const regionOptions = await screen.findAllByRole('option'); + const regionOptionLabels = regionOptions.map( + ({ textContent }) => textContent + ); + + expect(regionOptionLabels).toEqual([ + 'US, Atlanta, GA (us-southeast)', + 'US, Chicago, IL (us-chicago)', + 'NL, Amsterdam (nl-ams)', + ]); + }); + }); + }); }); diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx index e6dd87f1a14..12fcf7805a1 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx @@ -44,6 +44,11 @@ interface StreamFormClustersProps { mode: FormMode; } +const logGenerationOptions = [ + { label: 'Enabled', value: true }, + { label: 'Disabled', value: false }, +]; + export const StreamFormClusters = (props: StreamFormClustersProps) => { const { mode } = props; const { control, setValue, formState, trigger } = @@ -52,11 +57,12 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { const xsDown = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')); const { gecko2 } = useFlags(); const { isGeckoLAEnabled } = useIsGeckoEnabled(gecko2?.enabled, gecko2?.la); - const { data: regions } = useRegionsQuery(); - const logGenerationOptions = [ - { label: 'Enabled', value: true }, - { label: 'Disabled', value: false }, - ]; + const { data: regions = [] } = useRegionsQuery(); + const { + data: clusters = [], + isLoading, + error, + } = useAllKubernetesClustersQuery({ enabled: true }); const [order, setOrder] = useState<'asc' | 'desc'>('asc'); const [orderBy, setOrderBy] = useState('label'); @@ -66,18 +72,40 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { const [regionFilter, setRegionFilter] = useState(''); const [logGenerationFilter, setLogGenerationFilter] = useState(); - const { - data: clusters = [], - isLoading, - error, - } = useAllKubernetesClustersQuery({ enabled: true }); + const eligibleRegions = useMemo( + () => + regions?.filter(({ capabilities }) => + capabilities.includes('ACLP Logs Datacenter LKE-E') + ), + [regions] + ); + + const eligibleClusters = useMemo(() => { + const regionMap = new Map( + eligibleRegions.map(({ id, label }) => [id, label]) + ); + + return clusters + .filter(({ region }) => regionMap.has(region)) + .map((cluster) => ({ + ...cluster, + region: regionMap.get(cluster.region) + ? `${regionMap.get(cluster.region)} (${cluster.region})` + : cluster.region, + })); + }, [clusters, eligibleRegions]); + + const visibleRegions = useMemo(() => { + const clusterRegions = new Set(clusters.map(({ region }) => region)); + return eligibleRegions.filter(({ id }) => clusterRegions.has(id)); + }, [clusters, eligibleRegions]); const clusterIdsWithLogsEnabled = useMemo( () => - clusters + eligibleClusters ?.filter((cluster) => cluster.control_plane.audit_logs_enabled) .map(({ id }) => id), - [clusters] + [eligibleClusters] ); const [isAutoAddAllClustersEnabled, clusterIds] = useWatch({ @@ -138,10 +166,10 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { } }; - const filteredClusters = - !searchText && !regionFilter && logGenerationFilter === undefined - ? clusters - : clusters.filter((cluster) => { + const filteredClusters = useMemo(() => { + return !searchText && !regionFilter && logGenerationFilter === undefined + ? eligibleClusters + : eligibleClusters.filter((cluster) => { const lowerSearch = searchText.toLowerCase(); let result = true; @@ -167,32 +195,31 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { return result; }); + }, [searchText, regionFilter, logGenerationFilter, eligibleClusters]); - const sortedAndFilteredClusters = sortData( - orderBy, - order - )(filteredClusters); + const sortedAndFilteredClusters = useMemo( + () => sortData(orderBy, order)(filteredClusters), + [orderBy, order, filteredClusters] + ); // Paginate clusters - const indexOfFirstClusterInPage = (page - 1) * pageSize; + const maxPage = Math.max( + 1, + Math.ceil(sortedAndFilteredClusters.length / pageSize) + ); + const safePage = page > maxPage ? maxPage : page; + + if (safePage !== page) { + setPage(safePage); + } + + const indexOfFirstClusterInPage = (safePage - 1) * pageSize; const indexOfLastClusterInPage = indexOfFirstClusterInPage + pageSize; const paginatedClusters = sortedAndFilteredClusters.slice( indexOfFirstClusterInPage, indexOfLastClusterInPage ); - // If the current page is out of range after filtering, change to the last available page - useEffect(() => { - if (indexOfFirstClusterInPage >= sortedAndFilteredClusters.length) { - const lastPage = Math.max( - 1, - Math.ceil(sortedAndFilteredClusters.length / pageSize) - ); - - setPage(lastPage); - } - }, [sortedAndFilteredClusters, indexOfFirstClusterInPage, pageSize]); - return ( Clusters @@ -265,7 +292,7 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { /> { @@ -273,7 +300,7 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { }} placeholder="Select Region" regionFilter="core" - regions={regions ?? []} + regions={visibleRegions ?? []} sx={{ width: '160px !important', }} @@ -320,7 +347,7 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { eventCategory="Clusters Table" handlePageChange={setPage} handleSizeChange={setPageSize} - page={page} + page={safePage} pageSize={pageSize} /> From 0bb4f89be9573fa1cdc3b8f1fa65a98ddab3de9a Mon Sep 17 00:00:00 2001 From: Dmytro Chyrva Date: Tue, 10 Mar 2026 10:55:32 +0100 Subject: [PATCH 48/56] fix: STORIF-292 - Object url encoding corrected. (#13469) --- .../manager/src/features/ObjectStorage/utilities.test.ts | 8 ++++---- packages/manager/src/features/ObjectStorage/utilities.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/manager/src/features/ObjectStorage/utilities.test.ts b/packages/manager/src/features/ObjectStorage/utilities.test.ts index 7db2198d8d3..346aa230a9e 100644 --- a/packages/manager/src/features/ObjectStorage/utilities.test.ts +++ b/packages/manager/src/features/ObjectStorage/utilities.test.ts @@ -47,13 +47,13 @@ const mockHostname = 'my-bucket.linodeobjects.com'; describe('Object Storage utilities', () => { describe('generateObjectUrl', () => { it('returns the correct URL', () => { - expect(generateObjectUrl(mockHostname, 'my-object')).toBe( - 'https://my-bucket.linodeobjects.com/my-object' + expect(generateObjectUrl(mockHostname, 'my-folder/my-object')).toBe( + 'https://my-bucket.linodeobjects.com/my-folder/my-object' ); }); it('encodes the URL for special characters', () => { - expect(generateObjectUrl(mockHostname, 'my-object?')).toBe( - 'https://my-bucket.linodeobjects.com/my-object%3F' + expect(generateObjectUrl(mockHostname, 'my-object!@#$%^&*()_+<>.,')).toBe( + 'https://my-bucket.linodeobjects.com/my-object!@#$%25%5E&*()_+%3C%3E.,' ); }); }); diff --git a/packages/manager/src/features/ObjectStorage/utilities.ts b/packages/manager/src/features/ObjectStorage/utilities.ts index bd0bf35b84c..2b3bf462d6b 100644 --- a/packages/manager/src/features/ObjectStorage/utilities.ts +++ b/packages/manager/src/features/ObjectStorage/utilities.ts @@ -6,7 +6,7 @@ import type { ObjectStorageEndpoint } from '@linode/api-v4/lib/object-storage'; import type { FormikProps } from 'formik'; export const generateObjectUrl = (hostname: string, objectName: string) => { - return `https://${hostname}/${encodeURIComponent(objectName)}`; + return `https://${hostname}/${encodeURI(objectName)}`; }; // Objects ending with a / and having a size of 0 are often used to represent From 8c152e3a3af6f50328fa534d79cb652c18d8842f Mon Sep 17 00:00:00 2001 From: grevanak-akamai <145482092+grevanak-akamai@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:14:47 +0530 Subject: [PATCH 49/56] fix: [UIE-9888] - update node balancer type for enterprise and remove duplicate nodebalancer rows in VPC subnet table (#13472) --- .../.changeset/pr-13472-changed-1773131929522.md | 5 +++++ packages/api-v4/src/nodebalancers/types.ts | 2 +- .../.changeset/pr-13472-fixed-1773071273109.md | 5 +++++ .../NodeBalancerSummary/SummaryPanel.test.tsx | 4 ++-- .../NodeBalancerSummary/SummaryPanel.tsx | 2 +- .../features/VPCs/VPCDetail/VPCSubnetsTable.tsx | 15 +++++++++++---- packages/utilities/src/factories/nodebalancer.ts | 2 +- 7 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 packages/api-v4/.changeset/pr-13472-changed-1773131929522.md create mode 100644 packages/manager/.changeset/pr-13472-fixed-1773071273109.md diff --git a/packages/api-v4/.changeset/pr-13472-changed-1773131929522.md b/packages/api-v4/.changeset/pr-13472-changed-1773131929522.md new file mode 100644 index 00000000000..a63287e6a07 --- /dev/null +++ b/packages/api-v4/.changeset/pr-13472-changed-1773131929522.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Changed +--- + +Update node balancer type for enterprise from premium_40GB to premium_40gb ([#13472](https://github.com/linode/manager/pull/13472)) diff --git a/packages/api-v4/src/nodebalancers/types.ts b/packages/api-v4/src/nodebalancers/types.ts index 4ee00d3070c..75a1ee7babf 100644 --- a/packages/api-v4/src/nodebalancers/types.ts +++ b/packages/api-v4/src/nodebalancers/types.ts @@ -10,7 +10,7 @@ type UDPStickiness = 'none' | 'session' | 'source_ip'; export type Stickiness = TCPStickiness | UDPStickiness; -type NodeBalancerType = 'common' | 'premium' | 'premium_40GB'; +type NodeBalancerType = 'common' | 'premium' | 'premium_40gb'; export interface LKEClusterInfo { id: number; diff --git a/packages/manager/.changeset/pr-13472-fixed-1773071273109.md b/packages/manager/.changeset/pr-13472-fixed-1773071273109.md new file mode 100644 index 00000000000..fc996cab12f --- /dev/null +++ b/packages/manager/.changeset/pr-13472-fixed-1773071273109.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Update node balancer type for enterprise and remove duplicate nodebalancer rows in VPC subnet table ([#13472](https://github.com/linode/manager/pull/13472)) diff --git a/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.test.tsx b/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.test.tsx index 6ea7fc427be..e0500ff86b2 100644 --- a/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.test.tsx +++ b/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.test.tsx @@ -162,9 +162,9 @@ describe('SummaryPanel', () => { expect(typeElement).toBeVisible(); }); - it('displays type: Enterprise if the nodebalancer is premium_40GB', () => { + it('displays type: Enterprise if the nodebalancer is premium_40gb', () => { queryMocks.useNodeBalancerQuery.mockReturnValue({ - data: nodeBalancerFactory.build({ type: 'premium_40GB' }), + data: nodeBalancerFactory.build({ type: 'premium_40gb' }), }); const { getByText } = renderWithTheme(); diff --git a/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.tsx b/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.tsx index 2ef256ac4c2..46b759d43b5 100644 --- a/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.tsx +++ b/packages/manager/src/features/NodeBalancers/NodeBalancerDetail/NodeBalancerSummary/SummaryPanel.tsx @@ -112,7 +112,7 @@ export const SummaryPanel = () => { Type: {nodebalancer.type === 'common' && 'Basic'} {nodebalancer.type === 'premium' && 'Premium'} - {nodebalancer.type === 'premium_40GB' && 'Enterprise'} + {nodebalancer.type === 'premium_40gb' && 'Enterprise'} diff --git a/packages/manager/src/features/VPCs/VPCDetail/VPCSubnetsTable.tsx b/packages/manager/src/features/VPCs/VPCDetail/VPCSubnetsTable.tsx index fe49e01abee..37fea394caa 100644 --- a/packages/manager/src/features/VPCs/VPCDetail/VPCSubnetsTable.tsx +++ b/packages/manager/src/features/VPCs/VPCDetail/VPCSubnetsTable.tsx @@ -315,6 +315,13 @@ export const VPCSubnetsTable = (props: Props) => { const getTableItems = (): TableItem[] => { return subnets.data.map((subnet) => { + // NodeBalancers can have same VPC subnet as its frontend and backend configuration. + // and this can create duplicate entries in the resources count and also in the list of nodebalancers assigned to a subnet. + // To avoid this, we are creating a unique list of nodebalancers based on their id. + const uniqueNodebalancers = Array.from( + new Map(subnet.nodebalancers.map((nb) => [nb.id, nb])).values() + ); + const OuterTableCells = ( <> @@ -326,7 +333,7 @@ export const VPCSubnetsTable = (props: Props) => { )} - {`${isNodebalancerVPCEnabled ? subnet.linodes.length + subnet.nodebalancers.length : subnet.linodes.length}`} + {`${isNodebalancerVPCEnabled ? subnet.linodes.length + uniqueNodebalancers.length : subnet.linodes.length}`} @@ -336,7 +343,7 @@ export const VPCSubnetsTable = (props: Props) => { handleEdit={handleSubnetEdit} handleUnassignLinodes={handleSubnetUnassignLinodes} numLinodes={subnet.linodes.length} - numNodebalancers={subnet.nodebalancers.length} + numNodebalancers={uniqueNodebalancers.length} subnet={subnet} vpcId={vpcId} /> @@ -376,7 +383,7 @@ export const VPCSubnetsTable = (props: Props) => { )} - {isNodebalancerVPCEnabled && subnet.nodebalancers?.length > 0 && ( + {isNodebalancerVPCEnabled && uniqueNodebalancers.length > 0 && ( { {SubnetNodebalancerTableRowHead} - {subnet.nodebalancers.map((nb) => ( + {uniqueNodebalancers.map((nb) => ( ({ }), type: Factory.each((i) => { if (i === 1) { - return 'premium_40GB'; + return 'premium_40gb'; } if (i % 2 === 0) { return 'premium'; From 07ecd2b474185912066c4069e4ac46dd63ed5aac Mon Sep 17 00:00:00 2001 From: Harsh Shankar Rao Date: Tue, 10 Mar 2026 19:15:00 +0530 Subject: [PATCH 50/56] upcoming: [UIE-10151] Added new products to marketplace (#13475) * Add new products to marketplace * marketplace-bug-fixes * Revert "marketplace-bug-fixes" This reverts commit ae1b2108cc54f9a652e67649fd0fb7081943ced0. * Add changeset --- ...r-13475-upcoming-features-1773138396314.md | 11 ++ .../assets/marketplace/bitmovin-dark.svg | 20 ++++ .../assets/marketplace/bitmovin-light.svg | 20 ++++ .../marketplace/bitmovin-live-encoder.jpeg | Bin 0 -> 241495 bytes .../assets/marketplace/bitmovin-playback.jpeg | Bin 0 -> 212801 bytes .../marketplace/bitmovin-vod-encoder.jpeg | Bin 0 -> 241612 bytes .../assets/marketplace/cloudcasa-dark.svg | 31 ++++++ .../assets/marketplace/cloudcasa-diagram.jpeg | Bin 0 -> 153626 bytes .../assets/marketplace/cloudcasa-light.svg | 39 +++++++ .../marketplace/cloudcasa-process-flow.jpg | Bin 0 -> 117548 bytes .../marketplace/portainer-architecture.jpeg | Bin 0 -> 154965 bytes .../assets/marketplace/portainer-dark.svg | 10 ++ .../assets/marketplace/portainer-light.svg | 10 ++ .../ProductDetails/pages/cloudcasa.ts | 91 ++++++++++++++++ .../Marketplace/ProductDetails/pages/index.ts | 10 ++ .../ProductDetails/pages/live-encoder.ts | 78 ++++++++++++++ .../ProductDetails/pages/playback.ts | 79 ++++++++++++++ .../ProductDetails/pages/portainer.ts | 102 ++++++++++++++++++ .../ProductDetails/pages/vod-encoder.ts | 74 +++++++++++++ .../src/features/Marketplace/products.ts | 94 ++++++++++++++++ 20 files changed, 669 insertions(+) create mode 100644 packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md create mode 100644 packages/manager/public/assets/marketplace/bitmovin-dark.svg create mode 100644 packages/manager/public/assets/marketplace/bitmovin-light.svg create mode 100644 packages/manager/public/assets/marketplace/bitmovin-live-encoder.jpeg create mode 100644 packages/manager/public/assets/marketplace/bitmovin-playback.jpeg create mode 100644 packages/manager/public/assets/marketplace/bitmovin-vod-encoder.jpeg create mode 100644 packages/manager/public/assets/marketplace/cloudcasa-dark.svg create mode 100644 packages/manager/public/assets/marketplace/cloudcasa-diagram.jpeg create mode 100644 packages/manager/public/assets/marketplace/cloudcasa-light.svg create mode 100644 packages/manager/public/assets/marketplace/cloudcasa-process-flow.jpg create mode 100644 packages/manager/public/assets/marketplace/portainer-architecture.jpeg create mode 100644 packages/manager/public/assets/marketplace/portainer-dark.svg create mode 100644 packages/manager/public/assets/marketplace/portainer-light.svg create mode 100644 packages/manager/src/features/Marketplace/ProductDetails/pages/cloudcasa.ts create mode 100644 packages/manager/src/features/Marketplace/ProductDetails/pages/live-encoder.ts create mode 100644 packages/manager/src/features/Marketplace/ProductDetails/pages/playback.ts create mode 100644 packages/manager/src/features/Marketplace/ProductDetails/pages/portainer.ts create mode 100644 packages/manager/src/features/Marketplace/ProductDetails/pages/vod-encoder.ts diff --git a/packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md b/packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md new file mode 100644 index 00000000000..9509b7d6a18 --- /dev/null +++ b/packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md @@ -0,0 +1,11 @@ +--- +'@linode/manager': Upcoming Features +--- + +Add new Marketplace products ([#13475](https://github.com/linode/manager/pull/13475)) + +- CloudCasa +- Live Encoder +- Playback +- Portainer +- VOD Encoder diff --git a/packages/manager/public/assets/marketplace/bitmovin-dark.svg b/packages/manager/public/assets/marketplace/bitmovin-dark.svg new file mode 100644 index 00000000000..855edf634a8 --- /dev/null +++ b/packages/manager/public/assets/marketplace/bitmovin-dark.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/manager/public/assets/marketplace/bitmovin-light.svg b/packages/manager/public/assets/marketplace/bitmovin-light.svg new file mode 100644 index 00000000000..f0dd163ce53 --- /dev/null +++ b/packages/manager/public/assets/marketplace/bitmovin-light.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/manager/public/assets/marketplace/bitmovin-live-encoder.jpeg b/packages/manager/public/assets/marketplace/bitmovin-live-encoder.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..6d88dfad325a414bd3b0d2cdc0da747a1d228b24 GIT binary patch literal 241495 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

b$G1= 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 G&HW$5a^-3O literal 0 HcmV?d00001 diff --git a/packages/manager/public/assets/marketplace/bitmovin-playback.jpeg b/packages/manager/public/assets/marketplace/bitmovin-playback.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..aad039ac86b1f9b9e53811704ec65638ea2bbab9 GIT binary patch literal 212801 zcmeFZ2{@GB`#(PRgeKXNm-+uxmhbiZU)TTozn_}S^El6a?&WpvbKmzlC&pLCFk*sgLpI^6jiiY<_AqrW)`*J4CQcmF*)d=2AETWv(SeW)8 zn0c94c$paW2o&Igjp^t0^EL1f6Eh1d8#~7)&dpq)LCIDGGZPC7Gb;-l+eSA`KH&EV zR$jJkyAPgZ=hM5+vB#PJkY9AlCh=1RH3Ir=BnibEcl#X*)F%ntxYM>-P(q0)N!}3cr)2+Yg8Ba+N%ogu|B|a8p@Crjd9g49 zE3vQuOR<8Bje~9D;@HIT^V;FM6C41~H0hQ5YpAfkFA-Sr!L zE|V`uqz`6#*?&6KJ!r|AX)_*Y7<6XSdo@j;avZa_B6@Ml69$6$B?B>%z4~+=&pj@% z8zT@{5mR1Bm}sMA*BZJHJ=piTluOi-!}^nqV}83VNr7SuiLShEM=!K65Hwr@WSjr5 z+vuwd1Ou^|ix^L50aU9q36v}++CF3uYUy7+)i4moM~}mPD43bBCO(^1o4jkesR{4_ z(fk(4^bA#Z^myIbUy}XMREBqWH4zqxFQB1B24Zbbl|Q;@wRVw#IPjf7l6HdSV`1S{ zqT65nmFF+tzYk6EG7!Tu3`ES4C@$v(GZ%;?#X!7Asp0$XH`T#rN)UAs%|J*PSg)j# z83=nG6ijPnAU+5z9i%72g30B#hA0Bc41@qsF!v&<2=*(2h7E>jhUn$s`{=)jD@SpY zd;TJR9N!l^!hTzcE&|iOK|eIlKz7grwcfjYcP;>01P0yZJq6iCJrIYluPf8n-Y^hjq2X{Bw3RT0 zN`r>NqTsXnX_(nb(hCNnXgZuRJO4jaPi$SBa8ZSYDyC4_-EF((Am%%C5-KH`9VA}IlMaOigjptB%HiVkS> zfq@{&16yP|3$a08b`nTH)(=m#c8zX%Qv!NN!>89?!`)b3Em~bMmP&R8zg4QEUhzJI zTHMlxUT6T;m*{E7lRn`&k+eEss_M541f?89vC0pCmbicdm?r^9rvP%^$iTkiza$tu zCM4+Epg`kfAbv=Fl3FRHgrg@!Q-A71`&H}QUGh$-Mfo&9k`Rg(i#?C(O(OzaB$xr( z!od7OXCW&nKnlKo7l7p^K(o2gdQ%O0i9>tqpEKJYGNkk?&1~U*id1!5K)l+nlLd^y$Gl41&K|f&`HOxTJHyE!5`k|CVGg7So zQcly}k*jaweo_x1*fS6z8u0aUF=!?b;83E|fqIRmgIeVNLRe_nc+k@U$hM$4JQ)bf z4SU9dLGOYmH8T(#=qUj-%nlwlfHo#a#bMv{-v&OW#VbeVT7YOFKgjgg@LuFvkPUWq z1TYkn8NAX!NkC5sr$EDMpaV&xPKeYz#Lhtcq1LpYKx)Rb6Q=k8b-3_keaN-IDHH{H7udsa*@$+CPy?;AnnA-3O$@|N;C-yY zyyyF&4Zje3Boh17HKz*Lh2x|3$`?v1dP3+q&_xf>#Uq79G>;~!0R2Q>f{3xWO@QK_4Q=J2H^8IJ{BOG9 zOvs(ap-ISC~C211D2(gR`a{Nunf59wiKO7hk;t47E06o;YEp{2hl9e}@~1Qvla z!Xqu1G_10?a63Z_DKIOcxu3F%8cZ>9NFC8hZs$_D3oLevf9x z&}#A^k~$a*k(V&D5NX$Po8zB*2I9(5F4))d_b@t`G=LYw_veoQm?vljqe(j!0DyoJ z2k=51v|80;pj{6{OT=CWm=mLM09?qm!W;njiMCA{#($H5CsZGlYvt$bTur zp_4KN4**Z31?X(}C>_R}bvGDeeVc=F1BwJx_d5AK8xIvW(82J!*#fX8}>zGAcucy3+ zhfv$mQ%GVyjqRsuuhXll4n(cprvS(?IfBlPRDA{jIYilb7x1|qc-{@2Y=>JX;cM|| z%7H(OZw!wqW-Mhhu+XP8EN8b=!{iE`QjebCA>wIll^cemAEaoG@?Zd_c)Zm{|9K<;3VZi)Y=(TH)61f?(H zWi4X`&3uCdGlEqlj)fuv*Mu+-DJ9k;7cjB`%*&@|DBKYeg>jb8=irrAE)B!r}6V;KVJHhAs)&NHBZi$UiXoY zh_{9A-BFyD0kdnME0V@Qpy^Z;%}@sn4b=toOcnzny>!kYCVFCsl$XLl;DOBu77Rpa z8Z6L>UIgt|XCboTcP0G_(f?^1y?cUMPoUcJU>L%~^e9+5iehw;foKJTe5e38I-?hD znqN)C96(Grjaq{t>I#~Yg(jM70ImQCaljS=S7SAWuHW=1qshF2Cf68<1u#rTUj3bU zPhEcVz<;>;M>qfA=ASY3kH7g({q;Y-_`jaZ{?W}py7?!f`0qtqIY?fLzS`yn`S$Ub z3j3mLb>Dm}_Q2Th9pyZl_rQMf9&jeuCH)VHefwb_UWd{9r z7z1%qz%zEco+iKVMhHxLr`3Sl*Tl5)5*I84Q(#CthXS?3#V-ii7DVy#H7t>pp{8{H1|NArh zU7d=4s2-p+*Qdc)JiLa1_ok{Vk(GZ2!$0seT`$54dw}QnZu}|{O-aH~w3blo?0wKs z0O-*^W7?2`n4FyOL9Rz7gB-dBWZst;2*nyqg!cvXIQeX_y4goA;o z0)2$MYK^Qk>c0q4#{pmKA~0_&68a(!LS?2=z?uyM5pcI|Xo;&3ra$2H3Vb1GfG&*)%9Wmx-p6fc{PoZS}sYVuxWM zyrn>U>^Z1bkw{o)1)=+}5)d6l3U{}M{f?k1JR9_MuggH_3Doo%kd$ixQT;Hq*2Ml1 zp>Qo)JxEik#5W8rPUdUWfN$J^hIj!>hnFU4dj^F!Y9zrhixyB{J5(!2j9O_iaANDTo3jf{$1o zQ0I-`>bz7tw8YT?j3KB1?@g-hf^Yv#m9KFU?q8u6eGGL34ew3BNp9R-{&}~jDifFk zQ%hK4|MPw<%&V~3t*saoX4nAQLo$}_2rcNJYJ9%>OYBFO`qrJUaMv%U9snMPcCK{& zQG)#pnsVA3;Npb&@!w3^qKR8cptPg3Kx6$y(-YtFOO+=Ve#tFS)_@d^Oe)5&0@!Ju z#_e-oEX|jqlY#1avF1=Mim0&8Y&%5Z1c2bxW*|1X1wd0Apu#mQfd-1aerfIgPfP-9 z{{;G&B3Y;DU5N*J;TxcL2DhI=h5dg(LvIL_P$~<&b!Zdx1*r>QaTcP4VkjD_praFV z$_xa82(-GN$_dJtP^Rz#orCZbkN1WIyrF*Mc$nS*>}a4%#*QGq=K!~W8v*TQW}_&l zXrdb=6n~T02NWw)Ls(+!K$Eth;Jul8_(hKO=#9Y$5VV2DM(dH*`rQEIiO|9~?1s>C z-WsSy;op52^`S@s6h+u~2Nq@m=C0R=YI%nV>j+zj!U532t5xtHDK-R;OxAbwHHrwTwj09B&}ThbK(mnj>9qKWJz44rG;2xig%eHeP}U;Q;^{unz1 z2?TyH3R~!de0W29*C{pRT~Lc7mb$uO3oNK{)N&2u*M*AnY0SZ(Z5q54!|Fy_i320^ zB1Gn=KdlJBaqx;Ah@f6Pt1O!-8Xb?K1=g#dtlvH&lom8=A{+;gI?0$qvZR}hFy zBq=&q5(Y-p{8A>;OC9~(h8F3IV76JTr`@9fFRsB2SVRIA@sSLKpcbt~ z@s|>D4*^nSSwB4Gi~jnjGe|DEOwng^w%zy1;+fu;=IIkv9}VK^K?#uGN}Wwi3k`zf##%EI8crY@LxIv*tZp{fzz$= zOJcvL@U_Q~jZ-*Kg6(fQY3O2fqaLs!AhkNNp;_Q-N!eAx(3do@UQ!CAi)aIAC?iJE zH}62gTyg};0NQ?IUivp3)S-(pjZW*rd0?d!MY97$jT)hK;rU;;1PqwX3~2`dvl=G> zvz8mo=D&{$xz}Ba;`KJPwB)|G(!D;I#($tbMLbgJO|&7e0V3-;0pOw9?sTp(RhF z?{m2P5dw7pNg}k+q^cA8nL-(e9W;MX-~5Oi06(5H|6lkZ>!bS51GApA$1l%hFc9CB zT-QUWieSNlon%D655T2iM|(pr!O(7sy+MEP0qSWto>>-I0mhEu8P2D&OTj^1)FzYy zrS=EmEcCt9Yb^l!YKz9aUp==kmB68jNDbZh-}<})Z0Si+b7@&uLZRhtQ2EfuBo^O| z5h~_}U+#k9JS9Db>Ijs@N(Le?o0i?S&nx5>znnkaQm@ z*mrrrh>Oetp8x~BryZI?>N;}IC=u4!uRuMU2ur+1S&{J|8EM9>6NO-Z>1A#J#urSQ z{1-VsDNn*u@u=k$24Y<}KRtUw_XKe2E5lF+7>`p{RZsF|TyT9lM z1Hq3Tuz^BgEk@h=Lba5-8fg%kQm|kk(%K0Z?SITv1OF8*p8ax^pb*vk z=a@ZSJ${Q_il*}e2t|-WJO7kTrmjlL+qRg*o-P<+d-JeJ-S)?~Eq`8=}nu}2bXV`>9S`m{A*DRh!y-2G)R$_+g zA)Z;9^BTB1Fy{qxd@vZzi4ng4aU8pv`J=DBgnHLB{=-aK8~(hWrof_g_uqzq0Dp&u z19!a8Hd(#X>0{CF4K?**S}+Kv4^rtKLo|6OFu^aWZmbcpui$C-l5}T<)b@r}e^E6e zLIO3Ct%1v7JU6x*%f=X+Yq~sWI?COqh`4~fGK>@V_Mm8zVlTJ5pdVE2EooCIDGJ+X zWnxx1&sn9hL#0k^H0qFk$U~3eVLi9kd1Y$%0CW!g-78E~ULQqrQ&{SZ;DhAI6v4PO zTW60lx4YIi?Tn>K&x;fl*$gk5Bm`d6X7*LNA`?vUAWPMt1ZaxLa2(36&3?z}d9qyn zIdZfFKsW$93v=cn*Ihe+A|9*I&(aeK zWBwGW-)m90E4aQ%RPo*l2I6YD8ywSw&BPW-(H>%08Hle3(Mw122j4Id@Y$UFcGS89 zUMI1!*GK64n%ImcztM2Ur~kGm(nPO^pa-1B^*aHGU&Ye9VS_I_IsV=8$$W-Eyx;U} zlJ1HfzZ#Grt$covGR6OJCmH;DiAg9Y}i^MOBLmq1oAjsgXgF_k3JcGl|VPunmSs$YfG4cwehwLd&`Hv9-eg2ZzvLo)kxX2Wc&PimDl zJ%wP04<;13B=L(W7I!X8_9R8Z*FF7dIWzB$J<8)!IC@mQ^G=1Cn^D0#O@jhLLFb$}p~G=cMQH-x z&Mzt-M10RmnrL%GNAj3vZWN~eC7oGogsN#8g{$^TQ-t@4cKIhMy%@;l2Ide(npM6= zD7=6Lag%#_*WIhSR5iFQc{4qYru@o1tY)Qb1=Z^YS(KM{TAYqHd8DF}kbK(G5Z_7~bQ za&?~zlVddZ4~QTgDlJM6_Ek3PmUJ#ZvuZxq7B{#)?GpNJ_wLHZ>&0U}-^8?M+3lB+ zjSK`AZ8w>1Zh|aYRN0-Se=Ox;J$3t7rntZ2`}f0>qPpHZevcA`j`?4H4esfX3RrSbg z?Ynno`1NE|BPZ>$UVV^AMzF-#hfMLAm-0Ce^UQ7ynv3h2GLdM}lzqq#Sz4JL{ffp}yTN+r0Ts6bI%FnAr5ZVI7^OcCqN!9MS|82lnA?dq>0;jv1 z!y=!%NW3#*NnCu_O`~k1hK+^wT9JiKHf}g|vRqDSQfV>Xy2Rgdzr+#gnh?utn{1zH zfa>Dr6j5EDH1nN?e%03&RT9if9Sue;?{#$dP3OAanR@$1>e6ix-c0JA0>S#0<0A^R z*abc?KZslefrndu4fbpBiYW!6o&%kMyoR$oB?nYMYLC(5R&pva@1h{1HunXB?!H*IcP8t+JgjU=tgUAJcgbMl9hv0w~%FpEl{l*J-&>3 z%wP@7WYo)U^WyU!EKbzM@>dn7F035L%9l*3K>IlotkC_|b?WRC<@`ar_v?@2_zU8Z z=xCokxed>T{q#`0mS1NtW*L&w@2C&bOH?t`!?px|Z{c*BE$LqVh$wb8y46zsnMxgt zsrH@syWX2-yJq(nrQ8UC5^evTrL{ziY(^dJuryS{O_T$;KUvs+x)s45{6S&%FDX&*tZ zWx=K>AG8XG+uT;vB?>6o!_5Qsr@B?uRIXyL_L?8gQ9dweD%0qf^6+ef+a2K(t>@OQ zS8mXARh37vex8GAhlBFvdTKG8-xuwR29)mTylQr`IDU@wHaaosOwq#${TK19t4$A~ z8biX^36cUmNFL1nC-OmhIti+8t6I=1i-|hcT9ij%Z7|~@fyUoI{D$;saF02ksZj00 z?BhODE@!3cU2cibEN@0ieiM?CZMmIw;>J5 zxHD+}u5nSgba$=FjU$H?`G1gus2?h-LGyUAEu^Y!Vw9MDUtYYuk7v*0$IPY)`Zr1k zFIAkW=$tdMTB|0$emf=e9dBIbCauCG~IpG6AHtTK6;fpR@MsAtzp$6es8Y4};;x*;lLbi@e zNWXYxS!cmib`51sp;FJ&4$+^vRG1P(TGc+MymCBp<#KYi+}L!b(i8KxZIY@&_k>mV z-Pn}h4271O z@e$DQ3s0lK%G;WsL&P$P&6^zN*{486>oCt&h2+`UbEy3FluooxuV(T372=#kthtlL zG{geZ@e4Q}_o%D)wa8~8vfZr)iT?5_2P3EZj;KxWq7Dkt)3uszv+H^-%yChT-E~%6 z;p#VJ!Qd?WBVyvAwz3N@MJzQ5_qL_Kh&v{;r!e|q^;4I_iwiXVnL6C|*kP-%e6y3R zDtS-x`mflwXYGsqkStu;@2ct@XtCwQ!uEXm9vV+J4Y&Y*Yl^i=XWV3WCCWiP+o~nQ zqp*E`-r?M2UQI?s-K*n5UjtIuALTy(_9CBeDZddV28%GmuqUrXJ<_cIJAj!`lZId5E{g zh$Tspj;O*a1==ChCc2;Vr@PbT4w_`D`GrMejKp0##cxVv4T+q&{byv&ofi=T zw-MC>@29b(OX&MYaL6LEKxssdnVoXkrBg{-^MdXv!PW~C56`}TFdo{-K5--BAqP-= z9brv#A)GL?GRi>c%-Q!s!%1SyB-f$pPxkdHLDAM;uk6a_x}J5e9*}5Rd3_RbR^1X^ z!8Q=ODtq@U$39Idsc+}>+vJ-%@I~=+Skl5uOj)NK?J!SwT+a7%g#)(n{i?0IKX)Zb zow|H>)jP-C@|NR8VI7~7*Z>Biz_3zGjQ&+%E+m5-~?D&168|WnI^wQ9%&+fdv$? z{X2dZQ1a-dpV2lBE>K6_GX~;CLC-|c1~UiL1V zWnOY4CJp+}#Qo>lzhEFxO9Ms1hf3(>CHy)|kE@wNJ!*{w%+Xj-V12H3 z_>E#tI|$i@!Ax(q2duJaUd>YZw>8|(10ZjBxRDs5WbLG2sa5pyn$$+Bpyr*CsZ28v z`g3pTk$7(ruE58++tO}1QR07=P&&|tKhxT=|63n}5__AI+nF*`k5>t6;BN(}!*!Yp|zXCkfSsMfJtk4vNwvTUYM0WPE$?;uWIcAa{6s zo^XT z&>#GM;0a5c)9Pakwt7V8n{F<$nBatpEJxRxf>8Z?d5^CPa;KKJg2Hw9Ti7S6ME9r7 z_qR${J0TZ6hpi8fK_q>=C}n=KCJA|elvD@RihBtr=IG>SeHd@ZRPO7TH7yvQ{K!PQ zFpE03h@$MjTH-unin?DVUQu==cDkHrV77E@>vgZdqUcx-{G-xilcDQg@MbBnjW|68 zM6A|lLBwh@vt8mXk5&JKCg!Wih*Le45Oidax0@!i7f(bZZH(MJFI3G)H@#|+PYl1F z;9)H?H2;)_zq07W4%KL@i@UcsUG7jq23ebt&u)DtqubWd)q8V~hO_GT9jZY`?=>EI z#TG^%XF0r_KO1n89zolCvX!R2ynD@Tz^INuI;Z0<(tz4J-^>3=G$?V0y1J#d{DV^0UUb)Zcx5V9QM`b*95sA;}C*vONX4l zfip{2BOxZk4_h2f9YZGK@_iE5*{B9^ck*_6l1sMC`52yXMbSHZp zDKK8W{d~XmwG-9cbz}DcYkuDDB+16OT$&X{Yi}Ge!mzf^nP2(dC6(6$3CS}q`bRMd zyL;bk$vP&cOSOBK7f-$8u3$iZeVsV2E|PpXVM07Z(;e3q{*;Z)^8M)3v#!^`#n3ihu?U6$>^>Aqi20yJFvyr zIqPh1d5Y=qLO8^|^aRC6v2WPsfl=#>IsK)$&7*Xb^Xay2h7XnZO$%k_n@5e#KVl$? zFf=8F*zI93Z(a5iT?Rs`|FruNP%xXBTs=0EL@67#u6<@Sl0oB3U9EBZQt@pd0<5f^ zJcBy$xcmEL8E2z`j}8aId@3R;>>Ryp;!s9gwxQ!wp?dyW5Kc4)hJ^+Fp}i)hRKU zzr)P;VKci5lPL!=h9&`w<1>RpK1S`OxgUb5`adJ6z>GxW)q_QAATo4i^Dd$8gg!*k zJQ#?4^j7HmBfVz9C+1Badt+x^tG0vpBWUNyWkCya-Xf%rx=^ExbGeA9v`ocUxmjK# zpN87n-2E-#yoUE8(-W?1crp;PnbbRj-VWq}rrMzgo~&XhGM~f`$87~HwKq< zd5RC2nVl`r+!i0BwcAkOjLtz-1cyX&oSe5MRm0?)w*iGfT3zv|iWxy|o_>v`MAf(T zSDfitDR=BDE4Dr*eBI-#M`bvz;_NjZ1H-RR3e^L?;0}Sp#RZUgZ(0qibRrHI8OR!# znAklo6XMpAy5;=dq+kd!O!COfsK?2X^6$?%EL582d|#I=>8drUIg;io@Z!$5_rfv! zwk8^9YmBp)jeTz)Jxokiqd&rNQV2Dd+_5^Om$A>UnpO|>s=SQ16^$DY?BlLGgkjDJ z$ni6|zYT>taCi}#iylVvQ^JOgYLP+eid`e`dR#GL?p~*=x>C<@%Jv-TDQ%pzzx%e# z={kLOH1t)Y+>1nceVt27k#BoxSmJS~ZKjkXlUF)Y$!y=)r-#mYy?G4V2;H;Pxie_L z>uc||7v34kJnjp#pU8VwM>uLeDeIAsuU*|mTEske53zDe7R6|*pP$gja8Cs?vhj5{Ft2 zE{pP{0p=%NeMZk86}88F$#G+)UPuQTI^L=|BqKe46wDb$wO7?h=qLw?DiZpE3t_8i zy@Af&L=T?6#+E}Y35li3Mb~c@VQ;h4d#1&K9vn!B%xJpOiSZs(0+r;EDtQ6^-eMuh;})~=ghDosYAEjHzkq$4Dg z)3UEzG28P#yt|_qwaxa*4K4??L3@eN!6P#_nRhG61x3Ue#b|$E z#_#EWbyuyG04n3}UxUcwueHtmx}h*F6hF-pO#kee3`DxV(Yyd|r?)AZ?5YX|=AVaG z`R?JcBf->MBpLml(Xn1cT!b1RBA&`^3{5TNcWtI+Q#_%OVRvh|P7t+zF>XB*o9kWz zuY$OOi`Lqxy8Uv^4Rk$WV;Swor4>+a`VkeuHCjrNY^BK*?dxJ~6A~QbY(YF5+2b+r z)MZk*>2Qy4E!~=z8+|BB@!Z1c{H~{zEVwp2`_5aFtIcjxp6|T#sb=<7J3HVV^3hq1 zdpk?GUiIrY23qbS7aF3+pQSn^9LE!Anggi)PDXUn`Z&g+E>_lbO`PhMC$rd1*R$ ziG4PDbSdM*_UYE5O39H3sm7`u9o|MMIul=~AAfh|a$_pb-qI2gcfHq7pw`=((niGi z!2%dQN{ZDR>ggE=TWdT1R@E1RN56e!&hj@2sUE&_mV>-n?L@_(xEqJK;v2AEQ-P>x{ ztU&VOlI_*c4iCuOk9I~6D&=S7Ly4=2Se_hB_u9Lc=X@}2bUt{q45^)JT+*?OM@}c1 zr`Kol4GIO_^gYJn^=fyi{GEn7)m!+JWtR3F+h$;Ly05c z?_;M0g)SE;1q2{f&xacOp1p`U$~sztJ4z8>;iMP9JLqLF*cDW-%ThPgr)~s_QAH)@ z=Z0E;D6e^~81wY2HuWbziOR)ww_Q1v7FxLHqW(8p3<*o)s~AxZfp?j@53R(JJJt8< z*ow!PdU=KAp0e)@ER)@4c2$cva?A59aqkydbDxPb=#rt?FfwX%5-bRCQ95dpB7-fj zr`nSGFk=rMJBsza8zBF!L!BWI{O>w1){=|`iutg)j zPF*>Yxg{=Vs^{g(N1f-5-R9(k!TsmhU3ea9WEHSE7f(jXQ)EcUm4~F&8q@;c5rz8cW({vs=ZeCU2M-PRp z7>J#?&tgL4y)=~bn z!^8#lUJA?kf(RuMIW?E}vtJ!G>t8cO3{`)kJi_u2P<=llP6b`&{Z1?#>K!Fpnk3#@CN`?p)LLuayhfw>O4 z?&R(y%-xnf_oJrqjPtWDx4)e@{YvqIPuxQ<*P!EWUHqC8bp$L${@eLg)Zb65=4+>h zy)IPk|927w|9&#;-QH07+V_i2e?O3_2NuTubrN+cX z>_6Q6I;{JDPd8+RZSFVJ*f&|}+*eK-zis4rKyljs>nt?-aR`1Z1^a`|4%h`5wh)@C!w-2;Tyrqc?j+fsG`0TU%t5E zLGmBCKB0MIY{0_g!4blmVkp&Nnh40TFdcFd zUclyKjm`zC>n0Fp9&1gEtgvKFe$r_)y&8p+qzDlsANKV`x;}A`9%5}QEVW9=Hw=|* ziBT@x--MGPWv^sWCQ1Dxga?|dzLhA!2W=H15hks19#Bu>u8_*OvB|qmkA}Ugxs6JE zUy{Yf&zifz1dShNRJpW=UF(fTA!ARdLhl#|HFSNI^&D8ShQifZC>_M25hrG>NWu+g zfv(Et@qsHJ&)m}$yTB>BNjBnh_tC@C0&B-WN#Y|36Mic=tZJ9t<&NH|9mPjV@5vpw zY1(_;Lv%cRC&yX8e!|O%YZ*Z-%aLymc8Z@V&a4>_UrH8hk+Hb5?*8<&$4zkf9ZDvG zSaA0oDh5TGMkB$Ni!)%yXU%zt7JD_AGz4?Tk}_(q?ker^w#*x%6dpfzy5Orevq|6C zX8%;z%h6*OJ)}i7TyEu^q|2t3xK6AmW*sm`Mluj~3cW(Q^p{SRYF=I=CY5MVjG!rB zOx3U|+oN}-`#bs z`KhJJ*XFwm#bQ4kbpgc&9v?(U6byHmo3@UO!#V_AD;7SIep>r}p!_{qsf*X@PH6{Sg`4 zTfL2Xm-JU+-p%g}?N)c8r=qQ}AOS7L-FL`v&;IylBys%Tr$$i$bXP4>19n`$+=r3HAshM9(9hmvUX z@i1rEu&uhBa(xs ziA$nR8U;P$Jv~<{Lg!vQ?s7PPX5Wef)6Lj>o|Ajt*rUGIoiC)P_pd~WNk5x6)q8Rg z{y^RKU{Q&Oz4iE~&xl)-)}=CYS^KHl<`qEmAHd?!#f?RdpBt!*nt%Z=$BsC$(N2<- z=R}ARdnd1!ko>W>$r2s6Vn0>-pf2h?33I1>>&{E>)so%xnb$b#^}ejIqBlw9>e6JP zxdu`YNaBC=(e{*Akn!OQDeg-V>`l6rRE>exwI1+Iy&UH=W5U|E<~VE)hf%>oRxNhp zT+{5*Ao@r~eFWLGrZtO8Qs!3tt+Ksfw@>eBi{hP6N7ZKL-E-!4CFwl47J1C7Cc2Bc zX!PX>J7)B<^xK$TuDEx-YaUb$sYrDpnm$<>tnvhRw;cJ8q7 zS=OzE#?2EI_a9OmnPb$P%t?9C!%ls7SA0m0enPPsHp#+d(ZIshA9J%KCrrDZ2wQZ< zXpi*_@LyU%U3vhOu1Q+0+XHyr*6*RPWq; z!Tw&!7Nc)85;g+Gt-b~K6)iZAlbrc7O zUW?c)jnIHxy@DEnq8Xj*u|#5PJ&KzT%>Pf2^nK^(#`z!7!Pe-lm0(Hx`ZM4h&ut?Z z$t)8D8Hhm=*nR{hQWowPlydRHl4}60*cep7#)2lBH=cTf;#KDvU#ng6>Bh|xLc6@U z!x8;M?ahj;Ue4b__#KZ@sQ#tZjnQnGRt1Mf#naI&0czrJ@_JaUn-*B z=sQmAc9kVoF(pbbPUWEY=X-^=j#COXhwjYk4 zC!fry^URd>wVrs)dCrmR*>k_APj5bLMg>->!|ky8>#%x~oe-aNlf#j8x0`Zuw{lqo zt#*rt%0{%D@_X0HqDC;qZT40uplFfcy4uH7iOQxvSCIhJ%z`9K%dO#U*}fsk_x80O z9>bRA#g95@47)D(_|MPFH9m0_n8*|;D%4hgw&P9Qofq3)wZt4+k`7pD@F_*rpBEEX zarZ9cy6|*bC+@N>*8EtKp6*c5<8t%lMk9UcVw)O?{z9jerHlaD!8D3O-4&-mrA?=I z;Nlz~f06Qeb<9ewH_{|ZzdrUu9@i+Q2E##fAtjJ9!YV1J`Eoy{kEa;EEloVhn&N6H zJ$%>Z= z9Dg};`O3?*T>GT-cP~CD_Fh<-;i=ZZ%b$7}^tCBy^GWetyxoM8qmf6`j8iW@@RiOA zXJhe2h$8scWx`ZO&bKN*l1#kpdd$gwscKz*Y~t8wWmNO>$4IjZYv+G|Xj^|u?8iMvF1Prd%iC1Pn=CWt^tE}VyqjQq z9M3le%XPTWr7pE?>z?R4&LZDC_fkIQ;I@jV_0zr&ofjiz7BcdN|&zR?MT-SJBw|ogw(%`h_Vy0D$U$*iXuPtsf9n@01(N8M$Ht$}}soUiZP zKQ51R&@qkMrgTkZE@aQH(WnE|9uV2H2^L|4@Jv-g-n+gSzl?TJe$;=VLt#ZXOHEc2k$H4O$t7at(!>C>A5*4*j}e@Sr+#s z;M=@#WV^wrTL-#O>wYoVWc2weQ(@b66#Nk{rJ zt%0gA+c{El91&Ep+>s;fQQM2VO0w-K@)H4@di!;}to-$jSl_eNm^VFpm3EYc=gv8^ z5YEMhyGMMosn&2ul^i{(xOMZ8`=xUoC0ach??SJ?@^}+&DtkU%HIpxPV&|k9oA(2- zp6k?i?_-1N$t;?ruTAaYH(n{%Gi$g`)ZKPIUew6%zv&il=zVxII`k(LD&`<@)zdTS(ozLB%UncDtDJ6V&e z2zQII(_bt#zbel5P{Q(lkIpGuSF88GY@86tcXHq6y}{0#P3;N`m>yZ`_~>DS)Wte- zaY(4J zf9Z$L2*=!aa?e>x$B0wF5R%53;U427V(_k@IH<3CeSY0NSGaIO#zR{|`tgly-$U*K z))@M0$l=Kos=ZgfpK`Q@Y}<<%QI;zryb0{LV*UJDRgK;n;(#jqW*($X#vHHhtXL zt{Ir0ah5fZt^DyO?9un14@R4B%dmXmXdyf>Bfh*jlm@WspG28#9ONVS_|MT~MtF?Q zg!=3qACJPkOX|9LU7h7XNasP8@T5_Kt%5(gL@1Dkbfs#$H;t&(bPAg4Jk!v6{kFV# z$Em^d(Ha8TvVNO_wDmR_p5Iw&JRW&4&E<(#QhBL^sl_ULD6N+yH0LqGh5YJ2I;!FSb~Ed0iW_@ymcHlwAn&LCFW-xCHvkMq7g|Mi=Jj zWRd#vM}sPrBy5n&;mFfvMT*)EcJez;I&j}>`{Y>ou~{T>uNzNOiXlfq*T7WZ+>ydg zdRHnz5atC-dGDyQxK6>LqNaKRpP74F?RxHbZh+!I#Yb_tjceujEAE^H#NtkgHm8G8 zPk$I*&4qg*VRc#Wv-Ff(kd;DUQb}W!UF_Gdm=*irQmW4x_K*;*0Ywxws+WVY+ zPxgbkXYLL98lU6_eq1v@7&T|nF3$`Pr9}h-1`je@ zKls@j-hLr{VBQJ<-YV4^pi?Gu6N6f=?H8Vu7rX2~oR}x2gIykf3n1guegq}Ex!qqJ zSa^O|RlX|!XHp}AlROECn+$ERdFUjsRvjH9Jxol=1WSOtxt}%+-Ls) zb}No$k)3E5h}`1(%d8J^JkLx@QZX+8|D4nqRfXV_A`rPpdfNbqgrJ1~EsOahoB8iP zngCJk@3JRT=|7}U2B(_gs(`JsYTwZsx~q|;Vf#;<#+T}C)xY?4Kv?iUXHNc4p8Ev_ z2vNQ=BG>DXB4s0gK6+O}?fEA-)(jkpUZimV@HW;%v-ZD9D*q8t|IdzTvPrjo{S&}P zYqMSTB_QHX4WNY8`=wRFAub}Z*|{fvUQ4#a04v2BK#~C#%XcmF8`9nXp9J@^jnVUO z>i~AmIQXYMsmS<3aNBlEuisgL|xh1^2pb5de9Je>oDo zt8^9MW$sJvNuUMEYGc4=KHFZZZ=NF>GUfJpZ35aYV*f&|>1nE{M2F&oGS%~6Ti8o^ z;5+4q=qN%m2DffSh}#33!}aEKnP6c36f1&uA+&H@>)>7O3+)1c2jtUzW#a>#dN{%t z{^+D(LO4^0sO4M{VK%%+yEAJc-PydyC=y=6d>XqiV#{w6jY5s02 z%2NIq`UCne(g~*&_OY$VF{73y0hcONO!}F&iI^Ajtdg+|oB z)s6=}t*GDd=~nBl=vZC4yKjQd-aa5F)$f8;;7a(>g_=#(c@+h94apvxPQiqA>)}g| z6(P=VU+=zn{TqepIj1vu57BxE21E;(p-DiEXFE}mIA|9a&ADm3Ir!koV0YD}=LLME zK@OVG^9I3K2YZLYaZJ%_HNnbi@=XGlpjLv|cVAPjQzp#Uub8cxe_QMEzJFkzw6#cL z4Q)X~qfRyrcP7aCdjW_rp#)`zKcahy;yDT$ic>~;F}p?;zY`$KLX`F={SKw(j@8>nA1tfA# zh@R8(@^Po^y=$v=sYIc%jaJi>o=#PliB^z=K4vC=C!adWft$|TI%E6SSghBM;2hNp zM$bg;g}t{`!#V}1RToEAHt7fw>-$T@C0rsCN$9(mL&U_G>&Ui$Sf8YD`*L0OLsu5A zioEJc(A)kyzP?eX;hm*&7v6SJrOY zb=87x%qNjGpb!Nlh^VRmsfn0bKvKhJ-K!nSA9|h76NeSB@-)9M7O#1pmd1x4d&!({ zC)7=(%Wy}ddr-|37w?8Em4`lTCHqokNV>mz_n5}Jxb2zwR+Yik_O^i0$JX_XEsm*o zlh)3hZ$~Pl1sddz+dfd31awt< zD=sw^os?GEIxKK*1mn^BA;ag4P_Bw2__a~mFT2p~knrUPZzv4D8D~A9x>|i%S?EpW z=;M8qts>ZYFk1vX1yjx=|Ky`5g6bXcK}<#&`dFOYtT=NO zPjqMIfCF{%9n^IJ$B#?=Fw8SiB+ikR$Mq0Zptl;r(h>-!Ig-P#}{GwxbjiJ8^@|?kQ7|< zag^nvmi(vjJH3;XxY9@Nk)AyFF4?Tm-{4IgLVqgi@M0y_;6&T{!gIvY=_W>uE)~+bS$I>NlOxiX3-SI&H8!h}$;OK_OqjJK|r+bgU(p_6uQ3clSBEe&y9mV1*R zICXlno}O+sSz*w-uNWLarb5qah&6Tm!;@LG8<9)(*D$L|`}r5#P) ztl}uQG5qjZ_ic1H)to?(iRrsHo8IqxI_Ndcxe~) z5SVT73Zs#xvzy;n&C>g4>O7!L_iy{3LA$DKX6!Rs&qrbmDBVPD37+9a$VWzu)o=G3 zZ%;6n_dPD0PYB+TeYqnh6+@JwzJ9R*g_{N99G4T;cC(4ZHb``xSG2F#fU!ol*BecH z;kd829vLQB`m3DPRyo5y529=0h4FSED-W>Q&K*1oIkk$}?_FM4VvAeT?^;K1oJt)K zKO>m5FD4s5X-*MhEk6+8g=eTLKTwQB{jd`qm>VG}6i>KK_fWwH`4+h1k>#PbeiuTpPwj9CzEXFf-y z!9o}s)bnE@c(w#Mk)Qj)2`&J7$7iWZBHb zd)Lj%Y3-REmzVqnb(%t-;|O2*Mq40!m9faEI_8bW0%G-6;DymWMs+`N_;P}E;g`XD zIqiYdyeC2;N-dO;%8R4!$7TRWPZTh+p@F&2qcEimhWOcNlK8x>(D60fizAZaGI@2` z(B+CJ^r%d}q$^$Lu=Gz_9vEunt?~7l1yyGgl-dFymCGo6glRRowHzN@UC&B8W^+>J zUUBC1arMjb@6g_$(R^6sd^$#!b}h*TAw}>H&s)1suisHI>&AnM zmi3c9*GNh>l6rKjCgtNkp|xbG;DO-1f@i%h`>rLCa$_fUa?OHD+PBU<-#r^1(etWz zbNWhx&mjBGK?iz56(b-(R9%qeA_)_8BGoieM7I%!#0qP>mg1=A=~u4b>9_7_knO$R z3CY|+r6|lY!S(UTjp@0*Fvz)08ItNdSnmA0Y}|d91N_t!1}A+pP*hi7Yr@hzzR6e> z`&BWia_$JSS%KHV=|rNPyw17XapTFaaoxXBFk>C}B})}&R8_by)rHd3q|Vb1>PTqN zt30rg$Ktn1u}97)fs=q0 zNL6V}dq(&#Z1~p~f)j2F5F;Ca%)x=F&Sq?PkE#%pg(x;UPDz6 zmL+JOj6@Q17m>dW9|hq0fhHQ^IAFRO|Bgosp@xr0nM7Y70yA)v?DGr)3eLQ1Cy!90 zaGSqLuNUpkmpmYV<{>YD73}c*(GOq^J4G}*{!8Vr+^cSPR12Ar*S64XCjYkouFJ+21b&I&+{p%THL z%VG&dwp9f6cc0+u?+Y%@teIAF>iI^KKYl*^g!|54|JnNs*PKHPP+?+mK{7V@I4nTD z+Mx5I1DzSYqZ_9OLWGMoi$46CucgnSf^Sey|Hp)G9kM!N?$NqeyIuF znz7a|9|lQmdB^n9_t`Ruhn$)apiTM#3Z}l55H$`U29@BepB@siz8s!5OYFzQiq^ghwzda zx!|GKqUIEf`|AUa^BVGc=KRb#-Ff-ogd?@q;w zv@)DmiS_T3`+94(!UsB?^=RRJSyP#**QHC}Ukz3US`yL6^2nAOYD)MD+;DE|cHA{Z z)IR!bzQy?TDjq9T)o|;1=)8Dgcz!Zy??GJX8&CQh(u+CQ2ug9txwq&_>R3Q?uUj{$ zCYk?X^0gyDVjB?Aa0v&YS}g&tsq?8{ifxNy!mrZ*)7ENsl0=!2Ph1Ad zo$WBMN_4!lMCt7zAkd&PD6bk+6T)K*%5ShY7971i_vS}Ami(I;=KB`Jk5@`Qxt>&*r5yUxy&S*g|C}$ z34IYi6VG4DRJE2Vb)ed59eD6(>a|T_ZnM#|r@^hZV{jFGb|oRJ;L{KPD|NYdyJ;^b zzZWp&mX5&5IL-HUCyrroMQz}CbS2YUU@y2;9;B`yTHEwFAU;24X9veaJ1_?R_TB21 zE_2GRgp9=&c9TlsypUFc0&Udk55>(Cz7+navn_{mPl;3a-O_f-IQ<2c(N1j@C_y+;}6~ zp)$XCFWf2<1z|zUx7w(Oiokq~Qj)82aV z4_7u>e~fMtH%+RpD>)k$L6LC%{eJB9j%3RGE|`OS4lXxJmH^^uRUkP4xT`l0tg3Qj zM29v@FWUBbLpg>EqA3<@qiV08lA04+x24%gJbnznOa$ZAHTd9Kk;XMcBn9bp3oI16 z!Z23m6qGBasFNhDoKI$%AhapYjWAa5J9bUh^t}^2wx`7V2sekWvO^@G`casf+S5%~hUVeLiRPB~+ zQU6|=&Sav(=>8&Vyl6qE1359LatsO|qbImzq(GR?Za4L0VLF>jIt zT@dW7;#_v@P+=z+Z3Gd}dM7VPeha9GSw5(&FS1(wQy|OqJ9qaIRx!*)#!WWDH*S8- z)2EYms&%%i(+gdn3S@f~xTN_X1;>A&ovW&fwhtBNXBWE8Zt|3Z>dA~8(HP%7FZH5l zp^yH@5ou(-n!AcY%=1!wpsJb9y|r4EX62qsrfwPi@q98v!$C`M!Uf;%_UM384So+ykTU~4@Iq-N*-X^msk9p zYE`i9S;GnsHA&zDo;UauDuyqp^I&WTv%@lNwI@_xg@s&y{8^G>LG-K&e>~U&Rh`K& zuIlw3Ak{+=BX(zrd-yI)E1Kcs9&f24_I}lnU;OR0u@?5qc(zV2_fFx?3(gN=p!!37 z#<5M39v;(%WCcX#O*E0MBRh7pFz>nbcLVIQQur42pDZ85C@U`7a9>urK+CO6^K)l% z4%M=5#F$HinM-6w+E+E#Lscs4ovYkasc!YKYMU0&>oVPVpxi6@<@-;5W(<#MQ#h{i z+MwPbl&!QeJB|+OMPI>j;bNSGn3SIKnPdZjap9L{-_$dqwQ_i)xh6DFZaf0Gj;8LS z9Y$wonR#6M>uj-XM-}{f!_j(zildTV0!tF~wNcbG)pSSe`v%DHoJ&Mkf+QAnwu#*a zu2Bu;STPD(t;*~%Q@@eMoxKpb2^Kqt)BpUe``OsS7Swq^h{!%KZDkN(Lqy{0r*8)A zihRkuQ{$Yvn>@gu+wkydTBkZQ`zqe$NUQp#yres?OXcwM$yoVtj;Wj4gIrOJnY7B1 zaSm1DW=8HOI3B1c0)X*aM8V5IsyhX6t!gDsqRLcTkxXO|kp@t>hZ3E2@GFxI=qlu+ zG3&8Ivf;Mux1IA!8#9vu&b$fNGB(_=r7Wi;`7U(x0x{NIi@)Y+r-;VKPe8=4J+Ob% zpRa7x147S}Ij>`?BEZ1!Q1jUPA4Y6%)B+=pe~tLv;_m=3MY^?Q_u@B-L675)M~a<~ zQ6w;c?!E-j-P3Tff6NL0yT|{}qPr4}OVd?=xy)#?l;VDW!@$=m3GI-IEBh3W2K8zj zzhvs!=3F2wECA(NjWaN)pMlqjs%gVioqsCp^NgkR5|$e~^N{%$VF@7|f*`CcU>RDK z3vdae4w5U$f?vLGaOKKiwEZih&HJ;t^hKKv?0?YQ-rbG|u~r$y&Ys^x@~#<@O^15; zYiI@b_HP;61&W$A+@;(L@DTERy6*nJ!kHK#fz zMRN8g%YNVCu-LZX{V`atp;2|rO}ak#bNZewYnuiaL7@EYtwFa8 zfs|tIJxND9-78$9%V$1h7v!*A5dvQ@2b?k(2--ZpCgLM8{j1KrCGWCd=KFnc8~xFj zWswE=3Zi(*?iYzx*BDL~)%maGOdG9cHVc3O7X2)PB@xqd5F1ovCreY1q^m)?S7eez zhY>%D3#HpAA%OPTiB&;!sF-pX$BsX_o!|-mb_b!0>emZ3{sEyDN^Gq4InV}sN)iDH zA$|JU6_)1q-TTSQVL@N&OThAjMomX{*gYl6C%1g2J}Xz3${#+ev-PtxkRP4?4k)~c ztn2^f^1+{h{{Mf#{*ntulL7P7+Zf361+DMP?!l1u6pdWA;@b^oQT1g7H?JuUlpiI^ z35HSysi`K7_R2}9IPosLmwYNciO{n}Yj*cmSgANsmua9eR7kt-<&7rictk&_#vZ>_ z7%+zplcX9Ru8>!fU1pkTv zap92B&mUcLx3oVNhmD)i@4D?Vha+j=L4*_=D0A}!a^fs6&(4FmcZZ4*#KSEw~nljENP|Kxc7<3+gir;8R zwmxdq#6Wn+GBAxzFE!QqlZV3?8Zj^7G*0^y;v?tiBP2`4iNZ-H8hVW6cQZp!5>b3S zh${bX#jX%B_6Vq-J6%9&1MgFIb~b!_ww^m&skq!pZua z$-1;T3Q7KzNo{Q*7!~6_l-2GVT@}9b#%+9zn5p~eA98v%NM7_wdV03Ds;hpBKM_Wz zfl3_CYT&rXD~R>Vx1xUe!`At`R%D$$SuH?(EJ(7dCsyE}_O4jI>MM1*mn}ioQ3;H@ zU3wN9*baoFQcqi%Ll%OlJF z)^a|U%TFLRO+bDSrpE5MpTqcFzLA>lvYqtRUS4?*->%juCds0_%J;@SQ&F0!7Qal; zL(_n;zZnh&WH0J9H&B~;zV7Hi~X1AH(%l%<2$(dsLceP3ozQaPfU2|7Y41@l8(p&zfrI> zF~fC;2KLZnFzK?_Sy+J1aH-?4-)iN$HMhW;uBfgQ>8qW2c1(T!){7T+A8XT{+#qt! zxr3r}%b6n^PQ8a(_-)g7J2pnZ-(T9L^nSL^muVAJ8l2?i<>g90Innl_?e#=bu_?ET zGT_~pH5x)5;7Q*+RRojyO74AX+Vp;2T!D=f;+i}x6w{_9vO_ghe!)RBJ&xsiAKSI8 zPAwODj(X?ay}3ZAUld9~uAgz8z<6)qccmZ@3Ewv65L zfugPYJ@6R~Hu32w4owQrK^5ksEi};<} zy4(xOAP+>35<-k%)B;E=U@L792DmtWer8vzHq0pH27q6EF7xARW0g<5m?pa@KE9NK zVQJ%|KVix>7%VH&FUhoU%219kf8SJCloH-ZVBUW?pmCAtjKfAKFe3I_Wg{b~Lzg=#&E-0w z9-nk1bU_C!LKnN@&V)3drv0D@t|*FE0BAiwu5EYZMl0E=4ysAR>e5mQWKy67lP67l zQ8F?U(_>Q&mR)fdw^lp{x)7+mL|5ssQ~@1leBR990wSMK;AS}JCcqzt!5Zy^+_Law z#AYvVbqZ(K`yVeiM3H-e@FsPu2#VLAPn~^6QYx`E2oi~uNp%0H>8#%E`D(0FHGfj5 zTuKO&S1!ynyw}6_a?Cq_1%OMP(9~`qN`QK+w{DeC`raz-SZ_qeGcF@Yr zBkE8IeHw7g5&z`@JWIL>IHLGwgBMEm?+ntJpGX6%!#}z%A42wDo)k(W7_3&w ztoWQ9xITfkt?=RZO0h7NOJi?x9>20b_uyvng@Omy1!;Vr#Cm=;C@AZ5Cq@!90obTD zp0Pm(D8W^J-w31~l|Al!t$kaQWmzwmZ!_LvAIsU=-ryAELg3}AU3}Se;BJ z0WF%?pGN-q5BTdP^Z#w6Bg^1i{9 zIg2b@A8)4I!Oo%_qaCB7Y)S!GiU^Ok9x$IxXKAbpG?pvB)w}t@=!|H}vkvzqWswMl z-X5>`D9L4I&1Td)PNPHYYR18 z+U?BDjG@A%%SVt?ohZ$PM5b<>Q@BFG@JDMy_qanzn5gEd6fafE%m9ZhU)1Qo-GX6A z2T(*!4wyJw;HJ%S%{jcl)@jEEULs7R_&&?Q$B^yW(1%)pWSoP}Atza;^1N>1r8Dd` znVV{;&50f9BFBR&V3N;D&Q>>xJk|Cd>`QecA9$tw(;FI{6I_%GFhTy0x#j;~oNYfL z;Yj>A5}#p(Yz0===aS^}NEu`m(jmBLv&lJa#;i|n3H!RnKgg-+Q(j8;k>K53AWeDm zsZ0`!-Z=v~+RE)Lsru8w`_h)oCV+_efdm?W8@DyM+JW5G6E&p4N^}Dd_ zzX8^rT0x!%FZA}2>uPq&*05x?Qo!9S8TsQPpx(_TtT_KhVQYP8?gx+>1H7yL(AGQkpp?C+a_5$JU@jH1qXWH`iCkO)5z0|V?`98GAW!>sDtB&l zF2jMG;BU`)`L}_=>skVXoiw7a0rQu?F2%-w8VFpREyzfiFUPqB^2a50{uubzHT(aJ z7lx}I+jJk_%r?h7h9k($y8|<;Kl_L}Z8L^gSlf(!diJ5o>UW0`wBPz1geb;|vF>As z%MUjAyu0O?+iK3D&{fk7W;x~ ztZZ^_C8mayMB~2Q5}U4kS-Qk6LSD=~1jQ-*_|@mzXr5ov_7i?9v)IV}-TJkrmq+21 zhQ=}mA6L3q9MVj#UZF?WWF@`0vcg{a#?3u%z0Utr|7)%ADNd2g{^{rHnx^I!lsle4 zX1GXd?zolP#`o&_HP%hh&QA5}MvFH5&bKSwMBTv{6fR$*@T3;GxKOoyv^R(Zx-uNH zG$t;LwyPrJW?A-_L6fe1g*w5El{ZK9Zhb>Lhd&gBnb4^E48{<;2t@E12vyPp{Hs?x zL*dHW`Z`W|DOR>#V?T+RocipU51+{M)JXM3rqRyq* zHTU@oif6uL-F$HQ-~!}ZU!Fr_aO$7$ntntpn$fd?5fAk{xyK6Rps}9d%Fs_3>EvSl zyT}>afyDhs{Og<7$ovFrxwmoi-=J{ytiYFED_kA2ggfLi{J|-6M$8v0)3QP*^1YN~ z63;(hDAj?z`&i@m;N)MjxBp)+bmHJ@z%tOEvgPC%e)1k!R`pwh9U7BZr8#&q+tIZD zZ-EF4k|;KNLJwv{Z||)D@dz-h=)fd4FLF32V)o!@7nr#ve+fL`InK?W;kNOk#$+pRaBEV(a{u)FmYJ|acJZ_}4K)ge+~3AKCX@qaY$`A#2+_Qx?*LgX zU69dU+dTQWydYeUEJvHjmv*{oqb#6Z;~c&wLEg1NeSu%3&vMZ76pPhNYf1;Kt zPkm=EH}BBO`?PO`ca41OAMgv7gbYHfvgvnbjR&`dSSA6nQXd-R4J}h1&y3Q_TYMm}}4LL^7@Z6POiX{eb^q z{fr(d;ecvXY%I>}n9+6i$e15dGrH)E@dwVu;~>Y3tG}PC9bG5OBAb9~0U4LvP9KAi z$0Z~|_A7vikU~!G{3A5-uR132ozyXt9wC5=qg|aBIav$x5&gLjTrv6#xxw~JII)P{ z9C~uB>kjOP>+gUbTf(MCJ;#zjbl*T^CAR>d%iBiebyzrHd82K*3S=e*6+i8S;y?2N z0ug3%axeg|n(rPSe*bUm(*NPE{;w#pF>wMeu#BuY^ALsED8xnSeMYAKtw*;6)ljWi z7U%e#uiZQ=@!#ay;gQGu@XNz{%jlC22uaZi5_DmDl*hY^&Q?|jaUp@qt9H4A)3x&= zMGUR9$cF4h%<{?t8p}+H=sdcGI!R(JiY7S<3zMqN4zF03+ui-Nw*ddH4cw;zNcqy?uUdYbLz zmTlA{EzW9zp*K7-EAtl%or_ZJ;)QmZWbv3YStGD6xqVZ+P09CxRqvWykKQ3=Qa5wy zex(sWYa*}t*w&0Y@84B~XPVXBXN;4~y0S}qvcSBh&3#hdgZMc~x=1u~_4O)MW5UCzQOAHH(qGrxJ@1bto((QMMzxg4A;ta*9@24OEStmj(*O<8NSkt^V4bAn*(|V9? zySPKCiWaVp4{2c59`*r=9@5Ngz_%SxD3Yo{60h3QPlRA%oW8vLI1x_@W3{t!pc?b3 z;>;6NHl8YX(rD3QCk?-H;>z+Dfqk=?S~HlgsYi}>dL&NaVb{2BpU2qe<aG6nFk_0l{?9?J1^G|$F5BPCwf}+>nPb3sV@7k6 zezeni_q4#ye8-&Ik#}@yq01xs-f`X+VPP{L&M&*t8+NTs4Vf>@J_kGW#f^gLQ~!p#(I~AKTHLu_gUu;HMKj(mH0YRBx~fIBmr(BQDh1DxnZ~i z;pWZ+#u$IU^4ikzDYmQ4<%`Y+H($G2ZC>1xCtt9b!dqPGizqyKH)X@1DG|7IHdGoD zc>TI`P1$!{?$wM8w7Nn)>bW8yeN|@{t|kZ($qU-4f-Wl|F5%SKj}LvlW+QgakGg0; zUYQbJ=pFQhfGW|?0je}7LAoruaP8WqgK*CaHA7N+H(2hJD!n?@=DBd{t)E9$sDurV zIZuWsw*RMj7l;Av!5o2Rt<2>m=5fi&8!-~uP?J^hx7wtOm>$tT*vZlHz7@z2k9|tP zaG8C{41zb#eJ*EfZM%lxA$X?aGP~bZh5=l5?`(A-6UIu`o}qm4Z1D{7T1b$%Kc`wy z?wgn9-M}0{x-&%7_tr-=&)R@I7zXWKW6L{Rp%?I0gx z$Tia4lR^?5zGiMYkx+6kVhd>JI2s4U2 zuVs;!0aYz+8*uwZvIqQM9zr-^qQ-RuaBHT@-YjER$9;R+tFvQgI6{{n_EIIh4C?U$`W0eP+GN6b;+ZYvio*;(Pt!+Wg|9N!0i#fkb2a{n>uBF zYDevPbRN-ql`f$Lw-C`Q7UXHmHn^0EZpd&m>N8SpG-_84Ysr$4s6eF+@0%Y>+kvGs z?5qwgU668S)#>J=SH{OMm)hIDu_))=+uC?aWlEVGOofOd_vDs~Mk#C>4t5~9HgfOu zL&u#WwX>l0jgCvVR!6ve4pPg7d|Si5kU##=pvQZK`v6ua9bxZW4(}Fia6F!b=hti{ z!OAi|&(9W6tAZlZSjF-;Oe%f68%j?mh4V;z!5{bJaeXwGUtJ@#IVl8}SQQt#%=Y=8 z$lGp3=Ux-S0H7}7_x`R_i3KYvn?3_Iyhkg?JIm_a!5ZQ^H= z6tM_a=ilhUGzpb7^R`lb3GzF)RDe}BQn^l{O|uGx9bnPniXfgQR#+r%dMw^)2x|FJ z*i8T42kc+u)iu8f)cf0w0swa| zfZ6(E5aKf0ZdHN&^BK2MYKA~iD$Jeqw}7?b#N=NUyZvX^k;I!X@FLqM3Fwo!r#0l% zZb+jkQHT(?FuxKH)CL@e(Lc+qeqIH9#ByK3a>?tOB%>YhZ{LqNapiv>o7Rsmiedl- zD<`Nmcb|6<{fnX=gc>D5fL`yI-@Ah?+i`1;SE18@#bij0>u(fs$)fLTym!Ks*M5fV=^P)>;v?ta{exFtc3)F{*CPaM{$O|g=9#K z#mzpSIX%*J5mu&cprlnJ_q9CaQR;Z87Tbdt4BbK!GP=C49z9EeWD4*S7mkBTUIR|V zbbKb}nn*hCz7%?VBtSqfZC^R|f@$)ymMajOea&N&DUiJ>v0%_?^V&evVJ{(uxUz3} z@?Mm9=w3>6=(u(dhQtbRywLezp;P-XNt0_rci`rL_B~T^VGoP9lDqt40)6hs*Wu?H zKZTi85=Nd$7Y_dze3R;hla$8M&)kO3%5C}ypPjqhXROy!^x&R>&E65<91Rhl;JEQ4D$$FF=LU@t~;L=-$VVBghg%Z-@;Y!>K=Xlvpn z0w-p||80@hSxrdVvWkcA;iELQ=q#xc?zF34<4mh7s43=AFq--5a2zOfhJ~QiAsfX* zwb?@gJEymux6xtBMf$$G69w{cTQa3jW)EN!b@{=h;~x9k4%;tpp2-}Cr0a_X%8C>M zm;0Hc)wU~sqi_sv0#zL@kSznP4+3*H90IDI8i-^}{i?v}p8jXj=>OejGwhwj?G7th zOds{ShBASz$t?TrxIxfkpKht!x>|by$|n5!=V+|fC3ms=^+R4wS4g+B!+7uNsHzA zE#q<1>l9DvYi})m+d6OdtCMZPn>@gJFpYqYBZ2X|tr@xTa8p%l*K4<^=eJDa3m?Uu zqoWO}@YbQ=IsA;>UpdM2x)d)8wCsC+4|;m}Ko=b`#VIJWdWZKe3u5zin|0kRPq!^^2PLaLB8#J1e3$ znUXbM^_(?+)BBR7s?Bj;$5HqF&ox7plTl@xGV^+yTY`Sc;=mjb%6~7>)pf&+GL%Wn z3e^i@AlA(5G=s(yaiXoe`v!9J%&|_HhE11jFl^Ctws|hj5q_00ie-?U$UB%TYAf}gG#~IqpH?jO@_{-s7VT%P7)OY07iitY zcL^oU!ICxUt{ld^sXo2$iCNZ|$ZK*xNmE14&jNf+rakq54q)4vP#Pg$8u2AA?K}*F zRu#7Brg(_+WS4a4P6Z{qcfe(j^7ZKl_jGCw|ks(Jq9ounD7bCG6r|_T%xUB{qNSNQC*&D`b5-3M~}9yULYZ+@>|vQP$1O2=o34%iH2sHeiTLr3yj-Pw#Zw5!1L3Ft>U{xvsG zf!$5xXR6%vy6`-B)voe!iGGUqmIl;cV<)e{XFsHt7+ypYAZV21Ka*BxLW1`rEVjo0?QC!ci)L7|fEy9$D&v(fx~8I6)~;2^ zEQziC=w$OqRt=h6P1>GdWJm;Go8d>A3>1z$5ck-0k$&hOx19z5 zu=HXMo@TXsJe-`5)3=!o*Qgr89?dYTCJjQ4wg!~auo!DsEV@N|`U zZU=7MQ}Y~{oE@;XA8Q$v5|5i_)N6=AbL$58w)MYz;QFC{?(y2H+-Hpf{10q8gp+hF zfL=>qd#^i{-S7dK!_4PJ!{N@Qu*B>5lkUDCoc_{a)h(BtE9@A-7ZMc|d{A}si}g=Q zYbROoC+~^sXqP?^T(>G>;uv$ZQIk>0an_1kptYv~Mx<2^~uQ;>| zm=(s3kirlWTQfx72RZo#$x`x4(pCNpPw9#1o!?vJY;wmw6Ov>sd#ubYJve&({`V7( zyrxUQUhe9}Ld?f0VHh=We%V#%xF+eTOW~1|sRfmTJnY~JPMHR7v#}BnP&?*aGn*4E z7ed@VRs}dL1V|e*zb1jTWugq_nzt^l80%gz?TYmDl9BvsHyACXN6VDJH5XDOD$$t9 zk4QHN~D<+>s+f z=Z75w!7OzF9Xneo+e)-sY0sf1#+FELWt6q}m7ZFN-r9(X3zOKD5EW!v5m76GbzZKnjn2z$~4ArXT(f64akd-2IU0rpx5q$~1V zlO!BM0Q@z4`B~>XUgLp}h-Ys(yntw5Sua^%U%W{lwe4xJ<&>Yg?o&Unc%_%c66xk?3pnOTVkY*JFTB;r(YLP@^3zJIhF%Ne%i2b1005UjYCdGg*NA+Z14 zE9cmi=mBxcJ8vNm)5`ASate=);huveXmCFKb``!59ob-A`s2ufk*Vv*y|60fJXXcm zB!Si>@4boZt8{1Y(=qC~uY3+cZ%xcsK%r``$HpWmk)0C@WySJ1hcPzg`bn3?L-Va? zZ@gE0X{WMO_vMSM6v!omoBba9Y5A7!9QS&H?B)FuXD9-vN(wDt1Bx2`_lH8$B z-YZTk-FXxnyf+!)@mVu$>8dK%rYRhA0jj@Nn!CNAl5tH1zD<8}AZs^Vzi6EsZmA)_Tl6s?+>Vck< znnO^9^Y#G>;p3Irq8tbQD;}TpKV>I(z&rcHILIfVHIq}(twHfuy`vV_= z$rj7IDPCEk%mFB4^->?9l{W2fyu8`L=b$-3rlGjNIPe_*WaKwXtBmTZuAK*n720`w#YrQRA! zc+N1gu!|8cmv7bVs5fn=pvT>tF0PZiONo*%Y~TaSQu3otTY0$3T;e2n4uk=Xcem^x z2ng2nL+2T77DVZ?ZC^}aDkxp>40z`eZHa7#b z2d!em&G(msp9d-PX|Nz~{Re$W5KMt7JYR zGw{Mk+9-|2B8ryX0giLvW5xQa(ibrI?iW8v!C}h?)2(cf8^lNoE1u z)$3#@;j^k<$$(9?O5b=ua4z@e(!xX|2n(Vk^TG8Du7depIG%R7^bS}^w`N(_Lp!e* zIH+>&u;2b{a5XrkDzO*MitI8`y99I%4n+R!3AR%wEVMn1+{irEBN-0)R=WJ0jX|(B z<}`OG#~L>+^mZ+*By6c z;Cy2GzGHtSmd!wcKh6w)UfVQ-zEny2_KE&-P7B`5i9#d zi}BbC@1lf`1!KSN(4PUN)_C?bDsC?DUulO?p*K>G6(@*cWEK|-#4Y8SIw!6Bc)Z@ee>1NE>oV8`Pz zXK@_V+W6YhS1!-b5fFtN%Di_JW2Gef&R$oWN58#wE1pAn=%OI~hx}i~fH8W~@(BQD zIL$^0FcTveK#348-x77^HUZJJ^$jbn66{6G!jqQTFCN-E!Vg|Vvurz?Oo1pze@wG4 zW`1TDt1N2;%x8aZc>PCC$gKL$Oyz-&nYaFlS5;Z4by{&=OwxZy?+mPIH;T2RCCcH7 zN!APNwH`mmQ5VZ~B4(`9-J`>x3YR0rm$$yox+dcq zT7_*MUZ&vos5pfQ=3PMX!RlMl{0K^t`hcI0Nc4P^+MSH9%FDHAa`)iFj0sI4AvH%w zU{?Ef@hW>HNKA2hF7D=Px1d}CtQuz{H~o0^s`P2|GS)g&`pX`~zz>atZ^Y(xR&GjB zc<}j_T9G#KoX-$a%oDrVOHCrZt*w2S^obYbwojl5E1&Mis}E*nw>XrC^LO*xO3_bL zPS>>)n6ZGgZMIUW9Tg#Pp3o-1j^BPB8L?DdPwuQ7lG(H(H{ZeEO#V<(+Lk$^Cvuf- ztc2@sTeL3;+qW3p0~9vkS4Plo;8-+14R(cm!IjMYg&0t3`-7Dj(XCnCP&?|G|FB!Q zdN9e$E&BYOkNRm&xDZI@{hKGnYW8`EZ%5mSa8qaZkFZ%x#@=k$fTZ6Qt2L{J07)q2 zvs1R^Nf#Sp=$+l6<1Z*yKdtD@$eXv4ug30|5!L5nb7LpaZ4AuZ@$^(ferWn^rirfp zQdUO)>hw?ZbMoi69tFyMk+DQRKj56@RMRXXc@d%Bb+JbHh57Wzr9{I}-3vya*TrH3 zDI@+Db8j9GW!wIblO)**Suz!ptXV6|R6-Jx?8}rTBqm9=F(YLsArvuL%HEWnFm~B@ zLbkDHov{vPrr)Xi?tbp)`F)-+tEpU?00{ln{;>vCP!aUAD)Ugvq7$MQbz_`^36 z@2w3eJW`zY6ZKK-jzpJj26$m>v7yOa#D+;d;*AP{lCX@#FJb4l7VV2(H9y$ne~!F9 zm$LgT@F0uyC!j!vE1T}=FIdswDJj!LwQ7ohzq2=IpvazXLH0Q(6EmZT^vlOTt-JDl zG!Hyz+-?jhWNAE%wJt+Sj4Y~pg!R_zSjVI63N7(Wu%%Qf@w#cox;2+`)4oe{3Ga2V z)w=dS>^SlE4VE5TF+`sCz(&qNpfzm|`0+(1Jhr#r}Ee z;a+I__G{Nq;qRz9dS)YQnGe2{Q24JA;J(R8qcb@)fT$NjK}{?|H) z)^;=3RxLYgS6`qQRArhx$C-=1ZC)r`_FwCtOc+=gM_s{N2tA?|Vm&5$OM_Z|4LC^@ zCs*s>BP=))1xnybnk24nL^2BJ+~=luIqi`5x>RS{HuLV=$6vD^Lph0hxYgyT6wkVe zjpl5}FeG*1XZ_xn@^gF&=&muJ)|6GP!AsTa9U*Dv z_ieJ!f3NJjsFCB5W?4{AI9i#1r{DxL^_}!^>8~mgPd4%KOPz}0cR<*>6+CEQiyJ8j z3sx1SvbwPyH`qgmAfm}KCF=EV=?$ars{=TKW zA~>BSI>YqMiHbKiuS}a=YF81Eb4Cb%YJ1qLEZyW{wYi=pvT$mZLos1H9C2aqmL)=- zpbkt82wB`J%julS#}0SH&BlJ@&5RG{28W4%xO!@0Cwx!iz)KmiSG^SZ#Wln=V#5?e z>o$}L$@#;&Zs}$n%kI4bXSOd@?ys9>cV1FSkg#&6O^%mc$eOm9)%*q&YTd*ssbQA- zF{$n_PL6Qbh$%k$#QVs@$cX1)5(0X^h2Jp5GaZ# zfR*eomoM}}1p+mh0Cge@;{3=>{z$1*hlELpxI#j`&sEuC>70rH>o#xsI)T_-Su3`^ z>xkn;#2_a2-pZrFX4jkg9_y>$`<*5ID`di$fj~#O z)CGbhdrlQpY?Ygi^!7+7}MNz2!vF`#$6$lI?k7*;M48(Kc8_4qk9d6!vf-Hcb7GEIXk78s>!?_aXJ7^+m zBhZ&_KmO*&j_1GlQ>gLVq@!xueVbB4D9adK&8P?P!o{5TH|CZWFQy1FrL5NMMDV?F)3CYV%j4W5^w?|>udgaMy z*VP8{QY(8m4+|BS7r#+!l9S0Y)-dQd)jEVd?~Wy&j`ue=tca6b9L@xnYL zEwF#+VBT3FUB9nw!3+wXm*^0b3=#{G0hE44;d4CAtBvxhAK{!97eBCDS+%4c>Ajd8 zen#lj*=$MOL#83q(0k~i3^f48tzxg%wV7CHC!bjQaXNZMC?w4x=8hqKA6uuqOLjp? z)Y-)HGCZtq*<8O1 z0=gkAgjF&FN7uiSH`{l*ELtf-;mk7bjff`mk*`*ouUfocQtxFzQADw=`&}e@!bk%^ z1eK6C|FQ@2y@o7?+uv8{i=WF~8)<;6o;PO|L z)rh8Ie6Uz#o>FJ?uCveT967W?Y6|ic$x7sL!)fpNKn`0rd(iG)=Fm~nnwzntAEsLG z)VpkWHtJTv>h6JOuDze}+sn;(2ms}SKChxCWcWQEk{d<(Y8;a+I_V}CujnjX@LjG~ zsccm7ZQ^z~s}@Z-^`3UBp2R@JT{k6ooVkhRx9xkEw5Iw7JJE$AOZ_R7E+kzSi6z%b z(fbDP@$Vk4ozCpn*5n>4Q=34kSa+r>eYx*C6mu!;BUp|J?E_ezu|R(mOLnWcwcvbg z_(qBPQ6u&LQpex-68=W^z10VNrN7XAZ+G$2)nSS2AW7$A4k@Qwtb+nV$D5Mo$nLNi zs}QyC+IK*@Fyn8F#vI8M7r|GfdaNG-!-+N&zezLG@$nFy&b@i^N%cxSCNa>nQRhR*z1b`6BjVk1e*CtzIV9_<)vm`nvcOk~o@{5QE$-d; zV)7vGq*YXni~spPdvxsWBfXPBS$wTs{U8iV25g*uK@+pkkhA2N;0@4%xfckP$yT0C z30>fM$jg&>*(}##soSUDeEvA?BM7_dK{bNN7OIydkuj{E?pdPUTez&IQNflgJG7|4 zCRndMaa6pzaqg3~_fwc*x6y~5E?vatL@7KV2|>0&RRKSM#?Nit3#-G4&9AseI5ntp z6?9GYI#2GDm|aY(*uGqSZU=Sd1mc@;@9M7To{qSlhyhMQSC5C%IWC~=H1(AP`ABT4 zL9^j{U2Nm)o}h=hckg9nTybuDWR@cy!PvaM^X#N9_dw}t07aMp2P>Wv1zd+dx7>@jF~+G?LRZ3OV zjQQRthmVup8`J&p$K)$AT*ni9rWD4Eu2k4Of~-s&+Kmg<^-RpQvMTA45s!n>u4jn(IZse9(IRWkuF(Zmh zLFg6}oI4V;oy_uzE1aJva4r{(5)y<%m(9sO;tkL34skMHgU3}hr3NXDP3afc%H(8e zQpW~@@E#`QLj;5^oj+(f&&3$i@u4N|k8u(BvBetCrp^?O#C5&HGtE3N_lt1w5eZ>qOCPmW(M!an!juETN?bF{-uuvmP@=gBbY%**a}DA708<)^N4^)?Ag+nhY2 z34MGBh0V;K>uI~-owhzTF<6TZ9y&cFSkELLJIJM{uP`~6EH4h>%J4{TE684xOj!wU7ys2_?sf}$43?dsIJYO z6?*lRCd*n{2bt2XH@qOJhQk0CBO}S(d15sH#ah8PsUq21k7j~n3qK+RQ(sRO_?Q#J zy#w;1jzoF2@IB(E6+aeH@An;yFD6tYtmq_uyH0{-@+Va&LSnKe_uE49nf?mHj0lNa z9krLGi;5yf6TI$4-G<-Dz5{v9ZoFzHde(1(b8T>Gd=kz^gx8NBTX82V%;|-h61GxM z8I|?UyrX7XM=#$CMpuMirVipa?kl{VVcV_aS{rofn%zi#%QIpK112$fkoJ!OOlG0urwm^ef!Vnj<$um#Sd;^U|wGDuiJb`K>As zg!_jyu>>H-71`ukc-k8#h=Dpm)6qAFomx+LrY9@i3m23=bHtg7RJ5z3Zd~Ma_mKxw zWy4?s&FPs_H>_8O8S+=*g)bkr?caoP5^uGt7xg*|3N;H?WWN~XK2q&vtx8`r`YdYP zGhTxjgSVe5300LOLTlr#F5t)O`Hss--0QrNaI|lOtfm=0GSbZNRxaM9#c3BaPH--%XQ3u;o8dKs-{n&}qP6Y9^m|t%Ja(Sie)_`1ylMTUd|7#V zF7)WiCLPD@_#r1%Rf6U+_B}DIahMI?Gm239a?vG9yxG;u**1PYRl7L&^?>7h@h4)^ zSHGpNey0NwI09S*NPx2JR2ZE7N6AIok}*{REjiy(qg!quo;@YhmZ_irfML*~a!df0 zhPxUJ3Dr}?g8Jdehzh4%v(sqR&zV9-i%jA0Sq3L_2Tp5$L6MFY**Ko5w|k=;2}1{M z`q9UbZB+~e`#_WplTr=xWRH~GvbTy@{W;YnHxA85`4(1I71wP}C|Fuv4}WybdoZ#U zFWXQuUXW2^X}wrWk7IJ0{H%B}{@JF34c*QBGN$8w0*1A(DP4X-Q90qZ{C369c46vL z4yzBRjXvY)0#TEU1igp~`3%wp@|#pVF?3fc$;OPJ7m&Mgeq+QF={)cvb5*75AtMsj zau}jO|9BG{PTc_a$LotOTujPEruj9WPDfVcz(zeBQU2OSWHW_Z~SN&MNgG2*n zIzLq*#3kZg9GY(NWdjc2v{FQSmDOoKC8|X?-F%#Iex{shFDKk}CRUm7Qr$OFT|{~Y z>|5XMM|V*D{`*^!-T&nochbLE{`(OVjeTIrU0+`ER9VDhGJ-{)z&I=wQK(~uYrXFG z-ICAzbnJ}n4L@D!L)Ul&h1@ZD4%y+kE23gKkRu2K;+H9O*f`eY7%bOr z56T_+c-m4LN{T|YEFxo;*&DC8)Yvqc?OBI@^l^w%uIzjvwNhb@@7>Dmuh4OuAiG)N z=OPO$S*}03-7OI?ZRXzoHotKhkrJB{U}U*`f@v-C)w!?7xoc4jo{?JQ4@hOtM1x)z z=f_Dt6tJ^fY8|q%^Iu=`eh}3;U3Ls5`qjAU%0s6GGf}sBRf8GK5Vm$q5a0?|o%_DH z>)e6nDwtXZiTrv#!Nc<9h0$mH+u5LA$NXuS&tndBQx1Zti3aq(J`hRYU~@VOXFz}$ z5)}LrLXTOOIr(H}l!!c$<*dy)Rs3YyUzZxwb5?Xu(G;T;L6D&uh$S?uHhN?8f$)!;NzX`CX`4(hzW>N+x<}^*Vm8 zjySwn4`Vvj{p7vNpwr6GrfOpU3CM5A(|5)lw(d5Rya{( zQ;K*EH7UAhyk$RxUbfQQ8b{B1d5)H}?5u}7&th-Qf5?_wk<<|fs6#eH^LkJ$o6k4J z(?F-JzldJmQoyjdFyj5ICZ-K3L0XHqXAjhG9ROc#XxI6#91B9oBhfvTxicY{8;s@ znB(hacP~jiLwRie>)uGxp=)#s;IS?=hgl4wZeSm zXEbhCY)v{dBY9MuszAWwX{k`k+1^bSE>E-}>c|kE)_eS0f!mGZp#xynvOkY|Bf@ z79Q~Iqtt?LGouYoFuxD3kze{r#YUpWjUws)`|dX%|Iiuh` zio?u7*%ozPS&jqo9w5?U!7dpfHSLkYTdq?M6=nXfRT}y~36bTD{pe(7AGl!-K3gY) zykhkG;dU=~S@O4ur;O3(whV7M8C4x37gy-z58BA;yFVt*KU(4`D8Q z?_>M!ELn#)(Y*>(Z<4yDK;*BgAS2j{BKACdj8N7)3E(Z#Zz!B6;ajtD=z* zs5VTg6vM9 zTZ+XXb>nL^pMg1vo|I$#SKaWx)VsgyO8?F8|AFirD-VJo4)e5%-Er6oGqrrx@rhYu z4m{2L`$bs|$rU3_y>qYF_S-EJ>F53U1cx zDN}KxMn5c%>oMl0gZi|*nL?wl)0aL*T7lVknFk+Jk7ONGM!|EMZ6-TeWWp-7Zxxn) z3W&SJ2tQmJAz=9OW!7hHCDv^E6a1?*$UYb?<)r6}kywyd73S;+s~v-M95 zFE3rdWqJy31rc=!-1SCQ9QYTX1{3mD(5mSY3BwMyfnugtIfNEZi3Zxf^s{*>#;Qhj z+kf9DHT)ep4CR>_j5WVq*j*td;CGKFN-m@LUgaA754JC2SV)t_p4wz7b|QtK8aczH zp%)~hkb7!`f?WoU*_` zP6A=ndpG(%y2R$Cm6Y~=-b!jebCX^A5o~4ZEw0Lg9R5B6xE0TKe-qzAvy*PbH0lbR zUbi{#uAJ4Bhj{9nHEKy|fbwiYm~V&_05eLKTyJe#cU6+=`+K&&-ARoi;iMVV%o~-m z4_P0EnLR+sz8{cc?j>@blR~*VCis1b)QW1eeWs=3cHFRC+g|AN7i%WBXiEJ#!vY>W z)Z^Kd3W0GWsPWOY9eYg|N505g+}LL7WRO6y03NRvJ({Z5tj=$|ERN zV+E9L@bFuBXs|s|Kb?4GRp-U1WK_}Nyxey;vG#G?FTF%(UIq$oUv3o3A~e-WaW9xP z)j`-jxf{z5Aap?mXmS1F#jB&HP6~sp>P&qzHg@H=Wh4>AzGw&?zkV}ckX)n%zG;~S zk7?wk3oatl-7HU}u$^x!??4L&^j%C!U6%ZkI~`*0ypaB(?_?Rx%S-E!ArLYCiP$Td zlX73{VM2RVMs}iQf?a~K?W>+mEa->8Rr4}R0t=D zJ8d4qb`rnAn>iq7s@`9fl_p%{XKfrIDQJ>`5WmIowtz}nW_5@@wt@*akt`wY?TwQ5yT!uS4+; zKVwX_kTnT>?D*|TNZ?Y1IRL?YAeX1H#=z&;FK}0A@N9?Q;rQWa7Slh{a1eXotH1Gw@&bqD)6yyu|*oO6MD}CPBaZGQ%^)7 zRlG%!a6yY(yUgg>O@YVOisiaffhw2IvgsLJ(8^=m^_XG_PUgf*tOgaXvRPCZTZ#5t zcNcz54Vm@&IBRtGrQfo;q44OZ>~qnwRy>mc$IG~e7u&GPwNNETpbJ^rNP5)4w=8Kc zx?*r8`sU}nqHujd<*2e)?PHByN7)tWp6u)aa77oa10)p7=+2}mlTnK~sO6d?#yX;` zgA#On5sk5DGi#QykL^7E$Tx8dC@;|^ggr{rG3Z9@{jv)Ndb@qsjfDX!s{>GREXR*T zY^4eZH54ZpHjJg;1-6<8hR>tZ?~R$NX`bdZJ}LBof3{)}I1VH6+gFLglVXu!s;4Xa zl&@~x(#y3}zw3_LvfP#lj`&{ORpELr%<)LQLYsp0ZS+<0OH4E-N3s)Gri=zsja~OV(Q4aGSWv#R!&u5pvgo2#^zB?~w2Nn*o9PMhM5zJwJ_slGIjc$oUu7J{9MdOu} z&u=0Iega0yU3i7rbPO{NlM!UU-?n*taQf!(V z-tr%>Kd0DMu_1G9`VJ$9+p+n#$Oz-s@uJn5J#;vfc2kUro{z$ANj+%Z^*-{{U9Wo# z$ENQ3^EzywS_jEW0JIJKiw$EeR{msph^sKhs9&b13_}1-3!u zf#~hj^sA2%85N-1%A32tm-7D%Ab{GEkEu340Fw*6&sl!9C{&mz2fp^F+`Uza-v#+k5=u%~FQF(vo`Vx3+^ReZpwq=b&m$cM$- z4E&g9HD_{F@ao?2!ODV@dR*pwP)>*PCk51eH_QTZjjw5b7%~hLn}UYI@On@`E0q`K zoeaZz6A_mA-QRyO>R{gVaTmUPy%o7qe;2x}?+yQ|vN`KJqK>@8A^>XjerB3hz;ftQ zgh=x1MnZi9nhEA6%~aG%&%~LjsjbnE0ap9>M|B&mlh8&MDufe0T~(Usn+0a^Ns)jm z?L@85F--NQr!Uaqa#d}`)6d=dFi=UylaXQ2>yR4S_UXS-vqKp4EpULGmiEEKiL zjw&B-NucrjCsa(Y@xMEk&-jEq02`H)`@ZR;o5!y-UF%&bvebQCT#z5A9Tt+VbnDE1 ze!0)tOd<4T7#f=|ndD1|#MuM0h!c$c67KlD1s#T3QR$jz*9x6qEM%PE8V)wq+pSUD zj(7|$p$p$kQmdl~kdu@dP9qEn*LTDZUvY!K*O>U;diug`7tVs3U~O_Q><*EoCPA?d zd&r^c5Prj2LP;$@u!TCDi|q{UNdIVln|GX0vW_FZmi%?hD##T0((V4OFa3Ac?SJCv zY6W&sFM%mz@G(WlGVh;GbzB%nK`e~l5^B*Ob@p2>iUswRxrtILvX&QmjP`e`Xc_7l zaj+K4vcW^rnNrbZ61h=wLU}#LzrCC7lK9HQhuI7QwdJ9t1Tdzf7D|?J5Zd`|qA6inm(|Mo?Z z#P}D$B7u&@;(_634MZ8SrKwP^qlk>y9ocOk3Saz|E12TRgA@iApsn;n@ZYfokz~3R zEZ!Wbn2kC3z)VcgsL)k-iSw>M4 z#j5~JR3D(bweFn74Q zUpame%28C%QNyMEMeOy-gB#<5S2^kSZd`dWTlFE-BqK!R>A0wex4&$O_q#KhZ@J;?7G&jC?++G76}*jN3fuV7<-0bU;6+XxVCHh z!qUk3LZ-Yz@{hva>ngduRde&mqGTWllKjz($7x5y`DZ-vs+ci~+y{Y|j5tpyD z!%vE}yv<3=GS<|f%E@9(x8)`1F;ZG!%#Q)1$TR($AhWS}>e4H{w97cld%n88I&Y9m zaroxvjBg)^^EpxnwNW3>sD-?s93YMWoVg>OlG;(wKzXiS_rp?xChtuTJ^7kqxy}*$ zF!!2J+QW05dITuWIDo?D$!7qzTB5dL*L$KB5}WmfI(oi-KBe(I^Pc@fs;`?u%#I)J zR)WemFF-;eR3rw1fl)6>C#yBvAz82|%|SwboMl|=!-D=unQ+Q_+Fp0G9wW2NlPM9X zs;BnEa%3HJc=3uVckiZXVF~{9yWzkhM6Z>$M`k-Ry{LaFv83Z`8ue?|&;x$&j_fvF z25Ovy$7E%EgPS{8<61}0$)gGv`0lJpSSq*oklM1ZZ0%K)patg8A{Uf-p3 zpGv&@xuC=I%p)AfXhNTXf;M~znhE&xK?v_hmvKXUq4aP^$wd?Mzyzh{sgj5^+HSqh zvn#YukEt|@HKvh^s<=nk6hjfvDLn?qy;z~XA`FW~jXj&&(^)M@!flSmYwuSJq3$x@ zA)kY442;TgFdx(&kP~Z`8`WqQqPnOqCxi&6qBUVvqH^kcoMe7uu&~wANxeL9w|4hv zX>nPJtB`^E3C54%>48RcCqlcj++w#OXO-cTsA?oxcr{Db@;LAw8XRUS{X_T^1IzA@n~jNn&GD_a@q zZNb`=Eo-37BZakmx*kN8X9WLuN$?)l=>nz@uGQkke~ zSpgSYo?gDB)l^061+PIzSREu1CRvC&$~3Ox#UZZ3xp<3rp|fKS_$S)O?2njUFP{uP zTUT|-1FrA*ITF9V<%6fI9o4ib!<&OJBHpD(nx|h3_GrH!-s!N?C@OgnY#PQtF~LlA z;7ezaDiwaUcAWMHk{X|&EfABgK`<9zJm$oe1{BZBBpWdqQ18-)r%G4_FLUN`m>jIj)aMeG7`Mo3tb6>*!SaRbz1vKNp zO_jD!&2FWlQ8sF^k;tA)&KW885^Cxx8xjDK_P_Rzcc5tIwj9WxgR5bZIr_1J&JCo_qtE5dZ)4#0U-=Y48KzAnEZGrpR(i^%U_{(#Zgx~<4s~ik! zNmz>VLVmmG(Or+I9atc?0ZaiQs9$a?)BhjcR_il_big2vFis8!o98%fSeG+OWt=yX zWF-Yww{Pvas2{dP3wG$Ek!=XwzuZ=RTkwE6ilqH>)RNLZ%Hj?8JqcJy73;t|{9IU} z9_y%JEAyMoVXJFVQ$E5KIfAquhpt&LzLbS|qDQ2v(3B|0mTMC~;Yl!e>wo z+xUG7-J}bK&U3+nc3u^{Y_6xA`b{`m+NKMG@k z&Qs^@YultJk;I@1^`BIi@=4IPA~TkIzF75rw++(>ewE_KJNO3~@C*R&z|O-4uwp2R zk{;#c92=@j9LusUs-+THI*$p&PFAQMM|ENIelg;mfPzDV1Sxi8_*x0*r#_(I3%Eka z2eg4oBhzR8Z7(^LXhIpoGHa4rhsS>r$-?5tA`T&Z8c+LBHQKCigM6zLV+* zJ|GPlKSBu@bz3XmXQmgZ*wn=P&{@kts2KbgrH?|tDb*PJT;1ylC4vhzmndNC)%E2g z(rBFIod}>6Xo-#hb!g?wjya03fFdw^#!#LLgOTPWRbTnem!OVd05{S7x@q>0o8Tm6 zkx4X}Az^jK8FU!f=>)shWB*{#)JkIcknfHVR4) zGgkR0DJEk4pQJ<@Rk8{;4uz5crq?90VYyaSyzAH?p<1-hw(9S9%< z`bompbFN5{2zgg%JXZtuP@xF$rKC7nk@B#_O*tT|I)yuOC$4DqS37q9q+%Tj!Ok=9 ze-Wi9X`frDr@I{LNN))7Oy@pMy37Ff7h|9~{3A$`kacmeZ;1uwHGwqBNel<7i+`Wy z!&%#{RFE9Ip%6*}+nk_Cgv3AYga9c;>1qKpGM&LtF&G63_{DGle)+L$Fz|4r!~Vl8 z>(Hy2n2rJ<+bNt*Fw1ZCD zFrFoV26~ME8^RRxdgw1&=}^1@B!Gru2WO@H$+#r=|GNvm;9i-*gL9FTyW^7-`?{Z0 zC1oIg@ipP_PpXXHes}DU5=E!A8oEWVM`l{YW4B%rKc^uai6z;H%U#Zr4<2CN6^5Lw z7@89;d3x%>&VyEeV?nz2$T>=L1*Jok8bFQxa@S`PQ=aDqOtcj+1xJcceN9;ES4dD@ zfAO$ink4`9y{Vc0jLwt$%yZqqGK0DRi2&w=KkA2rBb$z#LRYh^>#2sL*R8bp18y7g zh}Yw(_@ljzr|BX|PE(yDbGW>wn(=_aM?WA(DpX{&a~G*~rJg7pjObFGHP|wt=PTan zj3|v9!opX>s!kO57D9%aCR>%0MTtS;55MP%Feg0j@e<|o#tgr2iJKREap}9fuM?hb z0uw|zK$7iMrcKG#R=y_Ew|Zp~1D~epc)dLmRVnKGG}~yu`rt2o z1w=Q1*+Ai8)vyD?<6(u42o1^!$HG08lQtTGgkrm%$#ljr`dc)1mMhz)fEa&gRY7@0Cnt{UJ& z7qk?p&1vL&J;IE-e`g*z9z1Q>GQjC&7%dyCYX79O71-MS9g8bcQNiO}?qu)TD}hf~ zC#30IEeAQibNGAOj3-rQMS#?y@j-+v?{|_Uu@2*4{Ar@$^_cvQTOqxK%UuUTa*DaY zTf*)eb%8P8x*^TaJBq$j=#kbf(?ei1Z^eysD)Tt5>-o6cD5yIy9p~61R~|eS7w!2W z!rNsP=7Kmt&QLvu?Aq0~0G0Xj+y#vMw&+}is7kin0hy{^G9@5|X@@>_z(OczM z-kF6W%^!xGYfVe&z3Yy!LVG{mw1-iqo*5dV@Q;p!>9b#}my%CtsoogTx~XgU?4$^F z;(~XJzT;5B>4fsX6t%y*6aK%(dT`SAw^zm%mc&P=vtEi2&;MGZ&vwZ4butx|ZA{ng zO}yrE7(vZ!(5@G2hkD*2S>ZfY`{}+En~xv+ zAMa9Hw+5jCs^>iiw>}M=a!tRoIvIIL^NgT#ESCNI8Re`yKDO`#I|?tE<0HppWZg2$ zq@JG~G$@(xpyTfGRCA3bDleGu`#057h=-=^I7jXiW9ed#)t>;GRNn*a73{3nn9 zhhQa~JDgw=J^7O=YNTd->j;?Dx@)nPPHSS6BWgdX1WTS_mpI)($XWoha>AYzOGM#2 ze^OnupQVVSn&r(0AiKAqia;F73N-4MM*jDX{{0*4fxQb#LLH}}R24~)&&FX7J8k=H zf%QAawF|nq2*zVimJ>cQ9ZHG;%iZDzYU2(1qo))gKLpIHWvCxFRm(wg5HXXI{@cc* zyowVcdF}t(h+;Tu0=|`4EcuZh`5*{o`!8)tXUpkb%u++oYJh2z>R^k#Y=T3wBc}};A<+E?D&oC4W*Wx<+b@D6euU<^SSj%@R;Byp8wevdXYPh7rAKO1cffAgJ-KISbg)k9iu zTi6kVm@~l$7H$M{C>s1&_%zKjS2D}V`{-5z;&u`)$NX+&@BYPsBBM?I5>$46^C6L#B44* z8Fzm`Y$?{UBssx z){iP|Ju>~Vm2EgI5AkY*P+g<0q2n!+ba9GlS#I%CEjdh}Tk6~c7&_P(mk=D;zK-i+ zo6t+irIe=`3T>K7ww}G?CmvnE^tu-oY3p0RY%FetygGU0ptZEZ5<|Fi)3L^LFn(0+ zGlEn&)DA{XJmeJ_Sm8RcrvfqP`6zUr7y3=1+JPDL{0jg&Ai6heD>|c=jmDOrIlp~`0~BaRe?%jPQk;X zDY0rz0GTWQ;-{0bPfz$ut0RO7<`eM^t>fQ%fk8paT?~61^q@s4fT9SqC`c*w)g8c@ zNHDc#z8D@m^Yvu^JSuOvi9x2HwHdBFJeaTP zvMOHVw#~tae3O!sw+nn75&{iU-xkij`|*>C1Icd^$1C-$!Z+7(SXsQGsvXp?l&LPG z9QAm_Vo*9;2s}U-Zqg-uTo8T|$#?&mc7IW4a5-1FWsSq>&}B)K+ru>4cOJLbsZP8+ zf2vY;LaNqLmBo{F-YhPK{26n9IAEX*vv67Yvsd=`C$DM4sUy;v6$cD2pWt}fMClo$ zBN&5qb%=t(fDt^2&^TP8`nI5MDl&y-H zHsp;ZVUa7NnvDf`%A?qeoa~EO_&IKCAN{oz}mM$T?Wcmnas)s{Us1)YX?~l-!aJ zGt9#Bi_wHc++d&_CZtN97@s2%n3OlJ>6kXuaOC}xLdhdBa@9RGp%lE$?OWMVsV}u< zZF(vD@CG9FED`Zgh^mmMFG<)g!vXb8fTwHaUMOxu)AdZk?ACmJThuioTkhSEBiHUo zGr*Bw_j{_Y)4$m27$G?si7yRK zYKMChy1QNqmLUMT`;&^ga1VH9pmY=gO0O!HzgESCY?I<}eM~z=~#1+LOivpRqJL2@gWEK2CxA z&<2ctc%Nah<0jd>B63=B*pkOek%#BRvu6hMX5x<`hN>+VxGrLszf4M)YbPt^D2)ef z8*{DK*G$Fn!27$qgJ?~!op|wXkZ#W$;ohHz5b>R~gjSC!eez*pb37y8@actw%#8Eq zVJ%h*34ppo^&t2tUn|u^CUv~imJcx&pSG1M`&GEFitmR2ANCV|EJZwX&2(hUQu9$c z!mlLZ20PD{bGME-Py6=oN#Ww_oW*e10L|w`i8*0PcTsmUz2d$ocgob_l%B(qOq}n9 zADTL^e5YTLQ@HO{;*GCF4}uWMsCYm^3c-oP9&T`m(x|H+IQPvr&*k~kst)U9XNrm5 zn7zyBV)$I-Tax?4DuXA(RxJ4qNn)a1azwM|L41=KQ(msM9E=#N9;Y(&ZLOoeK)@v0 z4fc4jZTu*L1()Zs6+t{Xr6Qu|6Tw{zLIdJZPNO*|%wfw+7tcGFh)LgD7oyeZ`nLL1 zpBpp2!zrAy(GE2ExPM)Gf1e}W5D=OzXL1fmK{$O&f^?j4oUgu$%OEy%j7T##oPiI| zzDOPYq~Y)ai4s283@ZZr;v_d*kl%v}oeB0X;%c==*hf!q2R~UYabYv<$0Fg)pG_|x zlhN?Q>v*6F&`r)XQy@z1z^t^$>aq2&6W3;rLYSI^G~dwQ#7Zr$u;lEZo9X_#{uen;GQ3;!e~68nrk-_;W01ZyfKicWpo=X;q<^;5 zVeG!R%Ubg)lv0+nvjH}X@utHg$R06?LQ#%UPanO6C+bIRUn&z;tX0<^s9PjIeD@?z zbZ`z)eCoZVp$|HH{Ig~QSZfguM79iKOrxZve3I(glveo{D$#O<8lKa3H>uqCLm|ga zxIlqrv%$G|5{DQ?r)7@PXbx7ppHwX{ zV1EYo(opCE*f;z-8yxL3-cRM#!a;ZG!N>r+jjzePShbUiCS9%Cw;Q5K(GXHd>eo+V4oE3dr(fri;!i4rKW+n7Lq;$R4NCra zh>{vf40)>s0wAC}LeL%d0ljB18v<$;iGqAHhpsCD{(uqdi)hByQ9$=6)eg9IrG-qh zPisv04_astP~ebXadrfNKUr`Tgi>8NcxWJtFjw-c)SaYG^bVl0GEC+HGN}syY4_U?$aKmfHLht6belhFj$+?Q zN&_G`&S0xn19bypu2R5fx>t;N93Ajs17u1usDW z=2l5*sBLFt)IM|ZM^RnIznFU|XSg8oW~UG}kvs$%4y^s4nA*qDAVs#T0cr%$#{0MKKMG8dx=TN)+Ao3j13m9y{KNSu zFnFJJ)g;rRreA?x8*3$e5m%~>G6|6^4D6+i=QT0IQ(NF0gK^_$o=FbGEbcj4+#V(53! zzn5VD>yV}lCxF8gL=wA72)Wln!pHvA!Ku$f%3Z{2>Uru8j z=5KQD@fV{fuwO}7&?sTPg8Nq z4bBGm$Q?+$CWXELNQvD6ZMCxC2sm)Er`%Vh0Hf<(6;^*f1BB+-gktBx$0!7Tf8{Dg z%bFXK1Sy&`S>WdTsD99qEnw7m^sj)k*3@ky60$@dY;S8d)%WIG=UKS|dqngdrzvkl+_ z9Sb;*NAF}oc0fz7?Cx`J3pm%K+{6OL4Sz8X4}<>oG_RywhfzOv4Oj=(L}o<6?KXei z4!(WnI=~EO-&eI=i#0y8FSgs?p5`i@Q!)plG=p*Q75$2iLjMfVM(tewNwpfV&%6|N z;XU|#=zdaFaqc$kOI~3PBuD+x$F3{h#TX!Y9r)s)r@>}r5WQ&tU3>PEYW&DP=axUI z`oXwvVFA@H#5NPaVkzYcC)0vSV1G~^7!0P6mCS#egO1ne$ms$ z$5%t~AZo<{!csL#&L9Ul6l0y%kezdPV!pJFpYEtsEE%X|55*Ty&UdVrpR1d7-vFFBUa3igUpPOGvIEmf)r}o|>R)-?>z!d$Ct_+*N0jYx z!6xbDnn9b|^IsRM#s;*wc?6SM&UKnO!YMY#cb$o6_#=KA2 zCA)E_2lI!UxL$r;q0>6e)HhAZH=e_gIMnJ~9mWfC69#H#7l)TOyOA{q>?$9vC5s~V@0eN#=41#mspvXk^FN)revp( z{wQFm^8GZBA5?@rz%NT$kuo8=w&ljr^FjR?TjkelDK>7%+iAE~=7Ug`4tn3Lc#b=! z20qr_mqV!y8(L(ai?6$yE5?O z^rH&-R|Y7r+ut?bMo*{6mcLol(^0;>O&w<#cdNGt!Eq7&8#T}oDVBBZ-PEhmn&zH^ z2frMTR=w=5#znW2H26WSCHN@U4g0mqLzj+@^IryGDnWd%Y7Y1W?e$ug))=$%Na+BR z?hoSL6IKP0^y|ynyx|1?&o~bdgI(w081m`RP7>c32#I8}JLrczZ%hK$Gu`5!bROTZ z^@Z5--4fw%A4jSd02HMW{M=IZw~a&GI4WsnpbX|5sVKB7yOimOJhB? z@s8=pWSRCDa<98c14Xm`!ccr-zw?VVkdVtlcK(RL4ed{pcxgp>GBeC5pH53DlNrsD zrf5FWFd<*pYhTp4=w|kOiUCnwq>H$2zsxy`^hJx2Ees;&Mzb;5eW(_~`LB5gC?Dh$ zUVNZeJC~ruVt#n~l*^fTYyQARU|a%u&=Gmoepg@4n4~NPWp@fRwJ&hh^Az6ueCDd& zhNX4oyf*tZA-cC=J2_~;5=ag@2}I>fJ2@{&ARD-s2~cnak3+xnbEgXyaGCvX?N%NT zD%^xB4?aY`ZEF_aRL+W*rXCwb4I zc3x_o0-8zZCQ-3H4;w=`Z}-YFH)EJ}Y>nfr8$8r_b@lRhX0#13%0 zDHVu|1HRfxRfhfXNNpKG@kd7c<9Hnx{OT_<8EW?i-y%&^o1@zi917}VY3$FiebTM8 zxDSgAvNnEA%-I%3aXxK_i&+N)&rJuT*zot|%9OHXsxf_r+JKF>QtxIQx+cqs4oyk_ za!y^Y_R*_Z9>wcw&62bM5Rkc#B5gutFZk}IKboanrbS||{dlj(r7u|S?m}7B4(Rn& zp53oU-rwFwN3XmNAOb*(K~yiWD995jN_pSrId>-)VC*%T&hQ%_w2UIvZ*s>Cm3s1a z72jpNFa&%q{~zK9Z=2=*L<;_IafI>5@x$+t%ku8>aFro)OV)5M3#|-QsX^neL^qmm zHnjQx*Hd-?2pT-|c6_Rt15`pCX7fa*ClEXus*@9dX*t-iENhtLb)u(?Zv=YY&rv=` z6QwxSth)&P0EX&jNCKyh%8TJwRR}K z0$FTyM>hHFhUKFu&S*BP`6U)8z^IBh%(dj@T%_+==dIf$uYI(VvU8KQH8s$o(_+Pl zQ)SO2(l(VRK8$_86DdG5zK>`ai?!zE6jGIbR69WtDJ<8}OiGKXW2ZJ#lhBc;_ZZi) zxSSnNv$)XN&#o}Mg#?E~RXBM`*%McX^#jL`=P?9E+|d59Sex^@7o zFYB_%z`dM7bK4bGGbXIc{wy|LPV_^3CsL+vMD&imCiC;)kg;TK72k5r5!EUJAN3xI zkqlKCoN(~h>KZTB)RY|{Pe#%oB9qyb4MP7zc+Er zZmR0oh3#eZ^k`vZ9yxe<*9b91>{R!#3J#rND z#s=}aa5Zj%Z}Q65V`EL7b!C_U+YB-uD4G+45^~KYuzuDmL3RC&%-+s0?t8`agQt$4u0UEvjKfqt1cabVq+_F9qMj{gYByNq9)R8f5A_!X;A6XLa51Gz*qY|dq#l`@&v zy+=6(Y^d2;7wt{DsHz!*_OWZ@{Q-$jjzy17jm#tAv<^y$f8~&D02zJ4QbFwSG|bw@{HA1|bIPOD9X6wr2Z)(@Qtv0z0Lg z!UQ#bo<^*#r9(4%1!N^uDdAHOH7?8tBt|odful50&%BQTZRrir+fd2C`KE>DTm^0N zx54GjVCDO)f&A*II@PtKzsD5#A7p9&x16|tsY(9|gY(~c2ArFv&}~CVBBGWXviV8Z z=hqxqiz%k6j>O2{U+aA_C?H~G_|@@avF^f3qOtR&_lmNf<>>0+q=cy^0{u439)RE+ z=jW@4q6&*|V$-UA+&o+{~^Jy+AI@EqPmI#F)^0cdPVLF=?irFBZ4W%NfnKu5y-zG_!w_E{cGKDo2PC3xL{mI(6;2M*&JybXBv`WQ(OSo=Su@M`uM zs4INml@RRsc~&kXpZ{y^kfyixHxbccELjP#@ROq7gfa6`6)SGGy>YQu5NF=FQfE=L zE8BC~I~^L~0$LLQ?Y|8Ix({^-T4v&JYh^%&Z)E*3qU_r8Nh-LO>fpC{DtI75TpN5j z+qABN2bA^w5YOGM0Alc~d9C#y3!0avWrYf%{7>4`+2#1u!~g9w4Fo8^m{6wtv%48T&OmrHn8j7qf!jgwS=$(?jq#1)ndev zOzvaXOy8gvJ|rIN%+`clEJ|271!$o)pTFShmkRy#$HZp zchqfD?R*XC#>tv}gh@w*oswbpqp$D8PU;mEg{DNSFg|~pcaHz*j>Z!u76HLQ)(V-8 z8V&2LVG+k0c^E)cy;tLhJP$qbyN;Vu8b(#)2VyyVQP0+ggoz7&FRK<8d9*tFo=65P zM98Ur=q2>ytt%L8paT9FdW*557iE%}4S7OR1N)R`?#ePf2(@?otnkUyn&Bl6Z#VlX z;WcUh>yCjPQaZ|aZT^8rZ~x6sedz@jb~w0$6V|!Fg}Z$Tz>omI1SrlpM3SKefQ#zt zlb(BQ>8&sN5M6FHxXqJ8V4;7K#)1=R#ys>P;UIn->uv#8_Cs)FitG6=8y9YX6Y1%{ zWdLN`*HuUoaZmF_L6V?0{rvXFnPwhEZV?}Kd>a_w|mWt7tpX$wa-%!jH#@^LZI{Omw69 z?AJXPvPz#%*;~txxHj%I>OCDEO&9ee`KaZ+@|`J}j{kOAMK{ODz0l~gI}!T+8%dXT z&~T-kls`5mfq~|&e?hEkk8okClZq#y67ZF5RLswA8uh;;O8)z0s4%S*El0*w^>c(0 zZ;k}3!P4YsqaDaRUNh6aYomz44P){5Cxi*)D_<@fFe+aWzy9ToW|VnUg)IEz(=@+` z(=(6|4t@sW^W~{^fBh!fW?_GJ>e24Nsn71D6@SaCQ_d5{s*(8lF3JPyqs}QP1kct} zUE-R;9p-(cu^A)O!*sZN{ltFjYrO2X?+3pwdLZwjTabAY&+yi$J(sN<4sceSs(4{) z+$}w+Zl&=0&OM%pp>x$~_47`5K9g40Y-WXL=v4)xbCIW{+Il(12sNRKvS?PSOGVzY zjFf>G`%s)!@e7OMW2MDcxFW9KRao)0U&8sAsMa$vj|?Wnk(v#2dlYmIckUCP*Q2-h z?tLc5Qq6y<+(@N(OzyT3g^8UtZM;C_j83oUW-TorE$==x8dHy9bw}uapU5RP1h{0z zA8*z=*ldHd5H&4tX?psGFP^*R%spj!y@QwGu(?egkS%z8SP|ery<=b-&3LU&V7_~(ZB&){~>3aGS5VU7_ zD=c%pj{-X%HG|H!V1ILI^rIcz!kr$MR;a=Z+LuvZ`Cp9kK{bZSy2Qy;j}&v9`h04{ zkj|=mpXnOz9TiEjf;-_OS25Sg{u$Q}(INBcFN6=XG?sWXsBfq{Yj zuA2eOt@~8k62Ge2QFSmdBR56wyy6Q&^LA~3#XKsk=HT^kF4HwzMz*LTNcPWH;d8zSc^61I)LKh`hsiK2z@1r$s>J6 zyp1Wd=VV%(zc%MR@|!-)Y)37iWgx8(`{A}d7nN%8ERPp%-Fvfh+KpZ*tD5Vr8Y_p3 zrJ3cIYL?!ep5(wF$QFeel2Qq-y`|Wb8gNOeihVx%)0vBI$~(f&^_28H&pVgnCiEsu zT_Hlt;riR2+Llz=i{X?i0AP-gSH_%z6gf!|t1Qo6`MYS07qG~91ghUPJY+&Vjnw-Jpf(Qs_g=X4kKKWxZNVyh{c z3ie{oBHP!P{21ctIxi~cuyEeqMNI5%_8GxT+<Z#zrpmyavMGh}Z$A8%3Rv6%Nt% zh&@`9=ZOnbr+3{CmSep9O0oh!TxZ45^&D(7gxrmqfhRtJ-jY+?^jiAGkp8LdV`^bUx5}1 zfs{LF%aS7BkB=$E$cZ^sfMId1-7Ty;?s~E1dEZt~F&X6CGpr%(nI78nEx|)-fw75) z$DsK33fH?EndMP>9F^n#2#vW@yF^(J`|1sk<X^yCK<;631JER99{LtNNN9j5z5XQTLj3&S{sdpYMzs<&InT% zB+~I|?L%EDPiDDe7dT0gI^-^r#0}DZ?PKj( zf={%L4CZo(O5J5&U-!tFlv5b@|H^)e6pv8tQn;L9G94@QzNcp+_oMXsw__ew;a_)x z-kqmqjx6~VUpMp#ke7d-VQBv*eU8heAR)%ww4&75iCR>T7Mhf$ntdwPS7kia_h{zS zYI%2|H)~#NJUk4uo4&Vr9?qcJ&8Sm*$T?uiON#0H{ybu z?KQuMi!UV86;1`o2om>g?tgn=9rt=}UWAC>^HBWAgG7y}tND|uO(~q6Ljjp36_`BL z)|;aTPkx!JcgfK6^X&I(MZU^MdmBa~)A)9w+RJVx8y%@46?`yATkDyo+D#b%38-~7Ue1tEOn;Q8_D zAYojP;`@KA0wx8~{q_0(iwK_O`$tqmKUVNkuYRLCq|MxzbM4o!iq_;N-^=+jvyj|FXed*>(4?D4P8nwednv_Ng#cfsm{^Nvt=M;Kz?NTFf6wfX zG=IU@AC41ljaj-w#&{ zJP`V|M@6J2@%Ve9Qz+Gq7+ePuVc%VxQtq06+aTqb;zozIN%gPizAk6L=P~?Lb(Yf~ zB#&gH<(J7YKZQ^BDJQvi96sKm)~kB#Wtios_*^yF=7GkyW629YkUWoCKc5vp?~&tS zI!Dq=<|J&+3@n;QOB@(6&70Ox`Nm8$RgjiW-9c)uArRB>wwjvA z{6YU9rtA7FCWGqj#(l1|h;bL=Lm6yu@5>s@<|BLChVfNd);Gy9BzcsUX7!fEi;rUG z1@!_XzweJPrrccI)Rnr#yQcEBoygGO)Ys4e?R2>tTWhWJEn863>f=D-AcN!h=DnybmtWU7!=O zc_4J!Qn8>~E;!k@)?W8emq&?P_uGV4Tc?;)`tBv}#@?tGXEd@!Fjc2)sKr0&;>9}W zR*KiA7T73OAfo(T?O{ToulcU(OI+qLEJLVz*;;??#YBPk8XgF*m#!EdGB@Rd`^s2$ z_VM=Plszx#eVkl^pCPRSi`5$T*gkAOObY*;CWlMJTjP66R%#0$Qm>FZ7T%HXalzlC z&&l*Hir=~Xxluj`anEm;;9GeKf!j6wsbetP33?&B_ufm!I&K^dL@N+f7+=&MV2V1GvRJ6;jdZynB zRIe`Eofi;U&N6X|eLueVBWu9seW7_)<~MSMVB6H2F27Kr>#x`oxw2UC=xj>G2*AmD z5YqoY!pZ)4xyj}nWv2Qh{-ndb2RB3h(u@)GQE;0(g4o*9rtO%?s*1lC1I!)G+FK)> zu&>CPP6xR2as#WY*>Ui`@~yV3U?TFV&@;+!3M>mV;^DO>; z+Cg_-l^4hBtiG~ftlxQ>(^2E?&WC=!ip4lzV3$BG-!H&z=|)LFef2(ZM@PQ90bDm41ta9DGctUQUkuZo z)k626s}Ok-4UqprIUGLzO5@mIO+3O@cF{KNNq4^*8tVTul3p(fdcZNRyJ!eBGyP z&G<09yxe{S>x0cj*5Uh^FX2f@A5N`6t>;^bVxZg+{&106Zb+*5J4&LVk$Z%k`m?^wY(5jzyc9#s}spRlFjm&Fg49pir z0Z?CCTL7MT2LO=A0rqjQiIxmaP1T^tXW~F*_FFrXa<^Jq(YRfkG=NT6q1*8*D$%krk@iv6bO=1sx05mgh0zXYlo;$~!SqVeXNFOTSiAp5{XlM@`v@C`o&g1%J zV6@lypLBlv@S7a?cOt@DEj6=5B$hySHCzCACsGmkXjDBTP=i&e@}lbiy~Sdgpy6sK zSQ$6X7^IkYW~+=D;7xz+c~88TKFuHGc|S^&P9*KG#rJMpFo>A|Jl9)Nc`6ZKav1sq zbrx?dzFQCsnc||y%TMY+4M~JJ~atwjy7{gLIW4L z`mH{;M3*G^d$WHxmN&a<5w(v`MpS|!jXrD=|1JpjKn}+dmYrRZ>kQxVtGjX2j;U;< zs6g`0AmME1+kZSkw*QTrvLAa0f&sUV5h&biSla1me3A+5QXzvNm%)lZ>2k2fz%ixK zzN@K14)K~C56>x4wU?1UdjL99Vc-;YOBAs@lL`@vA@Z6E`T{v0YW@KDRA?~uV_lm; zBSA;I4S9Q$>A4M zB&hVrQQj$JGlII8vNMRhfVa`+X5M_%iCp>){A81n`7)sl)M8s`yD_AR1naWu`gUU& z_}EuxY7W5AFuB6Gkht|AQre6a_@C`A(o`UuHXcw*2Y$O2G)NQPcdlO-ybL_2|4}U8 z1{b8gfY=^U@e78uO)M}|f45$bBvsB>fK!_A2DnYrY|1V-A&jA6aB3Zzl7j&;XIOPW z&#+dEqCp;qn!_T&@Bx@_Y>kEX!OQI@o#GMIUo}OD8j*(d)*n&){?#DxZ1!(kkQ)QH za`At>CL&EsE%QW9)Tn|{IR|Jz%66XzPCt>^V4y0!o!YecN#}!b)j=^}`vV&YtIS}B zEwung>u?>J1Yfp0i>+cKzUry`t$N1Co@kpnK+_Dj&npTV|_eGYdc zSQw}^`6vnr3|Hg%j8QYTKKy4ebJo9Rj>eFLzsS5`O*;IzGhh4nmw3?K1eQQ*&EtPO z$Y>*CGPg&h{LYU0}8x)y&`+@#PXANfiU&Au?+w`G` z%pFHWS1jRPJRA5VDG4eA&;!RaLf}3Gn<{vK`29hb#mpJ7q96XY5hTbAz^8CC3A&Ge zQ3KzJWrlbC0Mn&^6}rC^v4nhnCIlKCL_fODtsS*Ajy& zkvG$DO`RYffFWXKA93lomsB7}r(gm2jv^mu-5w8XW^piP_Woni_rp83vXs%fh=J5m zFjKF!1Chid03?e9Yr0fX472&n9n8RvY(Ne>TVQPEiXa_4hn>K{yMNNr(NIbF6Kx9w z(gUbPpavo{fvwXR#Z4=#5Z^8bq|R^U@{JXR=3|EbRMaL3FBrGJMh4!|%p-W}9&lQX zH$8_52rdR{6%`1Fr$rF;jY-3?y7CB0%^w$Aww~d*I;{de6BdgEGK=H)&f?LM2f+jA z7sMZFuV3@Jr`;Qj?;obHCqs0Z4oH?uijqJdpdu+v(+Omf3o(@(F_BP)&b{+ub&MOQ5~W8O$;3S<>!il zv#_#Q(X!V-n-F zdeXO|0GmX`XPcUjYDO+7CC&nXHVG}zH`~4BB-ZevKy$jQiYIHy(ekrTy=P#M@@?$XDU+~+PSzp%=WnU8(TQx9|m?l;%ma*R`={K6Xx_UGg^-oC6X$lW7g$p zsmG#{pupH-OF`CPo@~|R)Bb834D60I>teLD0#3;Rs^a$>zR4TQrly#<)Uz#q{HgB% zk;;AJWP~{;CJk3!21FD6Ann8XBIU08`4Dra_vH8UhhvSW?xzbRKwJD_VE|6X6^o-qT-bJ6{Qw4S&;(2tRdvv!c}KLxxkjHB6?Q40?# z=WX!$%r%sl+`=#k?&(kJ(t%!z>fAk3(h)N59~2JI8jdxP_H1|?p9CtO~+Y#+_;-L3?WHXY5yaY3*jA~-f5=L;o z^YfhaLfv@}Hm*BUZ(ZfrNaynjuZKV$0Fqk`5K`o=HVU#HMs%K^d$3pUyTkF~KI|el zdr-or?%wmHHb9$ui_OCZmkoq6cIpu0JC}JhOU_;{9pVW;>;IF^it)+aqEr#hQI&K0 zip@xbf*a)y8hqd(>X!l>&n!oDE*l*DKC1IBBlMK^N@cO4x}95cp0Vx>GfXy!625z!Cw|c%Q8@0e+oniOq&3wKmgp##Fj=9n$&oS z9M$*u0riMb1Yi~dGdQu%wt*8B$ktK2Q&f3yw4Kl=E`F>e88^OWjo7o1RM_r;`{3dlW zuTBWOYpeo4!G6P4ffa``K zmTHF~ySvTf0DD0Q1lGVI$z9$r0L5@A5Zn#9t-)DN0)bfopJBVxTYHRw`lSF-wM1(^ zErY;6w>u;lx{P%v|{c8;fVi*~MeWD>UGw3Uu@<^}Pe=3~**NXbj7;Z1`|12A- z*8j(LO11>x{4Y@y-2Fy2UOZ;r=kB{`Zhy1G>3;s|1@G^de*CyXs&^|hH9Szc(!jpa z@Rzf!`{WBRh7laAyR$xVe#`s4&TOn*R(5@w80IeiXOwRv|W{&jV{+tfzhidH#q@ zWw^12%AL-{jG+_6#mo`Jq1juUJ;%X5 ziDDXxj_#kyErslO$Ck94n8_ndw=s;&@{rR4GC+k>guGRJ()H_G*mr zA;$lFyvfR~Zi#|cWxv5$nRDh}o230tFPeYh^SSGe3mk5dK1aF99h#-`FjZHo!{xAr z;8^RTaLwSjuU$v3L(#{Nv0D`%a;IL zYw@gA!vuu8Q(e)cGL9|jEGtMMJpG=L!=$?4F;%hUQ=3m#mrywnk+@Ao3eaq$vfqM0 zjNwjNWCed4iERuUcshjNB_RAkN!_Lu(~&AmrL+g`qJl$amTrTc+&BU=S=9>(qMF zi>-9_7Brjz1n_pG;J-;vT+UxB!TjYjl8Eyh|EUp-`+vsq|M2QD^d`2gSCg4YZguMw zyNTij&K@6c33ezQh~_+V%IFZV8z_Wlgos2oPF4i`eeuTha3eELG}zaw$$WLKVyGzmyRrL?&t-2B|WU4V+8X9 z=N3K;?Sb}$>ESbg67mvUxxgj;Z_W%RRNw*V`w{@!3&Ts4Z4iBW1ch_w2A*7K1ohl@ zPO?pWFk)HDU@Z`Sg=uX9Nghfu;}39YfbZDbq1|s$m3cgXZq^}yo7?=twBH*2&WlW5 z#i*O;I@GeWBGXU0>n(Tf+=%)~=@l`FV}ex=(%hqmZtt1rHwQJ5I_8-1*QSws&5Yo`0|4q07fB-jmHK8dND-vX?Y|AJQgMUfx@GjAZ~-c(kx2 zj!QM{8YXwp^Y%06%K8yLv{H?P;)qw=zSlaFb+_$qKAU2i)twA_^Z>T8qYVWY=0fkS zGlkn$6jTmoeIkFp{xAft(^P+-(r@C_v#82Mlvw}Tx#l1Wv%4*DAMmUQf5KH@es>Zn zFZ^I9O6BqjXX?_^AA5IK$vs^BS0NLXN|2)Z{6=Xcs~$;9E@uNE56IM4O@x@+d^G`x#aslVvT%2A=~ zdr|df?0{B*arT58i>Yb-5fzDJm1^HCBU-=hh_LTYtlU&_V|eqR`-0ws0(>x|V|$E? zwUf1YM5lw;y``zH(XwWdh{~zgYF)LuFmGxm#sU4qGs|txCAAZke{w;8Ogl_Q*Y=Q8 zyVt41Zvr)6EO#!*8H>NQXt}@4ws@?5$DJ|)EdgnX=cd{x@VV))JVxxzq;5TXL7DrM zI;nZpk>^_z9wW~S@*OxFUIX*a4n{1=MACp(9x?>L)?!YA> z;l#HZ`A`?0c}7KQIfm~CtY(BrUHLHLqE3;Sa}>DhN_-wHtN9R#d}~i58Gu= zWIKY<*o(hik&E00u65OSY{g;%=N%VZkOCW3i|-2`4Lxo+?xDuz9KpHxFf@5{6Zf6a zi-Og#b%>AHt*dLBR;FabD1{=KuV>C?iiDj@@lYSqbz~}}nSyQDQg*q8Ltd=;p+>Cl zD?1a(J|V#flpp{l(BIJ}|FJ&*Pp!{$JAl0+H*45e=yoi zxOTri%~mM-nxxSfy`}K!mZoI7XhW{T`Dgta^IPa3D!8Nvrcwb=o~T)aiXs5pz_t#f zO|Am5JYxdzqIg&>3(h(x;k0W*<-hcH@@yyb_RIKa6h9R~E^r>hvY45YPu4!F6VLLR zo_Rl*o14FQS@(Dq{iD5eC`+I=cEV?%Zz&_VrX^sk5dK?-4D!>z`>&o$m(@#ZFcu*%Z#F&TOFzT-ZYlw@h0; z^n3IQI*45BU~FK0D7> z{a3V|om}{SuzYL*nQlg2_oi7LeW^0iBR9q{VDlmF`m~n0F;#!3}Dn9u1m%SAK78Qsn>}f#w4W0Ym?{EuZpYBBc zIA0%=r7ct`_vqY#c@rb99hJHkZKp#~`KY{&1ydq!{ds{j%uyUsQ_Dg0*oYM(?ss9` z$(|sM5NzLb)KMusy!^&XQM*@GeAh+{&VJjv3$zKXoqsa{qx5^4u!S4cSUecgxvxDS z@`%{%4Atfh^)%qf)A>3cLTjkbfh_WlUw`QzsOpGj$U`_@NBISnaxaAApGXWr(D|-0+MC7NIf2)dtutIr}9$DnqqGq(uGj zTpRb5b9Nd(+OPL}V1bW#ti_qvv640Vuh@ditTc;cxw<(_2Pu(We4%PnC-KitN5N0Q*`4Lnm@YAq^xpKzsH!gI}xw z_|qehb@9yF)X)ETpg+5+FV4{z-D?7o>7g%wD*KwsN_PE2*-oO;Nc-F!378&~t~1PP z*M~n&fH>RC)ZNfa=;NCr8hsn+Cp787NfjmpGQeg+;2QM?B4^l=*@-{aI>C7S`nk3x z62mm1d0z@iWQQ-qx%UXGY)C55zTS*A46D}M{7H9a6C$2K!6M*HWaJr1rR|#BE{Z2- ztX~kpcg^EqA0X$R;+C1$BBcQ``UY$QZED*QBpuAnU*bg|v&(?YXIe-)G#6MH7eIy< zP*D)hIw_OF0CooU5U9;?lVPhd4*CYH=fsn+bud(e^pXH|J^p9uys7H3p6j6G&JSSd z=lZ8Jj8ELcPt-!c^?LH3y&hFv_aqxZlRPr;ZXlrRI<@DQh#!B_wMhTgaxl&*DczFH z4$RaRzjr(458Xb9%)?bjf{*UQ6UCiianRy{31TwrlLtP_j6gMi63-6x8A)ueA&MEc zn*Y^je?%XCL=spE!68cK1fR^Qh0JrRzS(mP3px#kY;=-1xNBg&rZ6JDqj}?cg2SB^QI4CLo_NO@;iO?vI=R zi|Jp}vXVoKg7;%LpZ$P_9U8Vr2XsN7d>Wc$dkFSJ5rS&&&8e)L%AU)-_Q&~niywJa z!N^~t+yL+S0g)beQiQ!&FFp>&P!E3o)z+3s#Ge~_2mp+|2_+XBUT-47&09_m`TSsApv=30u3sWDL7(_ZFquuD@XY<4=Ql51D(i z5-f`|_E;)2=*$?1^K+ESh+NrI45p2Of#pzI?RuHtP1OVcxKLV9L{Q^SW@?oqL{yvt z(d=((&wCKL*4qE^+pu$0|D(Rs6yy$lEdJ+4_9}xca8FaSgTX5C*+5bs#X=U)Q)~Ek z5t4icv^W;E#>cM7^Bmd zzw#98817pxjT9a<8bfn>X#p1@U|hAWxJb0>_%XBf>~_?b6^BVWkC)fp#Yfa%=kng$ z^ium>&v?TN;46p65OP&RBr1->P0O02$h|0hTpC%|p@&uF>6CTk=Zn>;Y7@_cqZn)t zl)fovt^z6g00PisPm3eTU+ykLe7xjpe)TrRD&J97;L-eNhGK)K79X@sQ@rnF2o?~O^D)i~O|U-F<^>RB0e<9|6O%tGBzqq8jXU7uxD}6q(N|?T?ZtC~jAuKO1BU>;Fhd%-%ZEa{?A< zrjtLZn0brNI55ME7*b&)hnQPU1<&^`cL`oYgWMvs#p5HL7cU$gelm`>Za2UFihp`a zU$D@6P7guU$FqIZ5J&SHsS8tD`BOzsZJqLYPHnx3-?rhA`<3fshQ&k%3tuwTt#*bE zhOr+XcH^GRXIb(ETzQ3pSk4S`H5A1mA3|80_86DZGnwK zpA>O9+e_`)IeL4oV{e?7qYX>w!aI+$VbXDZ{nR_4Z#n|;Zlel5>dN^YhYMxt%e!|d zrZONjXbIT|R7u7F+-I>Aq>Ic!-E3Ao9}q14aB7#3+Nb~2sswybV9gK zkAt4>`gLaZapYfMT>tCZdcn>?gIGtycrPRJn-Rh@1akrQ`K^;tx^3!3wya{kPvZP) zlHMPE7W%H3E=-_vjls5rh+aGR%)pXP{v7gfu%X2W28J=B(ev07c+D>r#ir>)4$ z-8F{Tx$Z+N@iI;&7maDh&THljDIw_8%X|pJfZ-)x&iz>t?Xmh z14lwd#>`14l5OA56b2m`UEX?JSmbZ)>%06#|1ihV1L2K3pPskD0rPLba~hD4(;vw4 zKj|3O5mYpWY=i0hNe2fx`QeEWn5BlaT{yJs%C90I_{7=AAjgWwH)Q6(|*6m{P{w=eX0Gw|D(8*2JUl~bC{rmAZi!P zSMOI#tY+P6IJPH+_cp!d-76oblbu=~%+h@kIY*w!n7NScpQinO&eeHlqq{ZN-aajs zJNZsuc%>Cm2lZX~0W3+j1?v9j0ZqMychbJ8a7XQYjRvE<1y z=I4-ew9@KI<~!b*KU!-4K4LmPwtqbr6;6urH}dK)%jpFU4Y}kx~CLs zp}AJEoId@X&;Wd&Y?;Se$wS4=Ev+GIgS#w z(jV!KY6hoUYCM~z9WgD$eaDio#Blvx`bMMKfnt2_kUyYmgRz{PiKDgE&W}DSM zQL!PrrFuJRPwvOl@z=vrB2dD`GBYl-UTEXtuv1;yXKIy|C@~Jyes#~jE&gK^8FX6- zvQm5R`KRF$WtTJV#~9#s{H=ACYd9_)=gM`RiWbbNzk+Ljtb=OysBj2wAw@}&XIAv$ zN}=vXG1lpPB-H$9UU3)GffF1GpMr8xJ%**;Mj#f{6kp4CgZB%Le2SSGHUw6| zC;c`!jD2ek6^H+A#a=$;w}>`JQ9|gogSl+_vwwJmG0QV=x|A-MM#8K zw?pX;NzBM|_>2xpEZ$uw+9D^Sc4YSYGdqamFyXXa)|xrrhP?|qE054bRcaVH)8ucX z@-dMrr*%tjs9&){eIZrZ;zxxv`kSI6dFmrAueJzruVdjyL0GtBt;xW_r{Pu6W-j5y zEL2paDxSjt7*A*^uvUlBVlbrEPN}D zvLEmh*~rOjkpOo{z@N@slUWCY7IBiKI(HHdzlb(AoHAnrfWNc{d;zs}pK|LIV80){ z2_M03Z7;E{H=AU`#f|y%fO<3b4(jO!!{9WOA@yzNk1`eJC7)j&}1 zJuD54fg{hYwe1Eo_5``L0kRM<^yq;ED(r~wzxaFGLDk}^SGUhYqsWcNo-cFB{ ztqxTApb_+Os39Ipb8(t5@4`?$OaYJr6q#?zhL^>fK{aaCe+{JifBd&7n<+^mP~n`T zI8{BP&-RAQPSd&P3oplL>D3>sqm|?Ft zCfo(wgM)f*faBpkVN14WdIEi84#f_0YK~IoUYFf@ry!AjZSMH2YYHRxivxQj=~=#d z-mReio9aHL?6XhY3=Gt>yO|lX9&Wd6nh8nH>luat1oLlV`QHpWUUVLfef)%-os6g4 zhr1GliTFC`pdFGDbg~j&T9-w*ncC0gP4j_Z9$}*^XV3C$)OV3o&BjRI)j|tsd@4M6ny^<*T_s3nW6>**A!@O1&FM6*RCxBDgr3R zZJV4hFW488Ki1jA-_FV$Ium zp~2<&(bJW0MV>Mgc)I~uqJSa?waWkxmi>u9Alo;9K(NSVJD3L?vaN={VhcBXA#&_S#wq9K&zpu8RnQ19 zok?t+*v?>9^%zOjLNj`yi13RMrvZkW#ErnyiJgy|5uC<#4z~AwW$$Q9vlSeEum^;8 z_%>D77F5AW78~Z%9F+-CZk~y?e#I{@TU*3hwtQMGJoD_SyDf?7vhEk%IwI@FLiT2EC~Pz zQD)f4@IuOoY>*}RW}fxTdG^gbU`DAR;4>%h88v zAryxEKcOZT)-emb1YGiV zP)EIFX)k~m)g97@4-wNVjC^ZIOR1Lg%qC~-Ac@KOIN!(i`s95Flwa|soqZsaw?OYLsqCPepOX0Yl*$D_ zl{bpr?UhaeaC#u)ew3<6qk%@~!IxKCThY(;-$K&8=)2>c(`#G}lCU`(U1UerF z6tYi>K=i&7gOpsT%TSdJetdEsnrBXjruU=14LSsoTYy>({0rGzw)4pUDeVqBb;9c* zlH}+C9D0fWEU_Dd+fB#3Air1Q%#JU+zN#*ndmlDq-W$1oixw{wp5hcR#J#&W zXa9#wnUQUbX>|ORw{IfolES(z}>)zlsL^n&x$&{;JmSi`Oy-kHA^Q=t!iM2EH3l}kk>b5D9X4}*sjr4~a z>En{D)V_&Oi_IcZ)LZQ@|1b95JRIu3eH$lAAyRfR6_LFxSu>UF2^AA!l4MINVK8Qj zkaa=`F-gce*>_`CN%no;cV?`^ET8A)zQ6bV{oKp<_&vw>d7k6<9LMkXhr{4)<~{R% zy|34Go#%O-mtM)#ucflIb>ZJgPx1v?$2ePB3{q>t*G%`^4<+xH(4ou2I%;7hHBMiJ z$zS)*bWNXgd?#uwmX3~*4`KYW5&*%@~=ZtON-$2Z~q+QhW-_bxRs~ zDRqgzs&RE=McS?$x$hEuZ?2}CWKX6?b)rw?or}KH39DCij;vX~j~2bEnpBcqF;V*I zk(L-KNSR94kDvGoWi0YR7a}wp_-W~#Vds7b76+85(bb#ZM~`RiF-@T-@a;vnWhFKbTbQx3I59rhP*;F( zZn&+7Mx)OeWi1tc(!+^fy^eepdD_J9#&f^n7kW~^exdwu-!Y`~{oz%xDX{qlt3JkO zSvi@gEe^#ixv97BRQf-QHYguR>IyKNnJH=7n%^EPTT1`Zt(sXhm7u=aj6a6rMd~CE zEw|Kgbt&$xo@ikl3ix>E2mhrXrk=O!^yZ&FPj-I$uN$x8`rW&k8ew^Nz3_oFHl#4Y zy~lIx6af}gV{!BL#Tm?PH|t0(&cvE&T|f~2WwanyJ1M)qMv#aP zT345zYCT$fMaf-(C5cuf`sfpnO&jBD{~r!wq`w{0HoFSG={X9A-O>WkmfL zFN{rfez7}7-}U%Wsc2@V?76GCXg7m86&RYPb%r7u$rogAlljiLKZX{HPBReqBF zLP}bG@!<1=R;s^Vb(tsmq)Q|dt~9cDVDOw@N2%VMJXh z6W8c4zkQjE`=K`2kUkBDepk_IlJK-;DMqWR+)bF|WBh*Y;tyfAvr>8wZZSg?1Q#zl z6(kQwdkXGA4Z%wIelThBUu{^L6|qB-6FNb~KGh6X#I@HpUk85m?V6SH5Ot*FQW}J_ zFG~DGoY}(J<6fcd|Da=`$oC`Nh&9vA``Q6tt#pVyw{@|mB_+wGp{;LM@5mJ%9?`3v zR>^*I$FShhSTN)T0^OJ_NPHYGR66N$yVblqT|~z-V?@XO=`7;xqu_WpwTZr7Bm?28 z5i7}aCyG>VM{r)ro~SfpAFy`f9zqG|`#0L6Tj@eM&N^`JWeaIMxK?M(WJ11zyiZNl zkR!P@U{5Jh& zidHbgj;+>ed-IBrpY_c=W##2y7Q7~_zWM0jH!jm_BFTO=N*x+fsP1v@Egvkn7nxqN z9~~sAn%ncAFAWyjavG|xF67+osa-t&t<3J+`S&MP^M?anuaI_$I?WJ1ylwTJ78Fxy zS5dC2kHE4k*J8!DWM{IT%VXVS7M(XOkPlJWf?er+%t@c3F5DemscXAOmYj@hh6j%G zt}23<5;)Yd(^e9vIy~~Tq@R1CKw0Wg{8X6kQNEGHxUp)D8mMb9_7sYl!rz@o@l9Xg zpMP7dHmY`&fC`^{SzhF~ArI>77vtf6;E3W1J!=V%uLA1JZN~fv)Z71bg7mXPy z*sTz*(=4}$9=7jxbvBoPWy)Q@jE`lD%|(ZZzQGq=6&%m?tH(0Ld%P(ew`QT64x|@eXSvna5nO@ z^bzTiQrDU6eD>1v`(XW*N|vN9O*cN3fnT07x^#4wQ^0~&3`Whcqkf=V#2!^ZA8Scl z6wi_}oYIpSn>YKg#B)b!FrcvIG)E>{L?OphH|JIlU2Nt;Q+wuq(*3^bX<253#j-&@ zQ50vNe&5;Cz%E0_Q|@}dr*wG!4c_pz7jz~+L}2U$v8fyge+{<-mczEdMb1S_G-B;X zqE|^pam+-#(u0$qb${HxdS3TC)47@l)Y2+;d!i(qq&8td&RntSt1@tR*~zvI{^aJM zuNzMjdB)2|YP!%cHf#H$Yk|D+P5sgomJQLbSpu?*Vo4XcUe%^XyN~_3R>qn;MXtp? z?>s8xu-A{`j!-|+E|B~iV=Zv?suaigc51UY@oV&RI&6ZDsnA@|k-XDG*q7ZR zQOdTC>2^1?q<*z9XQ_xp*V4i2#)PPaH9UI6jHVsc_D1Q82nj(+JztJ^u7^sPdEde( z*(YM!IcC&O;OmbV`brZSCdUJ6)JXPP#l7xogX*&Ckxp(Fi@UNeNAg`nZZsWlP49Pp zJa+n%#JzwS+sL|%^+QoUf*Eg+Za|BF@4i#b(Y_q_VM)u3f`nkPp++CO$^z3Zk9xrG$=&rMrx-KhVNG9&D9N+D=Rmh#8m%$eMP3- z_;ZaZVLb%uv}|b9;GGdtB+CSb(^bqinpihY2CoTMcTJQZj+$xnQYoznJd2TUWp2Zc z`dzwBYM;V4xt^dH_s~vKj&v)ixT;@rc6OhVc5V!u7_iVo1{yf)rWA`yMgM@TvpgNh zuA2{05p4Ld9~-iVoeXNmof<)eHeuN`6bBqDAR+1yTkd?tz8I+j$ArM>3$9zO?(g|h z?+xnfM%?ocJN5lEyFX0|)dN4ZWlGANFk&Iy9U=Y!i? z&CiccdF7iAYdQdXmABv4$R&9m?|6^5Mq=V2rY3MH68khd+|`!!dII-$NINMFv0KZ1 zgr@Z^O0TF|zt7=O?AX$X?u}MH@e~17IJ*i`gbGNVlkIFI(SAe2 z%La=%ibwF4t2Zpxffoaw4|$s!S%iCw zVlotMZ%Eiuy|Py9k}2I7M{E;Kv)Q?~Ds(RLp;}U_nr;U20cV}!F60%@lpMmHsYyja z&wc!|;p!x5O}Jpgja((&T~$fkEpJH^W0CZW8I2hFcawSlZ!%fy-f<+32i5Q+pAy=` zkub@+w0n9UrE*_f#KWJuh?cVFGsquyq(6I2`8T~fETHqgO1hN+#4q%RNL}fO$Ww|sQ39v54O;Yfbb2~4od6TSpuSXqMG_q%X zCI}sU@;X*T{Io5{=Lk-FKJ}So7)>#rhMp9`wF1ut3!zh8Df$Wyb7kM_#YJMAMPh?R zQXWNh3a>dMLRAZ6EXq-QKPpQWtx9%XHk}6d<3T6wFW@0Vh%)*6BiL*b7mjj$eLry; zO#p?zgFOuo<~o&v&D;-9w%wNhj~7h+&lkP``ep%kdXEvpE^bj#LtYpWZ&NheluAX6yZg1jv{T)eJX@1YQLNe z-q-gX^!6Hj|1NtTAUkOi(9FM;@a$?NAk+}@KyUZrV?52E#92^z-j4<7)4H`LkC`6EswVkt9E>cfp~+@BT?;* zf6x`TteTna)5BqR)49){QDBEh19=ulloDCDj}XzMgOIK^;wp= z$;RF6kG_A<8B4CHPNL3$weTMfWeay=fUCj)F&DaXjT%4utt8ecs6tJxLEzE_O4O(5 z-KBZTrS+8`f6(1n*8$U>AP2g-l$U=ZTE4o)J)5<{B>r<1`A?NzP4s7sqs;XG^pTUG zQpN1I)Vlij(WI*LgX$B!>x5FJ40z3IwcdY)_AEE9FLk%9;A};P5Xa&OQ|&8-JM5(Ebs)-$w6OzQ-9Y>v#~C# z_HHkjEdjqXK#j|Dp-F{5LzzkK{7_Qbdg#KW;du18fs)H$gAQ$=l$ByHB433LR-)WI^BdS2|<+;(py`%{! z={!K-SC8sIF^X-LO-d}`osBTVBG>z09_!)7TS&gy6OdQtGjNg{XeCN0rG=K@`t~XB z{t5x(0R)U!bfxmRSOOILZP+rBb>E0~44k+qZW6yw=>?Fd1^LB+w8{?wIMQsAD>xnw ztf^{7GP8*VDTGf4V;nJaZaX87jfS#Ye!t0Qq*?ZByoP6K7~XPaT-yf^_WDkSC2; zEpIMGHK;D^-ptNukunjnOfu2@1@$+pw3e7?Y(#Y9I(mlxj`>KCHT@ulZuo&`A549~eQFGHv%VSt0rD6+3>a1YLi+5Z^UX=f4 zyNLey19>=`B1_t~Cy?O@W7EbRRa$nA&!to4Yu5^!Uj%gWW-?XyuUZW_%9usyFK&wZ zj)Sej6p+CF6Ru@0{Kax=f_ zY|ZPep{0|SO)hdjBx)yrWoY+;2wFNs16pklzbAnqdEpMc>NLg<*fiugB}S(=9dhqAmEHv2zD`l^|BG#%D_{s~ zTxt5ih{5?UE_p|`iU)>!!@zJ)HW93uuKrwD;3fX$#J&2P;KRU>vec}}+5a5JA_Z$UgG_)Vr99m4Z`{D& zzT-d2M%dG2;f?HMes>&IIsuJ{Nx`G&o?GppE$KYUuYW$nUqC~?1HB>!kge1x{PkrbfO~qsAuvSQ?^L5E z=x!Ed68!;0Kr;Q_g9Ag!fAdAp*{$iq8pm@|>MwS{-%YhlqJ9}2%p6Pe8mGv(f}3nh z{eX-;vV)~~lxTn@{6m8XrM@m^r;2$~xTtT@c6b1_7U3wOSVEE$e;bA(j2(pA(S9V1 zfgtmg43D4l+S!~Jy1qJG%BRxK+xPKQ==FJ{%=4Cb z@f+XO3C~Gs(AQ7#kD-Sn(-m+8rTq;T5rgyQpw=P~t0N354Exbr6$yEgWBelF(Plm~7MS}Po9_0yKD zeE0K+H>?|4$g}D=iRY)V^lkIyD0)4uIf*bbO0-H|OpUVAw)Ei}f(85v`_-lRF-R^( zq)e>lY-gNAr2gl*Sq;)>yb_$o>_WJY(0ApK3C<0j^xQFUkq#(JcyL1P*YAP?os(-U z(Xo$}P0w7i4r&0g%B20ZYUwLQIGi1;!A)WGl1}&sGL2PG_1Sgg@ze6yPWsM1Ix#%)S5S1NfOUqy0UgeEsyL~-N zKk)wLivk|>J7^5PsJ%gUu-~A#l32Alvcw-aZI|Y_R4{fcyFssbl;hl;I!~ME`oJ?G zw?0PCmZaVZg_Uoe=i1AkK$FDV>u?;)9S*b$oyD%K!y^~9dPFacT57jc)eFyoMOO5c zv_|&>=SxjNJF_1{{l*XQ2%YQLHhkRB_}uV((pu~TggjgQ-J+h92Z7CAUoe%FD6;iA<>JcqU=-xcRsLG(^MNe`Hi zTM@?_*?ACZmWj3d?rrIDK8})_f^8#RBbJAq-AU8G6u|||`)F(!YpuL1tOhv+*uMI7+9aXM7QW*j;HP0qs=6W3Z zXm~vY&Ze%E?MOS>DU;!qBNnAn%(upmNQpA@c%RBGQ?~btxs2`s^NhPJNgP|32xS^1 zg$!%=$tVg8XQmhm@3N>HHx%w}>WVzN@uJC=!R?avcZLL-W7(Gk;ptx|(eNZr-WwREngCPmP(nT#3>J*0h>WIkVhJ@s8^$HG5(Em{W#NIPbIu8NcGzWgU9Vpm3;}pr) z;7q7`Y$4BEy#4yIW!3hG1Q8-6#G?jyZK+zA_r87gg7YT^=QjziP+Cr>J98#=|=ji2@MdETaxCf?(kXbU~5lc zgQ&g^T?Xlm#FoC$lqD!zb#1JThz*n4;Y8eIU?pMM{3w3NY-Vue;*a8L%v|Y5TWr)- zCHmdy7hAU0`C1AqYj1kD>|5YqD!QO$3xwr7!6?jA2LRSVN-mStkHrP#BA@76ejk0I ze>N;%q_A;ytfmR~8y+%F3`ZAZ18d|hz}`htn~EK0M||`hklyARp1Ge-&boK_h4*TN z8#WoQowX$G6?gl=z6KBl{+l_GD0d_uiHU%lf@5mH_IVO{-Z5vi0hGvreLe%@&q~Dw zUcKQu?0HFLTXA1f>+a(&kMqqdn{8^f$zU?lgo|cF^5M=WMTROaPfuIktN)g&+xgC_ zB&_lsoz$T1>uBp^WRZnCPWb%w0CgqLnl6J?h)L0l1~7YP(n~x4JQd=UEGCJ9Ckh8tZH2f)YZr+Enm-col{yKC2cG% z7m`eNFX)&lE2}gi^zkdOX{$Ro2)G6u8zOq@NMWYa<<7P=tt>?FktF_-x$ ztF2MIGm$L}iu*}g%xN)!lb&ulZfi~rRt;PF z+qY|?E|;-WGZU%*?RPdp`&u0z zlOniOA7gS}OFwOYhqlS~355@C8U-$i1zyW>ev=bo`px~=cV%Vu5Tl{%LsPDy5c)@f zVv!Gt$Tne#C=S%mk$gd>z8d`J2(-@!m6!P&*j2s>_LGBSj_@M(`fRjP^B7Y&g?s_j zZozATE$)3-(GG))d{Jz?+5W`_axpE`0EKl@BaYE=KNm+mT=iWBl$2j{r;mScSkTs~ z_6^oLOTr1>%D~6v>@m4F&oo!V3c2c}IA0xW z^0wm~$y+<-XuF|3e2=7)LBiJ?)0$M*gVB@c%KCGfGbckmdh9ySb%W^AEnw`ot#A3Z zg)ZAKNbT;k)SdF&WbnK&LOtsU-~KHwNVV(FAV zEY8?hnw38MBZf{|BqHR)LzL+c^5knfiDS35&qPWO?s|xtP*l{gRe?BsWV#tb4N075$*iT{d^u z$&koc{L7f(jCo)_{d<{_SxtMaJ{h)CQCe08I*Fxs5Xo>!5G(^8`G#0J$qv0}5#;m~ z3)yM+hq5TN`@`84#_1hPqnETh+OG6czaMgLt<26!T247oz```jeMN~NQ#xhFW*-` zE#xGN5(^s}FO*^&0|&p)$V<|XJWak#W59F@I6M2OA#$b9>7IGbt^7Is`nhwg5?Nt% zpIGUX57mfJ->Ng^X-*z@o5n@F14+3l-sSO=JXTe&$CvXzsYpZ!elccKF9~zEAO{wG zU0ut2qq$cJ(0%jR1HmL<0<36CjHqsrz(Au}nUv3qU4+ z8f}rK3a9u>Lzmyc_m5`x{M}~>lHd&r_K;~n#eB;F9k%NIi*_jcXG!cdk+Ip}zqN2jB4`&;!c}S&GVmBpU>Mtzp=*FPPc% z0`*(y0yRbb@E5QVu!~6J5Ke%V^id0DG#PDp7E;h$p!73p_C(5yQ(r~wg)QXt9Sc=6 z%ZdOJ=Z83fw!^T|xrL72g}840a9$mvJ{`g>oANK5ZX?GEaE9iI{$J40}Xq4T-B8#eB3@6v+x_A2*G@T z4BK0unFljSjJobQyZ-Bo!_ttf;3Gm&yvj%^pTS9RDtxU{OL2@NI4MQ{Ks$S0>F~RD zHt>9L!ejQc_jz8VT$7GHBi{AVhNb4AnE0)qE$fEQAtxy|OrTZ|NjtKak~r#jdJz+;5SJ{1R25 zopT*6a6#heZ{2p0+b*InTV2@ad}v}d5`BZODte23Z%rnZ1Ob^)Sxo4q+L5)D#^|1C zD=bAE8wS}DM#KR)j|WY0!o$!u(1Fb{-8#5=)RQq%?kHWi-it>O6O8X(0pZo zq|e+GS>~@3cm}I5@jP5$K**?KF`)lTwQY=iSkdGqviy1KVjb=Iq{M0*h9n>G`J@L zR`%uxv2db2SOe0WPp#P)ZtoVlQ*4VbId_k3%_Go#pb^cWhH|9e^Zm*n7?=DuZoj0s^Y8gWp%dSG$ zS2`!E<(qJyl-_>n**@PLHDDEb{$`U%+OOoB^RI;ty_vtFtwJ)O3AF$tkV4=w0io^m z19f&WwDtnj0T&RBkdZ9<)|<1I+Ve6y^V+5JJ^G6U_YaNTkNo~~*o!f+!KIFJvjQwI zG^+3NuG}>qzv=QD53?04YCfF23Jtyyr%Sq0dO_p!=P*ZQ@^Fl4kI|?Gt`Z#ob+Lce zaJT-#Q~gKcaaOS5I~oKfNtccp*O%G|M2wK^N>YwEZe_-K2$7)jX3^VLj@_$VG7v;WLjWo~b2E5?KB<0^H?+d|O{l^klId1?{yCSb-=*&zr!7 zlkW)0-%s9T#g;POKL#&}+W_0b^Q~cYoiS3C_YFzW0j7Q`r}-GfXr%%3JDMisKM4ZA z@MSbf74rvOOw0!MpWYmZkEeEuK~O#Q2c0B843IWvBk$1}0Euo*#%*D;p_2<55J1<- z+k+tZ71$}6gT9P|u(GB71mJ+~;BS(Wv(SIMzB>Q>B2kzvurz|Mz!xFr;9T!0B#I-+ zQ2!l*F1^51KZgL**YDl*xe$^MgnGN3QidiE!$GFsa0u0h-#Uk$wbcjv-A@xTJ+1G} zDLa77%<8NP*d*!61=fpz5*MzI~(_-7;U5e<-SV1F-_4r%( zjv`pL0B|>#JpkNgPoe(?xObBa>+ETgSLo0^x7+^$xW9$X8~NQrI(`B+V6A`oO(<-p z=4AGRWl-;-be2%!f6!GMA81VL!7RZ(OzWX4gK21Ju@Squx#RxLwkNwa&Uy;=PhQ&& z(V3kNi=Bx;?BZN-v1o_Es_Z15F-go^3^DnP8P4DwPD=gbqdn8Uh~Ik9Y6o9?Mw?97 z@2}mt0=ZVnLt4e8kMB{Oq_)h#y04DoPou_`L=wdK!<;Kr=FZpAPNj~} zU=Lv5usQ|m6F&W_MeP7d(f;~TK76uT+yh( z;thJW7xmh)<{}}s5HaL|$zAO4cZ}+=v}#hw;>k1N{nmn#{ESPle@5evsuB}h>ZYX)p^^_DuaISdb2x z-M3h8N`mZY5(3)mSq!psZ+nRZF0MQvn~s=;EB>AfIg`^Eca%jU>eGzvI(t_A>~01Z zk8`Dyw|N0=@aM%3@!BUcRU?$Fmkh>6m-c0oTL!E(NEs9Cf!qwn#O7j`bjeJIl!w++ zPtfhk#tN8r#(>&2t>@#QPuW419{EDG2*qZ(@VGPK>~k)P_^ATJGLhf{Jc!H)hr4qhrG1{{bo?WgFiFc$*x0%_~#I}?*iyCMJgi#r(f2Ol+AI74GY#tv2k}krK@{&v+;Y{TgCv! z%~!Y7VAB{s=mYF9WD+-wo`i$(lg=WCQZmDO zdcy87v3WD*YbzjveevY5MtYLmJ?Td|_XWSa)onIiPZ#!IaqcdZVXAfFu(*uBfVpS0Eh6m# zU&rNZY*~$5&E3iBl@qvH=#XZ^I3wyDcK_J&6%=9?FYz_Vw_aynI>3{$nDS$bo~7Ki*FX)$cn)whFFngJz(+| zTY^#qSy1GnH8-)2M^(f-BS`9OX_-KZk7sdd88=B?!R`LfrG^w4Enjyc%Z?5ya;klp zNtgQR<*I=urlEvq|4L76cl)!_Sq0Lx-l67_HjanJtG_;Rghg5@tvZwWu^8`kERmsh zs1eM<$%{LAwXnU~B`-A~w4p{<(||Q!WzWvkErOYlW|1k7>wT$(9#Tz~G zI23pP8l!4nV&1TYV^`LN=pV^^Rm1M;$N*cmtLwZtnSRRgY{~<0{`Mq$^PZS_;P~UB zk^T5rhF3w?+M0|0d|q8fc*9pUo`FC(stHo;*_>pnTSQHvoilHrqzbRGI3_R69I17c zIP1!&t<7-6@!q%Tpc&XwP0$4XIKro{1Vz^^Wovk()yPUt?XtkTp&XQ1OZ(Ue9+7-6 z%1AV&O

-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�^Dhfx4lQM%Kew> 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/manager/public/assets/marketplace/cloudcasa-diagram.jpeg b/packages/manager/public/assets/marketplace/cloudcasa-diagram.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..401722fca6db8bc12aae8a2dcf652588b85af983 GIT binary patch literal 153626 zcmeFZ2UL?!*Dw0eL_k1#lcH2bK#*P%5NRS(q_G>y+O8YC%-%pCv7=W6T!c2-GdF21jP3@OQ@$dAX0suhczNVfY>3QGT z&&9>Z-`zKWxC1B}k)FP!FOLLnO5OkzZ|NCO{>}b3E&Ny3i(|YAQ^`OjuuaE z7!gG-rl+Y1F)}gK*1N0qmzd<7j*lKa{FB++C&14{=azt_m9+r%D(ScWk&qM|o&6ta z7#ZFDL;w5p5B-mTo%ow~RN_xr+h+wyiqSgl-qp>9Po_Dg{=xS@q-Y1}Vz?(K9J8DPYI{ zO@G(_kruT80BT4gk=Xc;v^z)u_@V#+wDtc;6H^2LCOQDpj_pTL3^cPbB^p0RZYW062R|B%bCIiDv}>Krssd-+YMQ z0H*Vl0JR?l*%g4CiHw4YjMxG2lQcy|_E-3;AkqgJIRz!vIqLH?v~(nfnu`EA83hG7 zB?T4LpAJbDPI?beGEp&Kmex4OV(dtLo-~X1s@8Fic3mAR#sKle66jkZ)j`p=FpaC9UGsR{5dtfgj!zt zwYs*xv5DFLeQ=09!X2Odk&6tV_**Q}=iie3cXBb2 zpJUcArgnVHaz*CpdDdGg@4vLt2;MY7vpM+<)3OW6E(v4)i1wFc|C(Tt|Bod555fK+ z*9@QukpC4Z$Vsh4K|yLMN>ZSrruq}8&r|;u&i`AW{VUM@3H1LFh@?WuNM(>RpCkRJ zr=h0#k9YqvL7XE^X(7aE-~t61sWVY90bt;4F+W}m_&*_j5a6q>Hlh@n7aTJwlSXKm z466g2|0f9kZ!(fKYVl|(#{fB)w7YS7}*7o^hSa&?ZNE){*M&X8X}j){F{ z?^{*TSj6RD+t2YbbFfHZO>QWXOA~ReT_8z=uj>VUQ7wDCSe}L!s}b417^#WF|J*TD zhA3Emy!-q$LGga%_ZbVp5^BnK;a7=(+ZcT975M0Y2w)l-3nOH=9tJ1sous6~m67V4 z@W0+d{(cJ@EFl7eV#vJ>BCs4-uLU@syian~Cir)s)aeNv zH|Jygze&X#aWHi9=Sh$fQcKK&5lp#-hx#V(TIgVd`VmfUy?q zf5ra~bYQ~F%G?cHNPR-4521ifBl#rpJcT;w?zUPH-uo7@-^bh%P`VQQA3WjFg}XW` zu$mUWXP-=s;x=5ATx{FfE=fo%*!O?pSgzf9Uxd52yVjOVH^FOY@~k?T`(0Fc8H1uY z^FexMBY&D&BGkss<5Uwi#8GrYR_3*NDLwsNw;K=N$Ar$yci{m{+u|cg*TJb?RfBw6 zs5NHwjem)|IgQW+w<^V%pjoQq6J})NphoVygPtuzOWYEsf0?fW%7R83)DIo>LtEKX z^1B@OogkSU%n^0GucghX^Vkkd9cc~P8PX?qhyY|IdDhR`QnkgT{Q){E8=O?G^8wOt zj!#Rlun0>soT6S{eBp1SE=n4nU~dB=V7uETo-0oTs(rVKKp?iB!+iKX1Knq^`0zcD;{FP@WkP+nkerZz4%*zY@@Yxe9r#&TtSq{9&tzA=+tGcnNT zfnWC7;lB@MK0_QBat%<&f-aXS%a`GFeNA_&>Yaz=;bUJ8f3y<@!atXBX6QJbA)rq>ck8-R5H z@vb{e%EQyxtHEti)#EIqibhA`y|Vm>ae8%TYGdW`OwG$`V_S|Sf=GzMQpvDQmqPgi zRn3nY1s?*WRcN&8Kl1FUMLW$v8nhWkDN3ElgEq4j)Sh?^tCY) zap)PNM)yM^z+^LL=Yee#b;%GHrk9o>`w|qXD8w=yp%O2aA3^({L@;sWAMo6OQdiRRsegREP#+9ZU=y?O-&AG&KFH~-OGJ~hH)+AJ~Xv%(#{=%eK zS?pQMqg?cLi^sl?eS;~3%~L-N^}SzCm1jsQ?;))@k;+Vv9|yk&0&mXRHtJt5vzq&{ z>Z+zES}J#P|CAP2Ydsc_%M@}8tCQ7!$1CjZt(DyCb6gZ%^@?<_=90}pHCxLvh1!|b z2?+1O5nOKj>tApDyGF`ZmVF+K*9J8lHzy-Y^5Zdv{S0oM^D<~;MD2tvmAxMHD;_C2iwP7*l5N2+5&_pa zA9Jr{YA@zFkH*1;&-KoIhtz9S4Mc$B4saUPhGbG@Sq>X8Z*R+LZYg}6ZyTOzl*Bt# z`x;KM!T@{o5k`+IMIWJfcMFSgqP8^?Zo{)$PzinIww09X7V@;0A(WF#t+*;wGIdBS zD!3hd;YR~MUX&mg4*K1ZNj0)y_*F%{zJwfVdm&H20S{P3twUo>L6UPF<&}SzhOSeyjpOxLNJbo74 z&B^n8S;(9SyuiCH!GZPrA(>su3CiY~K7EyQ_jI)+ALT8w^kNYm{LlHgCR|$*(YPw7gZoqvTZB2x>=^uMr5g62b=16e)aMd84f8I! z7U-FxsuA@%M+{!?eF##s3L_Qc>ogY7d`nucW{f((@BO+4s=kP%A&hDOi0f;k2N9sr zye-1*;N zx7=~|=^giW?CY~)S;h#ayITbz7P^h&feMK&#-XaWZxzN~gRNg_X2f2_bk3KfIXd|1 z4-C0T;8 znlBkl4^a)9IBEh-FA)$@FeL(Ca!DUUo#AKdRIJA8mrjTPqMkJ9yNQ5?b!q|R@CbbP zlL)MfoBYd$-@j@g{ukf>*qA22+09&CCI54XJxGnbq!%24_?F9NzX{=iyVI4dTpz61 zavEm?d1s&uB19e^Ia9`;El80h;#zSu4k&g5Xsgn=qe-%}l&9pY&>w&_!E*QGcB zoE^pmY2;34-{22yO;>v+t@s*moRsSi&j$wuNU#{9ClZ~P&P3#52Jc0xxEpH&x?R+K zXRxAz5xmNK_e_P_EUoC~cPFpr!&hE*mHh5c@O>FUcj?JQ@74g@%5OEpxIovviqqqh z=to50VhbP67X^u_fZjyu2V`7LX)2A65^nn7pvNT`sdADeUYGy8x3g4h)105lg3(-V zU9ZbH*udw_F$bEzgM0GZUa~)q(K01Edwj+t__<-9AKYK^9L(X-VKtH5xJyF;=w z&2F}hF>P&aqB)zZOC68eS)H%%c1Pp|BYKd@l@e<^CTNcfppk~eXAdo^zZLoKQd^%W z5NH*Ywb0^sYbHc8`03|ywYR@w1UqzzK-_~&iU9^4e3cr%s&o01H-&}Un}?}mXHp%# zIxL5mhCi8>>nT0?v;Y=e5Y6^ci}y2Iq0AWDVtQ_96o3S}`p8$$IYw z&H$k*yRTy8~p($@VT8+zpljs|4owb1>% z1eOF$#*DWmsjuufsc(v} z`Nm{evwtE2R1CN(sSeh7UuH}9EC=*E3r8EDSM5iLhdhEXe9X*mXSI*u8TrZfC&66{ z5l@n%mn~s}`l$6QQQPVgV_8bnJGUH~UaRl6bLBDCsb0l^+d#4y-xp0xd4sZ9h)79q zZ@FiwSK=1QW=|F3UAdeKgbqY z6@RfKy42Zcn}5Ss#H#qhbDXODIbBs$gqr@c!cI1tWf2m`(F&6qM@ThkJ8>|3a0|c6 zN?f^7tCQ~Bme;K)(RgW@?f2I>%<>Y1G*M1ZE-u6q*u5TaPCQzNiN&m5Nu(br%V#|n ziT?Hg6q~LVx7q;4iT=o5Y8<48>Wm+9I@IB!M3WACnhbT( za&GH$h+#MPL25`0N?K<9#H_3#alZqeh>E_~I_o2l(!*J?wz$`w91Z3>&`%6ovTtVp zLjNj~=Vy>Ahk5F|CDBMTi(8K#cQG)~L!(bAr$cNk#$nR9SgR!Q+&IJKW|IYbuRK1i zIOjV$RlAp%qVOQJ6%@r)H-94B9Ei->+xnV;8fq(TdPrQJZ{?M@vCVHeXOp{)<7`=x%)?5Salr z`-*dwaIOKJ*BM`~oR(M~x89|A#Nj^8HY{(c8yQjU-nD?O?6SgAL ztIWz(ML+aB9aD5Mb9&FT>F@anQ27vi@dKnXr~YF_x=3TG2MFq??-KZNBh6}h;ku{g zS&qe0E!qC=G>w2;7D>}fL?Ee24WrO%t<;{IQfi*wz{+e>rW53~ws&(Z1Q~s$RH&?m7M$?Ujxqc-APEaDyE&>%F zgy3`}kZ+Bs$4rg20M>ttaN_9yot;QkO}MDxWI$sxhgr1G^}Y9Dp(vl^OA((KlrHfV zq)b=47iHIIY2TB$BRRnTR+$KFU;fDJG8hBZC-?Bvdu7wZRUFOeWE|O}Q^DTShf_j_ zwJ)5*%TDtp>;?M!i)M#~iIMC5>Y}EI*1B{Jd!!_{^~%ETVfd5JD{qHRR7YP_*>*F0 zu4|}`+`og}^KOe5tGKzEJSbs^m1)M+VkW!b%q_|TtS53mV;C7`Jh-1>3@=^$MOG(% z$wpTld98|EPbjNq3G#EF2rN$S&@3UIBdLDHNYRDIheAb4NpLvbt-Bkx| z4Mn*xi;!p{P{SAvqY9~7Vkj?le^Rq=tyhdA?arqrG(4ns`|P4TJMU=UYbzYQ9Ol}x znjZmH2JsVtRwV+n6^=*$3of#D(q8CPjQazYJNtVO!tdLzbdixab&;uCU4_pmRu4Dj zeR>1exOgG6L1<9E7K>!)oAf_+>YZ(rXy@@8u2YS8->s$v%O?H!xA03uz}b)+sy_!PTr6kom-h14?B-{!-y21v0h-Dg}va=^bh^8{;6MM zSDI-%dFWZhMSe$i8O#{oy8*-JM}REPQd;Okkc+|XHVZT%6Z%|I6>@K94wRvTvi1h; zCzOciq}?52 z3cH4ijX_~*pY3$C2oB{tpaqWiB&da{%i_j$9)CMJ@SEPuzGwAtuwbdIOYxz8G$iH; zcog5_Ha<^@$w|Xdw{b%fsy)p0?e5LF^#~sMCeI7{w`%tY9PC-neV5}$N5C!% ztf2$T;A!y=Bbo)v`rYG z)~$YJvoWa+R+4=2$R))nG=6u!u@}1m2^6H(3S9qoqen2RXK^vPtMYrHiJ6q*RDkqy zg1G`qV&Yu`(R(z)ltdu?iAQ*#ojh12jX+a~Hp@}FcG{66(~N#~lO`Ws(^YfR!&9Tj z013_8h@4YIe8jtq-TLdK+Z_HDS?F8C!PZ~N>8tc2tcSNhVCNLBzQSb!0A-vSrhdGHy88xQft zP*{6IG%>R5sNotr3Zu+>bva}`dUqdC)BQ|I+0tnp{JFeX{0+$|nygCY0q3iGDEzs; zv8g#@Q@`d-lx!Lojg*KE_2)%0h$(407si{OB@kHf#+X;ROoEM*s)8u5*UuEPa%1GU zWT$)uDS&&W`%2wB@w?qzg*dZQb|@oG2{pjcZBJL#Y!Idsf1)rZS&@T6ogv1qCkG4u z`rts_+e7z*D%?#AfQDmYv0^wIjB{5k%B-AFzldNT;O_MQgmXPC6KT-mgeYkn_gwPn z+J5}b!VArUwI$V{B3T@~_%`fQvzM*FX4d?tN0V8J^9(x(@qHH69V6D43^(m{bJ1S| zh(H49+LsYusHUSwDX#yn7oG0*m9#tcqi(geFO2KGG7{fh5Ub}(0lDz7#W~tpJcZuJ zyzPQBLc>a}?{=FEdl#WsBXtwP8}E-y=-4dlLwplV!g1V_OuMO(oU^CBQAoOj`%V@Yp8 zHakjB@b2e+rtPQMoikl%Q68NLx{t7_TNmKoldm!0@u zZ$S>Z-<=2!-ZODZh?MOnUrek$F5U+!L=eV+;+9r2)^0UT97GlCKMs?RDx)zQ&-==d zzoH)XU0t;eIKGn>Y=j%YST&gyZj3;11^Q^JgP{(>!8B=?z;)zT44usq*K85~BUQ4xHO8IBH>R!xc4L zq8Yp1pb5PX4bk2eeA;pPvY+3JvnGTF*t5k^JXPoYXDfi8IQ9=KnB-_C^Oj=%AzV{; zfgQy3?K*8z)YF$*HiYp?!YO>AmI%-m>!+!+lZ?EF$d-j8l1rv7dB;X-ulDQ|j{f*Y z_Q4Pp@;|;8oSOHal2~91_-jQ5T(V@o|40z~ry@(!v<-lNt^@p!(my^J{$IAfqOYI4 zlIQkP8pX7^@Vexm9*h`K8hwfw6jA8uoZ*ez!I7E#n_>3vTaN#F{$u;~KSLK#8_aL4 zJUX{i|7|iW?v5#G*a-LE>3dV%1h+B@pH!QJU-bG7@8AdE?)=f#DH&=UCMF5DgBz4W zmmf9lp5uR`1An6hJ2u|gvX8#dS1#9gs59&`s~_LiJ=J(eE%%rRWDmBUhh2k>wpd^v zJlTsMRAln0lgfF0h!^*2hgT7S9eRwH5eLV#Yu@v{H&TJMAxwIkk45)*Hd!Zk;Zr+D zK1@2fc2VHIVo|j)lGkFo9L_)k-Wobw>N>nCf*up(3MK+EwX4uHv>?_1o!q8$8N*O@ zWour@IK3_fh#dby1g>9PTO|VCmEqD5>tU_X8n1h0^+mgbY2B-e@4PJ_Y#Gg2BO&op=fcIV8zs-1u9d7)dHi>S0ZttMZ)TqVMc`Yl6NfxK z+%tDa%pk@{r9;ISY)#gsguYDMs$Sccbme(&BJ)T(Yj7CsL|O}$Er-i$wix3!g20fA`^szEer)-KpZuu5 z%OiCs!B*k(E0O1a(8CsfE?9d8$)BVrMA~@OrMf?`Pe=v&;1}J==h%LPyzSy+LA$&h zgW8q-T%YJxdC*d)OR-!r)WI$|tWhD=j^u@1zd{*g|FU!Ac7G-TK-Dh-vtePItMl zA_Jg-u(RRWMVf47sH1r=*hgl2_IE#(^0F z_!(zHs;n_0nJxwPqHnyz<;J||+XBBE+Y4!@OQkSh{GY zhs?TI^50Ub5bRuFBXHr)X;3Gs8W+0%=0A20^n0PO%qjfsh@`YUV_T_bAW^6??rF+m zF7rm#XvuY_>Uy2mVw-nE8J}*|vdu;4ecN;=Bb^=J#U-POfb|5Vy#X92+c;-_Qy@${ ztZpS6ntS+0%cZ(T1@7i*Av*S^8nMqXN9}uw_7^Acj)=`*Yx-Y(GxIuOkA+?~r%!nWzY@Qs zkTK-~p1%VSQc0kx(rZtm;#)C{@v3r5;=*H1_di-~uqO+|xi!CWNa*?Y^8LG~brJW} zN+^Qjmy2+5i#)#chy)*1ox<+-N-hRk70c{DdURd%ZpJuh99xJcrPtWCz&ZowMANG*PnTd#01U z@_5qcTJEzJNvI@d1vT2*a&06qEb5(xcR-A5x2?9Wf3kx+#n9G|0R9&XbWQgWwb4)| zRHB0M#Kk`DzIpH86b#V8O#arWtb_YQlZ(OIMjyf6{V0G4*r32?pVawVOf6n|!mFvj zo$;6`lX^)xsh8Y(P57A{8OCnV$B0l3Mi`F0!il)TxaDi3{W*(FM4-W4?}Xa zUqPq-^rTUXDV0t6;Pt4dZ}`T`XvZrLmMct|h9+{if1!_-5Z@3{#v3hc7$NSK=V`W^ z9MjurI@nM*MLo!qTnQ#hN9i2--z3M}hCwk`>jy-;nj1C>N86G2c^(1AWutajT3gOf$f>zmd>wwXEyXV>=FuWW&CROAQw)@YSrn{<@D$mPhOa3A3qQ89@YLL`UbgDFd z51X7(1EPBMybg5@8ZtznnLBk0_f(xPQR{IF6A98O#ee&Ehjlx>B>;61RXB(Pej76^aVE9k7f(h|YfL#)z z5D@z-){&redL)pRlH7AB6T))KF9b#~xM`}d^eoXMl!K8q&#&yf;LuBTC2D}T`Cst` zv6(`whss>4EI$cQ_oX#_Ixt^2ejMFsiiUp6{aY8B{j^uB|vv` zkR6jgpZ6=6LHluvdC7ll>?%aNziGYiEGfNW!!x5-AUOWZGI_Oz(l^lMcgM20<(~%dc@PKIpk_ktf-LgPIqBw)l2P934 z6qOk!K|b3jE<&EN=W@XK7Zx@%gC-_wr)#oDx^7M1i|D;>!^%IWLQa~K$t3WyWU;5= zcq?>qcXE6VHwjlB$M_tgU!(k}u0~rtFf35|3a6jUW)t)$g%Fkt@l(yFV***Vw|&rZ z86zSIUSdR_H7HXMT2>WDIF|>FTbw=`I_T{{a>3}kJ9LW~wZ)#?4eOZPIPMFHtFyCx zE+Rktprz%`K3Be-&7^bn3}R?c3JA2+ByY&6WJvnH0^j)PVuG zT|s%Ujq#$VsNLtp;`l)$T9dVY%IzfGwkE%?p!?bN%Pn5Ne5b;eICj7oo>uOdLNvJR zQy%FMByDESDp8}{X2;&v$2Pz8w5LC60gWis*(N!Ssm?=QLk+u>2C?7YITNOas7WgV z<@VVJsKK&hDV`JeG+3BWn%9bLmfT#b{eewUOmY`;?hn0g;i0*Jc|&huayv-i7m^L+8v|oThJ)KOSblu{ z%-rispIAkiu^Vvzv^V#&svoduvC~!T?H`8j+x^kQ@)#WZApT+o7aUexiDt?HRH@cga8+GwXq|V|}iX%$%&bzc%g{*>$Ez`4MXV1lqa?+|8xwI%@8&f=NR2GU6TVJfUlW73|3$ zdm{A$>Vj%52ywetP3Rkvco0|o(%OdkeL?bN!Mka_lt}9n9Z~`Qiwm)_6@iH)=#Snq zq6+SeD|kV2zPSq;H6GBpJq&ieu7`K0=z)6~CR!(NH=+eK(F@OZDR61VF={-94KAza zck;=-Ue+(QExU%yhJRX?nnGe38*smu+zC=7M8UaYZm-UY>yFXSGA*Q~!N?pdO*V#5 zGutOwoAAX?^0f=oV8*@I(v|W@L&>|xtx-&eQzsTz(KFbvvs%2tA}<95ZP*cAJ0w-+ z^!8q~oJFE@t>b>4(QBS34gq-=5Yzft@ktWCNm43-gjmrk(R2PVz+xBrOe^exKD6>v zceUO{AI=*+M~G4I&!gpac}ZlE;aT=4%0*SoV%ayw24ToszIsvzzewnT z*BZvj+LSYP@?R`R95i1KRv2M{}1+6AVfho{LCnrLKPxZH8w79TPk?c=i4ZGz|N5<00{nc5) zry43Aw`kc>)@Tzq!A+x_IY7^~Wi zSI8;OJwCxG5S|^LPO0-p<$mezVB{kVE>u_H$uKVMU$aX$8T0L?ZdPf~uX9C)Xeb)A za~+zuB8Ct%x!CA&7$sgRW~R;Wm`@m^I_To^=!W%(u-)iA>Z6EbBdjwddx3@RK7rPl zOrsVgKC0L4|EpMTBNuH>=e3ODkDc`7*@ioeEe)cNS1o@sRt&*ufwr@^M8F{fH@Bn+ zlE6D-7z)l$)(*P)(l7?fx;+2AmSNZ7`!L-&YT^AyI1ktn5eFd)Ocd`XDKVp<%uB;Z zeSZgARNyT33nFIr;CV_^%1c94i!J!KumJ@l+|@;!W}#2kEl(XT7D?A%F@xpq#0)k+ z37k92$mW=q+I?UBLIv9U%Q92+>#Bfj1SkkC)n$0`C*g-L#%7s4`ElMB_qpuHB40d| zL%oG2ya-=7MC0lN;2|%?_jQ)w?eKUA+6WTQJ^2FaUolXO3%i>_-!HnyJT5HM?%_dm z_A@*$b%pO)jsffgVY(9T1MBBg%Dq*Ww69ohq9^n<#RYPWi>;9AWlGy27osP3%6Z9f z=Q4)B{bYp*kmDb;@K;whM$7RSLnq4idlH=eK9;9c-#8Zm>i=U@P}ZS8fOzU!a1fN; z9f>DDZeC~dyp~MWF7RV+I67qR%l>CY>XH)VVh*I*;>Dp|nDJR|i;(SLaBy*_YS!J_ zhxRD;DixpWbIHO+S6zMtr3*GYz}uxr3&^dT-K3cjU#3U81Gojjx|}6|WT8^H(?X~T zrU+3mr$GVfhhisVyh>M^;9b2_ zf>d!r2b`>AIMM|LDmh$KD9V>VM1Qd;rpx#9l}!bs&fgr(%_2O3f~UQFzmxT-Owa1! zZk8}^((MVG@^$pbfh8W(p+L7}>VQn=!QYn4={5*y3qnKuv9ktlX^Gwf`z398u%l$x zH{ij<>bPU%oI+p!L)wk4nj}Cy#g|tRRCC19%|A1Uh2mP#1szC+wNbf_G|S3V6{`nN z<=cahs?7Xv^Y5@Ff6ilUM7r?DA<mQk<%&UB&ARw z-Xa%^zz<^@#nl-wRGR0x^Nv}q(#Rjl2eTx~g*<9*d1X z+j$fNrvzU=-H&_l^<|e~G3}xe^}s?EWIG%I8)wgibHSuTGL7v(C!3Z#D;GqX$Al74 zR&>27m+lY&v2VQ&j}!dI@lQwq&@eC3E)SAh$uK=0;bb$$gxAM7Ts_|JwJyMf8nX&QkVf4Dcn(i_H^xVNNb z9=`^p)JL(x&2KGqLZU$Q=;S1r0AW};HiE#n&|A2fBQPPSe^qihNQ3RIp7?B4diz65 z<2WGl=QM)>{2qH&QFduTOLnMlNNKw)i%_fHI?b)ekSO>ULwwG!y|X|J2Vp#qu?PWQ zOwS?nWoVM;lO5M?{*_vLvz5+Twgb-U`5xbNBEKDs$c8)ZJqM}a=uY(v&~%;tNUUoy z+&_Qbs;a8}+jtMsNI$CAOw(M zi}9=*ny??!K8uWaGjm?})&#bk(A{!wv_%Nk&dvvni)4)S+rO~+lI8WN<$;If`$u#F z4iKg)+K6-OO%J#4z{A=f=6sM6B!TWtNZ5@N`mvZ^ON6X74Z8TB;l zgd`7v#s>Yvkdenuq4P;1) zmMakYt>KN4SwnF<9_@??r2-4}Rz1bwTNaodNZ{Y|o(AbwPBHwKlOf?sgreaT9F^Pw zpL&6fg-_L@?6&6IGbgtSj|~O&*vjX=(R)08Xp^3_?041vnesaquT3yc%x#As0To7f zy+v=eawIxd;IgPYvUO0f7t4c}aBp?T z_O=i0XzrV{T$eX5i@!{Ou8_)v1c@CPAR;)f>m0aaLP(%tdRuy0MRXJP8iV7i1U(MUVKk z>T8;Z%cQP9(DN>?iP6mg8K=Bt6W`XklXYY^8t^%>WPWCfM(@0jh^}UO*R4H4#hxF^ zq@`3H*N*O+!4{n5$d+rOSe28b<#?5Q52v;TO_@8xsjBv(@!u9i7DF$kK#~_KIkq>J z;L{4-Pu8MIsBnl!#)(-(W4!)lu3+Drt~}o_NGF9L)`Po(%_nmJ4BNnm;n~|K@_FXE z?{pJDgQD6d8u%^DTLMiO5fDxzEi+gu{u9+9>UBXV1NvzD?DQ(hq9l2r5fz8x(jUAy zV1erzk{c*jL8fS1hFOcQ1@s*%vow^*5cTdsOVqsenF4N)H4Vyw*?vs_9ja9NE=-~^ z?HKU-O-G>745XfExni};_qcZC7v1LDA};>td5lxfkrTzI?Z=ag5IoB;6Z|2)!^a4C zB~-JA|KK-0?C4E?t$BU+v&XkCBn^Bs)5sA0NtT7bNNU=UhTc=V&C1JtEh(sTCMr?> zG}QZfj2@&n6<2gYe6awggaN)Nw+cB=0)2zyNEd!{p9LhxoU<{14J`+02DbQ`93ZYdTyH@e^0qKwS$kPJH z{@CTSyqe^x(BTf{KmtZ_^ z4ZVvSMR*$7d12@py~Lfk7d1t%9m(`@)qY;{JfMCz!H8!wpTK~GLu3dJ1Fk2Om|}jh zz&fY?LxI&=sMM(84=jS+bEm*v z{FRi`@Gjpdf^bWkeoa%nLOO=+*Q@XFU}Qg;NHp4Xm*2kTq?6Q%J^1-r7&rJ->XQ`Z zWb6m;$AIfsdAU`KU<>Mc&75w96oVi3m$e_!C{mWo=hcRp2RoY!Rf866f%SQPIVR9)Kc= z03&dg2wpF92Oo_s;60I2Fjc4)?e6w9I!ias(oEzNc#E zSQ;w{RrxXOW$QkSIkP48eO}VvE&|q5Lo7%}7-sTUW;bIrlBxxaH_OGEpCu7EarRwn z2JfU2p`q+KE!uIczF&1ER(Rbg*&g~?KD1BxMsawA^*_sp@exKL^koD=Jg5$2`#Ofu z<^&ooo(Je!Z}95=FzfEyid1>JC%3dfIwd(qZ(+S~!EWfirSaS}-;2!l^LkPKC3en? zk5w4T<|39XXcgIZWyy|7!G2WRF#zQ?&my06Vm z2z%!Rs`6WJfENo|#D-K^NcO_iVCVeRCIhhUaEq|z0>n<2#?m{_WMB7IWXH9HcjR7R z?5nd{7zf@CXM@I^MluFR8|m!Ca;d$b{I*l#$h zMgHdvJ3nHV=phCe>2cv$Q*UAL@XmyL@I78O!>ssohDy`QlcA)|SlR>llrSwdt*T+! z(gT%jm^;q-Y-wS>es6lYm5&~mavBO7n5V^H(>yBHpJcp6wfYy&7r&vLH+z$z)}NAH z5#K)NPBBd&BMg8m_uBXP7&)N=n800R#ZRl*tF^vtpfB7S%Evx?KEjWm)&bvda3=W2 zqYZyTmJMSF%&_i-i?HiZv+-RH-62(f#GB$b^Q%ErI|VW4qnN+%>-Igbr||cGng)U5 zmCxQ1DDjuZeN}bPjo(hdF@Y+L3Y9rqhP6!k!c{W5!|c7s`dtY+ACvFkLFl!oP>baS zoJeglW7Kt*2}xBoj4KiN^-tu&E5FzvB^s8BUfZEB_JUUz z$CGaIH|{Vm8;q-}y|)gD={L%72?^Avi@M~es>>=9dQ3mmbk!Awngv}(S}ixH2oma?9!0R?^7!z?-FAr*v)XpnPfTauzbQB zj2^t8IS7NqObY3R`OE0B7Ze|7>Pk7%el!Okm|tfI+NDrJn4Y~MD0QFeLNAXHq^8|D zK$kvG6gS$4+tjCqK8TzMuKgXSW%PbtzU}0~N~AbO6B~`@CoSsE{ILrRJF0As(qk|& zsBk^brA(7i17T;|8Y5HT;tbeukQa(tv z2}yTJ+Y);E?lcR)cbw(5aJc`uBeYm(P2IM~y|8r=2Q!S`DyeD7EE#k#_|9?UXd``N z`%%bR@|{`?_*=_mlEo1k64i=ihjE4=Arl~OFOX0bnh3<>uU5>1-m_lx1fDh5WI(co zp13tX(*FT|)w~Ka{?9zT@5%!#%w1Cnvxrw5nZf! zajLRGGT=T!Z0&K*miu|5-aAWk@Id&@>RY{+2l3GB&o{SnGoAU=*Dzby;Ci%S8zOoV z%-C{+Fl?`cyNMb+=gD1IQLsc8T2NbiA6x38_mHW4_M{ z75?R@6t=?nz0@0ws9gT)Oo?oqZ@{7t&JQ{*B)@Qm~6RrHYC|31?Qxb-#X9-Ma zwQ|WgLsf}IWMVE&lNP#x@zQMgi}wGEz4wl4^4t1-g9wQ9-U$ebO7AUFM4AYwD7`2} znh-jnhTe;SfYPO^H0dq$CcXC_1f(a_03qJzxA%U}-R~Y}oO8#x=Z^P`d-fjz2FX~@ zd{)-8)|%fn=VzuB7P&$_?LA@bPmKnCy=mtT40t|wH-d3Tbr?r?{q+yX27ntt%@|;} z%|Nikt4{Rxy!#K-)>&pwxO$NKm)M%TcHJobzN7)2RWk0b$pgM-VYryS+f!EGE zI$}zI> z^uIR^t+|)gvBMkfRiqcT)M8{6N>!JEU2>AWIEJ@BIXpb!1!gNc;0%5Vx~7uuGPVfo zVRBg4aiG~t+mWTeKJKRKR#W8Z*bzQkX?&t;8FNr5S*9 z@iZZ6R!!}t4`E4mXlt!@8wEbDb9#jo^4d2I8s{s&_5jQ4x!Sjy;I0w-Qr4q}Dni0C z`tvQn;FK zi9{`qm~IdzdA2y|h!e*6tPug>C~{mFd-<4<^-j;r>QQ4QKW-9450ahJC1bUUvg<*Q zqI|aDIdGIi4d{6+SM)HYUdnXM*Zv#}OGCEu6pn(9x=1N~NtIa3*IX5JXAJwR{n_kr zD|0m+fcVjTK~q|- zFc-+lHF(Is4tB4Dr952bUh?+^V$O7xy1ItCOess)4Rw}c4~`FtWxr&;ceM8@)i{HpX`?j#>D-sJJFhF(XLju;{B#JGY(e+);0;LgYhh0y@!;NPp^MY zxd93EMi@`$f*m2mJUFU)s4TH(>?vpCvv0GjB5EOFECCPOoK41?fQ#VIj#I1ubrm8Y zCYb2D2>xazf;pvhm0u1{1ABTM^!ZNU0pB4flduu0Wc3F-Vs*MM4(Y<9}?u8&{2oCfd`v5{JdFhKB)r7c}{qPdObXNNU>1K!6=~a%FR*OUKv6#F+6@ z^~b&$kjBxj3E@X(dai>*9o>Ln_{p{S&ad(O$rcoo&chT^M_5KcJM_VQs~%dajt6eYX4Dtii$i3gD~;EM9SA++~7k_ao<8ke*(|0B_8NL~|BpEO+Glr6ta^Mu9j zPLKyD>sC&;e`UlQ1OL$qj#QjC0p1_bVadA!?xZ9jTyek*^H3nLe0P}~17{B|Sh0&I zFa0W3Y~{c|z#)MS(0@|$ie@yc=1g!e)7q=Ze+cm4+*!Oz1>T^pD>ZJSt6%nXdb}QM zv*H?!nHlXLY;{Y>e)?Eln&)1Coa=QF4rH5Mt=jnj%f;7cT|D;_D(2J6r0*EeGt(<) z9K7+~hkfco8+ElVxNmXA+$-4$rGiQLSwE>w9x7oF(iTS;#c3><7zJO|?$ECK=pC|2 zD68xACo6ryG2o>h0py|8!#MwY{?o0sWqE}d(M}wF18OsttfPOxE|osz`!!@Y`kP19 zL(&h$30YHD#3=l=yLIh?VU4N*YF|WbCLb}5P-^q;2oN_1X?K4 zzPUplm1h^<=B%Lr4l}D%4Tb0x`7bu66o38gommiVjQJ2<9Q^=U$2oU~)KkcoL>-UV zT@Mv8xCrSdY^OPZfHMd+R8bV*as)*!>^`^g&Pa1Yt7P&lyzKX=ovkP|8op&QFPk|_ zcj+f(27!T$x(u_d6WLx5>$xz9Y^hk+({g}l*-AOTagj0LwMlo!mTfW9~f23^N zpQRFoSO$;2FFbxt{b2w7TNj~;5l9;(M8GMJ!(-R1`K2mr-^O6{9cx(=CDLoMhXE0H zVhEIfe;3O8O+<^gE>GG*jImx@X$SJ<5-Ij&DSiw%eABq!he-JamQx{;hh^M zJ=H?vKMwve(lxNcfPGNafCh&Oh~%oh_4(w;&s6!t^zmo+L^+|IN9}Z1bx(=e$VC;v z;W+;5hE_nhin?T7CP2vtaE}R|-k)E#FO{1TMz@gt`Hi#ZQOnj>!N^n6e8N)S`E zx|!~|-WtW=NsYYw$};k$bP`LI0#Vj5a&Gk~TfXYXwmx>sIa1EonGd#gd><;bm8CgR8#ksK9xqn^~ckM4{> zO7ua0qFlyvq7A)01|ZZzW_L~bJVuTWqe8N;VK`~vz<(O8LTxl}7#o<(eYO zCiLnwMf!ar^t2I!dLHe0DzCR6h7P}eI)np};ewCLBB_h&HtWl?j@$y7sW^sQ&q%~&Y-h+jcOCf2)`+Ba1OC6rd_u1MY zLI)vnr+XnO(&p-?VjuA^{Ht(A|EZN9wFO@>kIy?Q?OWIy8*E=nMA=6Zb2Ae9*ya%A z2?RJ2fmW>(v@r?j;W1IOWbyVsQU8hAQ+HuairpO(q`Zy6uIwGd$ zPHJ>l{eYqwrNBn<`t1ieemB+kCt0taa%msr+;07V43P7^{@g;?i6UBiogK8<$Z%PG z^ysV;ffK=>jEm&rqXS=Z#c&(duIPoN&jXGt~?Jd5%-aeCi!|G{t{*K81?i^`N6GzHM%gx zo0cxpi)fzYH%muS{e}Q`4 z;7DXbJ~t!%Ie69naNYTIp zelZm)T<>Bxey?ym7F`Exqesp%g)-->0D5XB&cNiI${CLvpA)W;q zczA!!MIHY}MGYJ8S^hPmg~K*gW;(%nEuMV)S69^q_5AEMO3hPkU~@kasfQmNoB`4z z@IM`*)w@l-M*Z3}NSTyqLb@pCA)kH6*N(5NczZIpL2Fn+)RiJCwR1o)EKMyzte9W$ z>H$;S#WNKy8d>41;W_T4$(c29*h&1n(%D^1bBUd|e29Sf*D`t|;X8(!o>qQ#BQ4TY ztGbq4>|K_@W}^jCf9=%pXGe*KYP4x&o`0e)i?M9N31WgE6oDiBQk{*_cPK=)ZhlSXj)7 zTQ*D7wJihbr`pQaT2*|InE|4SZXTkvqp`wQT8nI+PbN!B_fOc&XBQXev~QB`^4*r` zyYnz}LERJpNnJ0+Nv&xM(CUw7BrDKb{}y`q_@I-tE8bNBobU&PdIcxPM4M{k!QX64 zUKS+^Vn=?=54l#!Iyd#JEM(2?n&r0Ql^*cR-G;GGA3Wg5;=et_9ra51XAGsKNbT)} zMXI#Z8V|F^EAobr!D>0aMBy^|7@ym_>2k|ScN*&(9gbz28=D`$5@g1|^wa(}V)FMiR7*P? zc+^*s)oFL$A*+B@vqh{aNP3Df#_CB_8>@4|^KCf>)NsK5z0iF9?csIO>6EcHeQ)Zh zhSK@__+VocE*NP~IF3~TKat!QUrum64t55e;1r>l%t`;dsfiD&y( zR};l`L;ZYOc5q(O<*+bl8rmC++&3ao@uV0p~o6hrrS?Zw?2OJ4Um#XHa6bB5td$H>;0&qdYo^6 z?+xF`hS8IXdz(88&+(ELPsNh9WlV;yTfVtkL;3e}oS`mgUd>w{-iA1;Y>-MxadDN} zyig#Tt~%N0c{;XgZ*s4Hxu3x!Ij=U-T*dQh@HL1a-gR<1loqdV+aDh#7yhlU)TV`f zd{3NMUC`aZnpCuci%1}XC82#QZDH~xmdB`$K5Zzu8G9S4NH?i2LS(!aRL{l5LsV)5 z|FV6WK<3xQ zhqt=wJSw!-@VM_=>q^~Bip!YV7ko12CS|yy{G(<9X-;yt&~KXDb$e^^?Q7=!NbW--`o_6xru^ ziC#RcQ|LQ}O4ME~ zkXBxsxhlqmI>v=K;R!l%TD$=pIYN|KXqhzvH62`NtH;3oxuCK-YU$Tfkf)ekevpdu zc=-+xKYP&dsAjmPz`%~ips^2ncM9PO5h!x9nVbB`5fdcjYV_(k0f`^4Mon|WWa<0W zumcoFLw(#`gLhOxG=om~a-&)zTB6-=7GXqfGu}u{+HU8(@q8m|=}C%H%}?p!Ck2vQ zkB-xJZE{GjfG>4&d0F#m|MLDmH}yg_nlJ1Dk?P~N{kJ(+^|00 zn6@E!(k%H(kv-3WuFb4z^Zs4`*hzoFAMt^Rd+<$m`NNYHtV_V7J5k4Qj3R>P4@d!s zjfTk{JJ+NTI)qEF>IMq*^ zmwJ)+qZ;1I+`62itm*I;<$ z*Ek9QD(bmPL3jUCVx;@8zu_Ve|8+lm{ZB*a?@j#2KV;XN{~KVI_Qj0U{`6nznK6I; z2)eZkwBy+ee+qm!E|@1!_31w{H~)I~Ute*U!|i`u*0b03AK0XqtK@rvhi)*^{^n_z}-O86Bqi z4~Xn8dIlHHvT}6}1#&BZ!}G923=qPk6nl7mRR`2ydIdMv#aUtgfIh&x?heUsoyxbE zVI!}Ul>G(ao$9_olFyf(bKEr$oQ3`_zn0$uuy{w;f#5lR07ZtG0?#J5e)gCD1x6FQ zYF}JyAEpACr~ad3X3;CCaWgjfZ)d=SRu5qNY8Q{O6^v^=ky`!(T4{pg#8v-cHxc%+ z@dOU8bF~3%U$d*l{?jcl0k_Qjuebc-I@0JObseYp?;HMq^bNOG@WMr~@SpNX>doxq z%j^|F+>`4sxvgB-2Uo^evr&O@P4go*{~4~qup@C*z%hNN7PK#SrRg7wy@zR9i;r%k zII9ioAu0Cd-;c@nnm+Kh279q!^qsujf0jMdH8Bj@Oey|(5d$1qRq^Gr&o{mdKURI! z?562A{YV!;E7SZ6`v3X)JB0|Q$@x)T&_>F zUZp8tuX)A@|Tif84HNm{k9|L=T zA~Lf310enLm*+UTKcM(6Ng5`O$?|EQV-`2N0w>C?heU5=ULW4ZBJ8D6azn#$|w=GNUYq3B;~->iO%f=1A^FAI&O-MrGR@bh|AU zQGpp+K2T76g-CzFP^f0cZ9rRK`FZEfYJcM&Rc`lJ6MmDEfn3LT4ZF<95KINObx;Ca zD_drt4S?n!TJ;t`^){&{TpCLBW0vE3rr6{plzO~&kyV7KZxX3O(`{KDikAh(e6_M3jMe~0SKDKDRNE=X zkJ0K*DStq_LPUICs~&XsGQYrz&CvYuk%+fsEt&KmD*eJbmS4zvRmPU`CF0c`pg=hk z(k=Gvn&3;J(lgJWMG2SYe}4bR~u-37{D3}dNn9r+AAJGsZj;`)0b zRldFGav2l(UKxt0nrn@xqYgD1Cc17Z(%gtB`sWc0EJpX5TH9q*3LUJ` z))4}+Jw@MpEU9`q?R{)+^{X-m*KxSNx6C?8%MK}=lH)SiJx}?txb3tpYAF4&*xVM( z@g8!NkDWyppd5osF{TGso#XM%0(kH_%@Ryt-sqdD zwWOy4BE}?w`U9alPvAIWnB@vs8D3`HZIl%CLN70erVc`d6@VhZb3Z{&LiWXDd;WJY z^yBM*1DWJdVt8?^Y2`7)i>ECe?U2lp{V^-AR8ulQ+{Y|bCOo9nP_|U}YA_S`CgJnu z2emd)${TS3X`nUEM$~m}!P?rYiP7`)*IAoXuC(XWeU78a>^5-84WLc|Q27vZEqq`ajlgLX!6S$uP;)70VNu`&FIm9HE@??-!5Ur<)=&N`-k_t*2v?;K{0bC7JqQ%(AH;5k618&qk^{Z49Gme#dWpkQ=g z1s(&VwUOYHg>7+`tEN&Fb+;u`*c&pR2bu{~)gp;XK3k=h_Bt?gvq)wvyWr%Z!<#r> z*Y_Wc2dIC=r-vY$?b{mZ3%)277Zx!0K*cqpzt-0KcHfgoiVL}9w@N$(%nlb_T=L3>ysVBD?@iGs_F%ZEBOtOl zEpzP{g{kc7P86czBcP@3j0T1WBhOP*eZHcP^OOaI=5Tkn=bM>-!)9KhnriZeY|`fY z8l`-@>m$BXdZfMx+$4>+TX!b|_xOuVxp|5EQO`UvkvNiVC|B;#mi2-k4c`g&V3~@$ zk3YwQBv!+%!@0~J!eq3=&(k0-m~4Yd9Uc3~kf^%U+l1VlFeWzMow-0*{_CCoHb1p; z3RGrM7yPzOU#?*2z99XBcg~__9R(qAMn#YCa&F=7N=9&^%|c4CyiU8$bj`oUx`r17 z2pYL=I%f#GGxiE1kxxJGVD^Ta;>9<$N27ZZ4B+)@LKDl@RH9M`Bvtk_Dy!I$^O9C4Ne z&wdjBYRnK~O$t_^7v#4>uf(33P+uNwE~uff&w1PJAA}aw*T1~VoXPy27kXOke_K=j z*~~%p5=mErU7GQa6b+^_vhFFwZ-4VL*H33CMQOsqDK~kV-=+^5|GK9ylSw*ZQssO1 zJ}PK*cRY=QaSPsLj_&Yhm`d+D#tfKF?45WKR8-egRL#!nI*jm@1>D#lC0`lDj|jWO zU>~AO+Z)n{qjjg~r6E1bfhJCLRUd%GSGOzysi_HJD8?9dQH$)-Gm9=R3^NA1+n|zI zzb|8sb2mHKhU?1l+t-yvBc8N$L+QDv)N>t)L`pwP<(XmRhh1`X zRq@(yp=H~(=J#2J@Xnu5>oYadez3HbA_C?-tPU)1Z6$zvvRr_(w!U>D<;-ToEg{Fo z@>pcYlU@37$kX&@a9g-e8ua##WNIog@iDc}XDdY(p{@5B)>2!gR=cJ&XjSYTcG9Ye z_qmO&sO$aMsqUuXgfH}C^;XNhwgZ$>Bc&e8;7Q0^cki*?7I5A8KBDr;m`SfJ!_SU= z#SC^Wzpr?5oS3lnju!ICnkFH#u3M2*Tpa46C3an&xAnmt4LYbwo0BnDXz30wQd|=# z6yuXB%#vYE#=yJbxDImLnr~X6gL$uXo3b~L3K;jKI`5McK9%|KbM~+%KtJLZAI3n&9QsuH|;`5*_lYHkOSn4AC`_0?N{^Nx)IW0K zEgUPuzAomUDvCU@sjg?g^A&AU(C)HG6?#?A_8VV*&2qxnS8nWHeZoe|tReP5yDe z1=0Ea=hhZmn>!BB z<&*RDjfpa_+qs}9FSmA3XxyvgdBjz_Fjg87uH-p&N-XY0JvA@tC9T_lryo?b!R7g4 zf^L7AcjBPNjAUotBr&|csWR)<#}7G(gyiSyt1jMYYrdkAU61Z{J{>Fb<+u4UuMBm# z`?EFVhgwITdbNudo)q{gXcMbR9}Y*WYz}l?W=u<{7btQ+t&4vj_7b2S+;BGZ$8VX; zuR@!|hYQ}D;^Q+&ebU$f7en;idFoYk_`NTNX4izZg#ySFkMK-8D1PhUS*TH{?7)<1 zk$T?$tCp%#Z$sWY7Zo3dP+eQ%)kh&-@;7I^?4RdfwenEg93XJJnu{HgW)1Fr3Od>+ z1XC;<8W}C^&S!~o;_LB*${c4fY*2hL%PBwEg5|Je^ z+PX$FT`kMW8?m0GXCGpv{E|3D>}oAe?)P@u*@C`iO||aEU>NtSh-2?F zXatUPrp!HkpuT$O&PDZthOEIn0sk#_%QC$bK5fuRDV$LJJRD*B6-MvVP+mek&$3I@ z02Q$r8=i^HIBJu8>{Y0d4{Pm^!4-YQ==P8qX->bBbTxz^m-PicfeuO*MOuj1ijCTF z;2EwNDAoem`jB7c+9FI=pJgy^dRZW{HBXp_8(3=wS|~Ajug6y_tI)KEa+zg|OJs7J zx&r3)VY;e;bFD25E`H9Y!Khj!5;V=w$m95ZH404&&HD zi54O8NpNJXtb=9O ztI&K9wfL1Ur-FOWH+WWeB^JvIM_wB#Pi#FFlQrOOY_|NUvi~sV$#=ZP+u7+(KoLA0 zU%B+oW!^EY(wd^!PMDE{x?@>Pj6*)?n+|8+e5VvGUXLl}Oq&$e)XnTB!gR`ewcz6* zL!2-7?EP=Tv%Zepqy;93UL{7gvwW>ou&)J?cy{I?x@_`nPf2YtGbfRbAqO9yuD2a^ z#IIqBcIb`Z=dw4k>8YIv(@lP%cPK#q>)~SD=gU_Wv%ZSaZQiNj1#u5fZN^IW$_9VZ zBMC2_lqY?B6B0zheRLl`aO`wRA6C19Bp4bjQk_11aPl$m)5VJ?pY*vGGORMyezI=X zwTNk!w)?CVj=oEj{Z!OYe>66CGk1ypaSUENf#R-?ojjpiGV05Z@q$L&L=dfy`MK6x zh8JtW?|I%_G@T9G7c`GzmA>y}kxoJR^YkW2%fE3ZGpdX~p~272=DBJBP&RC^Mx(DW#j25VFY1>xWB$*^qvBKCVb)nWqx1b6E zB7$l+Ymd$Pm_>x*o#&e1CJjA)y9~ydw`{@N^CQ766ZeV=mzDW!-93iGNRi6yw(~_$ zt>mfRFFR(a3T`xKq;B^~S1nny2CtCjVi{9a*naFuJI z_L^rqV}`wzWW(XEpu_2qvhQOHgV5u}hUgIvYEq?*qvM`Y8NDyCB8Bj-OM-)N*-zb* zFm)pRMVC?xm8s9BuW8a#c6MgJj|_M>!3!iVw+UFia#`tD;@3`dh!G~hs#lDC6n5rU zCt|m3vhrcD;%Ns>Mx03gaS(3{TCU;`2*}h9cjtdEaBStk-LCDD7e8GOWrBHjjSGg9 zxk;&%yXKf)7sBP-0)`@@EUVsFeL7>+-N-@nMDDq>fx9pH46O==nw~JrRyPQk1qn3^ zNpF>cT$oimi)P$d{Ghti;#_4bj|KcE$Od{@U#dyo$yeH#mAdI!^2nmAv9EBcl_M+_=#`oNKzwD?~4Mf&A)LgQLbFa<;> zr?bdxX>nWTbZlay2Jvaw;`7H!b(Xq8BG$O%z2uFvG@dA|I+9J+80}Y6n{J<1rD<<* zbH&E9{%y6|f!uRic2N2A|7qe0#lHZL|5@9|Khis^M=z~J$vrT}_*u%&EwkJhW^7*{ z;b2;fKcv5Ky`G{w8uHHWrPl6|XST)#r?y@S&7|lpuH}4D5jKh6ZDH$}=(PIeEtZ@Z z<9}ARGPDC!32^k`{Ezsq|Iu&Lb`(!l1R7alKJwVm8lZ&t;mG zFERH0{}+V{{@v#PyFw7~f8iqjr%{L|Sr5mi$TI`g*<8;5fK<|s`cLKKz(@L6U^Df0 zVC94)|*+Q#`l_vzHXkdT@)^KiGNDF1su#y;nE1Yb<0#n4qGJTe7YbX~#=mCA{DK z;H%jrkOkU$7ud4rKHcf~rPhK&ZTKgwI7ZR|seO9~D7ubt{@RxV)6ZSW8Ao)o84eUoLF z*?wKjTd#X1IL$2DpBC}M#+1y9U*LrL#wSWv{+{+ktwq+Pb1hZr?`F5e1xdEes(2!y zzHjr@%WR`dRk$mobV#H*Ju-I`86lHTo7Ht(nzXi!G|Dl2YvmahcB>mvIv?Nd^sq*! zrrkcPLzE8PEnQA4w(&h)-zQq#OwI3>?_8lV2;8}U8^&t9tKqr)Sszkb$xF$s}(r3+VBwjq+$w)j~VIhiR#?!Dw$ z_uB`P;mAdl^txNX5mq=;z2RVQ-=gg?0M{H4_NBzoecc7rVOx1>Q!|=W8?JYi&1J%vFirQ>jpI_ zM5N1+2}$p;I$i{+3T4VxYE$z4zdy}uCBx|yl6h|i|9MC zP`&>yJ4x=IAMfjE&0xK>VVk`&V*N5E#wU9+q3_=$>}$B@@1*EX&(wJ&DM4W*Mgw=~ z)D>1ga=#59Z~2B!)Zp2RT{WOGNaWXjv!U|%mlV^34GHO(bOVg#y$uj!(tM6Gwk7E6b z;7Bqvq+m}usvsCuAO0A*_(B_UhYQ2G(>A4i#Yex1| zP6;>&xINM$;nn7gneQ06`uSlM+rXc(wX1*an4g!czT~-k1o?)RkgK`X=p6IVbwX3l zzChAm{C-hOs-C7v-ufd!#p%*;ODvC^OD$1lf7=vqqK3qlXvRHp9L-@V;PTsZiX>nqK z(4sl5vQ3J8!lZXA)oeea;j;3Qlovj&!K`}3tJ$I6DxVDkxwyUW6XS3`)5;DzI3O!diA-eB}hC!0l&Obo-kUKa%&?6K6_qqG@C2Qfun z%WPrXLea7u*7>NhjOf|1NoaXkVJ)fy=Ami*qQ1dM>Aid8Gw?j=hR1bIa-ait)!&hG zE_=0?7SAQ>xb-IX;WU=3giYraCLVc6|M;yx~;%zFBq}V_w!K+ zW_K;6e4Xv_^3_vJAhP_H>dkxiYDSGTDW7#m9&=xLWW%md&PSDhnV`V7M5m{X`UTJl zq7~BhCIuZWY9zLF>xKN97r(LlFs`XVMgc2`v)6j*+5onxT*KNUTXzR-q+Sf<_3bWn zro55g{dwvo*6a9ZHK{IV*PD+Nb12ku>)~uz@hOCrm%V#F=DeGoLIXB08LZ$Sr7X=O z`|HX*bls7SaQa1D9%RO#0A}YP*(nV3UpJU^XZf_BhF`q&NxqufJ#N>wCwVsAJ^0xb+bNX?W@}vm-ob_d zArHGhsaUew=m3@Pm6;ivqaDks=RL# zHL2s8>8XsQ9TU%L(jQDY-)Gvn1r+KQh(cn$Q0uSJ833b1P6jO*oHE5``UtOjHI*QO zvjFIXwf=Sdw=aTR$lNX|!mP)9r3r&QOYIDY28AJ-#dd^?EB!+mYMZw>gT1$6e}t}D zvb*4UL>#p>!6DOKf2P_9w|@cm+B87@(F){ZC7HvS{*A9SD!9C-tV|(2?2zC0~|f7xi=gl zPaX*`v-9Vy50P@vc`dPd_76KK1~LR@!$H-^V8kYiE7%l)$y+zETV^s<8Lwd&CyV*genXPd)@h`|HF-g# z4xjrtE3dZ&Z_?M6AVWqw2BEaNZg+6V6F%Sd=%*9Nz<4DP=q45=5@46o6TejWo{--e z&#ga7m16uP2O3~^orWE^d56aUHOSnu8Fq2xKDLIc*$Vbl{B2eX8v|#%vfZ;3gAxxj z&bgvM+m~Yo>?EkznUHGbadCMnyXA+OR*BmCZ13mOD_PM@S8O%;Ml`v&L%IAJf&hzVefm-NmOYuRHxX}MSjZPIm4`dPy8x)ObJ#Y6 z6ZuhBIgT(W!^o-KJ2u=>u;&yTsE!xVt}`^fH|%=!y;jxO$pOaG!Qf9lrj`5+6R(dp zUUnTgyLOsS|4|;JiVJtJrSI+?xN2U^Na_Je0OO+yBab98qb-W~1&mXp;#UYsRh7>t z@q1e_70{|5n*5HC59DK!U7x^k$jsaI@|$L`0qweqafDtO=J8)f>?+y=ML(LmR)16LuZ*1v* z=*a_==_R3PU!hb+zD3ewzOCCjgswH>dOgR0eBeQ=0l!ay1tjs@6d(Ps1{bhin*onr zMzsO;9Ljy)7IYWcn%)N%KR#Dt&CQT$bEGmTp1){K(Us==5Q>O|R%)rQgMb<^KqN#*_6)#WcmU)U#N+5w zWBmutMrz;|&~f=HMDs$+Q2btbwU^WdeC8q@9uJwZUylcx?|d4sIgSOISJB@z&^!p4 z4%(Q!0ja%mC|&d+cX0}=BxH2CMYvBFyb1+AEw7QPHRb!F6w_#MPb7NCy=17%PJ!L< zI%<0SQ7{wJ<2jy9fS3S9!Oftw*;MgSrs76AK4-0aZ!T5OoZ|fttKMwCTmRWRfNT9n ze>{!qM%M+GVNLR41vStD6>HKV0}on8=SNNGj5kHk2JGu=CA_Ye4+w7^nzgmuYC(Bq zKZ+|xHoJBoX-cNm86F#aMjGR76wQ|MO<2P}GgW%8M}dBSEf;9Q$d@l-zF?KX-C*Vg z!=XEopB}|ZwEVp zs4`b}D1RApc5dt3r=F234K$bAFmeOKe$_tBKyO$cb-KdP2U)gT+#P!NF4T!A6+G*} zH}Ouz-|Ai8ZX9ny3t+-B3^0KKFk#-X`7aYF0296gCb&}+H1{Sd%)1Kvf?EKsd`C=I zI|h5#9obA*9V^-;Qx{rfORc?6Mmrz6YI*U6nKEb*$w9}wZ(lHty> zzzpKeIW=FTT+6hIK8SG+Jo|oc#&*Y(m-QSUc&>qdm};T4zs!y-KohhAR&3Xf8<*_n z8_FeIXET4h*^z4^pb^hs5&SuNHA85fZ7T-BWQ&G%F}_Oc^o?$o zNoMxcXKQ!_=2v8ypE|91V6Gp8RK@V7UYMGdV>xC{%c+LS4Sipr%VHh)zTMe2^x3}A z!BIbG!!y2_ZDEl)LDSdHY5{OOLdzi9Uo`S;=g+>aefwp}^>S?J2O|FM&CsjY&4W^o zv7h4EguHUdn0Y^IgByDCC?(ziD?ZvQ}E`Q-Gz0@ik zHQ^8WcXJsRW^XI2t}ZU>4u1>Bx!}#bFnx=JhXBE#5eP-O1`D)&PZqfDV~?K3c(xk- zi}xVPpe>F1Y>JrLZKFizz<@{iT{y<$JJimy1ezztf2!&Y8sBznZ$UJhcTYkB4wsj>z9tkN zc7o`jqD|4@hpZMvGt_!#SFaD>62>9q0q|x3QO&z z!31|s{Pr+hF3MSa7E%1&Hf+)C$*Uj(vOxw)tBT;pJ3?BZb=H*t9P3UNN!pQ#QLo%x zbVTE;SDJp+N44F=+}&p^ETXByEMCrSZLGiWt8x(o-GKgndPr+OVK3v^b;yKyN31Ju zBB|=fZP4>VfiLJ#qaj_u>wUk9H%O{n0ZkNUJ&l!g&M~w%Oo??B=i0p{WTuCSwI(KgU654qj!LlRShhO7^G8O$+{0&$>8_`LHz9}OS?)Lc z7Upby)Z`^WSybYO;2~v9bGe9dn2y zh~1m%P0GrURNo+hi1xs5U`xM-AVN*(p{(|&mP^+UX<_XG=KA9+W)9-H0mYVmf7!9( z_1jaF)D3iOfD^-LmSO6Q{LG$VQrE$^+eY)1w8y~e^ih2oKjr2MO*ER1kKa8;km3z1 zJh~TE@D20MPqpI+<3eWta^j$%n!eMZMq>R%Y)9zvWZ%scoHLj6Uv~5XlQ4>>li#Af zF?8sxcpccVz&fPYsQAke^R_|sq!gdQvu;$xUmc@2}{Df6Z!B%J@b%sL7dMM{89l!FmXd%ZM*rgV@%yLoY{S#HDK31d-rq2p6qWL~K^b{F}Oj zV46+I1-IP>$&B@Ik^nj5UmwVEQAOaeLTwTXayIK1K3}ZPwD(hl;5MHn9ImvU+*lbI z8NuZZEMXau_1XAXzG(z!v0Tx2Uu85j+8oAAWl`3W;*k6)cr(7jb~^Epv28HaN$XVx zCEo8>dPM8xVTQdiH6%X!yhx%b1Sc!yg{FN@Z5l^%rS>PFGV#PA*k9_xL=V5vtE^+B zQ^ycv0+GE}^>xYQ?w4Abt{y;@aVhX0eX5XxbCMV8;uMkFl=`duVkV4tO}B21&EiT= z2hc-+;o1QRBJE{zA00gZMG%3Q&&1)Fc5ouCb>)KM5j#(`5b< zM6^0Pbqp}3^5g?0K&;UN8;7_Gr#HA!>xX(H<{t`LGl&<3Z#|1|h~o`KnRR4BI}At8 z%8Jlj-8kOxeppL;Y0H1dhBx?QU(2|9;bb*Xrlt8MTR8|?HF$hkB6f9@MT<&Hf6F)9 z@dv`8GiSbEc+xs;=Omj-y6Ib9$*QDU?Q$=(Z64Mqa%9se%>Jj3o6|hRal$WQh?^|k-Hyg0UORN1^R-qer;s-WWbR2yUUVZ=s)|(VuL&i|OsAuQ|*g9U0b*Du%ZQO*XSMDClsYXvPUcmu!x83}ft^bk*%%#3# z@4k?hBC^p0zf<&g7HhC#({v60yG_O{iK!ZVN9YEh7TX}D65;7E;jF^nL=kU56e0HI znn8$`E0@}V{~?MHX-=)EOSnK82|~+0J4on!N4^*_KKZ{jku>c%$UkW!k`{z!b^6P! zWpXB=-Wi(#vN8|j!x6%A;cGwLScaf4rw{JLt~=QTQ=bUHned=@XdEe)L-uL|BN9M}PS~GL5HRl-L zIp%MKhF@f3G6D@Tt+-ow5cQA0k1|ZbkWldz3~i_jFgRCjG~6!)eE}R zKnPhE{7VJye$y_KD2-~zGt{AXg60Qz4*E4Z=`ROS6k6p@&-OLNkewxw!G!DEw}M}j zI5;Q+HpLg|+vp%8^ilBD@ttN~*oaYW$OnLi$O1Iv(s@7vH)m?#%~x%k^d<6@x9;q0 zIGItLC4YD9q7fBVYBQ%VjS}H=`Uv+@?Qnx{pfM`J{A-@XB8b(QHf_OW-UfKfPrwikA^aG0|wQf0u?oyv)}M+h1;$&Q1jcL>iJ z)#@6O3;u};L4VQ*Hu^u)2NBGjic!Qb^r17r1Y&1>=`xETCn;f!h6q89qMNNh8s5ny z6v8pFjlTh#(5(%$h^sD<-}irYv)P_GSftM4Tm7-imy*_A>6LuUj*l}tW1GdL*hTis zScwvYnI(Y51l5y+$b_bfcSy#%wO=a4_5xo2dVcW$DeTEgJCem+Hm7X8nI~1;MKZDy z8nGB8aj|=NcAT|f$o}%(b(Q5h3d(uFZWMu2E0oOu`CUp&pfo#oAmRgA$ros=fSlIZNcrF@cEZ^s5B)5N48a++foDKEn$N=z->oJcCDUyv|d_*oBntJDXr zK{6^VT4{cO+p{1;_>x8fV0vrL{0V`W3s3$;AXKD4E!b&=g6B|C5#|77c5#BRE91Xf_HCcuCd&zn;-E|j z!S%QFq*@Y==9j{I3@;R)3Uo&Z|J1R>f9PAlvd;?kh>3x9(uK6ut zDEK+%Q9bJT+WXJ7?t8k)!SC|f^t?jHzsmT8<38zg*<0Kcfd!rfvw zM3LWstp5UEi=VK!vDpLQ8#&c9p>gPnG}$~5OhEGOh3#RC;0{R;`1oRR@Zh)g5UC#$~xZWp}lsP*6-(|>eL4jq_fY~ zZT>GBqW>!mdHIuu?1Xy)G^B)T|5qBa;zre-m6`m?CF7Fn?`eqUpJ~YW`rI!xgswi? z;Q9ozv)7j9Wwz0;G-UQqG-Lqa0MGwILj-@NAsX3a=f{+lYC67sptj|mIa{DT=4QlF`gGYp;#OL zEZV6=V&B)~@BMZ4b z?jvGZssXTw10mv`pDYCYD+>|(g@yP>1MXgNH?stEVStcGTO1|yh6&$@x`CJihq8$b z34D)cbt(}BZqESR{sqKw08z1LZtQlKD;xw&swt=zvKO#exdg?LgPErtv3*rcsWH&5 zO^@?DkOn^#doqJfCrsL;%e(R5eLwql+zRY zP|${DnIJ|S=!8xt+{sK70L4}>Km62}3$e>4ZnWDi{H8Io)XEyaG+n06z0^wq-!EJXziy->dQgADrQdEOPbYZN?4yC~mmhMZ^ zjC7;>D+c2E{3iq9`3nQ7***4f>c6({YsS_}FnL%ah_Xv#wE65NZIT0WccxY7Ol3$j zLT{eX#@7~DYG2{xTyJ<)OFu-*5wBoRgti6v!<)#T3}nX#&uW!Q?$I;WWdG~^>5ZV$ zVP5sU0E-f{5J*dQ^Y&)|tUxBdFP{28>mb%BR+Wd-z~lv{zvD0vSN7u2?R@<59lf5x zmr2`_hNlA$oyz0^6I8Zpp&tZ|aTa8xyAE zPIJJbBf67XiHSn|0YG3f&dUJt!0DS-l0fWDqN_`S> zfV0OHTha50_NSwF8LKWTe!tp>g_{NvU_6L4eqni4DbcB?m7q{M3IeF((^F(LC zqxH$R;rr(rx3oL%tQ*oNchsDW=j0ivSqUWQRR2O9d{;8!F9_g9!auY><;K;ad<2JH z2>Hqa?iqP=L(^E37b=ZG$^K$zJn|Hh%fKM!`3c{VH`%;~dfG z*%Y$3(A8|u?1B8JmL)l4GQA&q!}`V6p*v~GKam3=U}nnD#+5-*d4k$^^Ru zsRUNW{26$nK|}*fynM?qzemG(u6k&T&a0dBAe-n9XTj)l^cFtt=7Y*9!!CH}5!gdc7h zUR8WqJ{q^hIzY!F72lB@A9_@~H~s^ZRKGe$0T|PH3$}UA1u&bbhqZ@W)~*l_W_4?6 z=;WgIJ>?aaBhha#b|A-jP{$eP50L!e{>O_3V9iGBNr4^yrBo3YJk8Tv1f(w=luBUg zw2oPiw3qc$7(S#C2Rk?y!0Pg$Qh$t0jiyLYH?4~DV^51{OF<$)6M_JRp7p}G9& zK4gjP-&dkTcek$Sk2Q%G>1`y@j>c;rI$U^}$`z!T;?b15-ftgf-E- zp(qqIU_ydT>X2)x8KS$=rM)-!zvLL)T1w61LN*PD1}_vSiew@rc$XNR8B|jwZ>wrG zCr>@!HK6OMfe|jwMc`SnR`BzX^0kKeSpGoMnlY&NX!&P&=8b zY6X4pHP4w`yO|+6x8h?>L{{A%!-}9<*=I-8;|FHO$%G-*i$R>6h?F;C= zMR1rb%i2k9RGxg^y1Q+;f`RUO&GItc+jE4z_1?B_y&NYNNxP~y_+_|1JaaNt;ONUx zea5Be@OeUOt9E9jR$)?_64TM;O)^qeeV%{6L|A!cvGTn(jjk5tV;Ot$x%TPv_nVg}KoSg7v zR>jBJz*WUjYG$gT>KKvb@omd_fE^oafSCpY7nkDr59+svv1;bIBB8MM0LzX$(Ggh% zqMO=A2#rq0;pOc)HS|Gzt?LCpFWad{7xF9PE^54g5z*<&5oOD_9LgJa(E+houHAc! z_8pg2jMdFP^#nV0F?Y%sm21&Cabb-W=H?Rooq+N%ckFngB5lF?HKdWv zI0{xFfOhQ_G}sSkH*a@&L+|<5V&^%M8QYfO?3TpuVb*H3gLl@FK4%(8`e`wDGC$gpzvzWVCMtE;|Waz4)&=a`QeT&XE2tHZ5kHV*)5DQwteV7La-R{}YR;JX6s z=#IH7@Ky12_}oSrUa?H=RDlw=dOC101&r$H@A2Rz&sU0GX+Zp+6h`DNN$mn2zE%P( zq;rl%VP9#48tpR;f_Dyp16-PC89{g__Kg}P;QF@#c@Au5=&2E&;VCNNjHH_K^voI1 zL#c*$T=aYbTzTC02MAu;a!ePsMGoEr^#2Vi!6z4@7V%15G}?eyif&J%X;~HhQ?;`G z>N1wEet=R)PqqM8cJLvbeOHz@vl*yGAPqJLxP8fg{k-2_=a*jxp0J6+`@4fvonAZFMy zVT21)`r~!*gMcuEB;~;r*PokGQ_-soXv!NHHN3wb=^4J^2WUwT{KxAY2C^Ry!b>OF z&xm?3K+B>+`L^J{Z*9(@zrIZMtskJT{%0DeB)iP2<*EyAi-y(uP8Iy*gQV6E13lJttsyEU#lSf zQ5EU`!E)}l;gaS@a1&S(ESQP_svVrjW*37eenDxy0 zj_+?fV`RT9v=OqHNR-_#lSQD#q5vHQBg|HI0!2PHX+*ucNrm+x8C&dO6h~)<0v|g< zc2~D5pp`)av}XBNl3l-lIR6D*MM58J8C|`2dkd4o0vrLi>0Ox7b($+r&@ZbI&CaCc z=n0}ePIjR^t~Ftqu%6EzH9_0@CAFj+9*ppJO(4k_n=lvMQeWAzXh&HQ^yzNy*Tni*Du)+g7~N~gGbE@fF0 zPeZPY7e4YG6}!MlP~XNSLQwSInacks&ef%-5IC69QMd|Ng?g?ELD#C@JjF>n^pu|O zc@g2>I|9gr9RcZ>%H9F_N2wm4i=ceaN?}GAJ+r87a$ruB_BG*@QV|%ky~@sjoGc}( zyo5r(J&<*J1^6_L%;a+AqU~_uE$b&;H)fwt>16P4?m}mTTkxIF@BsGT{B57W&fra}2T7_yIHP8m z1i!WVZ@ zo5aahT=6y_mDW{WLSQ~D-#0oT1x$xIpj$73e^(kzvMfQltvE;Wjy5*FrG5TDg&PfG zRd=%s@|MIgU|gC#1s32emQ1B3F?3%?H2okS!k0LUV!qpdody*9-06SY#J_9r=TMyH zLSM_}S(xg?Q$&K^$b9JfhK9PYKu!EjREq z@ZS_@3p7Orv%{`@D%?paR3@&NAp8h=jPDqNud)O4xA#*V?{5oyPeMU`zdgWt!cNL9u{w{ttv&mZ9pB!|y%Fi}>0@C_6KNcpCKp5qp#rOdl&gD;)7jCXVuRy4Rg` zh_lf_66^;k4`_)&HpJ>5U#{Q1de*|32@bT+s8#NQE-ej`*!|s(Fk~+D^bY(1dR8|G zB%rfa;!(V@$@#Xo|lQR=);tuG=iRP&B|a63UnYvu>xOX;daFg z&z#-3-dugosxqLVx2B_7mWL`kvh}cE*mP9IsCVw)Pl`1f89 zD^2Auf9T}jJP&{45%~YWr=Nl67_&Pm7c_pi{nm-FkJ8G+TDRgdx^@f5t3=&&7m3%} zJ6voymVyl*$4@K9l?Y1g*$8;!`w!6m{px?;q-03Duqv&S#*DxE!YU2Wn0(`Hz}G>j zyoXdUTgf|&nv(s(aQx~x=<7FOZ}qtj!wo}6i^Y%PdYGMH9D$vkq#@RDK((npvHe&$ zx9l*D_kjZ4beb9T^xY+GqCKBWh5yu_9QnHp@y|SwkgSW1WdvukkYdu#RHa%YxfL*; z=rmZad!Ig9M3}~yf%M`E1lWAwKiuHOtXeZz?ZHa@sZoFJa1hyP%26LlbG|Vcbj9aR z>vGc+s=pcGhA!%kPi4{%99uyzm(Zow1O)UMe9SI7|0eGXw=nHwZOXSEQ6%g-AJ&sG zy`wNh>rh6x-}e5oaL5~8cJFOh+pmsaEeZ4fy_V^pB~$->{}-2l@nC20$+5;66|L2{ z7U0yfH>90;=HY`weMGGzF!-Y4)l}MsQ757qSPU}#74+Il98E1%k4W=usYj=5WD5^P<1Gu8tq9y!zp>V zEmcOOs3~)ekAFmZjvdT!@A0^^9ran@n5R7iPFs`aSn%*k-x))@tNy%Cc-XQ8()W>0 zJa@UMQI}RT7XlNRk+CLeHr)VSMwsLarm+T$=*|(cI1JpG%b+{_R(H>kheL|uOUW`z z+hSi7i%P*d1xb)wwpz*BZKP_vRxMNJoMa!j_p=1L_iDnNu_4J2(Ag#j;fNLxUiSmk zdVGfTPJ3OVC0*E;HmkSgtzFn67Jo_?T2rLd_sx?UP*gYwQ^>QvbVTQpWSENSyPo1` zZe0KNbLG@=Es#G7vOC5lYnK7OET#bhc5Vy6_pg`v$@1WyVWNESqB!V~^bJ~kvPIFl z#YYS z`LvSfn+wpg6Fm-sp`w-u%1izBxo4S+$~A#@5&{g#IrO{{K0#DaL$PQdnJaDV6ktnM z!cIMawuE`#l1ItVjYd1>@C20DFnt%JeSUiHMPm;l*d~B`5fFt6I;*iOgD>dA9NT*x z1yWN`0}Pf8bR{Cf43ouzIkGnT@BE}^G8|J=5i_u(LklbqN`purYq@%8NE@c?;kLh} zuM{}jee@`PvV%KXychS=|Z{1JEuCrk-p!h&4t*U+2Q!>`qp^@C<3T!(x2OdPb`NWf8 z*cQ(To9K2$hRLP?iT;pSV*^26B6B2}S@gpY*~4jF(^eyXXwTE(CQ0zOjUH`7dUTH; z5Ef~*^K{UYu^7@2A7SpK!%222<@!P3vf_tcsjYVIfOkCHSt}sIci1Yx_>c|3*mX8D zVAwl(@lGqi0#tGPG;in0m0}yzLF(T zkz1R&W7MltYPmX7bGlP6lq^f^WvXLA=8;RUiG1F$gr1P0NZZ&$XL&}O)SwGS&>;9tce3Np3$0YDb$4 z+X)JAjgDKgU8RX0xKjOcTl4K_d7>i##$x?X<*~7v*ea9}=o{`nJEhYANspbyVK7em zWNfx5zn8&{Nscp~S73w#ROcem4Jz)7LNYJ9hI_N)Zq}h^W@>|)lu$+t23V8Fsn)FH zwf0k7z7FLtIO0X#65K2-mpE24;cO1WP`0MA>0%e3V*SyvJ@!})O$;ldN$=p}cuZ1C z%1l>-japsSo%UDBEbNIL;3_ZO2kKS zoRyDwela^%c@w-6@dJb>1F8n7N~5E{!3UTD)o6Mk`#7c$G@DrtU*IbL0ZJ7IJ{M~I zMYpvjxwcF ztn-oLsii277vaFWcG?06QU9k#|4JJrxng?U{TpQ>KJ%W$2NTFKk3P3nn^MCncD?JB zR`MAte-%Ay>dF>p?sJhh^RNC1iy9p?z|Xve@ID7+x=dv!GhloRJ>ZnPPo$q~w#J?o ztuuXG_C+VCHd@nS`1yW$Tt6quqV4i^beh8caHQ()r$8_h0!>RNQ0Exr9N!N7!WJjG^g zYw2~8O#+y{be}!Q8%S4dMCK`gxY8?@W0O1Me81)@9mo0|Cgo!Zfd=^)rH4+bx3JpI z=tl-Z-E#!hXX;C8-%5b(EBgI1V>KB>lN4OV5m%KIdSf$B9TQ-rPq9DxHqv3EPwxrGMJ*6%Rxps`c`D4FetUbF znlzoW(c)&Pmj8>7_3_QMt}RPmk2p&O86qF@7n~A%bd3cyC%Za6NlLi0;q<|9ykaSd zK0*X~r5mZyMR^_x>@f1?865~}GRXXL&MWL0`+DxpyO;WRmk63zPPJ#A@6iXy6805f z?SPjeAi=d!cfwPFG^C7P?RB(*vyFTxw_sTu2((0y+Vjy%>c#usk=Pe0BKQ^|g_XOp zR|1Nj@Lk$ogaHBKwStX})-)$wTq|WrvPJP=S;}u%GXMyDlU6B&W$8vK)gbDcPl>F# z3w3TMe17NB!$Il3BF&81>#@dw)v%hFu-1?TR*gZxb-?E)%h)`u-`)rN2RuiLAz2WT8LuWOHLr$Q!@Nd13+ ztiT{cm_CXOXVi=#M&J`&YA3Xiaoa)W6~`rxcGp6C$ZvmY9Bu}=C>cP%ouM8S-6hK=HK<#$3Z$oS|DVl*N=S?4{tM{$tSwFctsNG_EF zsk&m6g$#}KmqLviYs>&Dus#EuH4kK1w_o^3xB#@ONMDK7YNnwyGA(RdltIwXEleap zwqHu}I}Ia|b?dq2xN;5R^%jI^k*A$LS@I28Hi$6n1pCdRZQ*XkQ`B$Gk z+E8qnaGHYN>mHn&(NlA!)*w#bkdCe*QLZ~(B0ehXrwmg;?}7tmuV_q0Y|T#K>E7J? z^5S?=E$SKneLvQ|A0W0u9Ezo9(mEGwTp`|`79o2cqnKTSi6?_T(4gs)x?nLn{0v?> zjbtG_!>-W;$z*C?z`8Xmb1{-l8*9 z1dx@^QK4W8Y3YfgGHliTkw+;aE)#w`nzcSt>cZQR60QxKu7=O`i6Rxf&9Dh5?T#~x zLp|(`1p}^5N$2fK=QIjF$l=kAYoq4l&U;Ot-X%m?C^TJCW>p@@fXPz&(HkM`y0Ogy zf?)!KlGc+-rNMf0o2WszE$V5{RLgnlEZD=nS`mU1HHfP<97?+tJ~XZWHH`a7XWL>l zgPE?5>18F3ND5CVChgD%yMvBI=^tTDa@N_{lAqTM?{Dm(L_@8Enw%r)V8li5k0jcT zBPC-Wodqljp~JKdM3-VafJt6ogFKNj@j>KuHn|{ITzRjZ5Nnk-7z#hWZpaRVjrMiS zo#?zH*hrBdLr1BupSg2^2{#m4 z4hL*^U#H&lZhw$~U;*u>kg2bG{0E6}f>ejGT_DNjSTp###_*2Cqg*f1@lLugEopa-hikX~03lM-Siky#kdl3S z3Ey!AD6`7-;qzBN*}k~aHV^WypTq(6%Wo?*fZ%zCwqFg7u|JDp#rdSfM7ou3W!Ba> z^Ht6o?-ph6ky23G90zf>2sUvoj00xhMo|>A)f~A9RMmP$ZUb40ARfS76O&wMc$>($ zD1{#^^S_vRS(_}dkMO{-J{x!#=W8eE(06?VZ{YS)PbTAa+=h(kq%6 zfzo6MtaSaA&OWfOoJ}u)SmpHT&b8#bFHA^feGRWHObO9+V0uujhuH~P^7X?_x03W9 zzCem#;1I8}PehxS#1)peR^H7ZePpcuDKZ-U=g24p0}m;Yre6?n?AFGp$kh1e&RWGP zUXt$Rsti~$Q}3ksk}uawD5LHyNmp{IC1VY_)gWSTCHB^!J1SzmD*ZJxQMk|a{Dch3 zh!Qd@2witY0lTnd6iXfvuqTga*8k;=%kZTuDHXLA7 zo+ziDeK?)ra`IN`g@t({xBZt0n!?iXTh9aK+2#+@Nr!ZezKwIe*;{0viCi|-+<*R> z^t&#TbGYN2)!RPNk!y(0N|#TcEn23tDgycmXwk zUwllG^Z)NNp0Lt=LN710tuw8=JUt+J$OH;?qkr5SiX{9fV7hnx)#o71-BS3+>BupJ zrUH@J5Wm=JMRyairVp6l$>4u0S`S#_Cn3qnm9{;pd7CM<52`HtTzm7Q$y+Dx@GaXy zk426R-I)$A2*vmM>k>nzFVL?$q$7LAi^oX=>qfHWhoz>LG*=58Z~9^ZCwyP?ucbdt zty(smet=GJMrQ;YhLxh>Jv8*D)bS(PWs!Y;*?8tkuOgkxt->GtKZ$@4C^(BZl_Aaq zeUKOQYC`+IA6ZoO!|pC2@@#Tm;_Q&Dso2l85^ZHRnWZTzPh&o~Dru21>t8Uu`$4LD zvCu^W4Jm8IZDRWum^BFWutIIKLJev=7uMKV>Z)t&S|U$mgbmEajjolNj3k!Q-?nYl z0vjS$WC6S!sKX?f0niyVdTnfX?j^p5jra7rm}fIQ?R21J!UBCdvEEO+s&w0mrSxdm z<&3ht15>;h`0VD50>iELylYd?+36^4FORfXq#V}U`6DTwmT9f0>)w&_jWeHyos_g& zfJE&Me&}pq(zD5CU|>S@q(hN*AhgTF8dB>DA7T@Orvf-$l`^hWf8&N@@9Yeem9|=I zrg`NyDvbzxr$glZ z*i!}c{z&Ph>2URi2T!#7LK4GZ^rm%fW<6!9bob(XUfV{$;SZ2u6B-<3E6S=R7J9M_ z6-25CYBr2A8EdT|1#oagjK38+dN}>mZn~PN+YZIp<*d(s;A24VZD?thzs!o zei3VIbeSiNduWsWMI@mWkawcfPHU#2lV@uA{DAXJl+|pek2G>(ey*MG#s+7-?n?zkPWGME~X3n)Fp-`s*`gKX@ zSwP%bi~+NFMXe=6w4`vL4f<*RC(-@yGz4moMx3_Tx+#Q|5rLn-juE}qpL$TCKrN(r zUyk;f3&^<8+K_EfS_R6Q5M13SqcwXYt1gmx3bxIqk^vq1RK!_+DO|W%g7mGmaVTgB zXEYBc!pV&+4mUZcLz+3NLN&zhib^S$E~#iLk)$`u$ z-?c&9BH1nX_D&Hb9V#pGhfh1B;{Z+Zc*Yh!+p{Zc=aOgPzMtZO^Z4tn(6nb!G=x#f5{YD?$;Xb|kCfNxPMG zqj@9HrN-I!$Yrg2T?vHNSK>AmZLtZhvt*dWDm(gBN%I<{Q#-03L8e@qgnSj1%Eeg` zQO8nB;Vkl)G{rjYyethYx$^>QfC?)vKPH<0nRZl2WD2rf#U|!`uqded654z0Vf>K} z$d_GQqJRfG4V)aq&!_~f#?^{xT@-nIbgmOfpR+C; z6tz4!BYQOQDk3xLNwwb=mr1;03T=DLU2c-LbPB8gu7%$^;ghz>kWt+pP3ixERXYvK5f#1q{%DpF6Stz zTvlNw(PAXOBu`o=0$Ts2nF@b^tP!Ug-* zgitgFnrs?AD7=F|0fwL`&9gFlfV}s$oUT*iWt8~HvaCY8et-Y0Q^Q5PZvy;ilpW_D zsYU-_j5h4|-#Yx*b4Dom1GJM5#vZT~3q}<3(f{^KQCl8SCnNw}ntKe#tV`$^FhA20 z`rVhskAG=Vz`+F?_;Wiccqt=q3FTL^bIDNt%g3q&Gh^l!VrI zp#_Uh!?!a9;p5cw4}Mqt+waL$0$(jgQa{Rje7uk&tvSII2hOnSCq2uVr-F#1AWSX zHe20wZaF>$I9sbW(BB6I|GB>zvzJ--c$2UE4r>LuY(S3v2@?WhMw?WA@9Va!3fG6m z+5+$=a)NKq8~%N$W@`!+w z`pv!v732cN0w~0r+tclLA9F4p-6g!C$%ykE=@Lq@kgeM$rIkUhqMfhlG&XTh(3B587ci3Uz%v2^B#^R9#NuMi-@tJr*J? z+9vcY60)+-Y)adA zoevJ_62vc0O=~cdpYQ+J6vbJ08bEj{&QT9bfj%<85FdrwK5B#%tXtbA#6p_6#`cH6 zlg5`jO(TbQY0Py-DY{(QvSX7DZiqxkda+hBe^Q)z6W=|oV;fR;MXvXIrK%afDS4CF zuA1qJga`o&jLz}C2orjWZV48V(ibAJ(xS)6TX^JEi#=VBlC}x_y#C)!oY4DCw=WB+L9fuh_1Nd^DzHH=4OB_hKM#+B^wvl{cQ(e>u83r|7%SQAZ}c_PKBn_ho8jlPxT_DVLQ7?#!zrfa6P zM#3Yg4?7;CZR=fK56P(PEIh6u#$#fliM!V_gc)x=A4t4#FN^sDyCFNMnNffBL@Oj~ z(s1>yWt8VQwdG09VT%2^^`~w}nisb6BA=31E`%$Fo-0B;80#K2I`2tn%^t8gQhaR$ zSgWFV5T@k8*BE9INI$u(z}3ZBjs9$+!0$+}%cyXd+uTRi9P5RtLe++s;qEMwNy+H# zDP!2OqhG9c$iX(9&V+#=(7LFnr^9Nb+h4x?05#gTSn)6%ruj@*;a^3#BX@tl_rfg4csN{n1i>GwvxX`V-el*?!`7uSu@^Nf6K4&k~Q7rL5O( zE;U)q!^yG00ARq}MHjftkgN8dJ5*Po6k5vlNw;L1!*V(B@dbiKXB+A}e)6E>Ak>_X zHvl8huHhw~7Y8k?*6B{J^-lzDGV$_f5k8BcJLVsf4_W5u{@VCNLufmmXzZgaioWxB ze}D}qkDjeE%Uc6qDlOegP)O=BXL{%U?A3PoUV?5`jLqHJ-I_vNfWM#P=80-9jYG3X9cE)*s_9 zP29QehdLQ&eXvVLb_~6D-f;J;L_BgS{eDj}vxU{lT?Wt|kYZsVWTXSkfGC0(`{J(J z*@?Zad{7_sbqH!#aoziPFURiVROt666I4|2tmGj68U_7}s-gWKAkx)tr2Y+?c=*W4f*imyKNlkXd7Z$?9(i!q5grn>a!o%}&h^PYuT ziH2aoU84&e?mpp*fK@j_?=3za#65N@I^EgKzf{2%VX_qRY z$rj!*i68|Kar>NJ_pK@2*owRxf=AD7it~9KMpYLVH{GVDXib^S)bL58NLH^budNxi zSsvN8wMC5j4R=#1kVjgk!&Pr$^cpBRU=>}TkO*}$ed;BYNvU;gL%Cp zcd4O;>$T|^w{G>fZ~38p%*mamJTygK=&Mm z3<>nN9M)vW7Puv{X$Wtxu$kaCr(B`zHy4y%@)9n6v^$K%ke|?1EoxlopzV&!#JWC& za9K8uL0z@to+-VPnuNx>>?`ca(sLwbxnZ;yg#vL>ix*6x5Ab{xw4xMXz40b#Cts3` z!#4pXdK~xEskCO_cjSMrx_w-<=EXd}(_uu3wa`V|#%1VtWn%r-m-jTQ%-u{rt_biV|#Y7rxLISki!Gdt5PQ(j|NsjStCXpa?A3q=t+iosJW^79qqX*?w1lm zBi>z^5Fwa_-RtY5lVnjrc^REr;h&g$_}Z}+^2QQ9i0&D>k{Qq6>4j2v+82(@#VIj5F$!8QL|0IFss#=RAEPOvN2WbXx&Xz8aBr>0#oy z_I^H1j)2?eLQ&qMr!jA6r%1L65Q;Fxqizbjt=MmCY>amXY^SaTs%)Dl@oZN{$bLRK z|IJnV!>#>XB<|(JVtweGF1lwjyzG1Wm6`V4+p86bgMgGG2|VrTBX##5p!Gv=LUOD+ zo_A}`EBvflDs@lsCCsDK9UdZJn%d7(8$YW+(O)v^{k*>^-NG~^)<067sOZwO=zhD2 zXsvf^z3o>0OgyhMLvMn3|3aifK{q3l#MT=^g)ZKwtgTtr>g_3L?cLEXj8FLix(Zb~ zn}VMa7h05$FK@kqsLBo%D7(2dzKWf&%6w@tXgcpPzGV!7Zy+d7aPTt%KB@r|L%@LU z;f2m0oltjc*NNwCkiYz4NOw`WT%n_Xna zLpy*R#v+t-kmwCVrco$DiqU)Xu#!I{bzSvroON_Q5>}Q z|LN3wwC(cq{a2JRk+q8+qVKG{xoSqX>=Hk`|Ke_xwq#=%s)RJ1_Q0$e%)m5)oCdB; z;a+2d3axHWmj-#{zzk)CRTz?8lPI@@5Wxv|$s197w@4hS34qj4f4!>q+h6*R66XEI zi%i0#g`}gk{SiBi)2$P?uyD1HW2V06wc_|+xlPi1_=$$O!Y7_DoaxEH z10hCs_go{w6a{cQbBOVgc6zgqH0dvFX}2e}SADZ~5toD_vuFTE6iV)^`$zvP8}6lSno~Xe}H(fgTJgL*Jr{9|8!vJ>^FsxD%QjTMPPrYt!3K& zWq`!A^x{R}zb)tn{O5$9jq*R#4rx;jJZD4#@SRufcoUoO z6E$MHagu0YSeCKFw*Ux!ScjL;`)4#){f5!;1*^1!S)sEltWKf>dcY&9_Us3!6a!y< zzrIkHZ8-!e6cHH8W6ak!zoUyWDk4we)(xHGvl^+UVpUsIWKlDW7fv&&Q zx-XD07uI`HZXA+DX0|1%+pO(KAlpjRiW!Cf?tH1Zsfp-@DMZ?aretpr z=JB#&6xkHt%!DzeV@l1Cj#V?e`NHz(&a|xVH>6?CsKAZyDd{1!p9DfTCKir5XC7H< z1dFZ;W(5o@s@2A9v#u)eF?*PeEVyWa%91L1UtStkw7{zJZRw$ACzM9*=0merK1hhpH&Ir=vCWr*>Rzd^a?J3tQDM{<-tYZnN8msyo=-AxZYvK1FhdYJu}5`fUkqR5R_4mhzIp*v`iJEjVwSP!yfc zj+i(l*RwY>_o5(75H7Qo5a?<3)~&1W82Wb0pf-;eDGB8w*%gDM9+@uP^*D1hEwdHw zz9F_W%}dfHjcZrBy5`wyf9D8^($SuClyyC|t_*O}GGQ9)uw?369-bZzX(MGR=Xxhy zM+0X0Y_H#4U5Qr8|7JS6DJEQX*!K+mc06@-lsm-v5$tWvy(#0w0E*SB%qT!jIqRZB z<3v33s(w6IxY;q|+6SynsSEQIW|z{Ei(n#!HKUs#2JFUIxy=m?;f-ggSspo> zLA6Z`oAj)C#M#RdkH+&ZeiAh|6CKoO{`_XT_|WW=t>EOe-5N@0IUeGd)rA%15dGLr z?-#bD+c0jR;aEHaO-@L>Z0)pnqGsgQVUe)I6)s)aMgUgwPPrdzMS*N!$(Cywyji;@ zcvPxDn$HUy68;Vk^~ai*MGAp^1o#=Usx6DneDM#fx%S||-NjUt(PsXRhwYuzj1vc>%*9H|I??l} z&q6wKyn}&@lTpeXxFg<}rngzpQ19u<{dofq#egS`Q_}jTt|l3y@;ynhPruZy)@S3~ zZag=^GVau*+aB*vVb&Mcg9N(XBH@3OSbTiDmtJe6cqJ7N0QfKW5ONqx%lR{1&6AWH6 z6X*%N0~KN69UD<9%MEy0y8Fp(d;xFot#sG?OO*AID)VNF^5;}3lNsD^#R^a^3706J zEsdF)Z(Y80G0kMD>y{s~N>RGFsc~^Y$RdHvt?EoFpg^Ncl zW->S{pBxEN@A4I|Pj-aN>e*KD-Xc==gbo{*OqvxO0_{cx3t`6W%tvhp%XAr4)m3Xo<~5l& zYF}H0&CF@CULSoef895n1V`r1*Xvw6Mr4Va=umsP;^wUYCvxat|BRa1qc-krq8Y9_ z)G{`ml$vG}A~f5-c~c)PP%azWx1w;tc%~ut<+7(mXABnBk{0n$7;jy=E)zhVw==L+ z3Y=nkDvg`ve6{e>&EhF>rlp(=SZk0N=CE^)tPax^>4ul`{!q3l-KRFP=~yfBQn@6k z);$unh>p8@t=aRez6^k?It< zR-t0O3LeoLLfHx>8U4H~jOW6l1@d)`T%Q9cm{}$v7)eZOGc$ai4_sao06+VK+3F=` z*g{qsxbmnkzfzP1US@irVqO7&@6jSy$nR^M{(AEM0hap6|MdSG2D`eF>*m{`^mygy ziEEz~MI2sQX}b4Q+^B0t)d-eLcNC$Pr$&R#KprMhpG>+Ku zn%t(AwThFZa4~YXEWLAASBLeDzF!YpMH*!CpTQsgS^b~!9MQNOziDJ!I2$h^(LUWi zlXHfbyzBC&+>njC!bb~klGxm@rL(leOCZuOpbZ=x6yt#6{ncy{VPs#g8d?Vx#LmZN zh+~-_RB_Nvw7 za-2JWOMG(+7n$s>ukA`bJ=2$1A0hNqZXs>k9@~FKJ4Ozk`q@>OhQc-$RR# zb_5uheGHct(z4cmQP<&XCvS0SRYqXZ{?Y5i@;q%?vQs9U8pw(tgC@fdx^ANDSJK9; zeD*EoX%o^;^sOVsjD>TN2b+~DWvG$*1KDSVS43ILkG{FKq$`WG( zQcn+f%K+0>(uLnI{NE`kWe30LFOd1)U;m^0E6~S?@T(CnRCWy*o`f=hQu{c$2#_=a zS#Csp@`}X{691rD=im!7F)FT{Em|#>LC@?l{*_xN_rB4IqK`@Z%>5L>?Ky8Bvy-l*s%a!%`*?c($CxZ@T@x8ogR z?CyRhTjI@tt(ytW5a%8}EmpIX(!UP%<(YR3oOPN?dA&sl;qNjw%Oi9|Ro0Jx@n(4F zYIXcreDQv~6ju8g)$VmUi8E}^1WvCBt;bWMW=#EHAXWPn_Ti~_iD%bK3rWa1TFT}G z$}NVZ;{+*AMhI#jB1gr)2{P3P@b97A@3=SD(K zeefy;DOb^k{)qPG@dqb`!yRJDVq0vo#JhgfsZ!6o1NHOq(f=(Obz=SRWK^~#H&Ul2 z#WC)&9Zy9%ly8e3Lmem-smC}@*iXGZxnM}Y@E-@w0#x`+7A6Ataw+AFw zmZFC2Y+=sA)YZZ^QE981591W2=&TH`=o_? zx6D-?OoG)H2E8^`Rk{b)#s#?_2^O+INZvubiUi7d$l~fQ`i<3_)z$|9KHm?(UYcw3 zGViCj?SV1G(#B0-1p;e%^vBG4&EpQnfwg%Hv7Nz68NON#^`FZSw~>E*p#HOi_J5?__@Q5*I##Km6J((=o5-d5l)Wx*9L_zu?0f9=xfCeFqn9Zk1m?raC#npRdPV-=l<3;!?c8C{B2? zoap(+tLqHM(?3L~j{I@(8CSa%*I1D0;?~X9v|g#SkXi?i{Mj6FHCW&q)afIy9~(UJ z43j%nr^SDxYQ(EViSr#}&8ymI)XDaWQ?1zybpHI1yRd$uh;u;GTTDS`omd3ge@E*| zTUuk@BfSe6ymc9a1`ipZ6;chpJ8})O$B4q68$8s(+`ea9l&kI!&zov7c=-!C$A*_D48c}_EMT0bbq7P{g2wn?Q2FSKHa z8}dn=I=t*G^d|Wt=H6-kxBK#w!2aIg^MQYVNVsa~OHy)LVm8W$89XsS-R{Uy!42q3!Dzi(SH?6b>o-9CT^Cl zc_u-wu0*&gH<{Bw-vgI>ya-lXfBpGb@O;5d5M=rt(sL1OO$gl)Bb-ZYzSwN*#-fh7 z-&&hNgH2zIzYJ0$aJ4IOqA$58uZN2moz&@7Ouc2wNX~oBWCuBhpkLcUb5Xkxxiqd) z7n@j`p1A(y)bq$RrH;FjwLTsRnR?c&xY}LOYOHT7Z3L7Gsd&w%0V7n_I9PDBzKf8Z zHwbB}I#s&RDQbA~nCPODL8HA zk)D~kg^Q~2qUh9l)@jvKeD}^LeX?W#m(IuI#nC#{F3i?+LDEYy6G55|xh__xhpUR% zbY9nvpZj{HrTAfA56PLW1fplgMP%s?7*LryK)2MW)9F?moOFF0e^mBfTsoYlCp*sB z-qVBqaJPIsxH!X_%u%VN-IkC<6tu#rx6IS-3`Me<;SlfYI^zqSF&~^R&zX07MUljc z&To;W2wb4Bapij^*GWl#+o=mZgyKgVcYxI15DasS*ATS{PJX@LM8`8vHCQUv^A3m2 zeob*#qlQ1rwPhIw(fKrLF_03VAg1{?k^--WIE8b3SJ#9L6bUaV-Z<@d>yUj^MJm~- zfZKW5>1#p-Dl4PGcsP@`iQdAG3+>j<6)CYE<>G2Vk2IiRTa@IIC`2zqrUud zxxA+}bSk7fg9q~^RGHI>$clw$;(6z3yo1eeRx~z@QK7thH)zi$%fYES?sH!}j=m9g z0%C8&k=o}+yIVf79V?0M#&TAY#|sm=oF)S1(#x*o_vH2jiQO*@Grt>|#aj${%1re# zEuu3+o={9=!z*B#+k@RY(q!^81SYD?VFU6Uf-KrkY4Rk9pXcl{m3-*p>@D}(&a+SE ze;^K`lGB5+SHKsT$$J<3C`1l3Tk{-I;2dC6oyf9{%j=!W={=01QhdS_vT`&v3K@e} z515k$R-_PCKTot(+0sUtLVFs$bI55pb=4t3d1BPvA;tKKdNRx;e5O*Mho8pX`S^h* zntzKC4N#>qoaZp-;+M8$0cdBDi+kL{!s+z}vwS+f;sh^^jFkIy`!(w)5w6;oI>3n+ z{uEca1SJhRKaS_UBL(;E2;pzStQPG)mrd-w;uNQdTS~dp#|HnFa7Bodp+?eb7Hxem zL}^SBQ5JLwCyVamqSZmaj5u^{Ga8*Vs7hQX`#P~sJ9ibUQ5Dq2XYp12NV!!I$>fd# zA{<`k*BT6L+3y1S>pHf!wqE&r^QXyPVcqmPS)8)(7bHMBcW){~EEgBQoBzJ)tlyV~ zXxtZ7O<;O=YcP)dMAQC$ONv(7t_hA z{4|d*G_=GlUE1O1*_3{675>!L2bOQv1N}OmAM(zv%~Jw4uvq>M7!3V|)MXFV8HFqh z_2Wq-s!Mc8zev28$RE3VVUFgKjrw(AA;}mFbc-4NNmS8)VJhe*Z0Yu>B7Y#7gROny z;L4{*mFAr*TjlUsCMKs3Lg!V&Z+@eB|B$(p76olX&?>Xyy|7}DUcs7Iv6jS`0&AQr zhxl2C7$XllZ84JhkLML;4ULq0vy4aOWm~PI1HzNgIAvZx^t{0v?73Lwct_^~=bXM9 zW9=h#r`wfbJ;J5d!e*B)To9kA3{p9ivw~%k2GL^ty>ZzoEqf@&rS)S2siNVr0*?zL z29H5yS;*?)+b%vFsmmEG!%aN3Tkn@-<2%-Bm<~8o{Jmj>^izjw&v_Fg@3bX7L!Ddh zSN3IR-D^exn_F~tiE-<$*|>xJO#?pGEXr&;Sk0ELMFP~K z0W+5e_dQC?EH?GzYkXhndb#@=U3-9{{bIzi7$>PJWp!`?CgUSI^Ip|ZBo}2h^g)Qs ztGD*UCSF8v{Ae6<@vEu+4jt_k4Co|dRyJy6z zcF#9Qt4OoBF{-U`wzqTcQfiBVN!+F7$z~HgIj$Z(&*Ep-j$l_rI3hpzDQ~;ThoruA z7Rt}-SU+!&v8p3+`2)EEgW!F=8RAeTgQ9o|E)ja4C|`m3d=Fjnsahz;eCwBO=3W_2?@Oth(V);}X(h4MCjLGS zzDHk7zWOYn>t5pc0-EWANU;=dr?djWp0bKSyu6W;;GbglASGKRJ>SUiGR1Pd@JA(8 zLqaZ*R1>?@CU2FRw^0TlgzC+QhWUk$Q>VC}QW=Yr(Ww*b&Iu)c;Ba?-nELJL(3UDz zQX6NSjjPum7Zw(6;`1xt?P{BxOja|uJ6nqIJq$n zpmpf|=r%f%n-rpHspdA)j3djoeMgtWR!3N>tNW>9DD6l_p4`3YvggJXGL(jh#8WST z+&8!@`asrznc{*)s)xdNq-r%Iw+d?GdzIn!wtR60-QL}UcaKZWQ{jbiWfHh(M3mLV zn)mh-Qc+dU6*$DSm{{QjFG}-Qa=!5|p!MC_VRG)em%wgkv_K%+9w zy=oZ4U&(FbE01v~P$#KP@s*{scqG|#hFpNr&f*c(H)|u~G&~1}teH}o83$XO+3PFn zSv)+xnTF-QAiQ#7|AE7ce9tkDgUP&`=kEw?7a|6-Kx;)qSU?#3o)2q4$NcxHjkHf-2B0F zaOGh$k<=1_O@l6$Kpla9gIxr07O-x7hdi3dG(h6xKRY50-abbRi|F8wST6^kPz?go z2DRxS6fwLA{3oFx+rjN78?Kt*j}c8gunR#Md>F6VM-vjA`D~Fkwl6ySi%nJdR~|b) zI&u`IDTY))iI_J<_>kY1d}J*D@PulI^_;fsSFM-G70>O&XmkTPmb`VIu8IN6^`JcV z{d4iy7`2hAyAWBPW2CDV3kwNru8 z#(|mrG|TNhID6u>`tD)b?p!`I}7IOMONFR*d?cnoQ;cIgc`yi7r$ z#;n+Gb!J`{@yHPHnQY|bAW;(j+P;ToL!(O|5(A9ck{1GIdSHQA5C%aUu62R}yN`kj zKO(A238GL86M`tK{%ZsAPHj)wzx-6UMx3bJ{*T9b8R%`X+|5n@rIHIZ5t71%qlA8k zu$4zgE9KG{csBo3m-};nyhrrZt89DY{-Bd`dV?T%>OXrPzXgM8#^aA>0&=-YRaMTB z2tm2Fk|~<7g^YJ*Lp{Legcyph%rmzTo|Jz$>aXLaD{M-Zqjuc#L-)*G&oEWEp8ksa zHKBB8bM?CPf;dwV*O%X}Cgfhz>!vV#N^*yt>LhJY+FD`JvGQ9W_w$Dg4-c?@DnVQf z0|IXH+xUT2R1_mSh^UJH7?EgbO=<97hmyOdFiY-K458ZY(?7ZS(p?_rLzk}K<_0bB zOG~Jn&}B8T-S_c-o6mN=pPOQ=Rwe0vWW80w^|xV&%>B73A(v><1eWG$Bjvx%#3}Wk zS~7aiK+Y|W_|LA!|I|)du>j50TO6)KIedK;iw5S`DLLDO@2LfAkdBX|3>(`uJv_Z+ zH2uX>bIG|coU$_<@~kFt+l}gCDKisbjST~yh^$gtYT)m9@Ex*yavZu1^1S`N;x9%$ zQmD}@_|5ALV|1&5=jv;dNj&dN^N054T}==thvoa8Z)rKw6awVH!1stX0NMgXC%}}~ z3H!tR;+RjHe*;ou9a`T zc*(hv?+{hvu6dla4pCD5cV+8qBkB{yd-#)xQvZl=Nc=I7kmgVJP;aNW5%{UNHaKnZ z;M+z5GNQ;L+LYFtw+(}W0aVxk>|&|kS4eNiG6cII5iR8ZezAf7@6K5NWG2Kr5T@~& z8C?*s5iRRZQ~Zoig$Me!ykOULq8f23hz?UzT|TFSKzNgFNe}eL3co((As9B;o&?e( zfB+RHutm=FH6JXB5yN1u%?{T4z`;lkAOY1~#3uvBf{E$JR%SzPY#`&xVtQS4PL6pL zkyUB>jW_l9SbJ=9Fo3M*{r@PM`@dA@K8%ySG8$xA=7;K)wY=GGG{ICmD)p#)XC`vxmd=^}4BEo*HML)X4i(6Cji7ocn3buDT*j$mwLo zt%}RpCz*JY9+D>Bbvp9bz~$c|jsKNR(`Frjl}`-=!|;I)f%i?>ddqtN`{Kz4Q@@>g zpy2^{LIIf4vrf|A2WImfB3yIn(t5z+MI%61uL1}<&E9j&r5~LxopQ?8z1(*i^+75A zmQp;U@u9?FO@T6W;{_D&ihTB7%Ue{QH(GC8B7@>pH&oXJx$6T?VC7ecd4NKpaN7lF zLIT-GaQXsoHnt90DF$*n@k0p*5#X2}>DMoUKl`$|1tkW99yDtb8J$n@=q3~zavXU? zvV8=s+}j{lbXXg4xI+s>hulL6Kz9}92|||(5x80Qck9+ZRyhC*^RKRAzPzfsE*Sr> zJL1LO-KeTZ>~99H(HGw#d+S_3j0e111vG3nQ>~_xF&i>=O z3X7prDFBQ^pGhQK0SDIFueYcUdvfnEs{i_OT)*B?M`QoTZ>rKCGj7PW*#`vS6F}Sx z0aFd6yI%$;XH704AUc%TUttG}%X zFsk%3GhNQ4L+9VA>}R~ASx&R$p55|VvwdQVv5d&}5msMJi=*b2N_BP3OI$Ztp?V3w zxz2b=HyE2XQFJHj`l2d>{+ZuzaiJrKebzgOO)mfMkX(34$SZzuMCW%ATlO*!WKe%~ z1`0lR-lgf7LowZ!a>JwFVHoL7tQzE-zb; zmRW1F5wp>DgMtusSUQes>2%mfKeIT|>jPz5P4NYN`f<5Q5ag1O)Gn!TDD)0#Xa?`I30x^*C|M>-A zi2tKYWoF;RqM*z~F8sMynqOGgqg=j**;GIBuf2(Qds43JP@OVkNAG^pN_4$U+hXx# zVUb?UlZ+mr$~VNG2x5pE6eDO&6pY`DZ2q|V?K|WM_%xwQ7J+)?7EH0as&;QnkF|Tq_*t-xpdi8Bn-ao@yh0 z%Gg6Wu9o!UlOp-Cw(EU?rq%07ZW!eZVt33xd+c>NIs?;NHfswKuV0j$KTUS3h0IIp zU|HGh4+oh^?T@D6-&g#)EdR`STya|S*Q_7+=&eQBUsQ_H@6Z_zqYY@zv(!@5Z}ali zft?RmCnXtt?`^xIt{-@;o1LPg_ zgWdUa@vonp-+!k5Y&o|W(G564-e`j3DGh_1GA3#P2FLG^oh_h8=1CgYxnzE&0vooR z?nlPN2C-ek?~tSr41y47f%tUe{TSDR=KGKvdjbHQoly(&gaE|Zd*%B%(L&EKt^eIP zv4%Ds>?Z4cyBkB0vZidbHKnQ3Uc8ru#GrJ1^_K3lqc;%ta=hu&5jQ+P?X-6+5J<0M zZ&xg7vYeK7J30LUHQ(>xW6C|I_@y%R!IR6GPDy;1L=s*s*pU7)dFY?WH#5{E;%wH` z_`~C5 zivCSjhVz?PUs! zVr>KFoqLP+uxqH*V5^tMoKhv`jhl*N19i10*MU{N`#WZM7Q(1n)WrCg?qJ z-SX=RoV0?^-}as(8^OzF`>AV=1)b&5%;l?-PO2JEUVGti&6hV}D?_LZncQp#2Q+!c zILh4WLrFHxn38LnKH>cPmv&D}?})fh-jCH#tzQoc@qd`XCXS3K5_LSSVflGycK_AJ zXbSmglNGKs#p)tpB81*Qh%4~V$KBmiZ=U$V{pwAi+|KDT`)f}CvntYvkJ-nY$itR;)1=AtYSuklTQ3~oM3>R{#)-+_zLNTQmK zG~m*)uukU8<9KHTQ>xt}lEE)GI4}Rjw>-Q%x7LcP&lZm=^hHtPDSA5_&jBYKd5c7l zHqL#XZRZPzOPyGZo9GwUn>ShSw-u~mQI#198rDj5JT5>F$cY>yphu+ ziHko}_ls%a6i%CHh0`03R`oSX^nM*hjp@E=cs%!n?%L$YRz;Nq&1r6gc&a~tf+a_7 zCz4GS8?w|A!gK%nu+-3&&)6p1TS)VRD6)*qHu>|k?$J$NXO_n`%R-9*t1%JcJ6arm zjM(}62qy&HMkccq^yo}F+s%<6b>%X*qk~T!3$KcB>BMQ+alzkCy9KWDUX{Cdq{NG# zeT0Avx?7XrXT9iM8<~e`?27#OX57_VK=F$No7Q>7_bR*YqqNFPy^+|kQl~ebT+Vvd zoVdWHFERMwMZm*<;M=ygU45SzawqQWW-Hlywt(`fcCKtRE zEy~_C19WGJu%AD%Mb6gPZ$M+6M1dGzMQNX3%TgKbLw2{L1q#I}-eKnPemWqDA~nzj zujc`9ITQc% z?afSdSD9bRruR~Fl=4{^^a!e~%8DK{Q2#s%|DwOs(KqhGM;=cF`mxXFyQKG!(GAjh zxUROkh;Zp=4{8FQ)=&2qjC4vU9ap^nVe%9PwrG`#iD-F@yVWzXy4?NEa&`+fNmrp@ z64!E*f?VbPI&38TTw-gTtMc9svis0NG%&Q_u|bP=wD-)@^jfpSp~3T2jmD|#+aS87 ztK+|9Rr*KP5I<;yq5@izHV$!0Q3C-N4v;~D@KS0SpM)EpS`LJ~-Mp(*rq}&PT=@(* z+Q=4`=7jpT0RX?P46lyWX&Zm-XAeMS@qT-1m-^g)lVGg>Cc)e#LH*tf_Pa94_dmgC z&Tl>JHN>zcpYm|$O+U(~0@#S=)L60u0jBJ{fds&m-I6%YQ|6Usl@6>!$!TgCc_Mdg zqESbAD@<~9BPIMV>dHy4LYchEtgUc{OO}+EqE_Eai_y4DB#W!HaB3E9@x}2O@gBYH z17Ux}iLSRMo0|JHM>Xt4&|p=lx0D!UdtmoA8OT2F+S=D_?gB<)rQZgUQB$ueUh8$* zfv)K-iv@4q7bLhOQ$a;j?g$ZErp5G!ym#Mjnp`A{*F6gH@-kMc>_B{*1}nQ6m}#)R zGJZ&6pffP0tXdQ0E^$yZ4&A|8<9Ek^(V@Q?e>XNm2(XEx5QKf8bH?eCUs3g(Rx}1Q z$W`AVhu?r+$)4*N4H&~}fH^4ySYno*kPMGl><%#kPBA!?hzC}VE`cd@^ZphPXXjH9 zxD|+(l(FpYmZJ^`8@6>5W~M7WyY>EY=V$l&`;zwbT`V15PyPn5#O9X( zO{p0@_p4~dK+^aFQ>W#7E#YNC7hHpHCrIElN}tFhl#)@ zjpR-ib+15au=DEIGqq9Cl&Pc44vSCOcoz;{*kQ9Mb&8!U>Q(t>DAwG2M+MFtoXR-g z{L7rB39$+2*~J}yZ(u{6llkwN{XeuS!J_`LDodwl&1SO`C!AJweUfAELxLqvtj7OX z`#{0{l3>aT5;fd3Uzdrj==*qu^dSo^d-=)mF3b8_T8~eEHF`7NgW_Xlpu4m{XCA3} z-~8W5EouX-N`H%h2D*6UM#wARSN|)U2e1HN_0|(*OY_oG)hqnzq#*e^v~?d-bBK;_ z>6;E_;({8EI9OhvxFGSh)F#T#+DBWxT--_$L%N$AZGDfKNvB{279x)EuATZ0d41;H zn}#rDo>UcuXWWmjGcZ|reX-6?mp5+7WP{oX1Zkj8D02s~j{|-#W~}(*8I9w&<512+ z3L{C+*fU-pDHyGHGAIxT6s))Ulrcxjc-bqYC}vc)E;!QwpZXpL-Cf3UAwP-F;KFv7 z+ECE~%reHh4bS(e0`@_Jk?;R%<&O2S<$EXuYjEt=8ey$$3PZPq3Qx!(Pl& zBk@65vy#44{*l6$FVfbYL$5Zm;<$8hZVPa(7BiTCg>&)-+x39Hvnw;-Ar0+IsQR>3 zMYcr_{&!8R6`1mf)#nPw+nvU`9i9&P_})oupVYBZT=AC;%p{L4UY|(U&`hnFor|6Q z@=b9MP2LK~qJyr7bp)w1w)>hHbS~+P3ya#nZmN6|TWb5}L21+*_jl|UHY|4IF>H%9 z5e25s6F$aNcXkRDFT3W~C7bu9YtJiN>`7Lh=I6QCmMGpSZq=o#F=W?X)jaiWu{;6& zO!1~OJU}ZQUssm=Tx4_9*(cz^)V!zL?SbVkAv*09cDifJ@0FN$;W)!AT-bcO4^zsV zcXFE6ih7tcw9>J4i`inVdRjnQc&+aK zdYa*jw5NR^KJ7`+4Z_P}_C17>`JPa*k9pHh6)dV1lvx0(KI0NtU?3saH@5?!7@#z; zdgXLph4D!RI+8o(EMHXvw-`)>0Mu+q)LDbysL#IIx8MMlv+Em z4lVV9G7N~6SHntOF;VD#@=k+P=bGv6vdq)H>PV@Ze z%5%TV#BX||`C+^EX>!shUS@payfpnX{Pxqf&MEx@mUoPsQa4|j{t%d3|4BQO} z`HkQIaezn)wkv9~Mfn7lHkNZ{78$Yqe9K@u{KIXg3yMS&SD!CakCq-y8ZQo5_}yV*-sA%(6Ch?Kk z8tj*n({ItSzx^i7#B$*S!RhtkG7zoRMZ6e?aPdT?((jPXvq1dLO|GN(JFmLX?-*#@ zelJdgOhrFJ^9q}nWxYY7g_`*T_MH+_Jw&(b2C)&|ye+pzYV?=IE7ad~0e`&;r;hn% zh+TRA2$lO`|0L>z`Qvj9_4TPDTML){j%nEIWwf0ORl4vvtCF3hhrimd9Z{vzaw13_ zU_?tpBu59cSD%TmW>%&~;9oOeJd{g{f4l0s6^-GF05E51hLmPHMc2gXcPe$5bCC{X zOv9KP0g*}YO4d&k^|hP+YMIQlof1l~>d zSv8toow-@2y}@I2I04<+=lbgMTa5DM%V8St*b|*dV0{f9*pfx-w!jZn^Q^eUA??Og-?Abx z>32F`s&q@bqlnW2)&cua9o$|?kT>?>`~%@2L#{SjTDGFHJLmkOVXSy}x!C2`bEEt< zLnr7|8%Ltxy7?k9)Ax|XVt4f=;W@}X0@p+nIx815=|5T9Oh{dg_Cwl4o7|}mJgs5S zP!s3QcWo+SHfX2&Vis-jT28}W2N#nvD~|tWj2hNAN@|OH*QvdTdS-*3<--D0@#xU$ ziwqzJ-h9IedFOTfHN2q$`D;uTs!+PumKan z1c8u*cqiz_*GaHL`5>?n5X1LpaksyQ&>Q{A<|7pHi4;JBWy0;h6T5>S7iHMjl% z790ph?79LUtqMQTnZ*$gx&E^Oh9B635d&zYx7fi6C}BSaFYt3)Ki~}^(b%7{AXJ~ zkQxNWE5CF&{+G6XfJD}cf9~+lZ2_3czhC}e&U|+6tH5;KIQ41BkX?+QO4sl*m%HlO z(Vb)a*7`}#hb^~aH8?Qu?72L;%QVeRgtN?H-l&+Q&l+;P8OwcTFmDe{+6s9aO~s zTu6Ur$tGnai|1w4!SA{q?ttY?4{}=nR8sx-75^TOUq;~n)cUY2ughma`DmS+Uz7VBrwd{Mx%` z@QcfiAdts1?&bR-O|Zd_6ujX+bDh(=DgFxRv4$^|)NfmXIR4_^U~u7|aNke-v2-1V zD|_iOcLry^q(pj2Ey-XUuTWz8AxEYY_B=+zF6xRsobLm~v%@EZ@^#~wB1hIIRN|BR z>M`MkH%1DP$rtr3=x4&o)81i+qPoI@PNBtES*V9G#H8TjeUh5gkT%kxN?-W2c*Yd) z*rzq)c{w>pcNV!o3K0i4-<6LFins}_w_jpEWKkFY%^4&2g%MbLj%*NtC1$OoJpAqN z%Apkd3QN}U$^tIdj6ouR6`3i|d9hK)d`wJHr5G3fdCD!VPpdNF?5XML=FfBfdG4gj zh6ePHCMTq^tJQ$7adt8D@LXCZ@kMqP8E~F)9clx6Rf{!ZQ8pg|;tpEl2?dC?1!Obk z`4|)zeMtA}PQ%T`GEKFVcC(NYN6$Q!kN&k4+VO5&Q+>kqFUg(0_CDT+o+pBleRxH;Dr&X1YP>21+m075>@JXqouTxL6@JJB0fwn>JSuB#$$#n z^QS{N`mpMYJ9`gGzZh#ZOHNsT+KcB(du;V-QrvR7vH*KF@l3h=Q+{@I=z08Q9Nz*o zik7LUXj-EHHjyQrQJ>d+XGg)2gF=UsB^2@Sb-`$pf0z#H1d(6sP_b{RPtUje!Tb;ZjUt{v{I&yy25GaqKs zY-b+T2=Eq)kxn)*d0kI7X)Gc2tqzGPN|<)pWnm!s^mIQD=MePJs4^nQ1`(ts+xhqiN#rx{D8}6m%o=tElq^*yiG5{nA|YhYIB$C< zbwYKQFvR;z#Rr>a@EjL?(XIv)9%ibhaNYXu-GK{!u(lkcmaenWsYNh%TB}HndsV=BjWYInbZzgsWceAUx@^(ZPuJ3yF`%T`=o19wX zwyl}9I=%GYcmf#D#G9=spLMoofZiSuZQWapk497nDV4a?$n(m}MonnWZ%#>{zACN> zzgt?#g62QR&kLAtRTk^xBN3HKFEW_l2Pr|LiCika-X4x6YkjLOW?szt4IQGJP1{9m za-8;8(;E%aim-=Wb2PYEOmiFSWSBP$ZZ+<=)F#AZUSq{CTP&k_x~&}_JgE!LjnOKu zsimuL-Nz-X@W5-`^#Ka{mHXj`*bgn({o*G>mmo|EvuuAb+CoQ?S zx5C_h<$}A1p@{NXzvrD?Q_fh=PP2%x1ZB>)QWIW!0D-5zsh_Non`WvT>gW)A)~(X! z;{a47BznD$CZaqt#eA$xnuOFX((+Q$@%h8PMsxBRJw&!sK*@AZvGYVqtdsAh$&4oQN-ls5*+y@l97&r)nhyH`G>(WvP4R)tT4gTSJ0@T(_J^Z%4P)Vric9 z_jrAW+)53>8$;^_LkdA!F*j}WTC zDL1rJOCaiCv#14yWDjA$GL^aEc8JehQvdgZ|NlMI($$TpRqTS{T`!AumZ>2wUdw=z zsR=Hi-F$Zyy}qb4>OZFnjeb>J%Y4)C9&4AjaonIza$x>ZS$-_;*V##c$H|2AwKcf~xEQgG{IW&9Q#5TK-AWf;{KX%K4Qb z5(AtI1YmI7y54NAev1>me2^v)ti{K8nVEllBx&7QAnRz)j+FgD+I0bvyTMwgmGcv$ zAr_f8)pUwp=7j!VbkX2@w5iwrvRgBmo3Pfb)diE2A-S1)9q?%d4L64PK8f>CeIXuT zYkCa-NC*T*?kv{#mB65O4Z4wrIBVKpm<;gP{aOELAdyr+8Vbj&7vSNz`{+R2tQXu) z6VuP?6|U9$4IITzghD~b6`_x+NpW|Tgl0DSq~i&v@x;bkVK&Hq)=jawn&aaTBebb3X$&{eQ9yUp0 zb{~Xm=@Yem(I9_cOnjS3C!rZqUC;O&n zh%^mycz9z>YKvLBW>hN1sdTdxeGRxJRM_=YSttslvyK{)LTH|BsS{Q9pgWy91hUC) z@~-(BB4YW8-_`GsnSSuJA{S**LY+74^md6@1Si$#?FO}bZXdB^DdMR8`)+Br*RE(( zD%6BYJ_2Z{Ln=hiE1WU0Y3B<;(Q0yHXF2mo2(wsA{DUTT9Bg-~Xdrj`VqK$9<(90k zL}N#LHsYa`vqjfy~EwR2TJY3m16pFxl~Q) z*NDZU1`?1w6Ttv7K*oK<3w^pSlx>g;w*ki;j=Yk}$Ry{@g)#}PiDECV9inH}f5*voKMuCdyy)0ID}=5Mzu8`= zn!fVHp+?a+frS`kzv-GNK>UiepdQ+sU4X;TK1i%WhYPB40FTjha};A5_CKk9Qn>l+ za1y8gLV)qGuFBEU^KNifRR%j3ZUIBRHOKr}EzLXFZv;rTe`T^R=hY_<2^Ih{3lO2e4@GUVQ9x{IviyTnmgYC=`NHk# z)YbzfUY&`*CA3;Yh--G7#OmPr#1>1N-epd$uDWf`7I(Zm1PNcooO~Q9W9y?XA`1$$ zC?Uyq!MhjJwv16V_!?WXt5mw{^rF5&*}RvHxsQ`^3SEe88fh!06r}W7 ztfJ524i1x?+E4$m4GQ3z1$?Pd`QA-g5kk@|XG6;7O=Fe`9r|gv8XvqN%eh++r$$_8AFf=0i6kX@k=9 zlsC}fJf`DKXh->o38o6%l7n*5nRu-2^_17% zKHhLQIh4bZw30Q=lnzcxj)HW!OHccAe=2c>s6nAn7ls-u`d32FUuQi5i`Zt>i|mBu z&PoC$xNZlMlFE#d%2}b$(t0By{@$4W>EWH+vwPEqo`9G~>f~fs7NuK6eoLYXGQZQ% zrY`;@dWD!{LdVdm{vMW&Y%=dfiO6&7k5Wv&R53l`K(9lWjdpI~Ni_kKH7(d9yHu2p~?V4DP(cSFU+8360 z5G(qoPME=LZYZ{i$g)FdR&{cIfih(IyXKPk&NHT4h@&G7koao&U1>3NUsx~nLK`t= zT$%_ie8!AQJ1`dMHsOepMY@MP;hk)wj3mrw_EP6C3q?}n-HV7FOz_t9!7cL#JQ~V- zAsVnxHKpvDUkzs<>~TxP@B1%4^>$ztetk1OGYLpUZ%PojoT+%8GR>%>Rc+oVJFTK@ zeMB-DZu30FY!t<=f_kv}hKHM3Mf2uDDyvQ0vY}H+|@nzw5 z3hsGHN^!A?#C3Q0wK2U{a}S_0h9q zjnFY7ZjEPu&QJd;dDwE{vEt5M6^eLXWK)ZMcG7rIzPh6#j?cLJq)vVO$%IR<6Qj}s zd2yNI(;`;k6Q?sNTPYqCKXMx`vQr5yHQt`5sUIo$;9L@la7shH@?Ex2Rqg}MD}$Kgh)WF;jMN~X$#UQO=S66H*wwGQMO7FCn`5Sp1EH1AN*SddQ%47n%Lb&cl!!G-3`;p&> zEd{hD>&No=;|@MUtrC%8>Gwtg z4F8OfyXxx(hobKKk^;3OFD6?6Bm`B0ee#W-@m;8B|FSduvwBqB=?y#j1`2a+^%*>X z)|8a)qFdIjvS|D3C6UdP(QslWWh6;p5ef>HPgMEDyUSZ1pKe-P+GR)IUcVpo+zT<$ zq{`hhs4~WTI468}+CY}#>LNqCJZ*>!Df9)&?@}Q2#{fZM1q(n{Jq57ErhuCHpWl%A z4iBVXkBW`#4RvE(d}8V=d*p%nK${w;@0ZKOnX&5s#nKzG)<%SSw_kiTh3a2iS{!oT zUK)z7+PX~}p7z;Rl{2;ALv_wl!}R+AM${%aXIuk+u#G~xPR=t+O-dN(uqktPKSRc5 zVVYxa2M}>({vxG{NpJXCURd~3v-%Ej?EqAb+N|?uys$&(Nm(PH)&$TwriU>dSHY)u zAg_OVhrdR@|B`E6?gDY}A_!W$$!3SlHSQ1ohJ5CE(%0Fn}++ta2Wl2V~?( z(SER=+Ktylu{#W$7*FUj0_bY?cvJdIC(x0@0a@zJh0S_~uM7|-m{4ax7Vxu}IvNP~ zduPxPlSoh>=G`cCJq#nY0OasU0F;V^G!mFx+R2;%LFo$DtP_CN7F&-R`7i#hn;!!6 z1m4vz{)k|g4dUe~u7qdHgtt;EfQo>?Aud1`$DA=I88CntUVQ5-Ly+DI!V)`6h6I1< z|0Og0YVuFbs!|`i1Zu+-8&)!vr6c-#YmI)MbC>=ziDvF<6aDPzFFkqgH?T0SS@xAc z?lv5@2h?F{LACPQXKt}*wEQ=aUpZ>zXq)K-6@@ti1Kf~D+TeO112o(PJ_aDR(M^B-Ub6Zp&&iPUF``D}hMV}PwKe63^=*RNBK<=T#+t`3Ub&`PYPh!8Zv9mw$ES{<> z>j)nP@U^_IS17J7?5LDs`k@Rki}DL-4panF=-2YgD2VFq`X-%b3MZ3mUslaM4UA)u z0??#f(_5MFw$z4ipdcU2pe{S0cPm|JBe3qQmDWvu6gC7I47gQ1`~J%cRMU!GL)=FPowCtVLpEgHEd1$gtOH-DD>`<0W!MhOX;IN< z44%61lwKQYD~FJ#<0!4k&bs93f@rj6sb|pM!`qccuVy|Q7&eEet!d<^zIsAc$Fl(x ze%U?V!7l1efzg~u-AD;Ocqz*kgSy(M=xO6l#$0=85AkWSi!=Dan0}TxqjTw;Hl6cS ze?iaTUb${*LJa@3;b*iG%FT;7w8l=fX1sKl+^;P6DJhG12);8Q8wH?f(`t6*WPAOS zPRij9Wc~p4gapv9&A{$iAfa29epai}$nnwsNetB)Jz2^Wc5#dVHIKQ~N}t5!raV9E zbZ8m=8q?0mzQ|E1%3~h}hep(hLzwV9n|pNo3pd0lfv)IJTT-X;iAK$+e7{~o~)hFnyejT zI4K!Qu|4xbB3vXuxb?2eIeUpk*U?jyw!VTazWuoG*U!{$<)5ZaY-*^a#i3SNL0MPb zq?tU|k6xhWOw+&-=!XS^Px3c3;)bm3`^eYVS0Bf}W#;5`x#cYHJG`I%;Jn2Dvj33S zWCyhr*%s}ydENvJk70=Qgx#I8>==UR_lAvH4c2<}WYi)TV77(%160yi04-zQ@iszV zuJa5jCRC8phgz!0`6CRQBj(Yh7V8VJCT)_IQ&9WqWG?#2d6uv2V)-%gg9eX1RN3KmQS;Ige!cLzRmG8Yp$ziB%~D()=oSNCL59xgohzh2!m?l#9L zsx@%E%(#RF;%*fqYj-TsKJ@CC`_^dd`m41V%~^C|-FZ@rF%X7L74)RBrv$q0g_*ES zepOL@_+T_-JYh&|vkXDDpnUCdf>M=Iagd|h+Tx_cA~XVAXB9!!4!}VUv%*vtlSZWa zZQ#aG{g^ul%bMDI5koakLK()^u_r-J;5@wNnJ=6p*Vp!9TCO8qmi7?M_&u?tD2}u4 zOxnqsbUPOPnzg$VKF^$#4nkS+B-4@T`+kta(By=)yMX8U@}Dt`DgN4dO)7%+-Ts1U zT?O>Wh;0G9Pj4R6*CFY+lC?)F094mf<2U5guaCM(n{ASq8B{8KI1FZf09*QA2#^|U zmVzF^W~7W;TL2iGwL?RBmG_!qVK>^XYTYvlD_TZd7_x1=BX^pr$9NIzM!Q{= zcO#c2_uIc19mk;6e90FbuAn~39_22b1DaCWm+fcP(&;?1EO%$>%p|LgtwO)Lz)49q z4Un<@n9-{G=7TR8zfm7F@IHM{%6<1(|Ln(Vmm!$j>Jmm*JrubSPsR?8DI=RKTd4`I zmLKpFwoMsVh*{JVW%+90E6TepOwC^d646c2Mc@FCu23t_Fig-UAl4cMq%%H#=NbRk zZ-E7uMjZjQrHYUgObkH1xWLDFU>N@9lSA}$dxz4p-ZSMESIc*IX2!i~7ygs(uY!gA zjTP>~e$D_;e#vz>=HmqI=z2OtkL9HzT2Ps%;Uvs4ND5!BVZ9b)bKW$F@dvEYHi@=A zb4&Tnj~Rzfr8%HaWdR)YB>FnET4>?qE0DD;M`>VV<}83R`4#8_1S914``$KLKlXU{ zV-GIO`!VSH1nJokY)OXnm+uAqBmTenM{l5(Hn1<-_~&O}0O);774WI_r1tL)zGxxIf=&PD9*2bh<3l`@WM>`on}V z{W|qnK$GZSCP3Gx~991qDK z9y#O)+J`A;knZ^w^{%(b^f*}2XJ&W;aiG27*m zh(m|Jsf+@gk)K!m?}w!w{<1}By_k!W;SMDwVzn&8N-EoryVDLrJ|q;|k>?cjz84Vq zDl_Y*`E_)$KSW5M06-r=)iHGmN`dm}X(G;wl;H6rDag0Ia#C0C$S^XH+OsNQu5HKK z(?&V@b9_+qT-^;FVV3TJh@|$E{-ZT~lJ;Zz%0}xUZOyBPjihrE6 z#z*Vpu4j;!yk+)JBH{IP6F6=9mHO&o+I(#;c_j3{xDKcd6&q_BxPt2Lyp7R2FxCcyY5R-ua#fSPw zzSY0^z5vIsh?+-#cxBjY%D7}S8O^ueyl)S)v5n>(v(c^Wi4=UlhaCd)PH^PO&v_Z! zA3H^URVebvpOs24w>j1@8Ze>BoXbr$_8@H|#d$p0 zCcVQ`V6(-%U*5eCktSTHe4y4~-$VL%?AlY(Qg6~O*yrIzt1cMX&~gN?FexGG&1� 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 D78%AW literal 0 HcmV?d00001 diff --git a/packages/manager/public/assets/marketplace/cloudcasa-light.svg b/packages/manager/public/assets/marketplace/cloudcasa-light.svg new file mode 100644 index 00000000000..4065e292dd7 --- /dev/null +++ b/packages/manager/public/assets/marketplace/cloudcasa-light.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/manager/public/assets/marketplace/cloudcasa-process-flow.jpg b/packages/manager/public/assets/marketplace/cloudcasa-process-flow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59e6d262b5daed13a3ab3ffa27e0704f987aebae GIT binary patch literal 117548 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�ozDbc}S>;z7uyaTI1Qcv8epF(3MIgvchv8B$ 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 Sh-LrFHvVsa{)266{C@yu+7d1R literal 0 HcmV?d00001 diff --git a/packages/manager/public/assets/marketplace/portainer-dark.svg b/packages/manager/public/assets/marketplace/portainer-dark.svg new file mode 100644 index 00000000000..8d077c6ec95 --- /dev/null +++ b/packages/manager/public/assets/marketplace/portainer-dark.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/manager/public/assets/marketplace/portainer-light.svg b/packages/manager/public/assets/marketplace/portainer-light.svg new file mode 100644 index 00000000000..1a970b42d0c --- /dev/null +++ b/packages/manager/public/assets/marketplace/portainer-light.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/cloudcasa.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/cloudcasa.ts new file mode 100644 index 00000000000..1ae9f47a4f7 --- /dev/null +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/cloudcasa.ts @@ -0,0 +1,91 @@ +/** + * Product tab details for slug cloudcasa. + * + * Content is provided as Markdown strings which are rendered at runtime. + */ + +import type { ProductTabDetails } from '.'; + +const overviewMarkdown = ` +CloudCasa delivers Kubernetes-native backup, disaster recovery, and migration for containerized applications running on Akamai Cloud's managed Kubernetes services, including LKE (Linode Kubernetes Engine). It solves the critical challenge of protecting stateful cloud-native workloads by ensuring application data, configurations, and persistent volumes are recoverable in the event of accidental deletion, ransomware, infrastructure failure, or regional outages. Designed specifically for modern Kubernetes environments, CloudCasa eliminates the complexity of manual backup scripts and infrastructure-dependent recovery processes. This enables organizations to confidently run production workloads on Akamai Cloud with enterprise-grade data protection. + +The platform operates using Kubernetes-native APIs and integrates directly with Akamai LKE clusters without requiring additional infrastructure management. CloudCasa captures full application context - including namespaces, deployments, services, and persistent volume data - and stores backups securely in object storage such as Akamai Object Storage or S3-compatible targets. It supports automated scheduling, application-consistent backups through pre- and post-backup hooks, cross-cluster restores, and cluster migration capabilities. With a SaaS-based control plane, customers can centrally manage protection policies, monitor backup health, and perform granular restores through a simplified web interface. + +CloudCasa's key differentiator is its Kubernetes-first, infrastructure-agnostic design, allowing seamless protection across hybrid and multi-cloud environments - not just Akamai. It is ideal for DevOps teams, MSPs, and enterprises seeking simple, agentless backup with built-in ransomware resilience and rapid recovery objectives. It also offers the most cost-effective solution on the market, costing less than half compared to alternatives, while refusing to compromise on features and functionality. In fact, CloudCasa offers the most comprehensive Kubernetes-native solution for both containers and containerized VMs, all in a very lightweight offering that is easy to deploy and simple to use. + +### Key features + +- **Most cost-effective Kubernetes backup for Akamai LKE:** Enterprise-grade protection at a fraction of the cost from competitors. +- **Comprehensive Kubernetes data protection with RBAC and ACLs:** Protects cluster state, namespaces, persistent volumes, and application data with immutable backups. Offering granular file-level recovery with built in RBAC and ACL controls. +- **Migration and recovery into Akamai LKE:** Move or recover Kubernetes workloads from other platforms directly into Akamai. +- **Protect Akamai LKE workloads with automated, policy-driven backups:** Schedule and manage Kubernetes-native backups for applications and persistent volumes running on Akamai Cloud, ensuring consistent and reliable data protection. +- **Accelerate disaster recovery across regions and clusters:** Rapidly restore entire applications or individual resources to the same or different Akamai LKE clusters to minimize downtime and meet RTO objectives. +- **Strengthen ransomware resilience with immutable backup storage:** Store backups in secure, S3-compatible object storage (including Akamai Object Storage) to protect against data corruption or malicious deletion. +- **Granular recovery options:** Recover entire clusters, individual namespaces, specific resources, even single files from PVC's. +- **Ensure application consistency with built-in app hooks:** Execute pre- and post-backup hooks to capture application-aware, transactionally consistent backups for stateful workloads. +- **Reduce infrastructure overhead with agentless, Kubernetes-native integration:** Deploy quickly to Akamai LKE using Helm and leverage native APIs without managing additional backup infrastructure. + +### Use cases + +**Granular Kubernetes backup & restore** + +Recover exactly what you need - whether it's a single namespace, deployment, or persistent volume - without restoring the entire cluster, reducing downtime and operational disruption. + +**Self-service backup & recovery** + +Empower DevOps and application teams to initiate backups and perform restores directly through a simple UI, eliminating ticket bottlenecks and accelerating recovery time. + +**Compliance & data retention** + +Enforce policy-based retention schedules and maintain auditable backup records to meet regulatory and internal governance requirements. + +**Ransomware protection (immutable backups)** + +Safeguard critical workloads with immutable, object-storage-based backups that prevent alteration or deletion, ensuring clean recovery points after an attack. + +**Kubernetes migration to Akamai LKE** + +Seamlessly move applications and persistent data from other Kubernetes environments into Akamai LKE without re-architecting workloads or rebuilding clusters. + +**Disaster recovery into LKE (active/standby)** + +Replicate and restore applications into a secondary Akamai LKE cluster to support active/standby configurations and maintain business continuity during regional outages. + +Protect your Kubernetes workloads on Akamai LKE in minutes with CloudCasa's backup and disaster recovery platform. Request a personalized demo to see how CloudCasa streamlines backup, migration, and ransomware protection, and ask for a free trial of our offering. Our onboarding resources, guided setup, and expert support team ensure you can deploy quickly and confidently secure your Kubernetes workloads. + +`.trim(); + +const documentationMarkdown = ` +| Specification | Details | +| :---- | :---- | +| **Deployment Model** | Self-hosted, helm-based installation | +| **Supported Data Sources** | Kubernetes Version 1.23 or later and KubeVirt workloads | +| **API Type** | RESTful API | +| **CLI Tools** | Helm 3 (if using Helm installation method) kubectl access to the cluster | +| **Security** | TLS 1.3, AES-256 encryption at rest | + + +![Reference Architecture](/assets/marketplace/cloudcasa-diagram.jpeg) + +**Process Flow** + +![Process FLow](/assets/marketplace/cloudcasa-process-flow.jpg) +`.trim(); + +const pricingMarkdown = ` +Pricing details will be discussed directly with the third-party provider Sales team after your request is received, and the third-party provider contacts you. Costs of the product you will be purchasing from the third-party provider will be charged by the third-party provider. For the referral motion, Akamai is not a party in the purchase contract. + +The full price of the product cost should be clarified between you and the third-party provider within the agreed upon terms and conditions of the purchase contract. +`.trim(); + +const supportMarkdown = ` +For product support, reach out to the vendor directly. You can find contact information in the product documentation and on the vendor's website. + +`.trim(); + +export const cloudcasa: ProductTabDetails = { + overview: overviewMarkdown, + documentation: documentationMarkdown, + pricing: pricingMarkdown, + support: supportMarkdown, +}; diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts index cea07aca002..c1139db97b3 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts @@ -1,15 +1,20 @@ import { apiMetrics } from './api-metrics'; import { cambriaStream } from './cambria-stream'; +import { cloudcasa } from './cloudcasa'; import { dynamicAdInsertion } from './dynamic-ad-insertion'; import { heroEncoder } from './hero-encoder'; +import { liveEncoder } from './live-encoder'; import { multiplayerGameServerHostingOrchestration } from './multiplayer-game-server-hosting-orchestration'; import { myota } from './myota'; +import { playback } from './playback'; +import { portainer } from './portainer'; import { radSecurityPlatform } from './rad-security-platform'; import { scaleflexSmartMediaCloudAndDam } from './scaleflex-smart-media-cloud-and-dam'; import { sftpgo } from './sftpgo'; import { synadiaPlatform } from './synadia-platform'; import { titan } from './titan'; import { vindralLive } from './vindral-live'; +import { vodEncoder } from './vod-encoder'; /** * Tab content structure for product details page. @@ -29,17 +34,22 @@ export interface ProductTabDetails { const detailsMap: Record = { 'api-metrics': apiMetrics, 'cambria-stream': cambriaStream, + cloudcasa, 'dynamic-ad-insertion': dynamicAdInsertion, 'hero-encoder': heroEncoder, + 'live-encoder': liveEncoder, 'multiplayer-game-server-hosting-orchestration': multiplayerGameServerHostingOrchestration, myota, + playback, + portainer, 'rad-security-platform': radSecurityPlatform, 'scaleflex-smart-media-cloud-and-dam': scaleflexSmartMediaCloudAndDam, sftpgo, 'synadia-platform': synadiaPlatform, titan, 'vindral-live': vindralLive, + 'vod-encoder': vodEncoder, // Add more products here as you add their details files }; diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/live-encoder.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/live-encoder.ts new file mode 100644 index 00000000000..6ab83d0c5b1 --- /dev/null +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/live-encoder.ts @@ -0,0 +1,78 @@ +/** + * Product tab details for slug live-encoder. + * + * Content is provided as Markdown strings which are rendered at runtime. + */ + +import type { ProductTabDetails } from '.'; + +const overviewMarkdown = ` +Bitmovin's Live Encoder is a SaaS product on Akamai Connected Cloud, enabling reliable, high-quality streaming with fast startup times for social platforms, sports, news, entertainment, and large-scale events. + +It features an intuitive UI and robust API for quick configuration, management, and scaling. Supporting up to 4K resolution, it accepts RTMP(S), SRT, and Zixi inputs, and streams in codecs like h.264/AVC, h.265/HEVC, and VP9. Outputs include HLS and DASH, with features such as SCTE-35 monetization, input redundancy, Live to VOD, DRM protection, graphic overlays, and integration with other Bitmovin products (VOD Encoder, Player, and Analytics). + +### Key features + +- **Resilient and reliable:** Bitmovin's Live Encoder was built on the same backbone as our VOD Encoder, ensuring stream uptime is constant and reliable for global playback distribution. +- **Multi-protocol and codec support:** Ingest your live broadcasts seamlessly with support for RTMP, RTMPS, SRT, or Zixi single and redundant inputs, encoding h.264/AVC, h.265/HEVC, or royalty-free VP9 and package in HLS or DASH for distribution to end-user devices, helping you ensure your content can always be made available and viewable to your users on any device. +- **Live2VOD:** Stream and record your live content to give your users the ability to view it after the live event has ended or clip parts of it while it is still running to promote your ongoing stream. +- **Customizable with a robust API library:** Gain access to our extensive API library that enables you and your team to build out and customize the Bitmovin Live Encoder to fit your live streaming workflow needs. +- **Content security:** Keep your content protected with multi-DRM integrations that enable you to cost-effectively and securely deliver your media over the internet. +- **Simple and scalable:** Manage your live encoding process through our simple and Intuitive UI or API to get streaming quickly with the Bitmovin Live Encoder and scale the number of your live streams to meet your usage needs easily without worrying about peaks. + + +### Use cases + +**SaaS scale for 1000s of encodings per day** + +Deploy and manage large-scale live streaming operations effortlessly with Bitmovin's fully managed SaaS platform on the Akamai Connected Cloud. The Live Encoder automates infrastructure tasks - including compute allocation, storage, and networking - so teams can start or stop live events instantly without system configuration. Dynamic scaling ensures reliable performance during peak traffic, while consumption - based billing supports rapid recovery for 24/7 channels through on-demand redundancy and backup servers. + +**How Live Encoder can help generate revenue** + +Enable multiple monetization models - including SVOD, AVOD, and hybrid approaches - with Bitmovin's Live Encoder on the Akamai Connected Cloud. Support for SCTE‑35 ad markers, server ‑ and client‑side ad insertion (SSAI/CSAI), and DRM ensures secure, targeted ad delivery while protecting premium content. Integration with Akamai's global CDN and Bitmovin Analytics provides reliable distribution and actionable insights into viewer engagement and ad performance, allowing platforms to refine monetization strategies and maximize revenue. + +**Reduce operating costs with Live Encoder** + +Lower total cost of ownership with Bitmovin's Live Encoder on the Akamai Connected Cloud by optimizing encoding ladders to minimize egress and data transfer costs while maintaining broadcast-level quality. Unlike open-source implementations that demand heavy customization as scale increases, Bitmovin provides a secure, managed solution optimized for efficiency and performance. Its pay‑as‑you‑go model supports both continuous and event-based streaming, enabling flexible cost control without compromising reliability or viewer experience. + +Ready to deliver stunning live events with our encoder? Contact our team to schedule a personalized demo and discuss your specific video streaming requirements. + +`.trim(); + +const documentationMarkdown = ` +| Specification | Details | +| :---- | :---- | +| **Input resolutions** | SD (480i, 576i), HD (720p, 1080i, 1080p), 4K (2160p), Portrait (mobile) | +| **Input video codecs** | MPEG-2, MPEG-4, AVC/H.264, HEVC/H.265 | +| **Input audio codecs** | AAC, AC3, PCM | +| **Input transport protocols** | RTMP, Zixi Receiver, SRT Caller, SRT Listener | +| **Output file formats** | MPEG-2 TS, MP4, fMP4, MOV, WebM, CMAF, and more | +| **Output video codecs** | AVC/H.264, HEVC/H.265, VP9 | +| **Output audio codecs** | AAC-LC, HE-AACv1, HE-AACv2, AC3, Vorbis, Opus | +| **DRM** | Widevine, PlayReady, Marlin, FairPlay | +| **SCTE-35** | Inband MPEG-TS, API based cue insertion | +| **Subtitles & Closed captions** | WebVTT & OCR into WebVTT, CEA-608/708, Burnt-in Subtitles, and more | +| **Output streaming protocols** | MPEG-DASH, Apple HLS, DASH-IF Live Media Ingest, Progressive MP4 | + +### Live Encoder Streaming Workflow + +![Live Encoder Streaming Workflow](/assets/marketplace/bitmovin-live-encoder.jpeg) +`.trim(); + +const pricingMarkdown = ` +Pricing details will be discussed directly with the third-party provider Sales team after your request is received, and the third-party provider contacts you. Costs of the product you will be purchasing from the third-party provider will be charged by the third-party provider. For the referral motion, Akamai is not a party in the purchase contract. + +The full price of the product cost should be clarified between you and the third-party provider within the agreed upon terms and conditions of the purchase contract. +`.trim(); + +const supportMarkdown = ` +For product support, reach out to the vendor directly. You can find contact information in the product documentation and on the vendor's website. + +`.trim(); + +export const liveEncoder: ProductTabDetails = { + overview: overviewMarkdown, + documentation: documentationMarkdown, + pricing: pricingMarkdown, + support: supportMarkdown, +}; diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/playback.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/playback.ts new file mode 100644 index 00000000000..1be594b4204 --- /dev/null +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/playback.ts @@ -0,0 +1,79 @@ +/** + * Product tab details for slug playback. + * + * Content is provided as Markdown strings which are rendered at runtime. + */ + +import type { ProductTabDetails } from '.'; + +const overviewMarkdown = ` +Bitmovin's Playback solution, Player and Analytics, are fully managed SaaS tools designed to enhance streaming platforms by delivering high-quality content and superior viewer experiences across every device. + +The Player provides a robust features set, such as adaptive bitrate streaming, offline playback, ad integrations, and CMCD support, with dedicated SDKs for the broadest range of devices, including web, mobile, smart TVs, and game consoles to maximize viewer reach. Bitmovin's Analytics provides real-time monitoring and actionable insights on audience, playback errors and quality of experience (QoE) metrics, allowing platforms to access over 200 parameters to quickly identify and resolve issues, optimize streams, and boost viewer retention and engagement. + +### Key features + +- **Reach more viewers faster:** Easy to deploy on Smart TVs, Mobile & Connected TV devices. +- **Monetize your content:** Built-in monetization support for SSAI, CSAI, and SGAI-enabled workflows. +- **Modular architecture:** Reduce your bounce rate by loading only the parts that you need for faster load times and lower distribution costs. +- **Configurable ABR:** Deliver stunning quality in all environments. +- **Real-time actionable insights:** Easily deploy and view actionable data that helps you increase viewer engagement and retention, track and fix playback issues before they impact your users, and optimize for the best viewing experience. +- **Improved quality assurance:** Stream Lab integration for automated, real-device playback testing. + +### Use cases + +**Advanced Monetization Capabilities** + +Increase audience reach and ad revenue with Bitmovin's Player and Analytics (Playback) solutions. Flexible ad management supports both server‑side (SSAI) and client‑side (CSAI) ad insertion, ensuring smooth, targeted ad delivery across devices. With real‑time playback insights from Bitmovin Analytics and efficient global delivery powered by Akamai's CDN, platforms can optimize ad performance, boost conversions, and maintain a consistently high‑quality viewing experience. + +**Lower Development Costs** + +Reduce engineering effort and operational overhead with Bitmovin's dedicated Player SDKs. Pre‑built cross‑platform components eliminate the need for manual maintenance and customization common with open‑source or in‑house players. Continuous automated testing - over 150,000 daily tests and weekly updates - ensures reliability, while Stream Lab allows real‑device validation of active streams. With Bitmovin Analytics and Akamai CMCD data pre‑integrated, developers can identify and resolve playback or CDN issues faster, improving efficiency and minimizing downtime. + +**Flawless Video Experiences** + +Deliver premium, consistent playback across every device to strengthen viewer satisfaction and reduce churn. Bitmovin's Player, built with dedicated SDKs and a cross‑platform UI framework, ensures brand consistency and supports advanced features such as low‑latency streaming and multi‑view experiences. With Bitmovin Analytics providing session‑level insights, teams can proactively detect and resolve playback issues, integrate with observability tools for holistic user analysis, and maintain the highest quality of experience to grow and retain subscribers. + +Ready to deliver flawless playback on every device? Contact our team to schedule a personalized demo and discuss your specific video streaming requirements. + +`.trim(); + +const documentationMarkdown = ` +| Specification | Details | +| :---- | :---- | +| **Device SDKs** | Web, iOS, Android, smart TVs, set-top boxes, consoles, HbbTV, and more | +| **Browser SDKs** | Chrome, Edge, Firefox, Opera, Safari | +| **Cross-platform SDKs** | React Native SDK, Flutter SDK | +| **Workflows & Protocols** | Video on demand (HLS, MPEG-DASH, HSS) and live (Low-Latency HLS/DASH over CMAF) | +| **Functions & Qualities** | ABR, Multi-Language Audio, Offline Playback, Playlists, Live DVR, and more | +| **Subtitles & Closed Captions** | WebVTT, SRT, TTML/DFXP, CEA-608/708, Multi-Language CC | +| **Content protection** | Widevine, PlayReady, FairPlay, Client-side Watermarking, Offline DRM, and more | +| **Advertising capabilities** | SSAI, CSAI, SGAI, VAST 3.0/4.0/4.1, VMAP + Ad Scheduling & Targeting, and more | +| **Other Playback Features** | Multi-view playback, Preview Thumbnails, Audio Only Player, and more | +| **Collectors** | Bitmovin Player, Shaka Player, dash.js, hls.js, video.js, Dolby OptiView, and more | +| **AI Features** | AI Session Interpreter, AI Anomaly Detection, Assistant | + + + +### Playback Workflow + +![Playback Workflow](/assets/marketplace/bitmovin-playback.jpeg) +`.trim(); + +const pricingMarkdown = ` +Pricing details will be discussed directly with the third-party provider Sales team after your request is received, and the third-party provider contacts you. Costs of the product you will be purchasing from the third-party provider will be charged by the third-party provider. For the referral motion, Akamai is not a party in the purchase contract. + +The full price of the product cost should be clarified between you and the third-party provider within the agreed upon terms and conditions of the purchase contract. +`.trim(); + +const supportMarkdown = ` +For product support, reach out to the vendor directly. You can find contact information in the product documentation and on the vendor's website. + +`.trim(); + +export const playback: ProductTabDetails = { + overview: overviewMarkdown, + documentation: documentationMarkdown, + pricing: pricingMarkdown, + support: supportMarkdown, +}; diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/portainer.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/portainer.ts new file mode 100644 index 00000000000..66f1165c52e --- /dev/null +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/portainer.ts @@ -0,0 +1,102 @@ +/** + * Product tab details for slug portainer. + * + * Content is provided as Markdown strings which are rendered at runtime. + */ + +import type { ProductTabDetails } from '.'; + +const overviewMarkdown = ` +Portainer is an operator control plane for governing Docker, Podman, and Kubernetes environments from a single self-hosted system. It solves the operational gap that sits above managed Kubernetes services like Akamai LKE: how to centralize access control, enforce security policy, standardize deployments, and manage fleets of clusters without needing a dedicated platform engineering team. It is designed for the IT operations, infrastructure, and security teams that make up the majority of Akamai's enterprise customer base. + +Portainer connects to Kubernetes environments through lightweight agents and provides centralized role-based access control with Active Directory, LDAP, and OIDC integration; governed application deployment through form-based or manifest-driven workflows; a GitOps engine with deterministic policy enforcement; and fleet-wide governance with automatic drift remediation. All user actions are audit logged and can be streamed to SIEM platforms, supporting the compliance requirements common in financial services, healthcare, defense, and public sector environments. Portainer runs entirely within the customer boundary with no external SaaS dependency, aligning directly with Zero Trust and data sovereignty requirements. + +Portainer is the natural operational layer above Akamai LKE for teams running multiple clusters across cloud regions, hybrid environments, or distributed edge sites. It scales from a single cluster to one hundred thousand edge environments from one control plane and is designed for the eighty percent of enterprises that need modern container operations without the overhead of building and maintaining a bespoke internal platform. + +### Key features + +- **Govern access across every environment from one place:** Portainer centralizes authentication and role-based access control with support for Active Directory, LDAP, and OIDC, eliminating the need to distribute credentials or manage access cluster by cluster. +- **Deploy applications safely without Kubernetes expertise:** Guided form-based workflows and manifest-driven deployment options let IT generalists and developers ship applications consistently, with guardrails enforced automatically by the control plane. +- **Enforce security policy across your entire fleet automatically:** Fleet Governance Policies install, propagate, and auto-remediate policy across all connected clusters, so drift is detected and corrected without manual intervention. +- **Manage thousands of edge and remote environments reliably:** Asynchronous edge agents enable offline-safe operation across disconnected, air-gapped, and industrial sites, with updates queuing safely until connectivity is restored. +- **Maintain a complete audit trail for compliance:** Every user action and system event is logged at the control plane level and can be streamed to SIEM platforms such as Splunk or Microsoft Sentinel. +- **Adopt GitOps without rebuilding your infrastructure:** A centralized GitOps engine monitors repositories and enforces desired state deterministically, without embedding controllers inside each managed cluster. +- **Operate confidently in regulated and sovereign environments:** Portainer runs entirely within the customer boundary with no external SaaS dependency, and supports FIPS-140-3 compliant operation for government and defense requirements. + + +### Use cases + +**Governing Kubernetes Fleet Operations Across Multiple Clusters** + +Enterprises running Kubernetes across multiple environments quickly outgrow cluster-level tooling and need a single control plane for access, policy, and deployment governance. A global energy company with 100+ developers replaced a custom-built internal platform - which had taken five developers two years to build - with Portainer, achieving a 15% increase in developer productivity, $1.7M in savings, and a 99.99% uptime target across both Kubernetes and Docker Swarm environments. A leading French bank consolidated governance across 1,500+ containerized environments, reducing application onboarding from five days to three hours and recapturing $60K per year in platform team productivity. + +**Enabling Container Adoption Without Kubernetes Specialists** + +Most enterprise IT teams do not have dedicated Kubernetes engineers, yet increasingly face pressure to run containerized applications delivered by ISVs or internal development teams. A U.S. automotive manufacturer running 24x7 production across three shifts used Portainer to give non-technical shift staff the ability to monitor, restart, and triage containers without any CLI knowledge. A Turkish fashion retailer with 500 global stores adopted Portainer specifically because it allowed their 100-person IT team - most with no prior Kubernetes experience - to deploy and manage workloads through an intuitive GUI, without YAML expertise and at a fraction of the cost of OpenShift. + +**Securing and Auditing Container Operations in Regulated Environments** + +Financial services, healthcare, government, and defense organizations require centralized audit logging, enforced security policy, and verifiable compliance posture as conditions of operating. San Diego Superior Court containerized its public-facing infrastructure with Portainer, reducing outages from multiple per month to one in twelve months, improving availability to 99.9999%, and generating an estimated $10M in annual productivity savings - with Active Directory integration driving adoption across a Windows-centric IT team. A global AI-powered surgical intelligence platform operating in thousands of operating rooms used Portainer to enforce governance across globally distributed Kubernetes environments while cutting developer onboarding from six months to weeks. + +**Managing Distributed and Edge Deployments at Scale** + +Organizations operating across distributed sites - factories, vehicles, retail stores, city infrastructure - need a control plane that works reliably under intermittent connectivity, with no dependency on always-on networks. Cummins used Portainer to consolidate 35 separate telematics software variants into one unified architecture deployed over-the-air across thousands of connected vehicles, operating under low-bandwidth and intermittent connectivity constraints. Volkswagen built its Shopfloor Integration Management platform on Portainer to remotely deploy and lifecycle-manage IoT microservices across thousands of shopfloor devices globally. A U.S. building materials manufacturer uses Portainer to push updates simultaneously to edge cameras and sensors across 68 plants, replacing up to 40 manual daily deployments with one-click fleet rollouts and saving $100K per year. + +**Enabling MSPs and Service Providers to Deliver Self-Service Container Platforms** + +Managed service providers and technology companies building container platforms for their customers need a control plane that isolates tenants, reduces support burden, and scales without adding headcount. ilionx, a European managed IT services provider, replaced Rancher with Portainer after finding it too complex to operate, eliminating a daily bottleneck of 70–80 manual container restarts and enabling customers to manage their own isolated environments without contacting support. A major U.S. satellite and streaming radio provider managing 250 Kubernetes nodes estimated that operating without Portainer would require hiring two or more additional full-time engineers to handle update tasks alone. + + +Getting started with Portainer is straightforward and low-risk. Portainer offers a **free perpetual tier for up to three nodes** - no time limit and no credit card required - giving teams immediate hands-on access to the full management interface against real workloads. + +For organizations evaluating at production scale, a **30-day free trial** of Portainer Business is available, supported by a structured **Proof of Concept guide** that walks teams through deployment, configuration, and validation against their own environment and use cases. + +For enterprise evaluations, Portainer's solutions engineering team provides direct technical support throughout the trial period, including architecture reviews and guided onboarding. To get started, contact the Portainer team to arrange a live demo tailored to your infrastructure and requirements. +`.trim(); + +const documentationMarkdown = ` +| Specification | Details | +| :---- | :---- | +| **Deployment Model** | Self-hosted; runs as a container entirely within the customer environment - on-premises, private cloud, air-gapped, hybrid, or edge | +| **Supported Container Runtimes** | Docker, Podman, Kubernetes (any distribution), Docker Swarm | +| **Agent Types** | LAN Agent (trusted networks), Remote Agent (outbound-only, no inbound firewall rules), Async Edge Agent (disconnected and OT environments) | +| **Fleet Scale** | Up to 100,000 edge environments managed from a single control plane | +| **Identity and Authentication** | Active Directory, LDAP, OIDC-compatible identity providers, local users for air-gapped environments | +| **Access Control** | Role-based access control (RBAC) with predefined roles: Environment Administrator, Operator, Namespace Operator, Standard User, Read-Only, Helpdesk | +| **GitOps Execution** | Centralized server-side GitOps engine; supports Git repository monitoring via schedule or webhook; compatible with Docker, Podman, and Kubernetes | +| **Security and Compliance** | FIPS 140-3 compliant operation; AES-256 encryption of internal database at rest; TLS for agent communication; SIEM integration via webhook (Splunk, Microsoft Sentinel, Elastic) | +| **Audit Logging** | Full user-action-level audit logging at the control plane; exportable to SIEM platforms | +| **Policy Enforcement** | OPA Gatekeeper integration; fleet-wide policy propagation with automatic drift remediation across all connected clusters | +| **External Dependencies** | None; no SaaS control plane, no call-home requirement, no cloud dependency | + +Portainer uses a lightweight hub-and-spoke architecture consisting of two components: the Portainer Server and the Portainer Agent. + +The Portainer Server is the central control plane, running as a container on a dedicated management environment. It serves the UI and REST API, stores all configuration in an embedded BoltDB database, and manages identity, RBAC, GitOps execution, policy enforcement, and audit logging across all connected environments. It requires persistent storage and runs on Docker Standalone, Docker Swarm, or Kubernetes. + +Agents are deployed to each managed environment and act as execution proxies to the underlying container runtime. Three agent types support different network topologies. The Standard Agent accepts inbound connections from the Server on TCP port 9001, suited for private LAN environments. The Edge Agent reverses the connection direction — the agent calls home to the Server on ports 9443 and 8000 — eliminating the need for exposed inbound ports, suited for remote or internet-connected environments. The Async Edge Agent operates on the same outbound model but uses periodic snapshots rather than a live tunnel, designed for IoT, industrial, and satellite-connected environments with intermittent or limited connectivity. + +A single Portainer Server manages Docker, Podman, Kubernetes, and Swarm environments simultaneously, with tested scale to 100,000 active edge environments + + +### Portainer Architecture + +![Portainer Architecture](/assets/marketplace/portainer-architecture.jpeg) +`.trim(); + +const pricingMarkdown = ` +Pricing details will be discussed directly with the third-party provider Sales team after your request is received, and the third-party provider contacts you. Costs of the product you will be purchasing from the third-party provider will be charged by the third-party provider. For the referral motion, Akamai is not a party in the purchase contract. + +The full price of the product cost should be clarified between you and the third-party provider within the agreed upon terms and conditions of the purchase contract. +`.trim(); + +const supportMarkdown = ` +For product support, reach out to the vendor directly. You can find contact information in the product documentation and on the vendor's website. + +`.trim(); + +export const portainer: ProductTabDetails = { + overview: overviewMarkdown, + documentation: documentationMarkdown, + pricing: pricingMarkdown, + support: supportMarkdown, +}; diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/vod-encoder.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/vod-encoder.ts new file mode 100644 index 00000000000..082968617c5 --- /dev/null +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/vod-encoder.ts @@ -0,0 +1,74 @@ +/** + * Product tab details for slug vod-encoder. + * + * Content is provided as Markdown strings which are rendered at runtime. + */ + +import type { ProductTabDetails } from '.'; + +const overviewMarkdown = ` +Bitmovin's VOD Encoder is a fully managed SaaS solution that uses distributed processing and content-aware encoding to scale quickly and make content available in the highest quality at the lowest bitrates with the fastest turnaround times. + +With features like Per-Title, Per-Shot, and Multi-Pass encoding, Bitmovin enables video streaming companies to be more cost-efficient while providing an optimal viewing experience. It supports multiple codecs, including AV1, VP9, HEVC/H.265, and H.264, and can integrate with a range of DRMs to encode and secure content up to 8K UHD with HDR, including Dolby Vision. + +### Key features +- **Content-aware optimization:** Reduce total cost of ownership without sacrificing video quality through Per-Title and Per-Scene encoding that adapts bitrate ladders to each piece of content. +- **Cost-efficient, universal delivery:** Multi-codec outputs - including AV1, VP9, HEVC/H.265, and H.264 - create the most cost-efficient delivery to the widest range of viewing devices. +- **High-speed processing:** Leverage massively distributed, parallel processing that transcodes video up to 100x faster than real time, accelerating large-scale VOD workflows. +- **Optimized bitrate distribution:** Apply multi-pass and Smart Chunking features to eliminate unnecessary data use while maintaining top-tier Quality of Experience (QoE). +- **Advanced quality-based features:** Ensure premium visual and audio performance across devices with 4K and 8K UHD, HDR, Dolby Vision and Dolby Atmos support. + +### Use cases +**Monetization for Streaming Platforms** + +Enable multiple revenue streams across AVOD, SVOD, and TVOD models with seamless monetization workflows. Bitmovin's VOD Encoder integrates with major ad networks for Server-Side Ad Insertion (SSAI) and supports third-party subscriber management and paywall solutions to power subscription and transactional services. Built-in DRM and forensic watermarking protect premium content and revenue from unauthorized access or redistribution. + +**Cost-efficient Video on Demand** + +Reduce operating costs while maintaining top-tier video quality and workflow scalability. Bitmovin's VOD Encoder combines Per-Title and Per-Shot content-aware encoding with multi-codec output to minimize bitrate and storage usage without compromising performance. Automated orchestration intelligently distributes workloads across compute resources, enabling horizontal scaling and faster processing for large content libraries at a lower total cost of ownership. + +**Elevated Quality of Experience for Subscriber Retention** + +Enhance viewer satisfaction and reduce churn through superior streaming performance across all devices and network conditions. Bitmovin's VOD Encoder utilizes Multi-Pass, Smart Chunking, and Per-Title optimization to deliver consistently high-quality playback with reduced bandwidth requirements. Supporting resolutions up to 8K and advanced features like HDR and Dolby Vision, it helps streaming platforms strengthen brand loyalty, attract new audiences, and retain existing subscribers through exceptional visual experiences. + +Ready to deliver stunning video with our encoder? Contact our team to schedule a personalized demo and discuss your specific video streaming requirements. +`.trim(); + +const documentationMarkdown = ` +| Specification | Details | +| :---- | :---- | +| **Input formats** | MPEG-1/2/4, H.261, H.262, H.263, H.264, H.265, VP6, VP8, VP9, and more| +| **Input file formats** | MP4, MKV, MOV, AVI, MXF, LXF, GXF, MPEG-2 TS/PS, and more| +| **Input audio codecs** | AAC, MP3, DTS Express, FLAC, Dolby Digital, Dolby Atmos, and more| +| **Output file formats** | MPEG-2 TS, MP4, fMP4, MOV, WebM, CMAF, and more| +| **Output video codecs** | XDCAM HD 422 (MPEG-2), H.264, H.265, H.266, VP8, VP9, AV1, and more| +| **Output audio codecs** | AAC-LC, MP2, MP3, Vorbis, Dolby Digital (Plus), Dolby Atmos, and more| +| **DRM / Content protection** | DASH ClearKey, Multi-DRM (Widevine, PlayReady, Marlin, FairPlay), Forensic Watermarking, and more| +| **Subtitles & Closed captions** | WebVTT & OCR into WebVTT, CEA-608/708, Burnt-in Subtitles, and more| +| **Streaming protocols** | MPEG-DASH, Apple HLS, Progressive MP4, Smooth Streaming| +| **AI features** | AI Scene Analysis, Contextual Advertising, AI Vertical Video| +| **Innovative features** | Per-title, Multi-pass, Per-Shot encoding, Smart chunking, Multi-codec| + + + +#### VOD Encoder Streaming Workflow + +![VOD Encoder Streaming Workflow](/assets/marketplace/bitmovin-vod-encoder.jpeg) +`.trim(); + +const pricingMarkdown = ` +Pricing details will be discussed directly with the third-party provider Sales team after your request is received, and the third-party provider contacts you. Costs of the product you will be purchasing from the third-party provider will be charged by the third-party provider. For the referral motion, Akamai is not a party in the purchase contract. + +The full price of the product cost should be clarified between you and the third-party provider within the agreed upon terms and conditions of the purchase contract. +`.trim(); + +const supportMarkdown = ` +For product support, reach out to the vendor directly. You can find contact information in the product documentation and on the vendor's website. +`.trim(); + +export const vodEncoder: ProductTabDetails = { + overview: overviewMarkdown, + documentation: documentationMarkdown, + pricing: pricingMarkdown, + support: supportMarkdown, +}; diff --git a/packages/manager/src/features/Marketplace/products.ts b/packages/manager/src/features/Marketplace/products.ts index 6b8a0df8cd9..006dd4585b3 100644 --- a/packages/manager/src/features/Marketplace/products.ts +++ b/packages/manager/src/features/Marketplace/products.ts @@ -35,6 +35,23 @@ export const PRODUCTS: Product[] = [ name: 'SaaS & APIs', }, }, + { + categories: ['Kubernetes', 'Enterprise', 'Other Software and APIs'], + id: 'cloudcasa', + name: 'CloudCasa', + partner: { + email: 'info@catalogicsoftware.com', + logoDarkMode: 'cloudcasa-dark.svg', + logoLightMode: 'cloudcasa-light.svg', + name: 'CloudCasa by Catalogic', + url: 'https://cloudcasa.io/', + }, + shortDescription: + 'CloudCasa is a Kubernetes-native data protection platform that delivers cost-effective backup, granular recovery, and mobility across cloud, on-prem, and edge environments.', + type: { + name: 'Kubernetes', + }, + }, { categories: [ 'Compute', @@ -80,6 +97,23 @@ export const PRODUCTS: Product[] = [ name: 'SaaS & APIs', }, }, + { + categories: ['Media & Entertainment, Gaming', 'Other Software and APIs'], + id: 'live-encoder', + name: 'Live Encoder', + partner: { + email: 'akamai@bitmovin.com', + logoDarkMode: 'bitmovin-dark.svg', + logoLightMode: 'bitmovin-light.svg', + name: 'Bitmovin', + url: 'https://bitmovin.com/live-encoding-live-streaming', + }, + shortDescription: + 'Power live experiences through Akamai and Bitmovin with unbeatable reliability, quality and scalability, ensuring platforms can support and stream any event size.', + type: { + name: 'SaaS & APIs', + }, + }, { categories: [ 'AI', @@ -106,6 +140,49 @@ export const PRODUCTS: Product[] = [ name: 'SaaS & APIs', }, }, + { + categories: [ + 'Data Analytics', + 'Media & Entertainment, Gaming', + 'Other Software and APIs', + ], + id: 'playback', + name: 'Playback', + partner: { + email: 'akamai@bitmovin.com', + logoDarkMode: 'bitmovin-dark.svg', + logoLightMode: 'bitmovin-light.svg', + name: 'Bitmovin', + url: 'https://bitmovin.com/video-player', + }, + shortDescription: + 'Stream in the highest quality across the widest range of devices, and enhance engagement and retention with real-time Analytics to identify issues and optimize video performance.', + type: { + name: 'SaaS & APIs', + }, + }, + { + categories: [ + 'Development Tools', + 'Enterprise', + 'Kubernetes', + 'Other Software and APIs', + ], + id: 'portainer', + name: 'Portainer', + partner: { + email: 'partners@portainer.io', + logoDarkMode: 'portainer-dark.svg', + logoLightMode: 'portainer-light.svg', + name: 'Portainer.io Limited', + url: 'https://www.portainer.io/', + }, + shortDescription: + 'Portainer is a universal container management platform that lets IT teams manage Docker and Kubernetes fleets across cloud and edge to enforce security and simplify operations at any scale.', + type: { + name: 'SaaS & APIs', + }, + }, { categories: ['AI', 'Enterprise'], id: 'rad-security-platform', @@ -227,6 +304,23 @@ export const PRODUCTS: Product[] = [ name: 'SaaS & APIs', }, }, + { + categories: ['Media & Entertainment, Gaming', 'Other Software and APIs'], + id: 'vod-encoder', + name: 'VOD Encoder', + partner: { + email: 'akamai@bitmovin.com', + logoDarkMode: 'bitmovin-dark.svg', + logoLightMode: 'bitmovin-light.svg', + name: 'Bitmovin', + url: 'https://bitmovin.com/encoding-service', + }, + shortDescription: + 'Process entire content libraries in up to 100x real-time and minimize file size while maintaining the highest quality and security with support for the latest codecs.', + type: { + name: 'SaaS & APIs', + }, + }, { categories: ['Media & Entertainment, Gaming'], id: 'dynamic-ad-insertion', From f6b2e8d93f98010c2b34bfa7735c7cd904576a8c Mon Sep 17 00:00:00 2001 From: Hana Xu <115299789+hana-akamai@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:58:37 -0400 Subject: [PATCH 51/56] fix: [UIE-10423] - PgBouncer Connection Pool bugs (#13474) Fix various PgBouncer Connection Pool bugs now that we can test with a real API --- .../pr-13474-upcoming-features-1773090286395.md | 5 +++++ .../DatabaseConnectionPoolRow.tsx | 11 +++++++++-- .../DatabaseConnectionPools.tsx | 15 +++++---------- .../DatabaseNetworking/DatabaseNetworking.tsx | 7 ++++--- .../DatabaseSummary/DatabaseSummary.tsx | 10 +++++----- packages/queries/src/databases/databases.ts | 16 +++++----------- 6 files changed, 33 insertions(+), 31 deletions(-) create mode 100644 packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md diff --git a/packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md b/packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md new file mode 100644 index 00000000000..e1c9f1b3921 --- /dev/null +++ b/packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Fix Database PgBouncer Connection Pool bugs ([#13474](https://github.com/linode/manager/pull/13474)) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPoolRow.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPoolRow.tsx index 38d88d7bd58..c29d42b0ae0 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPoolRow.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPoolRow.tsx @@ -6,10 +6,12 @@ import { ActionMenu } from 'src/components/ActionMenu/ActionMenu'; import { CONNECTION_POOL_LABEL_CELL_STYLES } from 'src/features/Databases/constants'; import { StyledActionMenuWrapper } from 'src/features/Databases/shared.styles'; -import type { ConnectionPool } from '@linode/api-v4'; +import type { ConnectionPool, DatabaseStatus } from '@linode/api-v4'; import type { Action } from 'src/components/ActionMenu/ActionMenu'; interface Props { + /** Status of the Database */ + databaseStatus: DatabaseStatus; /** * Function called when the delete button in the Action Menu is pressed. */ @@ -25,12 +27,17 @@ interface Props { } export const DatabaseConnectionPoolRow = (props: Props) => { - const { pool, onDelete, onEdit } = props; + const { pool, onDelete, onEdit, databaseStatus } = props; + const editDisabled = databaseStatus === 'provisioning'; const connectionPoolActions: Action[] = [ { onClick: () => onEdit(pool), title: 'Edit', + disabled: editDisabled, + tooltip: editDisabled + ? 'Your Database Cluster is currently provisioning.' + : '', }, { onClick: () => onDelete(pool), diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx index a71ee633ee9..b6664b2cc9f 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx @@ -76,16 +76,6 @@ export const DatabaseConnectionPools = ({ database }: Props) => { page_size: pagination.pageSize, }); - if (connectionPoolsLoading) { - return ; - } - - if (connectionPoolsError) { - return ( - - ); - } - const hasVPC = Boolean(database?.private_network?.vpc_id); const hasPublicVPC = hasVPC && database.private_network?.public_access; @@ -190,6 +180,10 @@ export const DatabaseConnectionPools = ({ database }: Props) => { + {connectionPoolsLoading && } + {connectionPoolsError && ( + + )} {connectionPools?.data.length === 0 ? ( { ) : ( connectionPools?.data.map((pool) => ( setDeletePoolLabelSelection(pool.label)} onEdit={() => setEditPoolSelection(pool)} diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseNetworking.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseNetworking.tsx index 55d2c4050b0..dfcc395a451 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseNetworking.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseNetworking.tsx @@ -20,6 +20,9 @@ export const DatabaseNetworking = () => { {ACCESS_CONTROLS_IN_SETTINGS_TEXT} ); + const pgBouncerEnabled = + flags.databasePgBouncer && database.engine === 'postgresql'; + if (!isVPCEnabled) { navigate({ to: `/databases/$engine/$databaseId/summary`, @@ -40,9 +43,7 @@ export const DatabaseNetworking = () => { disabled={disabled} /> - {flags.databasePgBouncer && database.engine === 'postgresql' && ( - - )} + {pgBouncerEnabled && } ); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummary.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummary.tsx index 0c03ff20754..7c195b20347 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummary.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummary.tsx @@ -21,17 +21,17 @@ export const DatabaseSummary = () => { const { database } = useDatabaseDetailContext(); const flags = useFlags(); + const pgBouncerEnabled = + flags.databasePgBouncer && database.engine === 'postgresql'; + const { data: connectionPools } = useDatabaseConnectionPoolsQuery( database.id, - flags.databasePgBouncer, + pgBouncerEnabled, {} ); const showPgBouncerConnectionDetails = - flags.databasePgBouncer && - database.engine === 'postgresql' && - connectionPools && - connectionPools.data.length > 0; + pgBouncerEnabled && connectionPools && connectionPools.data.length > 0; const hasVPC = Boolean(database?.private_network?.vpc_id); const hasPublicVPC = hasVPC && database.private_network?.public_access; diff --git a/packages/queries/src/databases/databases.ts b/packages/queries/src/databases/databases.ts index cf15ce40e18..7357985e112 100644 --- a/packages/queries/src/databases/databases.ts +++ b/packages/queries/src/databases/databases.ts @@ -243,13 +243,11 @@ export const useUpdateDatabaseConnectionPoolMutation = ( { mutationFn: (data) => updateDatabaseConnectionPool(databaseId, poolName, data), - onSuccess(connectionPool) { - queryClient.setQueryData( - databaseQueries - .database('postgresql', databaseId) - ._ctx.connectionPools._ctx.pool(connectionPool.label).queryKey, - connectionPool, - ); + onSuccess() { + queryClient.invalidateQueries({ + queryKey: databaseQueries.database('postgresql', databaseId)._ctx + .connectionPools.queryKey, + }); }, }, ); @@ -266,10 +264,6 @@ export const useDeleteDatabaseConnectionPoolMutation = ( queryClient.invalidateQueries( databaseQueries.database('postgresql', databaseId)._ctx.connectionPools, ); - queryClient.removeQueries({ - queryKey: databaseQueries.database('postgresql', databaseId)._ctx - .connectionPools.queryKey, - }); }, }); }; From e12261f7e0330a7a2e34f6a2af226b7537aa9968 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Tue, 10 Mar 2026 14:06:53 -0400 Subject: [PATCH 52/56] =?UTF-8?q?upcoming:=20[UIE=209401]=20=E2=80=93=20Im?= =?UTF-8?q?plement=20Share=20Groups=20Landing=20page=20tabs=20(#13471)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added missing padding around the Managed dashboard card * changed spacing to spacingFunction * Implement share groups landing page tabs * Update image subtab interface * Fix image utils test case * Update packages/manager/src/features/Images/utils.test.tsx Co-authored-by: Purvesh Makode * Added changeset: Add share groups tabs * Update file name and consolidate imports * Rename file for consistency * Update packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --------- Co-authored-by: Purvesh Makode Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- ...r-13471-upcoming-features-1773085243886.md | 5 + .../v2/ImageLibrary/ImageLibraryTabs.tsx | 7 +- .../ImageLibrary/imageLibraryTabsConfig.tsx | 4 +- .../v2/ShareGroups/ShareGroupsTabs.test.tsx | 104 ++++++++++++++++++ .../v2/ShareGroups/ShareGroupsTabs.tsx | 69 +++++++++++- .../v2/ShareGroups/shareGroupsTabsConfig.tsx | 16 +++ .../src/features/Images/utils.test.tsx | 20 ++-- packages/manager/src/features/Images/utils.ts | 17 ++- packages/manager/src/routes/images/index.ts | 55 ++++++++- 9 files changed, 270 insertions(+), 27 deletions(-) create mode 100644 packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.test.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx diff --git a/packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md b/packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md new file mode 100644 index 00000000000..ba5d28e1179 --- /dev/null +++ b/packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Private Image Sharing: Add Share Groups tabs ([#13471](https://github.com/linode/manager/pull/13471)) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx index 31ada64c651..ea4d45933a6 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImageLibraryTabs.tsx @@ -10,7 +10,7 @@ import { TabList } from 'src/components/Tabs/TabList'; import { TabPanels } from 'src/components/Tabs/TabPanels'; import { Tabs } from 'src/components/Tabs/Tabs'; -import { getImageLibrarySubTabIndex } from '../../../utils'; +import { getSubTabIndex } from '../../../utils'; import { DeleteImageDialog } from '../../DeleteImageDialog'; import { EditImageDrawer } from '../../EditImageDrawer'; import { ManageImageReplicasForm } from '../../ImageRegions/ManageImageRegionsForm'; @@ -108,10 +108,7 @@ export const ImageLibraryTabs = () => { onRebuild: handleRebuild, }; - const subTabIndex = getImageLibrarySubTabIndex( - subTabs, - imageTypeParams?.imageType - ); + const subTabIndex = getSubTabIndex(subTabs, imageTypeParams?.imageType); const onTabChange = (index: number) => { // - Update the "imageType" param. diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx index 7b789dfa4e7..a6875dbd2d9 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig.tsx @@ -12,7 +12,7 @@ import { MANUAL_IMAGES_PREFERENCE_KEY, } from '../../../constants'; -import type { ImageLibrarySubTab, ImageLibraryType } from '../../../utils'; +import type { ImageLibraryType, ImageSubTab } from '../../../utils'; import type { Image } from '@linode/api-v4'; import type { HiddenProps } from '@linode/ui'; @@ -54,7 +54,7 @@ export interface ImageConfig { type: Image['type']; } -export const imageLibrarySubTabs: ImageLibrarySubTab[] = [ +export const imageLibrarySubTabs: ImageSubTab[] = [ { type: 'owned-by-me', title: 'Owned by me' }, { type: 'shared-with-me', diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.test.tsx new file mode 100644 index 00000000000..6d517924ed3 --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.test.tsx @@ -0,0 +1,104 @@ +import { userEvent } from '@testing-library/user-event/dist/cjs/setup/index.js'; +import * as React from 'react'; + +import { renderWithTheme } from 'src/utilities/testHelpers'; + +import { ShareGroupsTabs } from './ShareGroupsTabs'; + +const queryMocks = vi.hoisted(() => ({ + useNavigate: vi.fn(), + useParams: vi.fn(), + useLocation: vi.fn(), +})); + +vi.mock('@tanstack/react-router', async () => { + const actual = await vi.importActual('@tanstack/react-router'); + return { + ...actual, + useLocation: queryMocks.useLocation, + useNavigate: queryMocks.useNavigate, + useParams: queryMocks.useParams, + }; +}); + +describe('ShareGroupsTabs', () => { + beforeEach(() => { + vi.clearAllMocks(); + const mockNavigate = vi.fn(); + queryMocks.useNavigate.mockReturnValue(mockNavigate); + }); + + it('should render all share groups tabs', async () => { + queryMocks.useParams.mockReturnValue({ shareGroupsType: 'owned-groups' }); + + const { getByText } = renderWithTheme(, { + initialRoute: '/images/share-groups/owned-groups', + }); + + expect(getByText('Owned groups')).toBeVisible(); + expect(getByText('Joined groups')).toBeVisible(); + expect(getByText('My membership requests')).toBeVisible(); + }); + + it('should navigate to owned-groups tab when clicked', async () => { + queryMocks.useParams.mockReturnValue({ shareGroupsType: 'owned-groups' }); + const mockNavigate = vi.fn(); + queryMocks.useNavigate.mockReturnValue(mockNavigate); + + const { getByText } = renderWithTheme(, { + initialRoute: '/images/share-groups/owned-groups', + }); + + const ownedGroupsTab = getByText('Owned groups', { selector: 'button' }); + await userEvent.click(ownedGroupsTab); + + expect(mockNavigate).toHaveBeenCalledWith({ + to: '/images/share-groups/$shareGroupsType', + params: { + shareGroupsType: 'owned-groups', + }, + }); + }); + + it('should navigate to joined-groups tab when clicked', async () => { + queryMocks.useParams.mockReturnValue({ shareGroupsType: 'owned-groups' }); + const mockNavigate = vi.fn(); + queryMocks.useNavigate.mockReturnValue(mockNavigate); + + const { getByText } = renderWithTheme(, { + initialRoute: '/images/share-groups/owned-groups', + }); + + const joinedGroupsTab = getByText('Joined groups', { selector: 'button' }); + await userEvent.click(joinedGroupsTab); + + expect(mockNavigate).toHaveBeenCalledWith({ + to: '/images/share-groups/$shareGroupsType', + params: { + shareGroupsType: 'joined-groups', + }, + }); + }); + + it('should navigate to membership-requests tab when clicked', async () => { + queryMocks.useParams.mockReturnValue({ shareGroupsType: 'owned-groups' }); + const mockNavigate = vi.fn(); + queryMocks.useNavigate.mockReturnValue(mockNavigate); + + const { getByText } = renderWithTheme(, { + initialRoute: '/images/share-groups/owned-groups', + }); + + const membershipTab = getByText('My membership requests', { + selector: 'button', + }); + await userEvent.click(membershipTab); + + expect(mockNavigate).toHaveBeenCalledWith({ + to: '/images/share-groups/$shareGroupsType', + params: { + shareGroupsType: 'membership-requests', + }, + }); + }); +}); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.tsx index 120b5014ae3..a093a541ec8 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTabs.tsx @@ -1,6 +1,71 @@ -import { Notice } from '@linode/ui'; +import { BetaChip, Notice, Stack } from '@linode/ui'; +import { useNavigate, useParams } from '@tanstack/react-router'; import React from 'react'; +import { SuspenseLoader } from 'src/components/SuspenseLoader'; +import { SafeTabPanel } from 'src/components/Tabs/SafeTabPanel'; +import { Tab } from 'src/components/Tabs/Tab'; +import { TabList } from 'src/components/Tabs/TabList'; +import { TabPanels } from 'src/components/Tabs/TabPanels'; +import { Tabs } from 'src/components/Tabs/Tabs'; +import { getSubTabIndex } from 'src/features/Images/utils'; + +import { shareGroupsSubTabs as subTabs } from './shareGroupsTabsConfig'; + export const ShareGroupsTabs = () => { - return Share Groups is coming soon...; + const navigate = useNavigate(); + + const shareGroupsTypeParams = useParams({ + from: '/images/share-groups/$shareGroupsType', + shouldThrow: false, + }); + + const onTabChange = (index: number) => { + navigate({ + to: `/images/share-groups/$shareGroupsType`, + params: { + shareGroupsType: subTabs[index].type, + }, + }); + }; + + const subTabIndex = getSubTabIndex( + subTabs, + shareGroupsTypeParams?.shareGroupsType + ); + + return ( + + + + {subTabs.map((tab) => ( + + {tab.title} {tab.isBeta ? : null} + + ))} + + }> + + {subTabs.map((tab, index) => ( + + {tab.type === 'owned-groups' && ( + Owned Groups is coming soon... + )} + {tab.type === 'joined-groups' && ( + + Joined Groups is coming soon... + + )} + {tab.type === 'membership-requests' && ( + + Membership Requests is coming soon... + + )} + + ))} + + + + + ); }; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx new file mode 100644 index 00000000000..7c82202fc28 --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx @@ -0,0 +1,16 @@ +import type { ImageSubTab, ShareGroupsType } from 'src/features/Images/utils'; + +export const shareGroupsSubTabs: ImageSubTab[] = [ + { + type: 'owned-groups', + title: 'Owned groups', + }, + { + type: 'joined-groups', + title: 'Joined groups', + }, + { + type: 'membership-requests', + title: 'My membership requests', + }, +]; diff --git a/packages/manager/src/features/Images/utils.test.tsx b/packages/manager/src/features/Images/utils.test.tsx index 0b53914d38b..e7ab420a401 100644 --- a/packages/manager/src/features/Images/utils.test.tsx +++ b/packages/manager/src/features/Images/utils.test.tsx @@ -7,12 +7,12 @@ import { wrapWithTheme } from 'src/utilities/testHelpers'; import { getEventsForImages, getImageLabelForLinode, - getImageLibrarySubTabIndex, getImageTypeToImageLibraryType, + getSubTabIndex, useIsPrivateImageSharingEnabled, } from './utils'; -import type { ImageLibrarySubTab } from './utils'; +import type { ImageLibraryType, ImageSubTab } from './utils'; describe('getImageLabelForLinode', () => { it('handles finding an image and getting the label', () => { @@ -94,30 +94,30 @@ describe('useIsPrivateImageSharingEnabled', () => { }); }); -describe('getImageLibrarySubTabIndex', () => { - const subTabs: ImageLibrarySubTab[] = [ +describe('getSubTabIndex', () => { + const subTabs: ImageSubTab[] = [ { type: 'owned-by-me', title: 'Owned by me' }, { type: 'shared-with-me', title: 'Shared with me', isBeta: true }, { type: 'recovery-images', title: 'Recovery images' }, ]; it('returns 0 if selectedTab is undefined', () => { - expect(getImageLibrarySubTabIndex(subTabs, undefined)).toBe(0); + expect(getSubTabIndex(subTabs, undefined)).toBe(0); }); it('returns the correct index when selectedTab matches a tab key', () => { - expect(getImageLibrarySubTabIndex(subTabs, 'owned-by-me')).toBe(0); - expect(getImageLibrarySubTabIndex(subTabs, 'shared-with-me')).toBe(1); - expect(getImageLibrarySubTabIndex(subTabs, 'recovery-images')).toBe(2); + expect(getSubTabIndex(subTabs, 'owned-by-me')).toBe(0); + expect(getSubTabIndex(subTabs, 'shared-with-me')).toBe(1); + expect(getSubTabIndex(subTabs, 'recovery-images')).toBe(2); }); it('returns 0 if selectedTab does not exist in subTabs', () => { // @ts-expect-error intentionally passing an unexpected value - expect(getImageLibrarySubTabIndex(subTabs, 'hey')).toBe(0); + expect(getSubTabIndex(subTabs, 'hey')).toBe(0); }); it('works with an empty subTabs array', () => { - expect(getImageLibrarySubTabIndex([], 'owned-by-me')).toBe(0); + expect(getSubTabIndex([], 'owned-by-me')).toBe(0); }); }); diff --git a/packages/manager/src/features/Images/utils.ts b/packages/manager/src/features/Images/utils.ts index e8fb09d9d84..78d1646cb47 100644 --- a/packages/manager/src/features/Images/utils.ts +++ b/packages/manager/src/features/Images/utils.ts @@ -10,16 +10,21 @@ export type ImageLibraryType = | 'recovery-images' | 'shared-with-me'; +export type ShareGroupsType = + | 'joined-groups' + | 'membership-requests' + | 'owned-groups'; + /** - * Configuration for image sub-tabs within the Image Library tab. + * Generic configuration for image sub-tabs within the Images feature for Image Library and Share Groups. */ -export interface ImageLibrarySubTab { +export interface ImageSubTab { /** Whether this tab represents a beta feature */ isBeta?: boolean; /** Display title for the tab */ title: string; /** The type this tab represents */ - type: ImageLibraryType; + type: T; } export const getImageLabelForLinode = (linode: Linode, images: Image[]) => { @@ -82,9 +87,9 @@ export const useIsPrivateImageSharingEnabled = () => { * * @returns the index of the selected sub-tab */ -export const getImageLibrarySubTabIndex = ( - subTabs: ImageLibrarySubTab[], - selectedTab: ImageLibraryType | undefined +export const getSubTabIndex = ( + subTabs: ImageSubTab[], + selectedTab: ImageLibraryType | ShareGroupsType | undefined ) => { if (selectedTab === undefined) { return 0; diff --git a/packages/manager/src/routes/images/index.ts b/packages/manager/src/routes/images/index.ts index 417214f67d6..0e48c5b2c2a 100644 --- a/packages/manager/src/routes/images/index.ts +++ b/packages/manager/src/routes/images/index.ts @@ -1,12 +1,16 @@ import { createRoute, redirect } from '@tanstack/react-router'; import { imageLibrarySubTabs } from 'src/features/Images/ImagesLanding/v2/ImageLibrary/imageLibraryTabsConfig'; +import { shareGroupsSubTabs } from 'src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig'; import { rootRoute } from '../root'; import { ImagesRoute } from './ImagesRoute'; import type { TableSearchParams } from '../types'; -import type { ImageLibraryType } from 'src/features/Images/utils'; +import type { + ImageLibraryType, + ShareGroupsType, +} from 'src/features/Images/utils'; export interface ImagesSearchParams extends TableSearchParams { query?: string; @@ -31,6 +35,10 @@ type ImageLibraryTypeRouteParams = { imageType: ImageLibraryType; }; +type ShareGroupsTypeRouteParams = { + shareGroupsType: ShareGroupsType; +}; + const imageActions = { delete: 'delete', deploy: 'deploy', @@ -256,6 +264,20 @@ const shareGroupsIndexRoute = createRoute({ to: '/images', }); } + + const normalizedPath = location.pathname.endsWith('/') + ? location.pathname.slice(0, -1) + : location.pathname; + + if ( + context.isPrivateImageSharingEnabled && + normalizedPath === '/images/share-groups' + ) { + throw redirect({ + to: '/images/share-groups/$shareGroupsType', + params: { shareGroupsType: 'owned-groups' }, + }); + } }, getParentRoute: () => shareGroupsLandingRoute, path: '/', @@ -266,6 +288,33 @@ const shareGroupsIndexRoute = createRoute({ ).then((m) => m.shareGroupsTabsLazyRoute) ); +const shareGroupsTypeRoute = createRoute({ + beforeLoad: async ({ context, params }) => { + if ( + context.isPrivateImageSharingEnabled && + !shareGroupsSubTabs + .map((tab) => tab.type) + .includes(params.shareGroupsType) + ) { + throw redirect({ + to: '/images/share-groups/$shareGroupsType', + params: { shareGroupsType: 'owned-groups' }, + }); + } + }, + getParentRoute: () => shareGroupsIndexRoute, + params: { + parse: ({ shareGroupsType }: ShareGroupsTypeRouteParams) => ({ + shareGroupsType, + }), + stringify: ({ shareGroupsType }: ShareGroupsTypeRouteParams) => ({ + shareGroupsType, + }), + }, + path: '$shareGroupsType', + validateSearch: (search: ImagesSearchParams) => search, +}); + export const imagesRouteTree = imagesRoute.addChildren([ imagesIndexRoute.addChildren([imageActionRoute]), imageLibraryLandingRoute.addChildren([ @@ -273,7 +322,9 @@ export const imagesRouteTree = imagesRoute.addChildren([ imageLibraryTypeRoute.addChildren([imageActionRouteV2]), ]), ]), - shareGroupsLandingRoute.addChildren([shareGroupsIndexRoute]), + shareGroupsLandingRoute.addChildren([ + shareGroupsIndexRoute.addChildren([shareGroupsTypeRoute]), + ]), imagesCreateRoute.addChildren([ imagesCreateIndexRoute, imagesCreateDiskRoute, From 00427555611bd163345746aaa57795427d0320ea Mon Sep 17 00:00:00 2001 From: Connie Liu <139280159+coliu-akamai@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:49:30 -0400 Subject: [PATCH 53/56] fix: Fix backups bug for Linode Interfaces (#13458) * Fix backups bug for Linode Interfaces * clear vpc/vlan fields when selecting config profile interfaces on backups tab * Added changeset: Linode Interfaces network connection incorrectly disabled when createing a Linode from a Backup --- .../pr-13458-fixed-1772574441245.md | 5 ++++ .../Networking/InterfaceGeneration.tsx | 24 ++++++++++++++----- .../Networking/InterfaceType.test.tsx | 8 +++---- .../LinodeCreate/Networking/InterfaceType.tsx | 16 +++---------- .../Networking/LinodeInterface.tsx | 17 ++++++++++--- .../LinodeCreate/shared/LinodeSelectTable.tsx | 3 ++- 6 files changed, 46 insertions(+), 27 deletions(-) create mode 100644 packages/manager/.changeset/pr-13458-fixed-1772574441245.md diff --git a/packages/manager/.changeset/pr-13458-fixed-1772574441245.md b/packages/manager/.changeset/pr-13458-fixed-1772574441245.md new file mode 100644 index 00000000000..c7534259f0a --- /dev/null +++ b/packages/manager/.changeset/pr-13458-fixed-1772574441245.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Linode Interfaces network connection incorrectly disabled when createing a Linode from a Backup ([#13458](https://github.com/linode/manager/pull/13458)) diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceGeneration.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceGeneration.tsx index a7ce17a62e8..f5cf0e97de8 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceGeneration.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceGeneration.tsx @@ -1,4 +1,4 @@ -import { useAccountSettings } from '@linode/queries'; +import { useAccountSettings, useFirewallSettingsQuery } from '@linode/queries'; import { Box, FormControl, @@ -14,12 +14,11 @@ import React from 'react'; import { useController, useFormContext } from 'react-hook-form'; import { LinodeInterfaceFeatureStatusChip } from '../../LinodesDetail/LinodeNetworking/LinodeInterfaces/LinodeInterfaceFeatureChip'; +import { useGetLinodeCreateType } from '../Tabs/utils/useGetLinodeCreateType'; +import { getDefaultInterfacePayload } from './utilities'; import type { LinodeCreateFormValues } from '../utilities'; -import type { - CreateLinodeRequest, - LinodeInterfaceAccountSetting, -} from '@linode/api-v4'; +import type { LinodeInterfaceAccountSetting } from '@linode/api-v4'; const disabledReasonMap: Partial< Record @@ -31,7 +30,7 @@ const disabledReasonMap: Partial< }; export const InterfaceGeneration = () => { - const { setValue } = useFormContext(); + const { setValue } = useFormContext(); const { field } = useController< LinodeCreateFormValues, @@ -42,12 +41,17 @@ export const InterfaceGeneration = () => { const { data: accountSettings } = useAccountSettings(); + const { data: firewallSettings } = useFirewallSettingsQuery(); + const disabledReason = accountSettings && disabledReasonMap[accountSettings.interfaces_for_new_linodes]; const disabled = disabledReason !== undefined; + const createType = useGetLinodeCreateType(); + const isCreatingFromBackup = createType === 'Backups'; + return ( @@ -75,6 +79,14 @@ export const InterfaceGeneration = () => { if (value === 'linode') { setValue('private_ip', undefined); } + + // if Configuration Profile Interfaces is selected and user is on Backups tab, reset VLAN and VPC + // fields to prevent validation errors - config profile interfaces are not compatible with backups + if (value === 'legacy_config' && isCreatingFromBackup) { + setValue('linodeInterfaces', [ + getDefaultInterfacePayload('public', firewallSettings), + ]); + } }} value={field.value ?? 'linode'} > diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.test.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.test.tsx index 4e4147a7455..210ad0bbf62 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.test.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.test.tsx @@ -24,7 +24,7 @@ const defaultFormValues: Partial = { describe('InterfaceType', () => { it('renders all interface type options', () => { const { getByText, getByRole } = renderWithThemeAndHookFormContext({ - component: , + component: , useFormOptions: { defaultValues: defaultFormValues, }, @@ -44,7 +44,7 @@ describe('InterfaceType', () => { it('renders tooltip icons for each interface type', () => { const { getAllByRole } = renderWithThemeAndHookFormContext({ - component: , + component: , useFormOptions: { defaultValues: defaultFormValues, }, @@ -57,7 +57,7 @@ describe('InterfaceType', () => { it('selects the correct radio based on form value', () => { const { getByDisplayValue } = renderWithThemeAndHookFormContext({ - component: , + component: , useFormOptions: { defaultValues: { ...defaultFormValues, @@ -76,7 +76,7 @@ describe('InterfaceType', () => { it('allows user to change interface type selection', async () => { const { getByDisplayValue } = renderWithThemeAndHookFormContext({ - component: , + component: , useFormOptions: { defaultValues: defaultFormValues, }, diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.tsx index 4f9874f6ec8..0ec8e06176e 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.tsx @@ -11,17 +11,17 @@ import { FormControlLabel, Stack } from '@mui/material'; import { useSnackbar } from 'notistack'; import type { ChangeEvent } from 'react'; import React from 'react'; -import { useController, useFormContext, useWatch } from 'react-hook-form'; +import { useController, useFormContext } from 'react-hook-form'; import { FormLabel } from 'src/components/FormLabel'; -import { useGetLinodeCreateType } from '../Tabs/utils/useGetLinodeCreateType'; import { getDefaultFirewallForInterfacePurpose } from './utilities'; import type { LinodeCreateFormValues } from '../utilities'; import type { InterfacePurpose } from '@linode/api-v4'; interface Props { + disabled: boolean; index: number; } @@ -46,7 +46,7 @@ const interfaceTypes = [ }, ] as const; -export const InterfaceType = ({ index }: Props) => { +export const InterfaceType = ({ disabled, index }: Props) => { const queryClient = useQueryClient(); const { enqueueSnackbar } = useSnackbar(); @@ -59,16 +59,6 @@ export const InterfaceType = ({ index }: Props) => { name: `linodeInterfaces.${index}.purpose`, }); - const interfaceGeneration = useWatch({ - control, - name: 'interface_generation', - }); - - const createType = useGetLinodeCreateType(); - const isCreatingFromBackup = createType === 'Backups'; - - const disabled = isCreatingFromBackup && interfaceGeneration !== 'linode'; - const onChange = async (value: InterfacePurpose) => { // Change the interface purpose (Public, VPC, VLAN) field.onChange(value); diff --git a/packages/manager/src/features/Linodes/LinodeCreate/Networking/LinodeInterface.tsx b/packages/manager/src/features/Linodes/LinodeCreate/Networking/LinodeInterface.tsx index 053adaeee6f..a6ae4bddf9d 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/Networking/LinodeInterface.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/Networking/LinodeInterface.tsx @@ -2,6 +2,7 @@ import { Notice, Stack } from '@linode/ui'; import React from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; +import { useGetLinodeCreateType } from '../Tabs/utils/useGetLinodeCreateType'; import { InterfaceFirewall } from './InterfaceFirewall'; import { InterfaceGeneration } from './InterfaceGeneration'; import { InterfaceType } from './InterfaceType'; @@ -30,6 +31,12 @@ export const LinodeInterface = ({ index }: Props) => { name: `linodeInterfaces.${index}.purpose`, }); + const createType = useGetLinodeCreateType(); + const isCreatingFromBackup = createType === 'Backups'; + + const disableInterfaceType = + isCreatingFromBackup && interfaceGeneration !== 'linode'; + return ( {errors.linodeInterfaces?.[index]?.message && ( @@ -44,9 +51,13 @@ export const LinodeInterface = ({ index }: Props) => { variant="error" /> )} - - {interfaceType === 'vlan' && } - {interfaceType === 'vpc' && } + + {interfaceType === 'vlan' && !disableInterfaceType && ( + + )} + {interfaceType === 'vpc' && !disableInterfaceType && ( + + )} {interfaceGeneration === 'linode' && interfaceType !== 'vlan' && ( diff --git a/packages/manager/src/features/Linodes/LinodeCreate/shared/LinodeSelectTable.tsx b/packages/manager/src/features/Linodes/LinodeCreate/shared/LinodeSelectTable.tsx index e46f3cebac8..8497d2552a6 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/shared/LinodeSelectTable.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/shared/LinodeSelectTable.tsx @@ -149,7 +149,8 @@ export const LinodeSelectTable = (props: Props) => { private_ip: linode.interface_generation !== 'linode' && hasPrivateIP, region: linode.region, type: linode.type ?? '', - interface_generation: undefined, + interface_generation: + createPath === 'clone' ? undefined : prev.interface_generation, })); if (!isLabelFieldDirty) { From 9584699cd5ed57245e1bc9d492edf4fd01702256 Mon Sep 17 00:00:00 2001 From: bbanucha-akamai Date: Wed, 11 Mar 2026 10:24:13 +0100 Subject: [PATCH 54/56] change: [DPS-36768] - Display info how to enable log generation per cluster (#13473) --- .../.changeset/pr-13473-added-1773079125538.md | 5 +++++ .../StreamForm/Clusters/StreamFormClusters.tsx | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 packages/manager/.changeset/pr-13473-added-1773079125538.md diff --git a/packages/manager/.changeset/pr-13473-added-1773079125538.md b/packages/manager/.changeset/pr-13473-added-1773079125538.md new file mode 100644 index 00000000000..b91892779ac --- /dev/null +++ b/packages/manager/.changeset/pr-13473-added-1773079125538.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Added +--- + +Stream Create/Edit form: Show instructions in the Clusters section on how to enable Kubernetes API Audit log generation per cluster ([#13473](https://github.com/linode/manager/pull/13473)) diff --git a/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx b/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx index 12fcf7805a1..1ff4c4b448a 100644 --- a/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx +++ b/packages/manager/src/features/Delivery/Streams/StreamForm/Clusters/StreamFormClusters.tsx @@ -17,10 +17,10 @@ import useMediaQuery from '@mui/material/useMediaQuery'; import { useFlags } from 'launchdarkly-react-client-sdk'; import { enqueueSnackbar } from 'notistack'; import React, { useEffect, useMemo, useState } from 'react'; -import { useWatch } from 'react-hook-form'; -import { Controller, useFormContext } from 'react-hook-form'; +import { Controller, useFormContext, useWatch } from 'react-hook-form'; import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; +import { Link } from 'src/components/Link'; import { sortData } from 'src/components/OrderBy'; import { PaginationFooter } from 'src/components/PaginationFooter/PaginationFooter'; import { MIN_PAGE_SIZE } from 'src/components/PaginationFooter/PaginationFooter.constants'; @@ -262,6 +262,19 @@ export const StreamFormClusters = (props: StreamFormClustersProps) => { )} /> + + Select the LKE clusters that will send audit logs to the configured + destination. Logging must be enabled for a cluster before it can be + selected. To enable logging for a cluster, use the Linode API{' '} + + update the cluster + {' '} + to set audit_logs_enabled to true. + Date: Wed, 11 Mar 2026 16:19:33 +0530 Subject: [PATCH 55/56] fix: [UIE-10362], [UIE-10343], [UIE-10345] - Marketplace bug fixes (#13476) * fix: [UIE-10343], [UIE-10345] - Marketplace bug fixes * Added changeset: Marketplace product updates + contact sales drawer fix * fix smoke test --- .../pr-13476-fixed-1773151456914.md | 5 ++ .../manager/cypress/support/ui/constants.ts | 2 +- .../public/assets/marketplace/ateme-flow.jpeg | Bin 0 -> 101327 bytes .../assets/marketplace/rad-security-dark.svg | 20 +++--- .../assets/marketplace/rad-security-light.svg | 38 +++++----- .../public/assets/marketplace/sftpgo-dark.svg | 67 ++++++++++-------- .../assets/marketplace/sftpgo-light.svg | 67 ++++++++++-------- .../features/Linodes/LinodeCreate/index.tsx | 2 +- .../ProductDetails/ContactSalesDrawer.tsx | 12 ++-- .../ProductDetails/pages/cambria-stream.ts | 16 ++--- .../Marketplace/ProductDetails/pages/index.ts | 4 +- ...layer-game-server-hosting-orchestration.ts | 1 - .../scaleflex-smart-media-cloud-and-dam.ts | 14 ++-- .../ProductDetails/pages/synadia-platform.ts | 16 ++--- ...titan-video-processing-and-compression.ts} | 15 ++-- .../src/features/Marketplace/products.ts | 4 +- 16 files changed, 156 insertions(+), 127 deletions(-) create mode 100644 packages/manager/.changeset/pr-13476-fixed-1773151456914.md create mode 100644 packages/manager/public/assets/marketplace/ateme-flow.jpeg rename packages/manager/src/features/Marketplace/ProductDetails/pages/{titan.ts => titan-video-processing-and-compression.ts} (65%) diff --git a/packages/manager/.changeset/pr-13476-fixed-1773151456914.md b/packages/manager/.changeset/pr-13476-fixed-1773151456914.md new file mode 100644 index 00000000000..62a866e6c57 --- /dev/null +++ b/packages/manager/.changeset/pr-13476-fixed-1773151456914.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Marketplace product updates + contact sales drawer fix ([#13476](https://github.com/linode/manager/pull/13476)) diff --git a/packages/manager/cypress/support/ui/constants.ts b/packages/manager/cypress/support/ui/constants.ts index 3ca596c5182..9ac78aa7878 100644 --- a/packages/manager/cypress/support/ui/constants.ts +++ b/packages/manager/cypress/support/ui/constants.ts @@ -57,7 +57,7 @@ export const pages: Page[] = [ { go: () => { loadAppNoLogin(routes.createLinode); - cy.get('[data-reach-tab]').contains('Marketplace').click(); + cy.get('[data-reach-tab]').contains('Quick Deploy Apps').click(); }, name: 'Tab', }, diff --git a/packages/manager/public/assets/marketplace/ateme-flow.jpeg b/packages/manager/public/assets/marketplace/ateme-flow.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..c6d36ec68ba1fa36a0b4219598e47ec4e51097e5 GIT binary patch literal 101327 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 z

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 z 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 Y_&t*RRY2$G+x*uU`v1(jNWP8!KW4J+PXGV_ literal 0 HcmV?d00001 diff --git a/packages/manager/public/assets/marketplace/rad-security-dark.svg b/packages/manager/public/assets/marketplace/rad-security-dark.svg index 33de0a34ee2..a520419dd8f 100644 --- a/packages/manager/public/assets/marketplace/rad-security-dark.svg +++ b/packages/manager/public/assets/marketplace/rad-security-dark.svg @@ -1,11 +1,11 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/packages/manager/public/assets/marketplace/rad-security-light.svg b/packages/manager/public/assets/marketplace/rad-security-light.svg index ee76e11aecb..4099f481c6c 100644 --- a/packages/manager/public/assets/marketplace/rad-security-light.svg +++ b/packages/manager/public/assets/marketplace/rad-security-light.svg @@ -1,63 +1,63 @@ - - - - - - - - - - + + + + + + + + + + - + - + - + - + - + - + - + - + - + diff --git a/packages/manager/public/assets/marketplace/sftpgo-dark.svg b/packages/manager/public/assets/marketplace/sftpgo-dark.svg index 47d4f502811..f9f3813a3ac 100644 --- a/packages/manager/public/assets/marketplace/sftpgo-dark.svg +++ b/packages/manager/public/assets/marketplace/sftpgo-dark.svg @@ -1,31 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SFTPGo + diff --git a/packages/manager/public/assets/marketplace/sftpgo-light.svg b/packages/manager/public/assets/marketplace/sftpgo-light.svg index 47d4f502811..f9f3813a3ac 100644 --- a/packages/manager/public/assets/marketplace/sftpgo-light.svg +++ b/packages/manager/public/assets/marketplace/sftpgo-light.svg @@ -1,31 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SFTPGo + diff --git a/packages/manager/src/features/Linodes/LinodeCreate/index.tsx b/packages/manager/src/features/Linodes/LinodeCreate/index.tsx index 8743bd46ac4..a6851e6502f 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/index.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreate/index.tsx @@ -129,7 +129,7 @@ export const LinodeCreate = () => { to: '/linodes/create/os', }, { - title: 'Marketplace', + title: 'Quick Deploy Apps', to: '/linodes/create/marketplace', }, { diff --git a/packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx b/packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx index be4ae28a475..d84e49d66a9 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx +++ b/packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx @@ -142,12 +142,16 @@ export const ContactSalesDrawer = (props: ContactSalesDrawerProps) => { const onSubmit = handleSubmit(async (values) => { try { - if ( - values?.additional_emails?.length === 1 && - values?.additional_emails[0].trim() === '' - ) { + const cleanedAdditionalEmails = values.additional_emails?.filter((e) => + e?.trim() + ); + + if (!cleanedAdditionalEmails?.length) { delete values.additional_emails; + } else { + values.additional_emails = cleanedAdditionalEmails; } + await createPartnerReferral(values); enqueueSnackbar( 'Your request has been received by Akamai. After we forward it to the partner, you will receive a confirmation email.', diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/cambria-stream.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/cambria-stream.ts index 1109714aa2f..54f75b5cb62 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/cambria-stream.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/cambria-stream.ts @@ -40,14 +40,14 @@ Ready to simplify your live and file-based media workflows? Submit an enquiry to const documentationMarkdown = ` | Specification | Details | | :---- | :---- | -| Deployment model | Customer-managed software; deployable on-prem, cloud, or hybrid environments | -| Packaging & orchestration | Containerised (Docker); Kubernetes-ready for scheduling and horizontal scaling | -| Product scope | Live encoding & packaging (Cambria Stream) | -| Supported video codecs | Cambria Stream Ingest a wide range of live inputs, then encode and package them as HLS, MPEG-DASH, CMAR, SRT and Zixi. | -| File orchestration | Centralised job distribution, load balancing, and node monitoring via Cambria Cluster | -| Hybrid processing | On-prem and cloud resources managed within a single workflow, including workload bursting | -| Automation & integration | REST APIs for workflow automation and integration with existing media systems | -| Scalability model | Horizontal scaling based on available compute resources (CPU/GPU/VPU, environment-dependent) | +| **Deployment model** | Customer-managed software; deployable on-prem, cloud, or hybrid environments | +| **Packaging & orchestration** | Containerised (Docker); Kubernetes-ready for scheduling and horizontal scaling | +| **Product scope** | Live encoding & packaging (Cambria Stream) | +| **Supported video codecs** | Cambria Stream Ingest a wide range of live inputs, then encode and package them as HLS, MPEG-DASH, CMAR, SRT and Zixi. | +| **File orchestration** | Centralised job distribution, load balancing, and node monitoring via Cambria Cluster | +| **Hybrid processing** | On-prem and cloud resources managed within a single workflow, including workload bursting | +| **Automation & integration** | REST APIs for workflow automation and integration with existing media systems | +| **Scalability model** | Horizontal scaling based on available compute resources (CPU/GPU/VPU, environment-dependent) | ### **Architectural diagrams** diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts index c1139db97b3..26c4b79f44d 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/index.ts @@ -12,7 +12,7 @@ import { radSecurityPlatform } from './rad-security-platform'; import { scaleflexSmartMediaCloudAndDam } from './scaleflex-smart-media-cloud-and-dam'; import { sftpgo } from './sftpgo'; import { synadiaPlatform } from './synadia-platform'; -import { titan } from './titan'; +import { titanVideoProcessingAndCompression } from './titan-video-processing-and-compression'; import { vindralLive } from './vindral-live'; import { vodEncoder } from './vod-encoder'; @@ -47,7 +47,7 @@ const detailsMap: Record = { 'scaleflex-smart-media-cloud-and-dam': scaleflexSmartMediaCloudAndDam, sftpgo, 'synadia-platform': synadiaPlatform, - titan, + 'titan-video-processing-and-compression': titanVideoProcessingAndCompression, 'vindral-live': vindralLive, 'vod-encoder': vodEncoder, // Add more products here as you add their details files diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/multiplayer-game-server-hosting-orchestration.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/multiplayer-game-server-hosting-orchestration.ts index e781adf5e01..4f8d06b2e45 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/multiplayer-game-server-hosting-orchestration.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/multiplayer-game-server-hosting-orchestration.ts @@ -62,7 +62,6 @@ const documentationMarkdown = ` | **Compliance – Security** | SOC 1, SOC2, and SOC 3 (upon request) | | **Compliance – Regional** | GDPR, EU-US Privacy Shield, Swiss-US Privacy Shield, HIPAA (upon request), FedRAMP (upon request) | -### "Fully details" variation (with some modifications) ![Edgegap Architecture](/assets/marketplace/eg-architecture.jpeg) `.trim(); diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/scaleflex-smart-media-cloud-and-dam.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/scaleflex-smart-media-cloud-and-dam.ts index 4d31cf0ac6c..8ed828106e7 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/scaleflex-smart-media-cloud-and-dam.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/scaleflex-smart-media-cloud-and-dam.ts @@ -47,13 +47,13 @@ Interested? Book a demo with our team. In this demo, you will: const documentationMarkdown = ` | Specification | Details | | :---- | :---- | -| Deployment Model | Cloud-native SaaS, composable MACH architecture with online hub and headless API access | -| Supported Data Sources | Visual assets (images, videos, documents), ingress via drag-and-drop, CSV, and API | -| API Type | RESTful headless APIs for media upload, management, optimization and enrichment platform functions; CLI and widgets available | -| Programming Languages | Language-agnostic REST APIs; typical SDK use in JavaScript or any language capable of REST calls | -| Availability SLA | 99.9% uptime | -| Security | Standard token/API auth, permissions/roles, SSO / MFA | -| Compliance | GDPR compliance, MACH Alliance certified, 10 Core accredited DAM vendor | +| **Deployment Model** | Cloud-native SaaS, composable MACH architecture with online hub and headless API access | +| **Supported Data Sources** | Visual assets (images, videos, documents), ingress via drag-and-drop, CSV, and API | +| **API Type** | RESTful headless APIs for media upload, management, optimization and enrichment platform functions; CLI and widgets available | +| **Programming Languages** | Language-agnostic REST APIs; typical SDK use in JavaScript or any language capable of REST calls | +| **Availability SLA** | 99.9% uptime | +| **Security** | Standard token/API auth, permissions/roles, SSO / MFA | +| **Compliance** | GDPR compliance, MACH Alliance certified, 10 Core accredited DAM vendor | Full documentation under: [https://docs.scaleflex.com/](https://docs.scaleflex.com/) diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/synadia-platform.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/synadia-platform.ts index 4aa390d1dd6..a8b01954bfb 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/synadia-platform.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/synadia-platform.ts @@ -37,14 +37,14 @@ Ready to start your free trial of Synadia Platform on the Akamai Cloud? Contact const documentationMarkdown = ` | Specification | Details | | :---- | :---- | -| Deployment model | Managed BYOC on Akamai Cloud or self-hosted. | -| Cloud & edge support | Native operation across Akamai, AWS, Azure, GCP, private clouds, and constrained edge environments. | -| Operational footprint | Lightweight, single-binary core with minimal dependencies and simplified operations at scale. | -| Security | Zero-trust security with mTLS, fine-grained authorization, and no shared secrets or stored credentials. | -| Latency profile | Millisecond-level data and service propagation with local-first access via mirrors and replicas. | -| Architecture | Event-driven, real-time messaging and streaming built on a single global connective fabric. | -| Replication & locality | Built-in geo-replication, mirroring, and digital twins for fast local reads and global consistency. | -| Data capabilities | Unified support for messaging, durable streams, key-value storage, and object storage. | +| **Deployment model** | Managed BYOC on Akamai Cloud or self-hosted. | +| **Cloud & edge support** | Native operation across Akamai, AWS, Azure, GCP, private clouds, and constrained edge environments. | +| **Operational footprint** | Lightweight, single-binary core with minimal dependencies and simplified operations at scale. | +| **Security** | Zero-trust security with mTLS, fine-grained authorization, and no shared secrets or stored credentials. | +| **Latency profile** | Millisecond-level data and service propagation with local-first access via mirrors and replicas. | +| **Architecture** | Event-driven, real-time messaging and streaming built on a single global connective fabric. | +| **Replication & locality** | Built-in geo-replication, mirroring, and digital twins for fast local reads and global consistency. | +| **Data capabilities** | Unified support for messaging, durable streams, key-value storage, and object storage. | The Synadia Platform, running on Akamai, enables a globally connected NATS supercluster to act as a single logical event fabric spanning regions, clouds, and the edge. At the core, multiple regional NATS clusters form a supercluster, providing high availability, low latency, and seamless data routing across geographies. diff --git a/packages/manager/src/features/Marketplace/ProductDetails/pages/titan.ts b/packages/manager/src/features/Marketplace/ProductDetails/pages/titan-video-processing-and-compression.ts similarity index 65% rename from packages/manager/src/features/Marketplace/ProductDetails/pages/titan.ts rename to packages/manager/src/features/Marketplace/ProductDetails/pages/titan-video-processing-and-compression.ts index 8b648a7fe13..a2cb7e9b707 100644 --- a/packages/manager/src/features/Marketplace/ProductDetails/pages/titan.ts +++ b/packages/manager/src/features/Marketplace/ProductDetails/pages/titan-video-processing-and-compression.ts @@ -1,22 +1,28 @@ import type { ProductTabDetails } from '.'; const overviewMarkdown = ` -Ateme is a global leader of video compression and delivery solutions helping tier-one content providers, service providers and streaming platforms to boost their viewership and subscription engagement. With Atemesolutions you can build a platform for streaming, OTT or IPTV services that captivates your audience with outstanding experiences. And you do that while saving infrastructure costs and minimizing your carbon footprint. +Ateme is a global leader of video compression and delivery solutions helping tier-one content providers, service providers and streaming platforms to boost their viewership and subscription engagement. With Ateme solutions you can build a platform for streaming, OTT or IPTV services that captivates your audience with outstanding experiences. And you do that while saving infrastructure costs and minimizing your carbon footprint. Ateme helps by improving your end user experiences, reduces TCO, and simplifies operation. With the partnership with Akamai, Ateme expands its video streaming ecosystem offering further with Akamai Cloud and CDN. -Ateme’s solutions are deployed by professional service teams on Akamai Cloud. The solution leverages Akamai shared compute instances, Block Storage, VLANs & Node Balancer, LKE Kubernetes platform, and Akamai CDN. +Ateme's solutions are deployed by professional service teams on Akamai Cloud. The solution leverages Akamai shared compute instances, Block Storage, VLANs & Node Balancer, LKE Kubernetes platform, and Akamai CDN. ### **Benefits** -* **Offer a premium viewing experience:** Deliver the highest quality content at the lowest bitrate to delight your audiences with all kinds of content – including UHD, 4K, and HDR. Ensure low latency on all platforms and broadcast-level latency on streaming platforms, with reduced rebuffering. +* **Offer a premium viewing experience:** Deliver the highest quality content at the lowest bitrate to delight your audiences with all kinds of content - including UHD, 4K, and HDR. Ensure low latency on all platforms and broadcast-level latency on streaming platforms, with reduced rebuffering. * **Outstanding video experiences:** Launch broadcast-quality, low-latency TV services quickly and securely. Wow your audience with the ultimate viewing experience on any screen with 4K HDR and immersive sound. Engage with them based on personalized channels and interactive content enabled by 5G. * **Reduce total cost of ownership:** Save bandwidth and storage requirements with the unmatched compression efficiency of TITAN encoders/decoders, faster-than-real-time capabilities, and simultaneous processing of all formats. Reduce waste and complexity with a single workflow for both live and file transcoding. Optimize your delivery platform by repurposing available cloud-native resources for file transcoding. * **Go green:** Save bandwidth and storage requirements with the unmatched compression efficiency of Kyrion and TITAN. Optimize your delivery platform by repurposing available cloud-native resources for file transcoding. Reduce waste and complexity with a single workflow for both live and file transcoding. Go green – with no compromise on video quality. `.trim(); +const documentationMarkdown = ` +The Ateme Live OTT solution provides a robust, three-tier delivery workflow on Akamai. The process begins with the Cloud Gateway (TITAN Edge), which ingests live feeds via a public SRT stream. Next, the Live Transcoders (TITAN Live) encode the video pipeline into adaptive bitrate video layers, which are then delivered through CMAF ingest to the final component, the Live Packager (NEA Live). This component formats the content for seamless delivery to end users via the Akamai Global CDN and OTT video players. + +![Ateme Flow](/assets/marketplace/ateme-flow.jpeg) +`.trim(); + const pricingMarkdown = ` Pricing details will be discussed directly with the third-party provider Sales team after your request is received, and the third-party provider contacts you. Costs of the product you will be purchasing from the third-party provider will be charged by the third-party provider. For the referral motion, Akamai is not a party in the purchase contract. @@ -27,8 +33,9 @@ const supportMarkdown = ` For product support, reach out to the vendor directly. You can find contact information in the product documentation and on the vendor's website. `.trim(); -export const titan: ProductTabDetails = { +export const titanVideoProcessingAndCompression: ProductTabDetails = { overview: overviewMarkdown, + documentation: documentationMarkdown, pricing: pricingMarkdown, support: supportMarkdown, }; diff --git a/packages/manager/src/features/Marketplace/products.ts b/packages/manager/src/features/Marketplace/products.ts index 006dd4585b3..c5b205ed88f 100644 --- a/packages/manager/src/features/Marketplace/products.ts +++ b/packages/manager/src/features/Marketplace/products.ts @@ -268,8 +268,8 @@ export const PRODUCTS: Product[] = [ }, { categories: ['Media & Entertainment, Gaming'], - id: 'titan', - name: 'Titan', + id: 'titan-video-processing-and-compression', + name: 'TITAN Video Processing and Compression', partner: { email: 'inquiries@ateme.com', logoDarkMode: 'ateme-dark.svg', From 174f9630d9e0f76666532efb7e56bce94179369d Mon Sep 17 00:00:00 2001 From: Ganesh Revanakar Date: Wed, 11 Mar 2026 16:48:18 +0530 Subject: [PATCH 56/56] Cloud version 1.160.0, API v4 version 0.158.0, Validation version 0.83.0, UI version 0.25.0, Queries version 0.22.0 --- .../pr-13413-changed-1771602214397.md | 5 -- ...r-13418-upcoming-features-1771851737264.md | 5 -- ...r-13445-upcoming-features-1772199727781.md | 5 -- .../pr-13461-changed-1772617190589.md | 5 -- .../pr-13467-added-1772701469134.md | 5 -- .../pr-13472-changed-1773131929522.md | 5 -- packages/api-v4/CHANGELOG.md | 18 +++++ packages/api-v4/package.json | 2 +- .../pr-13397-added-1770981264750.md | 5 -- .../pr-13399-fixed-1771414399036.md | 5 -- .../pr-13403-tests-1771579513582.md | 5 -- ...r-13407-upcoming-features-1771317211182.md | 5 -- .../pr-13409-added-1771405985553.md | 5 -- .../pr-13410-changed-1772435694557.md | 5 -- .../pr-13411-fixed-1771418285151.md | 5 -- ...r-13412-upcoming-features-1771427444510.md | 5 -- ...r-13413-upcoming-features-1771602250906.md | 5 -- ...r-13418-upcoming-features-1771851666095.md | 5 -- .../pr-13420-added-1771523317072.md | 5 -- .../pr-13425-changed-1771593559752.md | 5 -- ...r-13432-upcoming-features-1772094828866.md | 5 -- ...r-13435-upcoming-features-1772580889092.md | 5 -- .../pr-13437-changed-1772019096600.md | 5 -- .../pr-13438-tests-1772047855280.md | 5 -- ...r-13439-upcoming-features-1772132438864.md | 5 -- .../pr-13440-tests-1772556190302.md | 5 -- .../pr-13441-fixed-1772114115915.md | 5 -- .../pr-13444-changed-1772188843247.md | 5 -- ...r-13445-upcoming-features-1772199672997.md | 5 -- .../pr-13448-fixed-1772228313479.md | 5 -- .../pr-13451-fixed-1772457963491.md | 5 -- .../pr-13452-added-1772466320530.md | 5 -- .../pr-13454-removed-1772484449775.md | 5 -- .../pr-13456-added-1772643395780.md | 5 -- .../pr-13457-tests-1772559220854.md | 5 -- .../pr-13458-fixed-1772574441245.md | 5 -- .../pr-13459-fixed-1772610765361.md | 5 -- ...r-13460-upcoming-features-1772610973355.md | 5 -- .../pr-13461-changed-1772617249955.md | 5 -- .../pr-13462-fixed-1772624564447.md | 5 -- .../pr-13463-fixed-1772640311940.md | 5 -- .../pr-13464-fixed-1772634680494.md | 5 -- .../pr-13467-changed-1772702080743.md | 5 -- .../pr-13468-changed-1772720184107.md | 5 -- .../pr-13470-tests-1772743282866.md | 5 -- ...r-13471-upcoming-features-1773085243886.md | 5 -- .../pr-13472-fixed-1773071273109.md | 5 -- .../pr-13473-added-1773079125538.md | 5 -- ...r-13474-upcoming-features-1773090286395.md | 5 -- ...r-13475-upcoming-features-1773138396314.md | 11 --- .../pr-13476-fixed-1773151456914.md | 5 -- packages/manager/CHANGELOG.md | 67 +++++++++++++++++++ packages/manager/package.json | 2 +- .../pr-13419-fixed-1771522382949.md | 5 -- packages/queries/CHANGELOG.md | 7 ++ packages/queries/package.json | 2 +- ...r-13418-upcoming-features-1771851880267.md | 5 -- packages/ui/CHANGELOG.md | 7 ++ packages/ui/package.json | 2 +- .../pr-13392-changed-1770898290092.md | 5 -- packages/validation/CHANGELOG.md | 7 ++ packages/validation/package.json | 2 +- 62 files changed, 111 insertions(+), 271 deletions(-) delete mode 100644 packages/api-v4/.changeset/pr-13413-changed-1771602214397.md delete mode 100644 packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md delete mode 100644 packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md delete mode 100644 packages/api-v4/.changeset/pr-13461-changed-1772617190589.md delete mode 100644 packages/api-v4/.changeset/pr-13467-added-1772701469134.md delete mode 100644 packages/api-v4/.changeset/pr-13472-changed-1773131929522.md delete mode 100644 packages/manager/.changeset/pr-13397-added-1770981264750.md delete mode 100644 packages/manager/.changeset/pr-13399-fixed-1771414399036.md delete mode 100644 packages/manager/.changeset/pr-13403-tests-1771579513582.md delete mode 100644 packages/manager/.changeset/pr-13407-upcoming-features-1771317211182.md delete mode 100644 packages/manager/.changeset/pr-13409-added-1771405985553.md delete mode 100644 packages/manager/.changeset/pr-13410-changed-1772435694557.md delete mode 100644 packages/manager/.changeset/pr-13411-fixed-1771418285151.md delete mode 100644 packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md delete mode 100644 packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md delete mode 100644 packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md delete mode 100644 packages/manager/.changeset/pr-13420-added-1771523317072.md delete mode 100644 packages/manager/.changeset/pr-13425-changed-1771593559752.md delete mode 100644 packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md delete mode 100644 packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md delete mode 100644 packages/manager/.changeset/pr-13437-changed-1772019096600.md delete mode 100644 packages/manager/.changeset/pr-13438-tests-1772047855280.md delete mode 100644 packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md delete mode 100644 packages/manager/.changeset/pr-13440-tests-1772556190302.md delete mode 100644 packages/manager/.changeset/pr-13441-fixed-1772114115915.md delete mode 100644 packages/manager/.changeset/pr-13444-changed-1772188843247.md delete mode 100644 packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md delete mode 100644 packages/manager/.changeset/pr-13448-fixed-1772228313479.md delete mode 100644 packages/manager/.changeset/pr-13451-fixed-1772457963491.md delete mode 100644 packages/manager/.changeset/pr-13452-added-1772466320530.md delete mode 100644 packages/manager/.changeset/pr-13454-removed-1772484449775.md delete mode 100644 packages/manager/.changeset/pr-13456-added-1772643395780.md delete mode 100644 packages/manager/.changeset/pr-13457-tests-1772559220854.md delete mode 100644 packages/manager/.changeset/pr-13458-fixed-1772574441245.md delete mode 100644 packages/manager/.changeset/pr-13459-fixed-1772610765361.md delete mode 100644 packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md delete mode 100644 packages/manager/.changeset/pr-13461-changed-1772617249955.md delete mode 100644 packages/manager/.changeset/pr-13462-fixed-1772624564447.md delete mode 100644 packages/manager/.changeset/pr-13463-fixed-1772640311940.md delete mode 100644 packages/manager/.changeset/pr-13464-fixed-1772634680494.md delete mode 100644 packages/manager/.changeset/pr-13467-changed-1772702080743.md delete mode 100644 packages/manager/.changeset/pr-13468-changed-1772720184107.md delete mode 100644 packages/manager/.changeset/pr-13470-tests-1772743282866.md delete mode 100644 packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md delete mode 100644 packages/manager/.changeset/pr-13472-fixed-1773071273109.md delete mode 100644 packages/manager/.changeset/pr-13473-added-1773079125538.md delete mode 100644 packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md delete mode 100644 packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md delete mode 100644 packages/manager/.changeset/pr-13476-fixed-1773151456914.md delete mode 100644 packages/queries/.changeset/pr-13419-fixed-1771522382949.md delete mode 100644 packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md delete mode 100644 packages/validation/.changeset/pr-13392-changed-1770898290092.md diff --git a/packages/api-v4/.changeset/pr-13413-changed-1771602214397.md b/packages/api-v4/.changeset/pr-13413-changed-1771602214397.md deleted file mode 100644 index 69bdb6b4dff..00000000000 --- a/packages/api-v4/.changeset/pr-13413-changed-1771602214397.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/api-v4": Changed ---- - -Export `HostEndpoint` and rename `private_access` to `public_access` ([#13413](https://github.com/linode/manager/pull/13413)) diff --git a/packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md b/packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md deleted file mode 100644 index 170fdf886d5..00000000000 --- a/packages/api-v4/.changeset/pr-13418-upcoming-features-1771851737264.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/api-v4": Upcoming Features ---- - -Add `shared` to ImageType ([#13418](https://github.com/linode/manager/pull/13418)) diff --git a/packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md b/packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md deleted file mode 100644 index 13779090c25..00000000000 --- a/packages/api-v4/.changeset/pr-13445-upcoming-features-1772199727781.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/api-v4": Upcoming Features ---- - -Add logs to `CloudPulseServiceType` and `capabilityServiceTypeMapping` ([#13445](https://github.com/linode/manager/pull/13445)) diff --git a/packages/api-v4/.changeset/pr-13461-changed-1772617190589.md b/packages/api-v4/.changeset/pr-13461-changed-1772617190589.md deleted file mode 100644 index 80c2a79bfa8..00000000000 --- a/packages/api-v4/.changeset/pr-13461-changed-1772617190589.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/api-v4": Changed ---- - -Switch delivery endpoints from Beta APIv4 to APIv4 ([#13461](https://github.com/linode/manager/pull/13461)) diff --git a/packages/api-v4/.changeset/pr-13467-added-1772701469134.md b/packages/api-v4/.changeset/pr-13467-added-1772701469134.md deleted file mode 100644 index 96651c0c718..00000000000 --- a/packages/api-v4/.changeset/pr-13467-added-1772701469134.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/api-v4": Added ---- - -Add `ACLP Logs Datacenter LKE-E` to the Region's `Capability` type ([#13467](https://github.com/linode/manager/pull/13467)) diff --git a/packages/api-v4/.changeset/pr-13472-changed-1773131929522.md b/packages/api-v4/.changeset/pr-13472-changed-1773131929522.md deleted file mode 100644 index a63287e6a07..00000000000 --- a/packages/api-v4/.changeset/pr-13472-changed-1773131929522.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/api-v4": Changed ---- - -Update node balancer type for enterprise from premium_40GB to premium_40gb ([#13472](https://github.com/linode/manager/pull/13472)) diff --git a/packages/api-v4/CHANGELOG.md b/packages/api-v4/CHANGELOG.md index 4256b21626d..d0f37f982d8 100644 --- a/packages/api-v4/CHANGELOG.md +++ b/packages/api-v4/CHANGELOG.md @@ -1,3 +1,21 @@ +## [2026-03-16] - v0.158.0 + + +### Added: + +- Add `ACLP Logs Datacenter LKE-E` to the Region's `Capability` type ([#13467](https://github.com/linode/manager/pull/13467)) + +### Changed: + +- Export `HostEndpoint` and rename `private_access` to `public_access` ([#13413](https://github.com/linode/manager/pull/13413)) +- Switch delivery endpoints from Beta APIv4 to APIv4 ([#13461](https://github.com/linode/manager/pull/13461)) +- Update node balancer type for enterprise from premium_40GB to premium_40gb ([#13472](https://github.com/linode/manager/pull/13472)) + +### Upcoming Features: + +- Add `shared` to ImageType ([#13418](https://github.com/linode/manager/pull/13418)) +- Add logs to `CloudPulseServiceType` and `capabilityServiceTypeMapping` ([#13445](https://github.com/linode/manager/pull/13445)) + ## [2026-02-25] - v0.157.0 diff --git a/packages/api-v4/package.json b/packages/api-v4/package.json index a16901f1527..691ce5ea5c4 100644 --- a/packages/api-v4/package.json +++ b/packages/api-v4/package.json @@ -1,6 +1,6 @@ { "name": "@linode/api-v4", - "version": "0.157.0", + "version": "0.158.0", "homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4", "bugs": { "url": "https://github.com/linode/manager/issues" diff --git a/packages/manager/.changeset/pr-13397-added-1770981264750.md b/packages/manager/.changeset/pr-13397-added-1770981264750.md deleted file mode 100644 index 871e76f5ba5..00000000000 --- a/packages/manager/.changeset/pr-13397-added-1770981264750.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Added ---- - -IAM: adds the URL params to Assigned Roles and Assigned Entities tables ([#13397](https://github.com/linode/manager/pull/13397)) diff --git a/packages/manager/.changeset/pr-13399-fixed-1771414399036.md b/packages/manager/.changeset/pr-13399-fixed-1771414399036.md deleted file mode 100644 index 9288b7e90f7..00000000000 --- a/packages/manager/.changeset/pr-13399-fixed-1771414399036.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -IAM Delegation: incorrect landing page after account switch, wrong top menu username, pagination disappears in the User Delegations table ([#13399](https://github.com/linode/manager/pull/13399)) diff --git a/packages/manager/.changeset/pr-13403-tests-1771579513582.md b/packages/manager/.changeset/pr-13403-tests-1771579513582.md deleted file mode 100644 index 5d51c465972..00000000000 --- a/packages/manager/.changeset/pr-13403-tests-1771579513582.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Tests ---- - -Object storage summary tests added ([#13403](https://github.com/linode/manager/pull/13403)) diff --git a/packages/manager/.changeset/pr-13407-upcoming-features-1771317211182.md b/packages/manager/.changeset/pr-13407-upcoming-features-1771317211182.md deleted file mode 100644 index 00595dfdf8d..00000000000 --- a/packages/manager/.changeset/pr-13407-upcoming-features-1771317211182.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Private Image Sharing tabs new layout (v2) ([#13407](https://github.com/linode/manager/pull/13407)) diff --git a/packages/manager/.changeset/pr-13409-added-1771405985553.md b/packages/manager/.changeset/pr-13409-added-1771405985553.md deleted file mode 100644 index 1c4b57f817a..00000000000 --- a/packages/manager/.changeset/pr-13409-added-1771405985553.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Added ---- - -IAM Parent/Child: add permissions to UI ([#13409](https://github.com/linode/manager/pull/13409)) diff --git a/packages/manager/.changeset/pr-13410-changed-1772435694557.md b/packages/manager/.changeset/pr-13410-changed-1772435694557.md deleted file mode 100644 index dcd3b8c1141..00000000000 --- a/packages/manager/.changeset/pr-13410-changed-1772435694557.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -Make firewall selection mandatory while creating linode and its interfaces ([#13410](https://github.com/linode/manager/pull/13410)) diff --git a/packages/manager/.changeset/pr-13411-fixed-1771418285151.md b/packages/manager/.changeset/pr-13411-fixed-1771418285151.md deleted file mode 100644 index df3ca3affe3..00000000000 --- a/packages/manager/.changeset/pr-13411-fixed-1771418285151.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -IAM: style fix for long username ([#13411](https://github.com/linode/manager/pull/13411)) diff --git a/packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md b/packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md deleted file mode 100644 index 81c5cb1f276..00000000000 --- a/packages/manager/.changeset/pr-13412-upcoming-features-1771427444510.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Empty message for `SwitchAccountDrawer` child accounts table ([#13412](https://github.com/linode/manager/pull/13412)) diff --git a/packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md b/packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md deleted file mode 100644 index ae8b475f78a..00000000000 --- a/packages/manager/.changeset/pr-13413-upcoming-features-1771602250906.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Use new hostname endpoint in Database Summary and Network tab ([#13413](https://github.com/linode/manager/pull/13413)) diff --git a/packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md b/packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md deleted file mode 100644 index 7de2513b206..00000000000 --- a/packages/manager/.changeset/pr-13418-upcoming-features-1771851666095.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Add reusable `ImagesView` and `ImagesTable` components, and integrated them for the `Owned by me` Images tab (v2) ([#13418](https://github.com/linode/manager/pull/13418)) diff --git a/packages/manager/.changeset/pr-13420-added-1771523317072.md b/packages/manager/.changeset/pr-13420-added-1771523317072.md deleted file mode 100644 index 66f3ce2e9ac..00000000000 --- a/packages/manager/.changeset/pr-13420-added-1771523317072.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Added ---- - -Add Gemma3, Qwen, Milvus, pgvector, and GPT-oss Markeplace apps ([#13420](https://github.com/linode/manager/pull/13420)) diff --git a/packages/manager/.changeset/pr-13425-changed-1771593559752.md b/packages/manager/.changeset/pr-13425-changed-1771593559752.md deleted file mode 100644 index 93a12fae9b4..00000000000 --- a/packages/manager/.changeset/pr-13425-changed-1771593559752.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -Delivery Logs - in Custom HTTPS form set authentication.details to undefined when None authentication is selected ([#13425](https://github.com/linode/manager/pull/13425)) diff --git a/packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md b/packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md deleted file mode 100644 index 5dd40f2c799..00000000000 --- a/packages/manager/.changeset/pr-13432-upcoming-features-1772094828866.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - - Add Recovery images tab (v2) ([#13432](https://github.com/linode/manager/pull/13432)) diff --git a/packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md b/packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md deleted file mode 100644 index 105a8c6351a..00000000000 --- a/packages/manager/.changeset/pr-13435-upcoming-features-1772580889092.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Add new Image Select table and use it in Linode Create > Images tab ([#13435](https://github.com/linode/manager/pull/13435)) diff --git a/packages/manager/.changeset/pr-13437-changed-1772019096600.md b/packages/manager/.changeset/pr-13437-changed-1772019096600.md deleted file mode 100644 index adfe3719b78..00000000000 --- a/packages/manager/.changeset/pr-13437-changed-1772019096600.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -IAM: update last login field for delegate users ([#13437](https://github.com/linode/manager/pull/13437)) diff --git a/packages/manager/.changeset/pr-13438-tests-1772047855280.md b/packages/manager/.changeset/pr-13438-tests-1772047855280.md deleted file mode 100644 index af35fa64ad0..00000000000 --- a/packages/manager/.changeset/pr-13438-tests-1772047855280.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Tests ---- - -Fix Cypress test failures following v1.159.0 release ([#13438](https://github.com/linode/manager/pull/13438)) diff --git a/packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md b/packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md deleted file mode 100644 index 8e1c634a320..00000000000 --- a/packages/manager/.changeset/pr-13439-upcoming-features-1772132438864.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Use new hostname endpoints in Service URIs and display public/private URIs for public VPCs ([#13439](https://github.com/linode/manager/pull/13439)) diff --git a/packages/manager/.changeset/pr-13440-tests-1772556190302.md b/packages/manager/.changeset/pr-13440-tests-1772556190302.md deleted file mode 100644 index 7ae6571a992..00000000000 --- a/packages/manager/.changeset/pr-13440-tests-1772556190302.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Tests ---- - -Cypress tests for Postgresql Synchronous Replication Advanced Configuration ([#13440](https://github.com/linode/manager/pull/13440)) diff --git a/packages/manager/.changeset/pr-13441-fixed-1772114115915.md b/packages/manager/.changeset/pr-13441-fixed-1772114115915.md deleted file mode 100644 index dc650537622..00000000000 --- a/packages/manager/.changeset/pr-13441-fixed-1772114115915.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -IAM Parent/Child: Use User infinite query in UpdateDelegationDrawer ([#13441](https://github.com/linode/manager/pull/13441)) diff --git a/packages/manager/.changeset/pr-13444-changed-1772188843247.md b/packages/manager/.changeset/pr-13444-changed-1772188843247.md deleted file mode 100644 index 8a0e84deaef..00000000000 --- a/packages/manager/.changeset/pr-13444-changed-1772188843247.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -Improvements for bucket selection in Akamai Object Storage Destination form ([#13444](https://github.com/linode/manager/pull/13444)) diff --git a/packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md b/packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md deleted file mode 100644 index 12637196e19..00000000000 --- a/packages/manager/.changeset/pr-13445-upcoming-features-1772199672997.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Integrate aclp-logs service to alerts with custom validation schemas, error texts ([#13445](https://github.com/linode/manager/pull/13445)) diff --git a/packages/manager/.changeset/pr-13448-fixed-1772228313479.md b/packages/manager/.changeset/pr-13448-fixed-1772228313479.md deleted file mode 100644 index 8b60e9f805d..00000000000 --- a/packages/manager/.changeset/pr-13448-fixed-1772228313479.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Database Connection Pools table page size ([#13448](https://github.com/linode/manager/pull/13448)) diff --git a/packages/manager/.changeset/pr-13451-fixed-1772457963491.md b/packages/manager/.changeset/pr-13451-fixed-1772457963491.md deleted file mode 100644 index 16cedfd4ef6..00000000000 --- a/packages/manager/.changeset/pr-13451-fixed-1772457963491.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -IAM / Entities & Roles client-side pagination on page refresh ([#13451](https://github.com/linode/manager/pull/13451)) diff --git a/packages/manager/.changeset/pr-13452-added-1772466320530.md b/packages/manager/.changeset/pr-13452-added-1772466320530.md deleted file mode 100644 index 0259d1e8b92..00000000000 --- a/packages/manager/.changeset/pr-13452-added-1772466320530.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Added ---- - -New condition for displaying volume metrics tab ([#13452](https://github.com/linode/manager/pull/13452)) diff --git a/packages/manager/.changeset/pr-13454-removed-1772484449775.md b/packages/manager/.changeset/pr-13454-removed-1772484449775.md deleted file mode 100644 index e6a3cb4946d..00000000000 --- a/packages/manager/.changeset/pr-13454-removed-1772484449775.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Removed ---- - -Remove New chip from Database Networking Tab and Access banner from Settings ([#13454](https://github.com/linode/manager/pull/13454)) diff --git a/packages/manager/.changeset/pr-13456-added-1772643395780.md b/packages/manager/.changeset/pr-13456-added-1772643395780.md deleted file mode 100644 index da7d049be31..00000000000 --- a/packages/manager/.changeset/pr-13456-added-1772643395780.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Added ---- - -New condition for displaying bucket metrics tab ([#13456](https://github.com/linode/manager/pull/13456)) diff --git a/packages/manager/.changeset/pr-13457-tests-1772559220854.md b/packages/manager/.changeset/pr-13457-tests-1772559220854.md deleted file mode 100644 index 1922b893a27..00000000000 --- a/packages/manager/.changeset/pr-13457-tests-1772559220854.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Tests ---- - -Fix cypress test failing for hostname endpoint changes ([#13457](https://github.com/linode/manager/pull/13457)) diff --git a/packages/manager/.changeset/pr-13458-fixed-1772574441245.md b/packages/manager/.changeset/pr-13458-fixed-1772574441245.md deleted file mode 100644 index c7534259f0a..00000000000 --- a/packages/manager/.changeset/pr-13458-fixed-1772574441245.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Linode Interfaces network connection incorrectly disabled when createing a Linode from a Backup ([#13458](https://github.com/linode/manager/pull/13458)) diff --git a/packages/manager/.changeset/pr-13459-fixed-1772610765361.md b/packages/manager/.changeset/pr-13459-fixed-1772610765361.md deleted file mode 100644 index a7ecf54bc4c..00000000000 --- a/packages/manager/.changeset/pr-13459-fixed-1772610765361.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Unnecessary API requests for Delivery services while searching when feature access is not present ([#13459](https://github.com/linode/manager/pull/13459)) diff --git a/packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md b/packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md deleted file mode 100644 index d7cda247dc2..00000000000 --- a/packages/manager/.changeset/pr-13460-upcoming-features-1772610973355.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Logs service integration changes for onboarding with `CloudPulse Metrics` ([#13460](https://github.com/linode/manager/pull/13460)) diff --git a/packages/manager/.changeset/pr-13461-changed-1772617249955.md b/packages/manager/.changeset/pr-13461-changed-1772617249955.md deleted file mode 100644 index 5de9a12ee9d..00000000000 --- a/packages/manager/.changeset/pr-13461-changed-1772617249955.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -Delivery CRUD mocks update from Beta APIv4 to APIv4 ([#13461](https://github.com/linode/manager/pull/13461)) diff --git a/packages/manager/.changeset/pr-13462-fixed-1772624564447.md b/packages/manager/.changeset/pr-13462-fixed-1772624564447.md deleted file mode 100644 index 190daf63ab7..00000000000 --- a/packages/manager/.changeset/pr-13462-fixed-1772624564447.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Await permissions to show error on User Detail ([#13462](https://github.com/linode/manager/pull/13462)) diff --git a/packages/manager/.changeset/pr-13463-fixed-1772640311940.md b/packages/manager/.changeset/pr-13463-fixed-1772640311940.md deleted file mode 100644 index d0a3846b468..00000000000 --- a/packages/manager/.changeset/pr-13463-fixed-1772640311940.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Throughtput quota conversion logic ([#13463](https://github.com/linode/manager/pull/13463)) diff --git a/packages/manager/.changeset/pr-13464-fixed-1772634680494.md b/packages/manager/.changeset/pr-13464-fixed-1772634680494.md deleted file mode 100644 index 229fecf3f04..00000000000 --- a/packages/manager/.changeset/pr-13464-fixed-1772634680494.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -IAM Parent/Child - SwitchAccount Drawer: hide search if no child account ([#13464](https://github.com/linode/manager/pull/13464)) diff --git a/packages/manager/.changeset/pr-13467-changed-1772702080743.md b/packages/manager/.changeset/pr-13467-changed-1772702080743.md deleted file mode 100644 index 06969619357..00000000000 --- a/packages/manager/.changeset/pr-13467-changed-1772702080743.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -Stream Create/Edit form: in the Clusters table show only clusters with a region that has "ACLP Logs Datacenter LKE-E" capability ([#13467](https://github.com/linode/manager/pull/13467)) diff --git a/packages/manager/.changeset/pr-13468-changed-1772720184107.md b/packages/manager/.changeset/pr-13468-changed-1772720184107.md deleted file mode 100644 index 4f6cad9389f..00000000000 --- a/packages/manager/.changeset/pr-13468-changed-1772720184107.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Changed ---- - -Improve UpdateDelegateDrawer & EntitiesSelect UI ([#13468](https://github.com/linode/manager/pull/13468)) diff --git a/packages/manager/.changeset/pr-13470-tests-1772743282866.md b/packages/manager/.changeset/pr-13470-tests-1772743282866.md deleted file mode 100644 index 6a685721520..00000000000 --- a/packages/manager/.changeset/pr-13470-tests-1772743282866.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Tests ---- - -Fix test flakiness in account switching spec ([#13470](https://github.com/linode/manager/pull/13470)) diff --git a/packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md b/packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md deleted file mode 100644 index ba5d28e1179..00000000000 --- a/packages/manager/.changeset/pr-13471-upcoming-features-1773085243886.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Private Image Sharing: Add Share Groups tabs ([#13471](https://github.com/linode/manager/pull/13471)) diff --git a/packages/manager/.changeset/pr-13472-fixed-1773071273109.md b/packages/manager/.changeset/pr-13472-fixed-1773071273109.md deleted file mode 100644 index fc996cab12f..00000000000 --- a/packages/manager/.changeset/pr-13472-fixed-1773071273109.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Update node balancer type for enterprise and remove duplicate nodebalancer rows in VPC subnet table ([#13472](https://github.com/linode/manager/pull/13472)) diff --git a/packages/manager/.changeset/pr-13473-added-1773079125538.md b/packages/manager/.changeset/pr-13473-added-1773079125538.md deleted file mode 100644 index b91892779ac..00000000000 --- a/packages/manager/.changeset/pr-13473-added-1773079125538.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Added ---- - -Stream Create/Edit form: Show instructions in the Clusters section on how to enable Kubernetes API Audit log generation per cluster ([#13473](https://github.com/linode/manager/pull/13473)) diff --git a/packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md b/packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md deleted file mode 100644 index e1c9f1b3921..00000000000 --- a/packages/manager/.changeset/pr-13474-upcoming-features-1773090286395.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Upcoming Features ---- - -Fix Database PgBouncer Connection Pool bugs ([#13474](https://github.com/linode/manager/pull/13474)) diff --git a/packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md b/packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md deleted file mode 100644 index 9509b7d6a18..00000000000 --- a/packages/manager/.changeset/pr-13475-upcoming-features-1773138396314.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@linode/manager': Upcoming Features ---- - -Add new Marketplace products ([#13475](https://github.com/linode/manager/pull/13475)) - -- CloudCasa -- Live Encoder -- Playback -- Portainer -- VOD Encoder diff --git a/packages/manager/.changeset/pr-13476-fixed-1773151456914.md b/packages/manager/.changeset/pr-13476-fixed-1773151456914.md deleted file mode 100644 index 62a866e6c57..00000000000 --- a/packages/manager/.changeset/pr-13476-fixed-1773151456914.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/manager": Fixed ---- - -Marketplace product updates + contact sales drawer fix ([#13476](https://github.com/linode/manager/pull/13476)) diff --git a/packages/manager/CHANGELOG.md b/packages/manager/CHANGELOG.md index fe7c4ebf449..462ec02d89d 100644 --- a/packages/manager/CHANGELOG.md +++ b/packages/manager/CHANGELOG.md @@ -4,6 +4,73 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2026-03-16] - v1.160.0 + + +### : + +- Add new Marketplace products ([#13475](https://github.com/linode/manager/pull/13475)) + +### Added: + +- IAM: adds the URL params to Assigned Roles and Assigned Entities tables ([#13397](https://github.com/linode/manager/pull/13397)) +- IAM Parent/Child: add permissions to UI ([#13409](https://github.com/linode/manager/pull/13409)) +- Add Gemma3, Qwen, Milvus, pgvector, and GPT-oss Markeplace apps ([#13420](https://github.com/linode/manager/pull/13420)) +- New condition for displaying volume metrics tab ([#13452](https://github.com/linode/manager/pull/13452)) +- New condition for displaying bucket metrics tab ([#13456](https://github.com/linode/manager/pull/13456)) +- Stream Create/Edit form: Show instructions in the Clusters section on how to enable Kubernetes API Audit log generation per cluster ([#13473](https://github.com/linode/manager/pull/13473)) + +### Changed: + +- Make firewall selection mandatory while creating linode and its interfaces ([#13410](https://github.com/linode/manager/pull/13410)) +- Delivery Logs - in Custom HTTPS form set authentication.details to undefined when None authentication is selected ([#13425](https://github.com/linode/manager/pull/13425)) +- IAM: update last login field for delegate users ([#13437](https://github.com/linode/manager/pull/13437)) +- Improvements for bucket selection in Akamai Object Storage Destination form ([#13444](https://github.com/linode/manager/pull/13444)) +- Delivery CRUD mocks update from Beta APIv4 to APIv4 ([#13461](https://github.com/linode/manager/pull/13461)) +- Stream Create/Edit form: in the Clusters table show only clusters with a region that has "ACLP Logs Datacenter LKE-E" capability ([#13467](https://github.com/linode/manager/pull/13467)) +- Improve UpdateDelegateDrawer & EntitiesSelect UI ([#13468](https://github.com/linode/manager/pull/13468)) + +### Fixed: + +- IAM Delegation: incorrect landing page after account switch, wrong top menu username, pagination disappears in the User Delegations table ([#13399](https://github.com/linode/manager/pull/13399)) +- IAM: style fix for long username ([#13411](https://github.com/linode/manager/pull/13411)) +- IAM Parent/Child: Use User infinite query in UpdateDelegationDrawer ([#13441](https://github.com/linode/manager/pull/13441)) +- Database Connection Pools table page size ([#13448](https://github.com/linode/manager/pull/13448)) +- IAM / Entities & Roles client-side pagination on page refresh ([#13451](https://github.com/linode/manager/pull/13451)) +- Linode Interfaces network connection incorrectly disabled when createing a Linode from a Backup ([#13458](https://github.com/linode/manager/pull/13458)) +- Unnecessary API requests for Delivery services while searching when feature access is not present ([#13459](https://github.com/linode/manager/pull/13459)) +- Await permissions to show error on User Detail ([#13462](https://github.com/linode/manager/pull/13462)) +- Throughtput quota conversion logic ([#13463](https://github.com/linode/manager/pull/13463)) +- IAM Parent/Child - SwitchAccount Drawer: hide search if no child account ([#13464](https://github.com/linode/manager/pull/13464)) +- Update node balancer type for enterprise and remove duplicate nodebalancer rows in VPC subnet table ([#13472](https://github.com/linode/manager/pull/13472)) +- Marketplace product updates + contact sales drawer fix ([#13476](https://github.com/linode/manager/pull/13476)) + +### Removed: + +- Remove New chip from Database Networking Tab and Access banner from Settings ([#13454](https://github.com/linode/manager/pull/13454)) + +### Tests: + +- Object storage summary tests added ([#13403](https://github.com/linode/manager/pull/13403)) +- Fix Cypress test failures following v1.159.0 release ([#13438](https://github.com/linode/manager/pull/13438)) +- Cypress tests for Postgresql Synchronous Replication Advanced Configuration ([#13440](https://github.com/linode/manager/pull/13440)) +- Fix cypress test failing for hostname endpoint changes ([#13457](https://github.com/linode/manager/pull/13457)) +- Fix test flakiness in account switching spec ([#13470](https://github.com/linode/manager/pull/13470)) + +### Upcoming Features: + +- Private Image Sharing tabs new layout (v2) ([#13407](https://github.com/linode/manager/pull/13407)) +- Empty message for `SwitchAccountDrawer` child accounts table ([#13412](https://github.com/linode/manager/pull/13412)) +- Use new hostname endpoint in Database Summary and Network tab ([#13413](https://github.com/linode/manager/pull/13413)) +- Add reusable `ImagesView` and `ImagesTable` components, and integrated them for the `Owned by me` Images tab (v2) ([#13418](https://github.com/linode/manager/pull/13418)) +- Add Recovery images tab (v2) ([#13432](https://github.com/linode/manager/pull/13432)) +- Add new Image Select table and use it in Linode Create > Images tab ([#13435](https://github.com/linode/manager/pull/13435)) +- Use new hostname endpoints in Service URIs and display public/private URIs for public VPCs ([#13439](https://github.com/linode/manager/pull/13439)) +- Integrate aclp-logs service to alerts with custom validation schemas, error texts ([#13445](https://github.com/linode/manager/pull/13445)) +- Logs service integration changes for onboarding with `CloudPulse Metrics` ([#13460](https://github.com/linode/manager/pull/13460)) +- Private Image Sharing: Add Share Groups tabs ([#13471](https://github.com/linode/manager/pull/13471)) +- Fix Database PgBouncer Connection Pool bugs ([#13474](https://github.com/linode/manager/pull/13474)) + ## [2026-02-26] - v1.159.1 diff --git a/packages/manager/package.json b/packages/manager/package.json index 447a005cce1..248080fb44a 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -2,7 +2,7 @@ "name": "linode-manager", "author": "Linode", "description": "The Linode Manager website", - "version": "1.159.1", + "version": "1.160.0", "private": true, "type": "module", "bugs": { diff --git a/packages/queries/.changeset/pr-13419-fixed-1771522382949.md b/packages/queries/.changeset/pr-13419-fixed-1771522382949.md deleted file mode 100644 index 084104eb476..00000000000 --- a/packages/queries/.changeset/pr-13419-fixed-1771522382949.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/queries": Fixed ---- - -IAM: fix useGetChildAccountsQuery ([#13419](https://github.com/linode/manager/pull/13419)) diff --git a/packages/queries/CHANGELOG.md b/packages/queries/CHANGELOG.md index 4f53ad09ab8..a4b7b082086 100644 --- a/packages/queries/CHANGELOG.md +++ b/packages/queries/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2026-03-16] - v0.22.0 + + +### Fixed: + +- IAM: fix useGetChildAccountsQuery ([#13419](https://github.com/linode/manager/pull/13419)) + ## [2026-02-25] - v0.21.0 diff --git a/packages/queries/package.json b/packages/queries/package.json index 12be9ddd82d..d83e0b688f0 100644 --- a/packages/queries/package.json +++ b/packages/queries/package.json @@ -1,6 +1,6 @@ { "name": "@linode/queries", - "version": "0.21.0", + "version": "0.22.0", "description": "Linode Utility functions library", "main": "src/index.js", "module": "src/index.ts", diff --git a/packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md b/packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md deleted file mode 100644 index d93ad8ea7fe..00000000000 --- a/packages/ui/.changeset/pr-13418-upcoming-features-1771851880267.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/ui": Upcoming Features ---- - -Add `ZeroStateSearchNarrowIcon` to UI package ([#13418](https://github.com/linode/manager/pull/13418)) diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 5fd2e64e839..697b97e47d8 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2026-03-16] - v0.25.0 + + +### Upcoming Features: + +- Add `ZeroStateSearchNarrowIcon` to UI package ([#13418](https://github.com/linode/manager/pull/13418)) + ## [2026-02-25] - v0.24.0 diff --git a/packages/ui/package.json b/packages/ui/package.json index 7667cb57000..914c69b150a 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -2,7 +2,7 @@ "name": "@linode/ui", "author": "Linode", "description": "Linode UI component library", - "version": "0.24.0", + "version": "0.25.0", "type": "module", "main": "src/index.ts", "module": "src/index.ts", diff --git a/packages/validation/.changeset/pr-13392-changed-1770898290092.md b/packages/validation/.changeset/pr-13392-changed-1770898290092.md deleted file mode 100644 index 320bf3b88b9..00000000000 --- a/packages/validation/.changeset/pr-13392-changed-1770898290092.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@linode/validation": Changed ---- - -Delivery Logs - additional validation in Endpoint URL and Custom Header Name fields ([#13392](https://github.com/linode/manager/pull/13392)) diff --git a/packages/validation/CHANGELOG.md b/packages/validation/CHANGELOG.md index 141033358bc..055619222c3 100644 --- a/packages/validation/CHANGELOG.md +++ b/packages/validation/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2026-03-16] - v0.83.0 + + +### Changed: + +- Delivery Logs - additional validation in Endpoint URL and Custom Header Name fields ([#13392](https://github.com/linode/manager/pull/13392)) + ## [2026-02-25] - v0.82.0 diff --git a/packages/validation/package.json b/packages/validation/package.json index af8cf34afc5..1c10510cd5e 100644 --- a/packages/validation/package.json +++ b/packages/validation/package.json @@ -1,6 +1,6 @@ { "name": "@linode/validation", - "version": "0.82.0", + "version": "0.83.0", "description": "Yup validation schemas for use with the Linode APIv4", "type": "module", "main": "lib/index.cjs",