Add uncategorised patterns GraphQL endpoint
Backend for the cookie banner detection page: a new uncategorisedPatterns connection on CookieBanner with sortable (NAME, LAST_MATCHED_AT, UPDATED_AT, SOURCE) and filterable (text ILIKE on name/description, source enum) paginated results. COALESCE handles NULL-first ordering for last_matched_at. Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -1434,6 +1434,61 @@ func (s *Service) CountCookiePatternsForCategory(
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) ListUncategorisedCookiePatterns(
|
||||||
|
ctx context.Context,
|
||||||
|
scope coredata.Scoper,
|
||||||
|
bannerID gid.GID,
|
||||||
|
cursor *page.Cursor[coredata.CookiePatternOrderField],
|
||||||
|
filter *coredata.CookiePatternFilter,
|
||||||
|
) (coredata.CookiePatterns, error) {
|
||||||
|
var patterns coredata.CookiePatterns
|
||||||
|
|
||||||
|
err := s.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(ctx context.Context, conn pg.Querier) error {
|
||||||
|
if err := patterns.LoadUncategorisedByCookieBannerID(ctx, conn, scope, bannerID, cursor, filter); err != nil {
|
||||||
|
return fmt.Errorf("cannot list uncategorised cookie patterns: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return patterns, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) CountUncategorisedCookiePatterns(
|
||||||
|
ctx context.Context,
|
||||||
|
scope coredata.Scoper,
|
||||||
|
bannerID gid.GID,
|
||||||
|
filter *coredata.CookiePatternFilter,
|
||||||
|
) (int, error) {
|
||||||
|
var count int
|
||||||
|
|
||||||
|
err := s.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(ctx context.Context, conn pg.Querier) error {
|
||||||
|
var patterns coredata.CookiePatterns
|
||||||
|
var err error
|
||||||
|
|
||||||
|
count, err = patterns.CountUncategorisedByCookieBannerID(ctx, conn, scope, bannerID, filter)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot count uncategorised cookie patterns: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) CountCookiesForPattern(
|
func (s *Service) CountCookiesForPattern(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
scope coredata.Scoper,
|
scope coredata.Scoper,
|
||||||
|
|||||||
@@ -53,6 +53,17 @@ func (cp *CookiePattern) CursorKey(field CookiePatternOrderField) page.CursorKey
|
|||||||
switch field {
|
switch field {
|
||||||
case CookiePatternOrderFieldCreatedAt:
|
case CookiePatternOrderFieldCreatedAt:
|
||||||
return page.NewCursorKey(cp.ID, cp.CreatedAt)
|
return page.NewCursorKey(cp.ID, cp.CreatedAt)
|
||||||
|
case CookiePatternOrderFieldName:
|
||||||
|
return page.NewCursorKey(cp.ID, cp.DisplayName)
|
||||||
|
case CookiePatternOrderFieldLastMatchedAt:
|
||||||
|
if cp.LastMatchedAt == nil {
|
||||||
|
return page.NewCursorKey(cp.ID, time.Time{})
|
||||||
|
}
|
||||||
|
return page.NewCursorKey(cp.ID, *cp.LastMatchedAt)
|
||||||
|
case CookiePatternOrderFieldUpdatedAt:
|
||||||
|
return page.NewCursorKey(cp.ID, cp.UpdatedAt)
|
||||||
|
case CookiePatternOrderFieldSource:
|
||||||
|
return page.NewCursorKey(cp.ID, string(cp.Source))
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||||
@@ -639,6 +650,115 @@ WHERE
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cps *CookiePatterns) LoadUncategorisedByCookieBannerID(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Querier,
|
||||||
|
scope Scoper,
|
||||||
|
cookieBannerID gid.GID,
|
||||||
|
cursor *page.Cursor[CookiePatternOrderField],
|
||||||
|
filter *CookiePatternFilter,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
organization_id,
|
||||||
|
cookie_banner_id,
|
||||||
|
cookie_category_id,
|
||||||
|
pattern,
|
||||||
|
match_type,
|
||||||
|
display_name,
|
||||||
|
max_age_seconds,
|
||||||
|
description,
|
||||||
|
source,
|
||||||
|
excluded,
|
||||||
|
last_matched_at,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
FROM
|
||||||
|
cookie_patterns
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND cookie_banner_id = @cookie_banner_id
|
||||||
|
AND cookie_category_id = (
|
||||||
|
SELECT id FROM cookie_categories
|
||||||
|
WHERE cookie_banner_id = @cookie_banner_id
|
||||||
|
AND kind = @category_kind
|
||||||
|
AND %s
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
AND %s
|
||||||
|
AND %s
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment(), scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"cookie_banner_id": cookieBannerID,
|
||||||
|
"category_kind": CookieCategoryKindUncategorised,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
maps.Copy(args, filter.SQLArguments())
|
||||||
|
maps.Copy(args, cursor.SQLArguments())
|
||||||
|
|
||||||
|
rows, err := conn.Query(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot query uncategorised cookie patterns: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
patterns, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[CookiePattern])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot collect uncategorised cookie patterns: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
*cps = patterns
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cps *CookiePatterns) CountUncategorisedByCookieBannerID(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Querier,
|
||||||
|
scope Scoper,
|
||||||
|
cookieBannerID gid.GID,
|
||||||
|
filter *CookiePatternFilter,
|
||||||
|
) (int, error) {
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
COUNT(id)
|
||||||
|
FROM
|
||||||
|
cookie_patterns
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND cookie_banner_id = @cookie_banner_id
|
||||||
|
AND cookie_category_id = (
|
||||||
|
SELECT id FROM cookie_categories
|
||||||
|
WHERE cookie_banner_id = @cookie_banner_id
|
||||||
|
AND kind = @category_kind
|
||||||
|
AND %s
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
AND %s
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment(), scope.SQLFragment(), filter.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"cookie_banner_id": cookieBannerID,
|
||||||
|
"category_kind": CookieCategoryKindUncategorised,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
maps.Copy(args, filter.SQLArguments())
|
||||||
|
|
||||||
|
row := conn.QueryRow(ctx, q, args)
|
||||||
|
|
||||||
|
var count int
|
||||||
|
if err := row.Scan(&count); err != nil {
|
||||||
|
return 0, fmt.Errorf("cannot scan count: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cps *CookiePatterns) MoveToCategoryByCookieCategoryID(
|
func (cps *CookiePatterns) MoveToCategoryByCookieCategoryID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
tx pg.Tx,
|
tx pg.Tx,
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ type CookiePatternFilter struct {
|
|||||||
matchType *CookiePatternMatchType
|
matchType *CookiePatternMatchType
|
||||||
cookieCategoryID *gid.GID
|
cookieCategoryID *gid.GID
|
||||||
excluded *bool
|
excluded *bool
|
||||||
|
query *string
|
||||||
|
source *CookieSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCookiePatternFilter(
|
func NewCookiePatternFilter(
|
||||||
@@ -37,6 +39,16 @@ func NewCookiePatternFilter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *CookiePatternFilter) WithQuery(query *string) *CookiePatternFilter {
|
||||||
|
f.query = query
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CookiePatternFilter) WithSource(source *CookieSource) *CookiePatternFilter {
|
||||||
|
f.source = source
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
func (f *CookiePatternFilter) SQLFragment() string {
|
func (f *CookiePatternFilter) SQLFragment() string {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return "TRUE"
|
return "TRUE"
|
||||||
@@ -64,6 +76,20 @@ func (f *CookiePatternFilter) SQLFragment() string {
|
|||||||
excluded = @filter_excluded
|
excluded = @filter_excluded
|
||||||
ELSE TRUE
|
ELSE TRUE
|
||||||
END
|
END
|
||||||
|
AND
|
||||||
|
CASE
|
||||||
|
WHEN @filter_query::text IS NOT NULL AND @filter_query::text != '' THEN
|
||||||
|
(display_name ILIKE '%' || @filter_query || '%'
|
||||||
|
OR description ILIKE '%' || @filter_query || '%')
|
||||||
|
ELSE TRUE
|
||||||
|
END
|
||||||
|
AND
|
||||||
|
CASE
|
||||||
|
WHEN @has_source_filter::boolean = false THEN TRUE
|
||||||
|
WHEN @has_source_filter::boolean = true THEN
|
||||||
|
source = @filter_source::cookie_source
|
||||||
|
ELSE TRUE
|
||||||
|
END
|
||||||
)`
|
)`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +105,9 @@ func (f *CookiePatternFilter) SQLArguments() pgx.StrictNamedArgs {
|
|||||||
"filter_cookie_category_id": nil,
|
"filter_cookie_category_id": nil,
|
||||||
"has_excluded_filter": false,
|
"has_excluded_filter": false,
|
||||||
"filter_excluded": nil,
|
"filter_excluded": nil,
|
||||||
|
"filter_query": nil,
|
||||||
|
"has_source_filter": false,
|
||||||
|
"filter_source": nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.matchType != nil {
|
if f.matchType != nil {
|
||||||
@@ -96,5 +125,14 @@ func (f *CookiePatternFilter) SQLArguments() pgx.StrictNamedArgs {
|
|||||||
args["filter_excluded"] = *f.excluded
|
args["filter_excluded"] = *f.excluded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.query != nil {
|
||||||
|
args["filter_query"] = *f.query
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.source != nil {
|
||||||
|
args["has_source_filter"] = true
|
||||||
|
args["filter_source"] = string(*f.source)
|
||||||
|
}
|
||||||
|
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,19 +20,35 @@ type CookiePatternOrderField string
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
CookiePatternOrderFieldCreatedAt CookiePatternOrderField = "CREATED_AT"
|
CookiePatternOrderFieldCreatedAt CookiePatternOrderField = "CREATED_AT"
|
||||||
|
CookiePatternOrderFieldName CookiePatternOrderField = "NAME"
|
||||||
|
CookiePatternOrderFieldLastMatchedAt CookiePatternOrderField = "LAST_MATCHED_AT"
|
||||||
|
CookiePatternOrderFieldUpdatedAt CookiePatternOrderField = "UPDATED_AT"
|
||||||
|
CookiePatternOrderFieldSource CookiePatternOrderField = "SOURCE"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p CookiePatternOrderField) Column() string {
|
func (p CookiePatternOrderField) Column() string {
|
||||||
switch p {
|
switch p {
|
||||||
case CookiePatternOrderFieldCreatedAt:
|
case CookiePatternOrderFieldCreatedAt:
|
||||||
return "created_at"
|
return "created_at"
|
||||||
|
case CookiePatternOrderFieldName:
|
||||||
|
return "display_name"
|
||||||
|
case CookiePatternOrderFieldLastMatchedAt:
|
||||||
|
return "COALESCE(last_matched_at, '0001-01-01T00:00:00Z'::timestamptz)"
|
||||||
|
case CookiePatternOrderFieldUpdatedAt:
|
||||||
|
return "updated_at"
|
||||||
|
case CookiePatternOrderFieldSource:
|
||||||
|
return "source"
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("unsupported order by: %s", p))
|
panic(fmt.Sprintf("unsupported order by: %s", p))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p CookiePatternOrderField) IsValid() bool {
|
func (p CookiePatternOrderField) IsValid() bool {
|
||||||
switch p {
|
switch p {
|
||||||
case CookiePatternOrderFieldCreatedAt:
|
case CookiePatternOrderFieldCreatedAt,
|
||||||
|
CookiePatternOrderFieldName,
|
||||||
|
CookiePatternOrderFieldLastMatchedAt,
|
||||||
|
CookiePatternOrderFieldUpdatedAt,
|
||||||
|
CookiePatternOrderFieldSource:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -177,6 +177,42 @@ func (r *cookieBannerResolver) ConsentRecords(ctx context.Context, obj *types.Co
|
|||||||
return types.NewCookieConsentRecordConnection(p, r, obj.ID, coredataFilter), nil
|
return types.NewCookieConsentRecordConnection(p, r, obj.ID, coredataFilter), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UncategorisedPatterns is the resolver for the uncategorisedPatterns field.
|
||||||
|
func (r *cookieBannerResolver) UncategorisedPatterns(ctx context.Context, obj *types.CookieBanner, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.CookiePatternOrderBy, filter *types.CookiePatternFilter) (*types.CookiePatternConnection, error) {
|
||||||
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookiePatternList); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.CookiePatternOrderField]{
|
||||||
|
Field: coredata.CookiePatternOrderFieldName,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
}
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.CookiePatternOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
||||||
|
|
||||||
|
coredataFilter := coredata.NewCookiePatternFilter(nil, nil, nil)
|
||||||
|
if filter != nil {
|
||||||
|
coredataFilter = coredataFilter.WithQuery(filter.Query).WithSource(filter.Source)
|
||||||
|
}
|
||||||
|
|
||||||
|
patterns, err := r.cookieBanner.ListUncategorisedCookiePatterns(ctx, scope, obj.ID, cursor, coredataFilter)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list uncategorised cookie patterns", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := page.NewPage(patterns, cursor)
|
||||||
|
|
||||||
|
return types.NewCookiePatternConnectionWithFilter(p, r, obj.ID, coredataFilter), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Permission is the resolver for the permission field.
|
// Permission is the resolver for the permission field.
|
||||||
func (r *cookieBannerResolver) Permission(ctx context.Context, obj *types.CookieBanner, action string) (bool, error) {
|
func (r *cookieBannerResolver) Permission(ctx context.Context, obj *types.CookieBanner, action string) (bool, error) {
|
||||||
return r.Resolver.Permission(ctx, obj, action)
|
return r.Resolver.Permission(ctx, obj, action)
|
||||||
@@ -369,14 +405,23 @@ func (r *cookiePatternConnectionResolver) TotalCount(ctx context.Context, obj *t
|
|||||||
|
|
||||||
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
||||||
|
|
||||||
|
switch obj.Resolver.(type) {
|
||||||
|
case *cookieBannerResolver:
|
||||||
|
count, err := r.cookieBanner.CountUncategorisedCookiePatterns(ctx, scope, obj.ParentID, obj.Filter)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot count uncategorised cookie patterns", log.Error(err))
|
||||||
|
return 0, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
default:
|
||||||
count, err := r.cookieBanner.CountCookiePatternsForCategory(ctx, scope, obj.ParentID)
|
count, err := r.cookieBanner.CountCookiePatternsForCategory(ctx, scope, obj.ParentID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.ErrorCtx(ctx, "cannot count cookie patterns", log.Error(err))
|
r.logger.ErrorCtx(ctx, "cannot count cookie patterns", log.Error(err))
|
||||||
return 0, gqlutils.Internal(ctx)
|
return 0, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CreateCookieBanner is the resolver for the createCookieBanner field.
|
// CreateCookieBanner is the resolver for the createCookieBanner field.
|
||||||
func (r *mutationResolver) CreateCookieBanner(ctx context.Context, input types.CreateCookieBannerInput) (*types.CreateCookieBannerPayload, error) {
|
func (r *mutationResolver) CreateCookieBanner(ctx context.Context, input types.CreateCookieBannerInput) (*types.CreateCookieBannerPayload, error) {
|
||||||
|
|||||||
@@ -123,6 +123,15 @@ type CookieBanner implements Node {
|
|||||||
filter: CookieConsentRecordFilter
|
filter: CookieConsentRecordFilter
|
||||||
): CookieConsentRecordConnection @goField(forceResolver: true)
|
): CookieConsentRecordConnection @goField(forceResolver: true)
|
||||||
|
|
||||||
|
uncategorisedPatterns(
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
orderBy: CookiePatternOrder
|
||||||
|
filter: CookiePatternFilter
|
||||||
|
): CookiePatternConnection @goField(forceResolver: true)
|
||||||
|
|
||||||
createdAt: Datetime!
|
createdAt: Datetime!
|
||||||
updatedAt: Datetime!
|
updatedAt: Datetime!
|
||||||
|
|
||||||
@@ -184,6 +193,22 @@ enum CookiePatternOrderField
|
|||||||
@goEnum(
|
@goEnum(
|
||||||
value: "go.probo.inc/probo/pkg/coredata.CookiePatternOrderFieldCreatedAt"
|
value: "go.probo.inc/probo/pkg/coredata.CookiePatternOrderFieldCreatedAt"
|
||||||
)
|
)
|
||||||
|
NAME
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.CookiePatternOrderFieldName"
|
||||||
|
)
|
||||||
|
LAST_MATCHED_AT
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.CookiePatternOrderFieldLastMatchedAt"
|
||||||
|
)
|
||||||
|
UPDATED_AT
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.CookiePatternOrderFieldUpdatedAt"
|
||||||
|
)
|
||||||
|
SOURCE
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.CookiePatternOrderFieldSource"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
input CookiePatternOrder
|
input CookiePatternOrder
|
||||||
@@ -194,6 +219,11 @@ input CookiePatternOrder
|
|||||||
field: CookiePatternOrderField!
|
field: CookiePatternOrderField!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input CookiePatternFilter {
|
||||||
|
query: String
|
||||||
|
source: CookieSource
|
||||||
|
}
|
||||||
|
|
||||||
type CookiePattern implements Node {
|
type CookiePattern implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
cookieCategory: CookieCategory @goField(forceResolver: true)
|
cookieCategory: CookieCategory @goField(forceResolver: true)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type (
|
|||||||
|
|
||||||
Resolver any
|
Resolver any
|
||||||
ParentID gid.GID
|
ParentID gid.GID
|
||||||
|
Filter *coredata.CookiePatternFilter
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,6 +54,17 @@ func NewCookiePatternConnection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewCookiePatternConnectionWithFilter(
|
||||||
|
p *page.Page[*coredata.CookiePattern, coredata.CookiePatternOrderField],
|
||||||
|
parentType any,
|
||||||
|
parentID gid.GID,
|
||||||
|
filter *coredata.CookiePatternFilter,
|
||||||
|
) *CookiePatternConnection {
|
||||||
|
conn := NewCookiePatternConnection(p, parentType, parentID)
|
||||||
|
conn.Filter = filter
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
func NewCookiePatternEdge(cp *coredata.CookiePattern, orderBy coredata.CookiePatternOrderField) *CookiePatternEdge {
|
func NewCookiePatternEdge(cp *coredata.CookiePattern, orderBy coredata.CookiePatternOrderField) *CookiePatternEdge {
|
||||||
return &CookiePatternEdge{
|
return &CookiePatternEdge{
|
||||||
Cursor: cp.CursorKey(orderBy),
|
Cursor: cp.CursorKey(orderBy),
|
||||||
|
|||||||
Reference in New Issue
Block a user