From 14d7d37a6674079dd6b73902963c4635e2554261 Mon Sep 17 00:00:00 2001 From: andrea-putzu <106688558+andrea-putzu@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:56:33 +0200 Subject: [PATCH 01/10] Merge back (#813) Co-authored-by: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Co-authored-by: manuraf From f0f7eddc513b51c6d6cf07de60de8136ca2306fa Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:15:56 +0200 Subject: [PATCH 02/10] [SELC-5791] Fix: Fixed interop logic for active product section --- .../ActiveProductsSection.tsx | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/pages/dashboardOverview/components/activeProductsSection/ActiveProductsSection.tsx b/src/pages/dashboardOverview/components/activeProductsSection/ActiveProductsSection.tsx index be2d71c4..8db0c7a5 100644 --- a/src/pages/dashboardOverview/components/activeProductsSection/ActiveProductsSection.tsx +++ b/src/pages/dashboardOverview/components/activeProductsSection/ActiveProductsSection.tsx @@ -6,7 +6,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Party } from '../../../../model/Party'; import { Product } from '../../../../model/Product'; -import { interopProductIdList } from '../../../../utils/constants'; import { startWithProductInterop } from '../../../../utils/helperFunctions'; import ActiveProductCardContainer from './components/ActiveProductCardContainer'; @@ -19,19 +18,35 @@ export default function ActiveProductsSection({ party, products }: Readonly - party?.products.find( - (p) => - p.productId === productId && hasPermission(p.productId, Actions.AccessProductBackoffice) - ); + const interopProducts = party?.products + .filter( + (product) => + startWithProductInterop(product.productId) && product.productOnBoardingStatus === 'ACTIVE' + ) + .map((p) => p.productId ?? ''); - const authorizedInteropProducts = interopProductIdList - .map(findAuthorizedProduct) - .filter(Boolean) - .map((p) => p?.productId ?? ''); + const authorizedInteropProducts = party?.products + .filter( + (product) => + startWithProductInterop(product.productId) && + hasPermission(product.productId ?? '', Actions.AccessProductBackoffice) + ) + .map((p) => p.productId ?? ''); const hasMoreThanOneInteropEnv = authorizedInteropProducts.length > 1; + const isRelevantInteropProduct = (productId: string) => { + if (startWithProductInterop(productId)) { + if (authorizedInteropProducts.length > 0) { + return productId === authorizedInteropProducts[0]; + } + if (interopProducts.length > 0) { + return productId === interopProducts[0]; + } + } + return true; + }; + return ( us.productOnBoardingStatus === 'ACTIVE' && - (startWithProductInterop(us.productId) && hasMoreThanOneInteropEnv - ? us.productId === authorizedInteropProducts[0] - : true) + isRelevantInteropProduct(us.productId ?? '') ) .sort((a, b) => { const aHasPermission = hasPermission( From 8e9b39b946ebac95a871d50ebf5349037765f22d Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:19:49 +0200 Subject: [PATCH 03/10] [SELC-5842] Feat: update selfcare commons for new action Co-authored-by: manuraf Co-authored-by: andrea-putzu <106688558+andrea-putzu@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8d1b42d0..f2ed4234 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "@mui/x-data-grid": "^5.0.1", "@mui/x-data-grid-generator": "^5.0.1", "@pagopa/mui-italia": "^1.5.0", - "@pagopa/selfcare-common-frontend": "^1.34.43", + "@pagopa/selfcare-common-frontend": "^1.34.44", "@types/react": "^18.2.22", "@types/react-dom": "^18.2.7", "@types/react-router-dom": "^5.3.3", diff --git a/yarn.lock b/yarn.lock index acacda43..dccae70d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2034,10 +2034,10 @@ write-yaml-file "^4.1.3" yargs "^15.0.1" -"@pagopa/selfcare-common-frontend@^1.34.43": - version "1.34.43" - resolved "https://registry.yarnpkg.com/@pagopa/selfcare-common-frontend/-/selfcare-common-frontend-1.34.43.tgz#73c566ae9ee0d021260adbf347afa1bce3789b83" - integrity sha512-Wgb+PJQzZl9inIVhZKm/NwbARzJ/U9aZKtVU3wNfBTqP9kkbtSBogsNncBawRcsq1p7fVfwHRUSSVvbxcYm0Sg== +"@pagopa/selfcare-common-frontend@^1.34.44": + version "1.34.44" + resolved "https://registry.yarnpkg.com/@pagopa/selfcare-common-frontend/-/selfcare-common-frontend-1.34.44.tgz#d276cf4583526d9be6000e993f48a7b34d7663f2" + integrity sha512-Gv9KHHTZ1tYIDcqjx9vslpg23ei9fhbGAaNUkmKN3Pg1UunPkzeHpf/hcvJuBXRVW1C7yXj0TH92ZxYRNiWsxg== dependencies: "@emotion/react" "^11.11.1" "@emotion/styled" "^11.11.0" From 9635568a6708421a6530b2d942967e8f988b4911 Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:37:10 +0200 Subject: [PATCH 04/10] [SELC-5780] Fix: call api /roles only for authorized products --- src/components/DashboardHeader.tsx | 6 +++--- src/hooks/useProductsRolesMap.tsx | 25 +++++++++++++++++-------- src/pages/dashboard/Dashboard.tsx | 18 +++++++++++------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/components/DashboardHeader.tsx b/src/components/DashboardHeader.tsx index 24d8d7c2..f805b1d0 100644 --- a/src/components/DashboardHeader.tsx +++ b/src/components/DashboardHeader.tsx @@ -63,7 +63,7 @@ const DashboardHeader = ({ onExit, loggedUser, parties }: Props) => { const hasMoreThanOneInteropEnv = authorizedInteropProducts.length > 1; - const onboardedPartyProducts = party?.products.filter( + const authorizedPartyProducts = party?.products.filter( (pp) => pp.productOnBoardingStatus === 'ACTIVE' && (hasPermission(pp.productId ?? '', Actions.AccessProductBackoffice) || @@ -72,8 +72,8 @@ const DashboardHeader = ({ onExit, loggedUser, parties }: Props) => { const activeProducts: Array = useMemo( () => - products?.filter((p) => onboardedPartyProducts?.some((op) => op.productId === p.id)) ?? [], - [onboardedPartyProducts] + products?.filter((p) => authorizedPartyProducts?.some((op) => op.productId === p.id)) ?? [], + [authorizedPartyProducts] ); // eslint-disable-next-line functional/immutable-data diff --git a/src/hooks/useProductsRolesMap.tsx b/src/hooks/useProductsRolesMap.tsx index 3510c1e0..ee7e35ff 100644 --- a/src/hooks/useProductsRolesMap.tsx +++ b/src/hooks/useProductsRolesMap.tsx @@ -1,4 +1,6 @@ +import { usePermissions } from '@pagopa/selfcare-common-frontend/lib'; import useReduxCachedValue from '@pagopa/selfcare-common-frontend/lib/hooks/useReduxCachedValue'; +import { Actions } from '@pagopa/selfcare-common-frontend/lib/utils/constants'; import { useMemo } from 'react'; import { Party } from '../model/Party'; import { @@ -15,26 +17,33 @@ export const useProductsRolesMap = (): (() => Promise) => { const party = useAppSelector(partiesSelectors.selectPartySelected); const products = useAppSelector(partiesSelectors.selectPartySelectedProducts); const productsRolesMap = useAppSelector(partiesSelectors.selectPartySelectedProductsRolesMap); + const { hasPermission } = usePermissions(); - const activeProducts = useMemo( + const activeAndAccessibleProducts = useMemo( () => products?.filter((p) => party?.products.some( - (us) => us.productId === p.id && us.productOnBoardingStatus === 'ACTIVE' + (us) => + us.productId === p.id && + us.productOnBoardingStatus === 'ACTIVE' && + hasPermission(us.productId ?? '', Actions.AccessProductBackoffice) ) ), [products, party?.products] ); const fetchProductRolesNotYetCached = async (): Promise => { - if (!activeProducts) { - return new Promise((resolve) => resolve(productsRolesMap)); + if (!activeAndAccessibleProducts) { + return Promise.resolve(productsRolesMap); } - const promises: Array> = activeProducts + const promises: Array> = activeAndAccessibleProducts .filter((p) => !productsRolesMap[p.id]) .map((p) => - fetchProductRoles(p, party as Party).then((roles) => [p.id, productRoles2ProductRolesList(roles)]) + fetchProductRoles(p, party as Party).then((roles) => [ + p.id, + productRoles2ProductRolesList(roles), + ]) ); const fetched: Array<[string, ProductRolesLists]> = await Promise.all(promises); @@ -45,9 +54,9 @@ export const useProductsRolesMap = (): (() => Promise) => { 'PRODUCTS_ROLES', fetchProductRolesNotYetCached, (state: RootState) => - !activeProducts || + !activeAndAccessibleProducts || (state.parties.selectedProductsRolesMap && - !activeProducts.find( + !activeAndAccessibleProducts.find( (p) => !(state.parties.selectedProductsRolesMap as ProductsRolesMap)[p.id] )) ? state.parties.selectedProductsRolesMap diff --git a/src/pages/dashboard/Dashboard.tsx b/src/pages/dashboard/Dashboard.tsx index 31d3c694..b02c433e 100644 --- a/src/pages/dashboard/Dashboard.tsx +++ b/src/pages/dashboard/Dashboard.tsx @@ -164,15 +164,19 @@ const Dashboard = () => { getAllProductsWithPermission(Actions.ViewDelegations).length > 0; const isHandleDelegationsVisible = useMemo(() => { - const hasPermissionForManagedInstitutions = + const canDelegateSeeHandleDelegations = + delegableProducts.length > 0 && + (isPT || hasDelegation) && getAllProductsWithPermission(Actions.ViewManagedInstitutions).length > 0; - const canShowDelegations = delegableProducts.length > 0 && (isPT || hasDelegation); - return ( - (hasPermissionForManagedInstitutions && canShowDelegations) || - canAggregatorSeeHandleDelegations - ); - }, [authorizedDelegableProducts, isPT, hasDelegation, canAggregatorSeeHandleDelegations]); + return canDelegateSeeHandleDelegations || canAggregatorSeeHandleDelegations; + }, [ + authorizedDelegableProducts, + isPT, + hasDelegation, + canAggregatorSeeHandleDelegations, + delegableProducts, + ]); // Check if the current route matches any path in the array // TODO `${ENV.ROUTES.USERS}/add` add after release in PROD From ffa3bf56d8651d1b7b4a278ca35501c2ce2c6a36 Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:54:27 +0200 Subject: [PATCH 05/10] [SELC-5831] Feat: use ListProductUsers to handle users section visibility --- .../dashboardSideMenu/DashboardSideMenu.tsx | 2 +- src/services/__mocks__/partyService.ts | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx b/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx index 519b2498..b3bd2841 100644 --- a/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx +++ b/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx @@ -55,7 +55,7 @@ export default function DashboardSideMenu({ const ptRoute = DASHBOARD_ROUTES.TECHPARTNER.path; const { getAllProductsWithPermission } = usePermissions(); - const canSeeUsers = getAllProductsWithPermission(Actions.ManageProductUsers).length > 0; + const canSeeUsers = getAllProductsWithPermission(Actions.ListProductUsers).length > 0; const canSeeGroups = getAllProductsWithPermission(Actions.ManageProductGroups).length > 0; const overviewPath = resolvePathVariables(overviewRoute, { diff --git a/src/services/__mocks__/partyService.ts b/src/services/__mocks__/partyService.ts index cea3f562..9d8176e2 100644 --- a/src/services/__mocks__/partyService.ts +++ b/src/services/__mocks__/partyService.ts @@ -262,6 +262,7 @@ export const mockedParties: Array = [ Actions.ListActiveProducts, Actions.ListAvailableProducts, Actions.ManageProductGroups, + Actions.ListProductUsers, Actions.ManageProductUsers, Actions.AccessProductBackoffice, Actions.ViewDelegations, @@ -309,6 +310,7 @@ export const mockedParties: Array = [ userProductActions: [ Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -329,6 +331,7 @@ export const mockedParties: Array = [ Actions.ListAvailableProducts, Actions.ManageProductGroups, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.AccessProductBackoffice, Actions.ViewDelegations, Actions.ViewBilling, @@ -348,6 +351,7 @@ export const mockedParties: Array = [ Actions.ListActiveProducts, Actions.ListAvailableProducts, Actions.ManageProductGroups, + Actions.ListProductUsers, Actions.AccessProductBackoffice, ], }, @@ -362,7 +366,7 @@ export const mockedParties: Array = [ recipientCode: 'NBG455B', publicServices: true, }, - userProductActions: [Actions.AccessProductBackoffice, Actions.ManageProductUsers], + userProductActions: [Actions.AccessProductBackoffice, Actions.ManageProductUsers, Actions.ListProductUsers], }, { productId: 'prod-interop-coll', @@ -374,7 +378,7 @@ export const mockedParties: Array = [ recipientCode: 'NBG455B', publicServices: true, }, - userProductActions: [Actions.AccessProductBackoffice, Actions.ManageProductUsers] + userProductActions: [Actions.AccessProductBackoffice, Actions.ManageProductUsers, Actions.ListProductUsers] }, { productId: 'prod-interop-atst', @@ -386,7 +390,7 @@ export const mockedParties: Array = [ recipientCode: 'NBG455B', publicServices: true, }, - userProductActions: [Actions.AccessProductBackoffice, Actions.ManageProductUsers] + userProductActions: [Actions.AccessProductBackoffice, Actions.ManageProductUsers, Actions.ListProductUsers] }, { productId: 'prod-pn', @@ -400,6 +404,7 @@ export const mockedParties: Array = [ userProductActions: [ Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -456,6 +461,7 @@ export const mockedParties: Array = [ Actions.ListActiveProducts, Actions.AccessProductBackoffice, Actions.ViewBilling, + Actions.ListProductUsers, ], }, ], @@ -497,6 +503,7 @@ export const mockedParties: Array = [ Actions.ListAvailableProducts, Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -517,6 +524,7 @@ export const mockedParties: Array = [ userProductActions: [ Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -561,6 +569,7 @@ export const mockedParties: Array = [ Actions.ListAvailableProducts, Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -578,6 +587,7 @@ export const mockedParties: Array = [ }, userProductActions: [ Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -619,6 +629,7 @@ export const mockedParties: Array = [ }, userProductActions: [ Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -677,6 +688,7 @@ export const mockedParties: Array = [ Actions.ListAvailableProducts, Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, @@ -707,6 +719,7 @@ export const mockedParties: Array = [ Actions.ListAvailableProducts, Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewManagedInstitutions, @@ -1214,6 +1227,7 @@ export const mockedParties: Array = [ Actions.ListAvailableProducts, Actions.AccessProductBackoffice, Actions.ManageProductUsers, + Actions.ListProductUsers, Actions.ManageProductGroups, Actions.ViewDelegations, Actions.ViewBilling, From d93581833751d9093a1d199ea932ec7c4dbbf95e Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:30:20 +0100 Subject: [PATCH 06/10] [SELC-5370] Feat: hide the side bad for add users page --- src/pages/dashboard/Dashboard.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/dashboard/Dashboard.tsx b/src/pages/dashboard/Dashboard.tsx index b02c433e..e4065eba 100644 --- a/src/pages/dashboard/Dashboard.tsx +++ b/src/pages/dashboard/Dashboard.tsx @@ -179,8 +179,7 @@ const Dashboard = () => { ]); // Check if the current route matches any path in the array - // TODO `${ENV.ROUTES.USERS}/add` add after release in PROD - const paths = [DASHBOARD_ROUTES.ADD_DELEGATE.path]; + const paths = [DASHBOARD_ROUTES.ADD_DELEGATE.path, `${ENV.ROUTES.USERS}/add`]; const match = matchPath(location.pathname, { path: paths, From 377dd8bdd85af81ee8c64f5702fca34721802f6e Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:51:42 +0100 Subject: [PATCH 07/10] [SELC-5886] Fix: handle ADMIN_EA from roles api response --- src/model/Party.tsx | 4 +-- src/model/ProductRole.ts | 7 ++--- src/model/__tests__/ProductRole.test.ts | 34 +++++++++++++------------ src/pages/dashboard/Dashboard.tsx | 9 ++----- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/model/Party.tsx b/src/model/Party.tsx index f08b352d..6dbb30b8 100644 --- a/src/model/Party.tsx +++ b/src/model/Party.tsx @@ -4,8 +4,8 @@ import { InstitutionResource } from '../api/generated/b4f-dashboard/InstitutionR import { ProductOnBoardingStatusEnum } from '../api/generated/b4f-dashboard/OnboardedProductResource'; import { ENV } from '../utils/env'; -export type UserRole = 'ADMIN' | 'LIMITED'; -export type PartyRole = 'DELEGATE' | 'MANAGER' | 'OPERATOR' | 'SUB_DELEGATE'; +export type UserRole = 'ADMIN' | 'LIMITED' | 'ADMIN_EA'; +export type PartyRole = 'DELEGATE' | 'MANAGER' | 'OPERATOR' | 'SUB_DELEGATE' | 'ADMIN_EA'; export type UserStatus = 'PENDING' | 'ACTIVE' | 'SUSPENDED' | 'TOBEVALIDATED'; type OnboardedProduct = { diff --git a/src/model/ProductRole.ts b/src/model/ProductRole.ts index 30b11e3f..bfd7fa12 100644 --- a/src/model/ProductRole.ts +++ b/src/model/ProductRole.ts @@ -1,4 +1,5 @@ -import { UserRole, PartyRole } from './Party'; +import { PartyRole, UserRole } from "./Party"; + export type ProductRole = { productId: string; @@ -20,9 +21,9 @@ export type ProductRolesLists = { export const buildEmptyProductRolesLists = (): ProductRolesLists => ({ list: [], - groupBySelcRole: { ADMIN: [], LIMITED: [] }, + groupBySelcRole: { ADMIN: [], LIMITED: [], ADMIN_EA: [] }, groupByProductRole: {}, - groupByPartyRole: { MANAGER: [], DELEGATE: [], SUB_DELEGATE: [], OPERATOR: [] }, + groupByPartyRole: { MANAGER: [], DELEGATE: [], SUB_DELEGATE: [], OPERATOR: [], ADMIN_EA: [] }, }); export type ProductRolesByProductRoleType = { [productRole: string]: ProductRole }; diff --git a/src/model/__tests__/ProductRole.test.ts b/src/model/__tests__/ProductRole.test.ts index 7272f68f..d459e6cb 100644 --- a/src/model/__tests__/ProductRole.test.ts +++ b/src/model/__tests__/ProductRole.test.ts @@ -1,5 +1,5 @@ import { mockedProductRoles } from '../../services/__mocks__/productService'; -import { ProductRole, productRoles2ProductRolesList } from '../ProductRole'; +import { productRoles2ProductRolesList } from '../ProductRole'; test('Test productRoles2ProductRolesList', () => { const rolesList = productRoles2ProductRolesList(mockedProductRoles); @@ -15,7 +15,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-legale', title: 'Referente Legale', description: 'Descrizione referente-legale', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, { productId: 'PRODID', @@ -25,7 +25,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-amministrativo', title: 'Amministratore', description: 'Descrizione referente-amministrativo', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, { productId: 'PRODID', @@ -35,7 +35,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'incaricato-ente-creditore', title: 'Incaricato Ente Creditore', description: 'Descrizione incaricato-ente-creditore', - phasesAdditionAllowed: ['dashboard-async'] + phasesAdditionAllowed: ['dashboard-async'], }, ], LIMITED: [ @@ -47,7 +47,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-dei-pagamenti', title: 'Referente dei Pagamenti', description: 'Descrizione referente-dei-pagamenti', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, { productId: 'PRODID', @@ -57,9 +57,10 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-tecnico', title: 'Referente Tecnico', description: 'Descrizione referente-tecnico', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, ], + ADMIN_EA: [], }, groupByPartyRole: { DELEGATE: [ @@ -71,7 +72,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-amministrativo', selcRole: 'ADMIN', title: 'Amministratore', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, ], MANAGER: [ @@ -83,7 +84,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-legale', selcRole: 'ADMIN', title: 'Referente Legale', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, ], OPERATOR: [ @@ -95,7 +96,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-dei-pagamenti', selcRole: 'LIMITED', title: 'Referente dei Pagamenti', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, { description: 'Descrizione referente-tecnico', @@ -105,7 +106,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-tecnico', selcRole: 'LIMITED', title: 'Referente Tecnico', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, ], SUB_DELEGATE: [ @@ -117,9 +118,10 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'incaricato-ente-creditore', selcRole: 'ADMIN', title: 'Incaricato Ente Creditore', - phasesAdditionAllowed: ['dashboard-async'] + phasesAdditionAllowed: ['dashboard-async'], }, ], + ADMIN_EA: [], }, groupByProductRole: { 'referente-legale': { @@ -130,7 +132,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-legale', title: 'Referente Legale', description: 'Descrizione referente-legale', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, 'referente-amministrativo': { productId: 'PRODID', @@ -140,7 +142,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-amministrativo', title: 'Amministratore', description: 'Descrizione referente-amministrativo', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, 'incaricato-ente-creditore': { productId: 'PRODID', @@ -150,7 +152,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'incaricato-ente-creditore', title: 'Incaricato Ente Creditore', description: 'Descrizione incaricato-ente-creditore', - phasesAdditionAllowed: ['dashboard-async'] + phasesAdditionAllowed: ['dashboard-async'], }, 'referente-dei-pagamenti': { productId: 'PRODID', @@ -160,7 +162,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-dei-pagamenti', title: 'Referente dei Pagamenti', description: 'Descrizione referente-dei-pagamenti', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, 'referente-tecnico': { productId: 'PRODID', @@ -170,7 +172,7 @@ test('Test productRoles2ProductRolesList', () => { productRole: 'referente-tecnico', title: 'Referente Tecnico', description: 'Descrizione referente-tecnico', - phasesAdditionAllowed: ['dashboard'] + phasesAdditionAllowed: ['dashboard'], }, }, }); diff --git a/src/pages/dashboard/Dashboard.tsx b/src/pages/dashboard/Dashboard.tsx index e4065eba..a96fa2aa 100644 --- a/src/pages/dashboard/Dashboard.tsx +++ b/src/pages/dashboard/Dashboard.tsx @@ -130,13 +130,8 @@ const Dashboard = () => { ) ); - const authorizedDelegableProducts: Array = activeProducts.filter((ap) => - party?.products.some( - (p) => - p.productId === ap.id && - hasPermission(p.productId, Actions.AccessProductBackoffice) && - ap.delegable - ) + const authorizedDelegableProducts: Array = delegableProducts.filter((ap) => + hasPermission(ap.id ?? '', Actions.AccessProductBackoffice) ); const canAggregatorSeeHandleDelegations = useMemo(() => { From ddef92327e42f95b6b600fc45f91f9b3862f9063 Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:46:39 +0100 Subject: [PATCH 08/10] [SELC-5822] Feat: institution name is clikable for type EA and add rederict --- src/pages/dashboard/Dashboard.tsx | 2 +- .../dashboardSideMenu/DashboardSideMenu.tsx | 2 +- .../DashboardTableContainer.tsx | 18 -- .../DashboardTechnologyPartnerPage.tsx | 86 ++++---- .../TechPartnersTable.tsx | 66 ++++-- .../TechnologyPartnerTable.tsx | 194 +++++++++--------- .../components/TableCellWithTooltip.tsx | 72 ++++--- src/services/delegationServices.ts | 128 ++++++------ src/services/technologyPartnerService.ts | 2 +- 9 files changed, 295 insertions(+), 275 deletions(-) delete mode 100644 src/pages/dashboardTechnologyPartnerPage/DashboardTableContainer.tsx diff --git a/src/pages/dashboard/Dashboard.tsx b/src/pages/dashboard/Dashboard.tsx index a96fa2aa..024f91dc 100644 --- a/src/pages/dashboard/Dashboard.tsx +++ b/src/pages/dashboard/Dashboard.tsx @@ -344,7 +344,7 @@ const Dashboard = () => { /> - + {buildRoutes(party, products, activeProducts, productsMap, decorators, DASHBOARD_ROUTES)} diff --git a/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx b/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx index b3bd2841..d3572d53 100644 --- a/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx +++ b/src/pages/dashboard/components/dashboardSideMenu/DashboardSideMenu.tsx @@ -40,7 +40,7 @@ export default function DashboardSideMenu({ isHandleDelegationsVisible, setDrawerOpen, hideLabels, -}: Props) { +}: Readonly) { const { t } = useTranslation(); const history = useHistory(); const onExit = useUnloadEventOnExit(); diff --git a/src/pages/dashboardTechnologyPartnerPage/DashboardTableContainer.tsx b/src/pages/dashboardTechnologyPartnerPage/DashboardTableContainer.tsx deleted file mode 100644 index ea0462cd..00000000 --- a/src/pages/dashboardTechnologyPartnerPage/DashboardTableContainer.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Box } from '@mui/material'; -import { DelegationWithInfo } from '../../api/generated/b4f-dashboard/DelegationWithInfo'; -import TechPartnersTable from './TechPartnersTable'; - -type Props = { - delegationsWithoutDuplicates: Array; -}; -export default function DashboardTableContainer({ delegationsWithoutDuplicates }: Props) { - return ( - - - - ); -} diff --git a/src/pages/dashboardTechnologyPartnerPage/DashboardTechnologyPartnerPage.tsx b/src/pages/dashboardTechnologyPartnerPage/DashboardTechnologyPartnerPage.tsx index 937d332f..903fc0f8 100644 --- a/src/pages/dashboardTechnologyPartnerPage/DashboardTechnologyPartnerPage.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/DashboardTechnologyPartnerPage.tsx @@ -1,44 +1,42 @@ -import { Grid } from '@mui/material'; -import { Box } from '@mui/system'; -import { TitleBox } from '@pagopa/selfcare-common-frontend/lib'; -import { useTranslation } from 'react-i18next'; -import { Party } from '../../model/Party'; -import { Product } from '../../model/Product'; -import TechnologyPartnerTable from './TechnologyPartnerTable'; - -type Props = { - party: Party; - ptProducts: Array; -}; - -export default function DashboardTechnologyPartnerPage({ party, ptProducts }: Props) { - const { t } = useTranslation(); - return ( - - - - - - - {/* Table */} - - - - - - - ); -} +import { Grid } from '@mui/material'; +import { Box } from '@mui/system'; +import { TitleBox } from '@pagopa/selfcare-common-frontend/lib'; +import { useTranslation } from 'react-i18next'; +import { Party } from '../../model/Party'; +import TechnologyPartnerTable from './TechnologyPartnerTable'; + +type Props = { + party: Party; +}; + +export default function DashboardTechnologyPartnerPage({ party }: Readonly) { + const { t } = useTranslation(); + return ( + + + + + + + {/* Table */} + + + + + + + ); +} diff --git a/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx b/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx index d3c0fe8d..3593f4e4 100644 --- a/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx @@ -19,11 +19,14 @@ import { } from '@mui/material'; import { grey } from '@mui/material/colors'; import { ButtonNaked } from '@pagopa/mui-italia'; +import { resolvePathVariables } from '@pagopa/selfcare-common-frontend/lib/utils/routes-utils'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router-dom'; import { DelegationWithInfo } from '../../api/generated/b4f-dashboard/DelegationWithInfo'; import { useAppSelector } from '../../redux/hooks'; import { partiesSelectors } from '../../redux/slices/partiesSlice'; +import ROUTES from '../../routes'; import { compareDates, compareStrings } from '../../utils/helperFunctions'; import EmptyFilterResults from './components/EmptyFilterResults'; import EnhancedTableHeader from './components/EnhanchedTableHeader'; @@ -35,6 +38,7 @@ type Props = { export default function TechPartnersTable({ delegationsWithoutDuplicates }: Readonly) { const { t } = useTranslation(); + const history = useHistory(); const [order, setOrder] = useState<'asc' | 'desc'>('asc'); const [filterBy, setFilterBy] = useState(''); const [searchTerm, setSearchTerm] = useState(''); @@ -205,23 +209,51 @@ export default function TechPartnersTable({ delegationsWithoutDuplicates }: Read {getSortedData(tableData) .slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage) - .map((item, _index) => ( - <> - - - - - {item.taxCode?.toUpperCase() ?? '-'} - - - {prodIdToProdTitle(item.productId as string) ?? '-'} - - {item.createdAt?.toLocaleDateString() ?? '-'} - - - - - ))} + .map((item, _index) => { + const isClickable = + (item.productId === 'prod-io' || item.productId === 'prod-pagopa') && + item.type === 'EA'; + + return ( + <> + + { + history.push( + resolvePathVariables(ROUTES.PARTY_DASHBOARD.path, { + partyId: item.institutionId ?? '', + }) + ); + }} + > + {item.institutionName ?? ''} + + ) : ( + item.institutionName ?? '-' + ) + } + /> + + + {item.taxCode?.toUpperCase() ?? '-'} + + + + {prodIdToProdTitle(item.productId as string) ?? '-'} + + + {item.createdAt?.toLocaleDateString() ?? '-'} + + + + + ); + })} diff --git a/src/pages/dashboardTechnologyPartnerPage/TechnologyPartnerTable.tsx b/src/pages/dashboardTechnologyPartnerPage/TechnologyPartnerTable.tsx index a77325bd..cde2a12a 100644 --- a/src/pages/dashboardTechnologyPartnerPage/TechnologyPartnerTable.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/TechnologyPartnerTable.tsx @@ -1,95 +1,99 @@ -import { CircularProgress } from '@mui/material'; -import { grey } from '@mui/material/colors'; -import { Box } from '@mui/system'; -import { useErrorDispatcher } from '@pagopa/selfcare-common-frontend/lib'; -import { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { DelegationWithInfo } from '../../api/generated/b4f-dashboard/DelegationWithInfo'; -import { Party } from '../../model/Party'; -import { Product } from '../../model/Product'; -import { getDelegatingInstitutions } from '../../services/technologyPartnerService'; -import DashboardTableContainer from './DashboardTableContainer'; - -type Props = { - party: Party; - ptProducts: Array; -}; -export default function TechnologyPartnerTable({ party }: Props) { - const [delegationsWithoutDuplicates, setDelegationsWithoutDuplicates] = useState< - Array - >([]); - const { t } = useTranslation(); - const [loading, setLoading] = useState(false); - const addError = useErrorDispatcher(); - - const retrieveDelegationsList = async () => { - setLoading(true); - await getDelegatingInstitutions(party.partyId) - .then((r) => { - if (r && r.delegations && r.delegations?.length > 0) { - const filteredArray: Array = r.delegations.reduce( - (result: Array, current: DelegationWithInfo) => { - const existingItem = result.find( - (item) => - item.brokerId === current.brokerId && - item.institutionName === current.institutionName - ); - if (existingItem) { - // eslint-disable-next-line functional/immutable-data - existingItem.productId += `, ${current.productId}`; - } else { - // eslint-disable-next-line functional/immutable-data - result.push({ ...current }); - } - return result; - }, - [] - ); - - setDelegationsWithoutDuplicates(filteredArray as Array); - } else { - setDelegationsWithoutDuplicates([]); - } - }) - .catch((reason) => { - setDelegationsWithoutDuplicates([]); - addError({ - id: `FETCH_PARTY_PT_ERROR-${party.partyId}`, - blocking: false, - error: reason, - techDescription: `Something gone wrong while fetching technology partners with party id ${party.partyId}`, - toNotify: true, - }); - }) - .finally(() => setLoading(false)); - }; - - useEffect(() => { - void retrieveDelegationsList(); - }, []); - - return !loading ? ( - - {party.delegation && delegationsWithoutDuplicates.length > 0 && ( - - )} - {delegationsWithoutDuplicates.length === 0 && ( - - - {t('overview.ptPage.tableEmptyLabel')} - - - )} - - ) : ( - - - - ); -} +import { CircularProgress } from '@mui/material'; +import { grey } from '@mui/material/colors'; +import { Box } from '@mui/system'; +import { useErrorDispatcher } from '@pagopa/selfcare-common-frontend/lib'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { DelegationWithInfo } from '../../api/generated/b4f-dashboard/DelegationWithInfo'; +import { Party } from '../../model/Party'; +import { getDelegatingInstitutions } from '../../services/technologyPartnerService'; +import TechPartnersTable from './TechPartnersTable'; + +type Props = { + party: Party; +}; +export default function TechnologyPartnerTable({ party }: Props) { + const [delegationsWithoutDuplicates, setDelegationsWithoutDuplicates] = useState< + Array + >([]); + const { t } = useTranslation(); + const [loading, setLoading] = useState(false); + const addError = useErrorDispatcher(); + + const retrieveDelegationsList = async () => { + setLoading(true); + await getDelegatingInstitutions(party.partyId) + .then((r) => { + if (r && r.delegations && r.delegations?.length > 0) { + const filteredArray: Array = r.delegations.reduce( + (result: Array, current: DelegationWithInfo) => { + const existingItem = result.find( + (item) => + item.brokerId === current.brokerId && + item.institutionName === current.institutionName + ); + if (existingItem) { + // eslint-disable-next-line functional/immutable-data + existingItem.productId += `, ${current.productId}`; + } else { + // eslint-disable-next-line functional/immutable-data + result.push({ ...current }); + } + return result; + }, + [] + ); + + setDelegationsWithoutDuplicates(filteredArray); + } else { + setDelegationsWithoutDuplicates([]); + } + }) + .catch((reason) => { + setDelegationsWithoutDuplicates([]); + addError({ + id: `FETCH_PARTY_PT_ERROR-${party.partyId}`, + blocking: false, + error: reason, + techDescription: `Something gone wrong while fetching technology partners with party id ${party.partyId}`, + toNotify: true, + }); + }) + .finally(() => setLoading(false)); + }; + + useEffect(() => { + void retrieveDelegationsList(); + }, []); + + return !loading ? ( + + {party.delegation && delegationsWithoutDuplicates.length > 0 && ( + + + + )} + {delegationsWithoutDuplicates.length === 0 && ( + + + {t('overview.ptPage.tableEmptyLabel')} + + + )} + + ) : ( + + + + ); +} diff --git a/src/pages/dashboardTechnologyPartnerPage/components/TableCellWithTooltip.tsx b/src/pages/dashboardTechnologyPartnerPage/components/TableCellWithTooltip.tsx index 75131f68..c61aade2 100644 --- a/src/pages/dashboardTechnologyPartnerPage/components/TableCellWithTooltip.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/components/TableCellWithTooltip.tsx @@ -1,34 +1,38 @@ -import { TableCell, Tooltip, Typography } from '@mui/material'; -import { useEffect, useRef, useState } from 'react'; - -const TableCellWithTooltip: React.FC<{ text: string }> = ({ text }) => { - const textRef = useRef(null); - const [isOverflowed, setIsOverflowed] = useState(false); - - useEffect(() => { - if (textRef.current) { - setIsOverflowed(textRef.current.scrollWidth > textRef.current.clientWidth); - } - }, [text]); - - return ( - - - - {text} - - - - ); -}; - -export default TableCellWithTooltip; +import { TableCell, Tooltip, Typography } from '@mui/material'; +import { useEffect, useRef, useState, ReactElement } from 'react'; + +interface TableCellWithTooltipProps { + text: string | ReactElement; +} + +const TableCellWithTooltip: React.FC = ({ text }) => { + const textRef = useRef(null); + const [isOverflowed, setIsOverflowed] = useState(false); + + useEffect(() => { + if (textRef.current) { + setIsOverflowed(textRef.current.scrollWidth > textRef.current.clientWidth); + } + }, [text]); + + return ( + + + + {text} + + + + ); +}; + +export default TableCellWithTooltip; diff --git a/src/services/delegationServices.ts b/src/services/delegationServices.ts index 171c52b5..9afbc84b 100644 --- a/src/services/delegationServices.ts +++ b/src/services/delegationServices.ts @@ -1,64 +1,64 @@ -import { DashboardApi } from '../api/DashboardApiClient'; -import { DelegationResource, TypeEnum } from '../api/generated/b4f-dashboard/DelegationResource'; -import { mockedBrokerResource } from '../api/__mocks__/DashboardApiClient'; -import { mockedParties } from './__mocks__/partyService'; -import { mockedPartyProducts } from './__mocks__/productService'; - -export const mockedDelegations: Array = [ - { - id: '0000', - brokerId: mockedBrokerResource[0].code, - brokerName: mockedBrokerResource[0].description, - institutionId: mockedParties[2].partyId, - institutionName: mockedParties[2].description, - productId: mockedPartyProducts[0].id, - type: TypeEnum.PT, - }, - { - id: '1111', - brokerId: mockedBrokerResource[1].code, - brokerName: mockedBrokerResource[1].description, - institutionId: mockedParties[2].partyId, - institutionName: mockedParties[2].description, - productId: mockedPartyProducts[0].id, - type: TypeEnum.PT, - }, - { - id: '2222', - brokerId: mockedBrokerResource[2].code, - brokerName: mockedBrokerResource[2].description, - institutionId: mockedParties[2].partyId, - institutionName: mockedParties[2].description, - productId: mockedPartyProducts[2].id, - type: TypeEnum.PT, - }, - { - id: '3333', - brokerId: mockedBrokerResource[3].code, - brokerName: mockedBrokerResource[3].description, - institutionId: mockedParties[3].partyId, - institutionName: mockedParties[3].description, - productId: mockedPartyProducts[2].id, - type: TypeEnum.PT, - }, - { - id: '4444', - brokerId: mockedBrokerResource[4].code, - brokerName: mockedBrokerResource[4].description, - institutionId: mockedParties[4].partyId, - institutionName: mockedParties[4].description, - productId: mockedPartyProducts[2].id, - type: TypeEnum.PT, - }, -]; - -export const fetchDelegations = (partyId: string): Promise> => { - /* istanbul ignore if */ - if (process.env.REACT_APP_API_MOCK_PRODUCTS === 'true') { - return new Promise((resolve) => - resolve(mockedDelegations.filter((d) => d.institutionId === partyId)) - ); - } else { - return DashboardApi.getDelegations(partyId).then((delegationsResource) => delegationsResource); - } -}; +import { DashboardApi } from '../api/DashboardApiClient'; +import { DelegationResource, TypeEnum } from '../api/generated/b4f-dashboard/DelegationResource'; +import { mockedBrokerResource } from '../api/__mocks__/DashboardApiClient'; +import { mockedParties } from './__mocks__/partyService'; +import { mockedPartyProducts } from './__mocks__/productService'; + +export const mockedDelegations: Array = [ + { + id: '0000', + brokerId: mockedBrokerResource[0].code, + brokerName: mockedBrokerResource[0].description, + institutionId: mockedParties[2].partyId, + institutionName: mockedParties[2].description, + productId: mockedPartyProducts[0].id, + type: TypeEnum.EA, + }, + { + id: '1111', + brokerId: mockedBrokerResource[1].code, + brokerName: mockedBrokerResource[1].description, + institutionId: mockedParties[2].partyId, + institutionName: mockedParties[2].description, + productId: mockedPartyProducts[0].id, + type: TypeEnum.EA, + }, + { + id: '2222', + brokerId: mockedBrokerResource[2].code, + brokerName: mockedBrokerResource[2].description, + institutionId: mockedParties[2].partyId, + institutionName: mockedParties[2].description, + productId: mockedPartyProducts[2].id, + type: TypeEnum.EA, + }, + { + id: '3333', + brokerId: mockedBrokerResource[3].code, + brokerName: mockedBrokerResource[3].description, + institutionId: mockedParties[3].partyId, + institutionName: mockedParties[3].description, + productId: mockedPartyProducts[2].id, + type: TypeEnum.PT, + }, + { + id: '4444', + brokerId: mockedBrokerResource[4].code, + brokerName: mockedBrokerResource[4].description, + institutionId: mockedParties[4].partyId, + institutionName: mockedParties[4].description, + productId: mockedPartyProducts[2].id, + type: TypeEnum.PT, + }, +]; + +export const fetchDelegations = (partyId: string): Promise> => { + /* istanbul ignore if */ + if (process.env.REACT_APP_API_MOCK_PRODUCTS === 'true') { + return new Promise((resolve) => + resolve(mockedDelegations.filter((d) => d.institutionId === partyId)) + ); + } else { + return DashboardApi.getDelegations(partyId).then((delegationsResource) => delegationsResource); + } +}; diff --git a/src/services/technologyPartnerService.ts b/src/services/technologyPartnerService.ts index e5da14fa..b9fc6e50 100644 --- a/src/services/technologyPartnerService.ts +++ b/src/services/technologyPartnerService.ts @@ -32,7 +32,7 @@ function generateDelegationWithInfoArray(n: number): Array { productId: `prod-pagopa`, status: `Status${i}`, taxCode: `TaxCode${i}`, - type: TypeEnum.AOO, + type: TypeEnum.EA, updatedAt, }; From a1d50f3deaab16da6a975e84b662988facf9761b Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:51:32 +0100 Subject: [PATCH 09/10] [SELC-5823] Feat: add check if delegation is present in getInstituions list --- .../TechPartnersTable.tsx | 10 ++++--- .../__tests__/DashboardTablePT.test.tsx | 26 ++++++++++++++++--- src/services/__mocks__/partyService.ts | 4 +-- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx b/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx index 3593f4e4..e804ef67 100644 --- a/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx @@ -50,6 +50,8 @@ export default function TechPartnersTable({ delegationsWithoutDuplicates }: Read const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(Math.ceil(tableData.length / itemsPerPage)); const products = useAppSelector(partiesSelectors.selectPartySelectedProducts); + const parties = useAppSelector(partiesSelectors.selectPartiesList); + const partyIdsSet = parties ? new Set(parties.map((party) => party.partyId)) : new Set(); useEffect(() => { setTotalPages(Math.ceil(tableData.length / itemsPerPage)); @@ -210,9 +212,7 @@ export default function TechPartnersTable({ delegationsWithoutDuplicates }: Read {getSortedData(tableData) .slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage) .map((item, _index) => { - const isClickable = - (item.productId === 'prod-io' || item.productId === 'prod-pagopa') && - item.type === 'EA'; + const isClickable = item.type === 'EA' && partyIdsSet.has(item.institutionId); return ( <> @@ -223,6 +223,10 @@ export default function TechPartnersTable({ delegationsWithoutDuplicates }: Read { history.push( resolvePathVariables(ROUTES.PARTY_DASHBOARD.path, { diff --git a/src/pages/dashboardTechnologyPartnerPage/__tests__/DashboardTablePT.test.tsx b/src/pages/dashboardTechnologyPartnerPage/__tests__/DashboardTablePT.test.tsx index cdd3fda7..2aeb6cc4 100644 --- a/src/pages/dashboardTechnologyPartnerPage/__tests__/DashboardTablePT.test.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/__tests__/DashboardTablePT.test.tsx @@ -13,15 +13,25 @@ import TechPartnersTable from '../TechPartnersTable'; const mockedDelegation: DelegationWithPagination = { delegations: [ { - brokerId: '123', + brokerId: '111', brokerName: 'Broker 1', - id: '456', - institutionId: '789', + id: '1', + institutionId: '1111', institutionName: 'Institution 1', institutionRootName: 'Root Institution', productId: '7890', type: TypeEnum.AOO, }, + { + brokerId: '222', + brokerName: 'Broker EA', + id: '2', + institutionId: 'institutionId0', + institutionName: 'Institution EA', + institutionRootName: 'Root Institution', + productId: '7890', + type: TypeEnum.EA, + }, ], pageInfo: { pageSize: 0, @@ -80,3 +90,13 @@ test('test input field change and filter on click and search by name', async () expect(removeFiltersButton).toBeEnabled(); fireEvent.click(removeFiltersButton); }); + +test('delegation of type EA should be clikable for same institution is present on instituionList', async () => { + renderDashboardTablePT(); + + const delegationOfTypeEA = await screen.findByText('Institution EA'); + + expect(delegationOfTypeEA).toBeInTheDocument(); + + fireEvent.click(delegationOfTypeEA); +}); diff --git a/src/services/__mocks__/partyService.ts b/src/services/__mocks__/partyService.ts index 9d8176e2..1e9fb3ba 100644 --- a/src/services/__mocks__/partyService.ts +++ b/src/services/__mocks__/partyService.ts @@ -42,7 +42,7 @@ export const mockedBaseParties: Array = [ userRole: 'ADMIN', }, { - partyId: '6', + partyId: 'institutionId0', description: 'Scuola Media Oswald Von Wolkenstein di Bressa', status: 'ACTIVE', userRole: 'ADMIN', @@ -601,7 +601,7 @@ export const mockedParties: Array = [ { description: 'Scuola Media Oswald Von Wolkenstein di Bressa', urlLogo: 'image', - partyId: '6', + partyId: 'institutionId0', digitalAddress: 'comune.bressanone@pec.it', fiscalCode: '111122211111', category: 'Comuni e loro Consorzi e Associazioni', From eec2bcb1e89c25efe6d914fd2044d71a9adfa6c1 Mon Sep 17 00:00:00 2001 From: OraldoDoci <117348307+OraldoDoci@users.noreply.github.com> Date: Wed, 30 Oct 2024 10:01:58 +0100 Subject: [PATCH 10/10] [SELC-5822] fix: change method used for the redirect to refresh the selected party on header --- .../dashboardTechnologyPartnerPage/TechPartnersTable.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx b/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx index e804ef67..0febc291 100644 --- a/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx +++ b/src/pages/dashboardTechnologyPartnerPage/TechPartnersTable.tsx @@ -22,7 +22,6 @@ import { ButtonNaked } from '@pagopa/mui-italia'; import { resolvePathVariables } from '@pagopa/selfcare-common-frontend/lib/utils/routes-utils'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; import { DelegationWithInfo } from '../../api/generated/b4f-dashboard/DelegationWithInfo'; import { useAppSelector } from '../../redux/hooks'; import { partiesSelectors } from '../../redux/slices/partiesSlice'; @@ -38,7 +37,6 @@ type Props = { export default function TechPartnersTable({ delegationsWithoutDuplicates }: Readonly) { const { t } = useTranslation(); - const history = useHistory(); const [order, setOrder] = useState<'asc' | 'desc'>('asc'); const [filterBy, setFilterBy] = useState(''); const [searchTerm, setSearchTerm] = useState(''); @@ -228,11 +226,12 @@ export default function TechPartnersTable({ delegationsWithoutDuplicates }: Read fontSize: '16px', }} onClick={() => { - history.push( + window.location.assign( resolvePathVariables(ROUTES.PARTY_DASHBOARD.path, { - partyId: item.institutionId ?? '', + partyId: item?.institutionId ?? '', }) ); + }} > {item.institutionName ?? ''}