Filter trust center subprocessors server-side
Subprocessor filtering for the compliance portal happens in the backend rather than the client. Add a SubprocessorFilter (query, category, country) to the trust API's subprocessors connection, thread it through the resolver and service, and extend the coredata ThirdParty filter with category equality and country array membership. The connection stores the filter so totalCount reflects the filtered set. Add e2e coverage for the new filtering. On the frontend, convert the page to a refetchable fragment whose filter arguments are driven by URL-persisted, debounced toolbar state (category and region selects plus a search field), populate the dropdowns from an unfiltered facet selection, and offer to clear filters from the empty state. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -30,6 +30,7 @@ type TrustCenter implements Node {
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
filter: SubprocessorFilter
|
||||
): SubprocessorConnection! @goField(forceResolver: true)
|
||||
|
||||
references(
|
||||
@@ -245,6 +246,12 @@ type Subprocessor implements Node @nda {
|
||||
countries: [CountryCode!]!
|
||||
}
|
||||
|
||||
input SubprocessorFilter {
|
||||
query: String
|
||||
category: SubprocessorCategory
|
||||
country: CountryCode
|
||||
}
|
||||
|
||||
type SubprocessorConnection
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.SubprocessorConnection"
|
||||
|
||||
@@ -670,7 +670,7 @@ func (r *subprocessorConnectionResolver) TotalCount(ctx context.Context, obj *ty
|
||||
|
||||
switch obj.Resolver.(type) {
|
||||
case *trustCenterResolver:
|
||||
count, err := trustService.ThirdParties.CountForTrustCenterId(ctx, scope, obj.ParentID)
|
||||
count, err := trustService.ThirdParties.CountForTrustCenterId(ctx, scope, obj.ParentID, obj.Filter)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot count subprocessors", log.Error(err))
|
||||
return 0, gqlutils.Internal(ctx)
|
||||
@@ -798,7 +798,7 @@ func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter
|
||||
}
|
||||
|
||||
// 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) {
|
||||
func (r *trustCenterResolver) Subprocessors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, filter *types.SubprocessorFilter) (*types.SubprocessorConnection, error) {
|
||||
compliancePage := compliancepage.CompliancePageFromContext(ctx)
|
||||
scope := coredata.NewScopeFromObjectID(compliancePage.OrganizationID)
|
||||
trustService := r.trust
|
||||
@@ -808,13 +808,27 @@ func (r *trustCenterResolver) Subprocessors(ctx context.Context, obj *types.Trus
|
||||
}
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
thirdPartyPage, err := trustService.ThirdParties.ListForOrganizationId(ctx, scope, obj.Organization.ID, cursor)
|
||||
var (
|
||||
query *string
|
||||
category *coredata.ThirdPartyCategory
|
||||
country *coredata.CountryCode
|
||||
)
|
||||
if filter != nil {
|
||||
query = filter.Query
|
||||
category = filter.Category
|
||||
country = filter.Country
|
||||
}
|
||||
|
||||
showOnTrustCenter := true
|
||||
thirdPartyFilter := coredata.NewThirdPartyFilter(&showOnTrustCenter, nil, query, category, country)
|
||||
|
||||
thirdPartyPage, err := trustService.ThirdParties.ListForOrganizationId(ctx, scope, obj.Organization.ID, cursor, thirdPartyFilter)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list subprocessors", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewSubprocessorConnection(thirdPartyPage, r, obj.ID), nil
|
||||
return types.NewSubprocessorConnection(thirdPartyPage, r, obj.ID, thirdPartyFilter), nil
|
||||
}
|
||||
|
||||
// References is the resolver for the references field.
|
||||
|
||||
@@ -28,6 +28,7 @@ type (
|
||||
|
||||
Resolver any
|
||||
ParentID gid.GID
|
||||
Filter *coredata.ThirdPartyFilter
|
||||
}
|
||||
)
|
||||
|
||||
@@ -35,6 +36,7 @@ func NewSubprocessorConnection(
|
||||
p *page.Page[*coredata.ThirdParty, coredata.ThirdPartyOrderField],
|
||||
parentType any,
|
||||
parentID gid.GID,
|
||||
filter *coredata.ThirdPartyFilter,
|
||||
) *SubprocessorConnection {
|
||||
edges := make([]*SubprocessorEdge, len(p.Data))
|
||||
for i, thirdParty := range p.Data {
|
||||
@@ -47,6 +49,7 @@ func NewSubprocessorConnection(
|
||||
|
||||
Resolver: parentType,
|
||||
ParentID: parentID,
|
||||
Filter: filter,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user