Jelajahi Sumber

feat(core): Add `Facet.valueList` resolver for paginated values

Relates to #1257
Michael Bromley 2 tahun lalu
induk
melakukan
09c7175f8b

+ 10 - 0
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -1607,9 +1607,16 @@ export type Facet = Node & {
   name: Scalars['String'];
   translations: Array<FacetTranslation>;
   updatedAt: Scalars['DateTime'];
+  /** Returns a paginated, sortable, filterable list of the Facet's values. Added in v2.1.0. */
+  valueList: FacetValueList;
   values: Array<FacetValue>;
 };
 
+
+export type FacetValueListArgs = {
+  options?: InputMaybe<FacetValueListOptions>;
+};
+
 export type FacetFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
@@ -1678,6 +1685,7 @@ export type FacetValue = Node & {
   createdAt: Scalars['DateTime'];
   customFields?: Maybe<Scalars['JSON']>;
   facet: Facet;
+  facetId: Scalars['ID'];
   id: Scalars['ID'];
   languageCode: LanguageCode;
   name: Scalars['String'];
@@ -1701,6 +1709,7 @@ export type FacetValueFilterInput = {
 export type FacetValueFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
+  facetId?: InputMaybe<IdOperators>;
   id?: InputMaybe<IdOperators>;
   languageCode?: InputMaybe<StringOperators>;
   name?: InputMaybe<StringOperators>;
@@ -1739,6 +1748,7 @@ export type FacetValueResult = {
 export type FacetValueSortParameter = {
   code?: InputMaybe<SortOrder>;
   createdAt?: InputMaybe<SortOrder>;
+  facetId?: InputMaybe<SortOrder>;
   id?: InputMaybe<SortOrder>;
   name?: InputMaybe<SortOrder>;
   updatedAt?: InputMaybe<SortOrder>;

+ 10 - 0
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts

@@ -1551,9 +1551,16 @@ export type Facet = Node & {
   name: Scalars['String'];
   translations: Array<FacetTranslation>;
   updatedAt: Scalars['DateTime'];
+  /** Returns a paginated, sortable, filterable list of the Facet's values. Added in v2.1.0. */
+  valueList: FacetValueList;
   values: Array<FacetValue>;
 };
 
+
+export type FacetValueListArgs = {
+  options?: InputMaybe<FacetValueListOptions>;
+};
+
 export type FacetFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
@@ -1618,6 +1625,7 @@ export type FacetValue = Node & {
   createdAt: Scalars['DateTime'];
   customFields?: Maybe<Scalars['JSON']>;
   facet: Facet;
+  facetId: Scalars['ID'];
   id: Scalars['ID'];
   languageCode: LanguageCode;
   name: Scalars['String'];
@@ -1641,6 +1649,7 @@ export type FacetValueFilterInput = {
 export type FacetValueFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
+  facetId?: InputMaybe<IdOperators>;
   id?: InputMaybe<IdOperators>;
   languageCode?: InputMaybe<StringOperators>;
   name?: InputMaybe<StringOperators>;
@@ -1677,6 +1686,7 @@ export type FacetValueResult = {
 export type FacetValueSortParameter = {
   code?: InputMaybe<SortOrder>;
   createdAt?: InputMaybe<SortOrder>;
+  facetId?: InputMaybe<SortOrder>;
   id?: InputMaybe<SortOrder>;
   name?: InputMaybe<SortOrder>;
   updatedAt?: InputMaybe<SortOrder>;

File diff ditekan karena terlalu besar
+ 641 - 659
packages/common/src/generated-shop-types.ts


+ 10 - 0
packages/common/src/generated-types.ts

@@ -1595,9 +1595,16 @@ export type Facet = Node & {
   name: Scalars['String'];
   translations: Array<FacetTranslation>;
   updatedAt: Scalars['DateTime'];
+  /** Returns a paginated, sortable, filterable list of the Facet's values. Added in v2.1.0. */
+  valueList: FacetValueList;
   values: Array<FacetValue>;
 };
 
+
+export type FacetValueListArgs = {
+  options?: InputMaybe<FacetValueListOptions>;
+};
+
 export type FacetFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
@@ -1666,6 +1673,7 @@ export type FacetValue = Node & {
   createdAt: Scalars['DateTime'];
   customFields?: Maybe<Scalars['JSON']>;
   facet: Facet;
+  facetId: Scalars['ID'];
   id: Scalars['ID'];
   languageCode: LanguageCode;
   name: Scalars['String'];
@@ -1689,6 +1697,7 @@ export type FacetValueFilterInput = {
 export type FacetValueFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
+  facetId?: InputMaybe<IdOperators>;
   id?: InputMaybe<IdOperators>;
   languageCode?: InputMaybe<StringOperators>;
   name?: InputMaybe<StringOperators>;
@@ -1727,6 +1736,7 @@ export type FacetValueResult = {
 export type FacetValueSortParameter = {
   code?: InputMaybe<SortOrder>;
   createdAt?: InputMaybe<SortOrder>;
+  facetId?: InputMaybe<SortOrder>;
   id?: InputMaybe<SortOrder>;
   name?: InputMaybe<SortOrder>;
   updatedAt?: InputMaybe<SortOrder>;

File diff ditekan karena terlalu besar
+ 571 - 590
packages/core/e2e/graphql/generated-e2e-admin-types.ts


File diff ditekan karena terlalu besar
+ 613 - 631
packages/core/e2e/graphql/generated-e2e-shop-types.ts


+ 14 - 1
packages/core/src/api/resolvers/entity/facet-entity.resolver.ts

@@ -1,4 +1,6 @@
-import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
+import { Args, Parent, ResolveField, Resolver } from '@nestjs/graphql';
+import { FacetValueListOptions } from '@vendure/common/lib/generated-types';
+import { PaginatedList } from '@vendure/common/lib/shared-types';
 
 import { RequestContextCacheService } from '../../../cache/request-context-cache.service';
 import { Facet } from '../../../entity/facet/facet.entity';
@@ -6,6 +8,7 @@ import { FacetValue } from '../../../entity/facet-value/facet-value.entity';
 import { LocaleStringHydrator } from '../../../service/helpers/locale-string-hydrator/locale-string-hydrator';
 import { FacetValueService } from '../../../service/services/facet-value.service';
 import { RequestContext } from '../../common/request-context';
+import { RelationPaths, Relations } from '../../decorators/relations.decorator';
 import { Ctx } from '../../decorators/request-context.decorator';
 
 @Resolver('Facet')
@@ -35,4 +38,14 @@ export class FacetEntityResolver {
             this.facetValueService.findByFacetId(ctx, facet.id),
         );
     }
+
+    @ResolveField()
+    async valueList(
+        @Ctx() ctx: RequestContext,
+        @Parent() facet: Facet,
+        @Args() args: { options: FacetValueListOptions },
+        @Relations({ entity: FacetValue }) relations: RelationPaths<FacetValue>,
+    ): Promise<PaginatedList<FacetValue>> {
+        return this.facetValueService.findByFacetIdList(ctx, facet.id, args.options, relations);
+    }
 }

+ 0 - 7
packages/core/src/api/schema/admin-api/facet.api.graphql

@@ -35,8 +35,6 @@ type Mutation {
 
 # generated by generateListOptions function
 input FacetListOptions
-# generated by generateListOptions function
-input FacetValueListOptions
 
 input FacetTranslationInput {
     id: ID
@@ -91,11 +89,6 @@ input RemoveFacetsFromChannelInput {
     force: Boolean
 }
 
-type FacetValueList implements PaginatedList {
-    items: [FacetValue!]!
-    totalItems: Int!
-}
-
 type FacetInUseError implements ErrorResult {
     errorCode: ErrorCode!
     message: String!

+ 1 - 0
packages/core/src/api/schema/common/facet-value.type.graphql

@@ -4,6 +4,7 @@ type FacetValue implements Node {
     updatedAt: DateTime!
     languageCode: LanguageCode!
     facet: Facet!
+    facetId: ID!
     name: String!
     code: String!
     translations: [FacetValueTranslation!]!

+ 12 - 0
packages/core/src/api/schema/common/facet.type.graphql

@@ -6,6 +6,10 @@ type Facet implements Node {
     name: String!
     code: String!
     values: [FacetValue!]!
+    """
+    Returns a paginated, sortable, filterable list of the Facet's values. Added in v2.1.0.
+    """
+    valueList(options: FacetValueListOptions): FacetValueList!
     translations: [FacetTranslation!]!
 }
 
@@ -21,3 +25,11 @@ type FacetList implements PaginatedList {
     items: [Facet!]!
     totalItems: Int!
 }
+
+# generated by generateListOptions function
+input FacetValueListOptions
+
+type FacetValueList implements PaginatedList {
+    items: [FacetValue!]!
+    totalItems: Int!
+}

+ 5 - 1
packages/core/src/entity/facet-value/facet-value.entity.ts

@@ -1,4 +1,4 @@
-import { DeepPartial } from '@vendure/common/lib/shared-types';
+import { DeepPartial, ID } from '@vendure/common/lib/shared-types';
 import { Column, Entity, Index, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm';
 
 import { ChannelAware } from '../../common/types/common-types';
@@ -7,6 +7,7 @@ import { HasCustomFields } from '../../config/custom-field/custom-field-types';
 import { VendureEntity } from '../base/base.entity';
 import { Channel } from '../channel/channel.entity';
 import { CustomFacetValueFields } from '../custom-entity-fields';
+import { EntityId } from '../entity-id.decorator';
 import { Facet } from '../facet/facet.entity';
 
 import { FacetValueTranslation } from './facet-value-translation.entity';
@@ -33,6 +34,9 @@ export class FacetValue extends VendureEntity implements Translatable, HasCustom
     @ManyToOne(type => Facet, group => group.values, { onDelete: 'CASCADE' })
     facet: Facet;
 
+    @EntityId()
+    facetId: ID;
+
     @Column(type => CustomFacetValueFields)
     customFields: CustomFacetValueFields;
 

+ 26 - 0
packages/core/src/service/services/facet-value.service.ts

@@ -137,6 +137,32 @@ export class FacetValueService {
             .then(values => values.map(facetValue => this.translator.translate(facetValue, ctx)));
     }
 
+    /**
+     * @description
+     * Returns all FacetValues belonging to the Facet with the given id.
+     */
+    findByFacetIdList(
+        ctx: RequestContext,
+        id: ID,
+        options?: ListQueryOptions<FacetValue>,
+        relations?: RelationPaths<FacetValue>,
+    ): Promise<PaginatedList<Translated<FacetValue>>> {
+        return this.listQueryBuilder
+            .build(FacetValue, options, {
+                ctx,
+                relations: relations ?? ['facet'],
+                channelId: ctx.channelId,
+            })
+            .andWhere('facetId = :id', { id })
+            .getManyAndCount()
+            .then(([items, totalItems]) => {
+                return {
+                    items: items.map(item => this.translator.translate(item, ctx, ['facet'])),
+                    totalItems,
+                };
+            });
+    }
+
     async create(
         ctx: RequestContext,
         facet: Facet,

+ 45 - 0
packages/dev-server/scripts/generate-many-facet-values.ts

@@ -0,0 +1,45 @@
+/* eslint-disable no-console */
+import {
+    bootstrapWorker,
+    ChannelService,
+    FacetService,
+    FacetValueService,
+    LanguageCode,
+    RequestContextService,
+} from '@vendure/core';
+
+import { devConfig } from '../dev-config';
+
+const FACET_VALUE_COUNT = 1500;
+
+generateManyFacetValues()
+    .then(() => process.exit(0))
+    .catch(() => process.exit(1));
+
+// Used for testing scenarios where there are many channels
+// such as https://github.com/vendure-ecommerce/vendure/issues/2233
+async function generateManyFacetValues() {
+    const { app } = await bootstrapWorker(devConfig);
+    const requestContextService = app.get(RequestContextService);
+    const channelService = app.get(ChannelService);
+    const facetService = app.get(FacetService);
+    const facetValueService = app.get(FacetValueService);
+
+    const ctxAdmin = await requestContextService.create({
+        apiType: 'admin',
+    });
+    const facet = await facetService.create(ctxAdmin, {
+        code: 'color',
+        translations: [{ languageCode: LanguageCode.en, name: 'Color' }],
+        isPrivate: false,
+        values: [],
+    });
+    for (let i = FACET_VALUE_COUNT; i > 0; i--) {
+        const facetValue = await facetValueService.create(ctxAdmin, facet, {
+            code: `color-${i}`,
+            translations: [{ languageCode: LanguageCode.en, name: `Color ${i}` }],
+            facetId: facet.id,
+        });
+        console.log(`Created channel ${facetValue.code}`);
+    }
+}

+ 10 - 0
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -1551,9 +1551,16 @@ export type Facet = Node & {
   name: Scalars['String'];
   translations: Array<FacetTranslation>;
   updatedAt: Scalars['DateTime'];
+  /** Returns a paginated, sortable, filterable list of the Facet's values. Added in v2.1.0. */
+  valueList: FacetValueList;
   values: Array<FacetValue>;
 };
 
+
+export type FacetValueListArgs = {
+  options?: InputMaybe<FacetValueListOptions>;
+};
+
 export type FacetFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
@@ -1618,6 +1625,7 @@ export type FacetValue = Node & {
   createdAt: Scalars['DateTime'];
   customFields?: Maybe<Scalars['JSON']>;
   facet: Facet;
+  facetId: Scalars['ID'];
   id: Scalars['ID'];
   languageCode: LanguageCode;
   name: Scalars['String'];
@@ -1641,6 +1649,7 @@ export type FacetValueFilterInput = {
 export type FacetValueFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
+  facetId?: InputMaybe<IdOperators>;
   id?: InputMaybe<IdOperators>;
   languageCode?: InputMaybe<StringOperators>;
   name?: InputMaybe<StringOperators>;
@@ -1677,6 +1686,7 @@ export type FacetValueResult = {
 export type FacetValueSortParameter = {
   code?: InputMaybe<SortOrder>;
   createdAt?: InputMaybe<SortOrder>;
+  facetId?: InputMaybe<SortOrder>;
   id?: InputMaybe<SortOrder>;
   name?: InputMaybe<SortOrder>;
   updatedAt?: InputMaybe<SortOrder>;

+ 10 - 0
packages/payments-plugin/e2e/graphql/generated-admin-types.ts

@@ -1551,9 +1551,16 @@ export type Facet = Node & {
   name: Scalars['String'];
   translations: Array<FacetTranslation>;
   updatedAt: Scalars['DateTime'];
+  /** Returns a paginated, sortable, filterable list of the Facet's values. Added in v2.1.0. */
+  valueList: FacetValueList;
   values: Array<FacetValue>;
 };
 
+
+export type FacetValueListArgs = {
+  options?: InputMaybe<FacetValueListOptions>;
+};
+
 export type FacetFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
@@ -1618,6 +1625,7 @@ export type FacetValue = Node & {
   createdAt: Scalars['DateTime'];
   customFields?: Maybe<Scalars['JSON']>;
   facet: Facet;
+  facetId: Scalars['ID'];
   id: Scalars['ID'];
   languageCode: LanguageCode;
   name: Scalars['String'];
@@ -1641,6 +1649,7 @@ export type FacetValueFilterInput = {
 export type FacetValueFilterParameter = {
   code?: InputMaybe<StringOperators>;
   createdAt?: InputMaybe<DateOperators>;
+  facetId?: InputMaybe<IdOperators>;
   id?: InputMaybe<IdOperators>;
   languageCode?: InputMaybe<StringOperators>;
   name?: InputMaybe<StringOperators>;
@@ -1677,6 +1686,7 @@ export type FacetValueResult = {
 export type FacetValueSortParameter = {
   code?: InputMaybe<SortOrder>;
   createdAt?: InputMaybe<SortOrder>;
+  facetId?: InputMaybe<SortOrder>;
   id?: InputMaybe<SortOrder>;
   name?: InputMaybe<SortOrder>;
   updatedAt?: InputMaybe<SortOrder>;

File diff ditekan karena terlalu besar
+ 613 - 631
packages/payments-plugin/e2e/graphql/generated-shop-types.ts


File diff ditekan karena terlalu besar
+ 645 - 663
packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts


File diff ditekan karena terlalu besar
+ 0 - 0
schema-admin.json


File diff ditekan karena terlalu besar
+ 0 - 0
schema-shop.json


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini