diff --git a/apps/console/src/pages/organizations/compliance-page/CompliancePageLayout.tsx b/apps/console/src/pages/organizations/compliance-page/CompliancePageLayout.tsx index 1b3e71ab2..beab92c07 100644 --- a/apps/console/src/pages/organizations/compliance-page/CompliancePageLayout.tsx +++ b/apps/console/src/pages/organizations/compliance-page/CompliancePageLayout.tsx @@ -78,7 +78,7 @@ export function CompliancePageLayout(props: { queryRef: PreloadedQuery - {__("Vendors")} + {__("Subprocessors")} diff --git a/apps/console/src/pages/organizations/compliance-page/vendors/CompliancePageVendorsPage.tsx b/apps/console/src/pages/organizations/compliance-page/vendors/CompliancePageVendorsPage.tsx index 6695745b5..7c4b69270 100644 --- a/apps/console/src/pages/organizations/compliance-page/vendors/CompliancePageVendorsPage.tsx +++ b/apps/console/src/pages/organizations/compliance-page/vendors/CompliancePageVendorsPage.tsx @@ -29,9 +29,9 @@ export function CompliancePageVendorsPage(props: {
-

{__("Vendors")}

+

{__("Subprocessors")}

- {__("Manage vendor assessments and third-party risk information")} + {__("Manage subprocessor assessments and third-party risk information")}

diff --git a/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorList.tsx b/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorList.tsx index 240385cac..75fa5c2a9 100644 --- a/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorList.tsx +++ b/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorList.tsx @@ -42,7 +42,7 @@ export function CompliancePageVendorList(props: { fragmentRef: CompliancePageVen {vendors.edges.length === 0 && ( - {__("No vendors available")} + {__("No subprocessors available")} )} diff --git a/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorListItem.tsx b/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorListItem.tsx index aa63d5cf8..fb1a910d1 100644 --- a/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorListItem.tsx +++ b/apps/console/src/pages/organizations/compliance-page/vendors/_components/CompliancePageVendorListItem.tsx @@ -47,8 +47,8 @@ export function CompliancePageVendorListItem(props: { >( updateVendorVisibilityMutation, { - successMessage: __("Vendor visibility updated successfully."), - errorMessage: __("Failed to update vendor visibility"), + successMessage: __("Subprocessor visibility updated successfully."), + errorMessage: __("Failed to update subprocessor visibility"), }, ); diff --git a/apps/trust/src/components/VendorRow.tsx b/apps/trust/src/components/SubprocessorRow.tsx similarity index 62% rename from apps/trust/src/components/VendorRow.tsx rename to apps/trust/src/components/SubprocessorRow.tsx index 836193191..42439fadf 100644 --- a/apps/trust/src/components/VendorRow.tsx +++ b/apps/trust/src/components/SubprocessorRow.tsx @@ -4,10 +4,10 @@ import { IconPin } from "@probo/ui"; import { useFragment } from "react-relay"; import { graphql } from "relay-runtime"; -import type { VendorRowFragment$key } from "./__generated__/VendorRowFragment.graphql"; +import type { SubprocessorRowFragment$key } from "./__generated__/SubprocessorRowFragment.graphql"; -const vendorRowFragment = graphql` - fragment VendorRowFragment on Vendor { +const subprocessorRowFragment = graphql` + fragment SubprocessorRowFragment on Subprocessor { name description websiteUrl @@ -15,9 +15,9 @@ const vendorRowFragment = graphql` } `; -export function VendorRow(props: { vendor: VendorRowFragment$key; hasAnyCountries?: boolean }) { - const vendor = useFragment(vendorRowFragment, props.vendor); - const logo = faviconUrl(vendor.websiteUrl); +export function SubprocessorRow(props: { subprocessor: SubprocessorRowFragment$key; hasAnyCountries?: boolean }) { + const subprocessor = useFragment(subprocessorRowFragment, props.subprocessor); + const logo = faviconUrl(subprocessor.websiteUrl); const { __ } = useTranslate(); return ( @@ -34,16 +34,16 @@ export function VendorRow(props: { vendor: VendorRowFragment$key; hasAnyCountrie
)}
- {vendor.name} -
{vendor.description}
+ {subprocessor.name} +
{subprocessor.description}
{props.hasAnyCountries && (
- {vendor.countries.length > 0 && ( + {subprocessor.countries.length > 0 && ( <> - {vendor.countries + {subprocessor.countries .map(country => getCountryName(__, country)) .join(", ")} diff --git a/apps/trust/src/layouts/MainLayout.tsx b/apps/trust/src/layouts/MainLayout.tsx index d2c078d44..2d7ba45f7 100644 --- a/apps/trust/src/layouts/MainLayout.tsx +++ b/apps/trust/src/layouts/MainLayout.tsx @@ -37,7 +37,7 @@ export function MainLayout(props: Props) { {__("Overview")} {__("Documents")} - {trustCenter.vendorInfo.totalCount > 0 + {trustCenter.subprocessorInfo.totalCount > 0 && {__("Subprocessors")}} {__("Updates")} diff --git a/apps/trust/src/pages/OverviewPage.tsx b/apps/trust/src/pages/OverviewPage.tsx index dc23ebce9..1655f42df 100644 --- a/apps/trust/src/pages/OverviewPage.tsx +++ b/apps/trust/src/pages/OverviewPage.tsx @@ -15,8 +15,8 @@ import { AuditRow } from "#/components/AuditRow"; import { DocumentRow } from "#/components/DocumentRow"; import { RowHeader } from "#/components/RowHeader"; import { Rows } from "#/components/Rows"; +import { SubprocessorRow } from "#/components/SubprocessorRow"; import { TrustCenterFileRow } from "#/components/TrustCenterFileRow"; -import { VendorRow } from "#/components/VendorRow"; import { documentTypeLabel } from "#/helpers/documents"; import type { TrustGraphCurrentQuery$data } from "#/queries/__generated__/TrustGraphCurrentQuery.graphql"; @@ -37,12 +37,12 @@ const overviewFragment = graphql` } } } - vendors(first: 3) { + subprocessors(first: 3) { edges { node { id countries - ...VendorRowFragment + ...SubprocessorRowFragment } } } @@ -86,7 +86,7 @@ export function OverviewPage() { />
@@ -163,22 +163,22 @@ function Documents({ } function Subprocessors({ - vendors, + subprocessors, url, organizationName, }: { - vendors: OverviewPageFragment$data["vendors"]["edges"]; + subprocessors: OverviewPageFragment$data["subprocessors"]["edges"]; url: string; organizationName: string; }) { const { __ } = useTranslate(); - if (vendors.length === 0) { + if (subprocessors.length === 0) { return null; } - const hasAnyCountries = vendors.some((vendor) => { - const vendorData = vendor.node; - return vendorData.countries && vendorData.countries.length > 0; + const hasAnyCountries = subprocessors.some((subprocessor) => { + const subprocessorData = subprocessor.node; + return subprocessorData.countries && subprocessorData.countries.length > 0; }); return ( @@ -191,10 +191,10 @@ function Subprocessors({ )}

- {vendors.map(vendor => ( - ( + ))} diff --git a/apps/trust/src/pages/SubprocessorsPage.tsx b/apps/trust/src/pages/SubprocessorsPage.tsx index fda8d610a..16a506843 100644 --- a/apps/trust/src/pages/SubprocessorsPage.tsx +++ b/apps/trust/src/pages/SubprocessorsPage.tsx @@ -3,21 +3,21 @@ import { useTranslate } from "@probo/i18n"; import { type PreloadedQuery, usePreloadedQuery } from "react-relay"; import { Rows } from "#/components/Rows"; -import { VendorRow } from "#/components/VendorRow"; -import type { TrustGraphCurrentVendorsQuery } from "#/queries/__generated__/TrustGraphCurrentVendorsQuery.graphql"; -import { currentTrustVendorsQuery } from "#/queries/TrustGraph"; +import { SubprocessorRow } from "#/components/SubprocessorRow"; +import type { TrustGraphCurrentSubprocessorsQuery } from "#/queries/__generated__/TrustGraphCurrentSubprocessorsQuery.graphql"; +import { currentTrustSubprocessorsQuery } from "#/queries/TrustGraph"; type Props = { - queryRef: PreloadedQuery; + queryRef: PreloadedQuery; }; export function SubprocessorsPage({ queryRef }: Props) { const { __ } = useTranslate(); - const data = usePreloadedQuery(currentTrustVendorsQuery, queryRef); - const vendors - = data.currentTrustCenter?.vendors.edges.map(edge => edge.node) ?? []; + const data = usePreloadedQuery(currentTrustSubprocessorsQuery, queryRef); + const subprocessors + = data.currentTrustCenter?.subprocessors.edges.map(edge => edge.node) ?? []; - const hasAnyCountries = vendors.some(vendor => vendor.countries.length > 0); + const hasAnyCountries = subprocessors.some(subprocessor => subprocessor.countries.length > 0); return (
@@ -29,8 +29,8 @@ export function SubprocessorsPage({ queryRef }: Props) { )}

- {vendors.map(vendor => ( - + {subprocessors.map(subprocessor => ( + ))}
diff --git a/apps/trust/src/queries/TrustGraph.ts b/apps/trust/src/queries/TrustGraph.ts index a005dc169..0b0d87088 100644 --- a/apps/trust/src/queries/TrustGraph.ts +++ b/apps/trust/src/queries/TrustGraph.ts @@ -43,7 +43,7 @@ export const currentTrustGraphQuery = graphql` } } ...OverviewPageFragment - vendorInfo: vendors(first: 0) { + subprocessorInfo: subprocessors(first: 0) { totalCount } audits(first: 50) { @@ -97,19 +97,19 @@ export const currentTrustDocumentsQuery = graphql` } `; -export const currentTrustVendorsQuery = graphql` - query TrustGraphCurrentVendorsQuery { +export const currentTrustSubprocessorsQuery = graphql` + query TrustGraphCurrentSubprocessorsQuery { currentTrustCenter { id organization { name } - vendors(first: 50) { + subprocessors(first: 50) { edges { node { id countries - ...VendorRowFragment + ...SubprocessorRowFragment } } } diff --git a/apps/trust/src/routes.tsx b/apps/trust/src/routes.tsx index be4f67677..f8f7f8d92 100644 --- a/apps/trust/src/routes.tsx +++ b/apps/trust/src/routes.tsx @@ -17,7 +17,7 @@ import { currentTrustUpdatesQuery, UpdatesPage } from "#/pages/UpdatesPage"; import { currentTrustDocumentsQuery, currentTrustGraphQuery, - currentTrustVendorsQuery, + currentTrustSubprocessorsQuery, } from "#/queries/TrustGraph"; import { DocumentPageErrorBoundary } from "./components/DocumentPageErrorBoundary"; @@ -112,7 +112,7 @@ const routes = [ { path: "", loader: loaderFromQueryLoader(() => - loadQuery(consoleEnvironment, currentTrustVendorsQuery, {}), + loadQuery(consoleEnvironment, currentTrustSubprocessorsQuery, {}), ), Fallback: TabSkeleton, Component: withQueryRef(SubprocessorsPage), diff --git a/pkg/server/api/trust/v1/schema.graphql b/pkg/server/api/trust/v1/schema.graphql index d6bf676f8..79f80045c 100644 --- a/pkg/server/api/trust/v1/schema.graphql +++ b/pkg/server/api/trust/v1/schema.graphql @@ -409,7 +409,7 @@ enum CountryCode ZW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeZW") } -enum VendorCategory +enum SubprocessorCategory @goModel(model: "go.probo.inc/probo/pkg/coredata.VendorCategory") { ANALYTICS @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryAnalytics") @@ -480,28 +480,28 @@ enum VendorCategory ) } -type Vendor implements Node @nda { +type Subprocessor implements Node @nda { id: ID! name: String! description: String - category: VendorCategory! + category: SubprocessorCategory! websiteUrl: String privacyPolicyUrl: String countries: [CountryCode!]! } -type VendorConnection +type SubprocessorConnection @goModel( - model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.VendorConnection" + model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.SubprocessorConnection" ) @nda { - edges: [VendorEdge!]! + edges: [SubprocessorEdge!]! pageInfo: PageInfo! totalCount: Int! @goField(forceResolver: true) } -type VendorEdge @nda { +type SubprocessorEdge @nda { cursor: CursorKey! - node: Vendor! + node: Subprocessor! } type TrustCenterReference implements Node @nda { @@ -572,12 +572,12 @@ type TrustCenter implements Node { before: CursorKey ): AuditConnection! @goField(forceResolver: true) - vendors( + subprocessors( first: Int after: CursorKey last: Int before: CursorKey - ): VendorConnection! @goField(forceResolver: true) + ): SubprocessorConnection! @goField(forceResolver: true) references( first: Int diff --git a/pkg/server/api/trust/v1/types/vendor.go b/pkg/server/api/trust/v1/types/vendor.go index f737fabed..678b69bf1 100644 --- a/pkg/server/api/trust/v1/types/vendor.go +++ b/pkg/server/api/trust/v1/types/vendor.go @@ -21,9 +21,9 @@ import ( ) type ( - VendorConnection struct { + SubprocessorConnection struct { TotalCount int - Edges []*VendorEdge + Edges []*SubprocessorEdge PageInfo PageInfo Resolver any @@ -31,17 +31,17 @@ type ( } ) -func NewVendorConnection( +func NewSubprocessorConnection( p *page.Page[*coredata.Vendor, coredata.VendorOrderField], parentType any, parentID gid.GID, -) *VendorConnection { - edges := make([]*VendorEdge, len(p.Data)) +) *SubprocessorConnection { + edges := make([]*SubprocessorEdge, len(p.Data)) for i, vendor := range p.Data { - edges[i] = NewVendorEdge(vendor, p.Cursor.OrderBy.Field) + edges[i] = NewSubprocessorEdge(vendor, p.Cursor.OrderBy.Field) } - return &VendorConnection{ + return &SubprocessorConnection{ Edges: edges, PageInfo: *NewPageInfo(p), @@ -50,8 +50,8 @@ func NewVendorConnection( } } -func NewVendor(v *coredata.Vendor) *Vendor { - return &Vendor{ +func NewSubprocessor(v *coredata.Vendor) *Subprocessor { + return &Subprocessor{ ID: v.ID, Name: v.Name, Description: v.Description, @@ -62,9 +62,9 @@ func NewVendor(v *coredata.Vendor) *Vendor { } } -func NewVendorEdge(v *coredata.Vendor, orderField coredata.VendorOrderField) *VendorEdge { - return &VendorEdge{ - Node: NewVendor(v), +func NewSubprocessorEdge(v *coredata.Vendor, orderField coredata.VendorOrderField) *SubprocessorEdge { + return &SubprocessorEdge{ + Node: NewSubprocessor(v), Cursor: v.CursorKey(orderField), } } diff --git a/pkg/server/api/trust/v1/v1_resolver.go b/pkg/server/api/trust/v1/v1_resolver.go index fb966b037..009081d78 100644 --- a/pkg/server/api/trust/v1/v1_resolver.go +++ b/pkg/server/api/trust/v1/v1_resolver.go @@ -932,7 +932,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error r.logger.ErrorCtx(ctx, "cannot get vendor", log.Error(err)) return nil, gqlutils.Internal(ctx) } - return types.NewVendor(vendor), nil + return types.NewSubprocessor(vendor), nil case coredata.TrustCenterEntityType: trustCenter, err := trustService.TrustCenters.Get(ctx, id) @@ -1071,6 +1071,24 @@ func (r *reportResolver) Access(ctx context.Context, obj *types.Report) (*types. }, nil } +// TotalCount is the resolver for the totalCount field. +func (r *subprocessorConnectionResolver) TotalCount(ctx context.Context, obj *types.SubprocessorConnection) (int, error) { + trustService := r.TrustService(ctx, obj.ParentID.TenantID()) + + switch obj.Resolver.(type) { + case *trustCenterResolver: + count, err := trustService.Vendors.CountForTrustCenterId(ctx, obj.ParentID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot count subprocessors", log.Error(err)) + return 0, gqlutils.Internal(ctx) + } + return count, nil + } + + r.logger.ErrorCtx(ctx, "not implemented: TotalCount for parent type") + return 0, gqlutils.Internal(ctx) +} + // LogoFileURL is the resolver for the logoFileUrl field. func (r *trustCenterResolver) LogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) { trustService := r.TrustService(ctx, obj.ID.TenantID()) @@ -1174,8 +1192,8 @@ func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter return types.NewAuditConnection(auditPage), nil } -// Vendors is the resolver for the vendors field. -func (r *trustCenterResolver) Vendors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.VendorConnection, error) { +// Subprocessors is the resolver for the subprocessors field. +func (r *trustCenterResolver) Subprocessors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SubprocessorConnection, error) { trustService := r.TrustService(ctx, obj.ID.TenantID()) pageOrderBy := page.OrderBy[coredata.VendorOrderField]{ @@ -1186,11 +1204,11 @@ func (r *trustCenterResolver) Vendors(ctx context.Context, obj *types.TrustCente vendorPage, err := trustService.Vendors.ListForOrganizationId(ctx, obj.Organization.ID, cursor) if err != nil { - r.logger.ErrorCtx(ctx, "cannot list public vendors", log.Error(err)) + r.logger.ErrorCtx(ctx, "cannot list subprocessors", log.Error(err)) return nil, gqlutils.Internal(ctx) } - return types.NewVendorConnection(vendorPage, r, obj.ID), nil + return types.NewSubprocessorConnection(vendorPage, r, obj.ID), nil } // References is the resolver for the references field. @@ -1398,24 +1416,6 @@ func (r *trustCenterReferenceResolver) LogoURL(ctx context.Context, obj *types.T return logoURL, nil } -// TotalCount is the resolver for the totalCount field. -func (r *vendorConnectionResolver) TotalCount(ctx context.Context, obj *types.VendorConnection) (int, error) { - trustService := r.TrustService(ctx, obj.ParentID.TenantID()) - - switch obj.Resolver.(type) { - case *trustCenterResolver: - count, err := trustService.Vendors.CountForTrustCenterId(ctx, obj.ParentID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot count vendors", log.Error(err)) - return 0, gqlutils.Internal(ctx) - } - return count, nil - } - - r.logger.ErrorCtx(ctx, "not implemented: TotalCount for parent type") - return 0, gqlutils.Internal(ctx) -} - // Audit returns schema.AuditResolver implementation. func (r *Resolver) Audit() schema.AuditResolver { return &auditResolver{r} } @@ -1447,6 +1447,11 @@ func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} } // Report returns schema.ReportResolver implementation. func (r *Resolver) Report() schema.ReportResolver { return &reportResolver{r} } +// SubprocessorConnection returns schema.SubprocessorConnectionResolver implementation. +func (r *Resolver) SubprocessorConnection() schema.SubprocessorConnectionResolver { + return &subprocessorConnectionResolver{r} +} + // TrustCenter returns schema.TrustCenterResolver implementation. func (r *Resolver) TrustCenter() schema.TrustCenterResolver { return &trustCenterResolver{r} } @@ -1460,11 +1465,6 @@ func (r *Resolver) TrustCenterReference() schema.TrustCenterReferenceResolver { return &trustCenterReferenceResolver{r} } -// VendorConnection returns schema.VendorConnectionResolver implementation. -func (r *Resolver) VendorConnection() schema.VendorConnectionResolver { - return &vendorConnectionResolver{r} -} - type auditResolver struct{ *Resolver } type complianceFrameworkResolver struct{ *Resolver } type documentResolver struct{ *Resolver } @@ -1474,7 +1474,7 @@ type nonDisclosureAgreementResolver struct{ *Resolver } type organizationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } type reportResolver struct{ *Resolver } +type subprocessorConnectionResolver struct{ *Resolver } type trustCenterResolver struct{ *Resolver } type trustCenterFileResolver struct{ *Resolver } type trustCenterReferenceResolver struct{ *Resolver } -type vendorConnectionResolver struct{ *Resolver }