Przeglądaj źródła

docs: Add guide on how to make an entity channel aware (#3209)

Drayke 1 rok temu
rodzic
commit
7e90ddc303

+ 1 - 1
docs/docs/guides/core-concepts/channels/index.md

@@ -31,7 +31,7 @@ Many entities are channel-aware, meaning that they can be associated with a mult
 
 - [`Asset`](/reference/typescript-api/entities/asset/)
 - [`Collection`](/reference/typescript-api/entities/collection/)
-- [`Customer`](/reference/typescript-api/entities/customer-group/)
+- [`Customer`](/reference/typescript-api/entities/customer/)
 - [`Facet`](/reference/typescript-api/entities/facet/)
 - [`FacetValue`](/reference/typescript-api/entities/facet-value/)
 - [`Order`](/reference/typescript-api/entities/order/)

+ 116 - 0
docs/docs/guides/developer-guide/channel-aware/index.md

@@ -0,0 +1,116 @@
+---
+title: "Implementing ChannelAware"
+showtoc: true
+---
+
+## Defining channel-aware entities
+
+Making an entity channel-aware means that it can be associated with a specific [Channel](/reference/typescript-api/channel/).
+This is useful when you want to have different data or features for different channels. First you will have to create
+an entity ([Define a database entity](/guides/developer-guide/database-entity/)) that implements the `ChannelAware` interface.
+This interface requires the entity to provide a `channels` property
+
+```ts title="src/plugins/requests/entities/product-request.entity.ts"
+import { DeepPartial } from '@vendure/common/lib/shared-types';
+import { VendureEntity, Product, EntityId, ID, ChannelAware } from '@vendure/core';
+import { Column, Entity, ManyToOne } from 'typeorm';
+
+@Entity()
+class ProductRequest extends VendureEntity implements ChannelAware {
+    constructor(input?: DeepPartial<ProductRequest>) {
+        super(input);
+    }
+
+    @ManyToOne(type => Product)
+    product: Product;
+
+    @EntityId()
+    productId: ID;
+
+    @Column()
+    text: string;
+// highlight-start
+    @ManyToMany(() => Channel)
+    @JoinTable()
+    channels: Channel[];
+// highlight-end
+}
+```
+
+## Creating channel-aware entities
+
+Creating a channel-aware entity is similar to creating a regular entity. The only difference is that you need to assign the entity to the current channel.
+This can be done by using the `ChannelService` which provides the `assignToCurrentChannel` helper function. 
+
+:::info
+The `assignToCurrentChannel` function will only assign the `channels` property of the entity. You will still need to save the entity to the database.
+:::
+
+```ts title="src/plugins/requests/service/product-request.service.ts"
+import { ChannelService } from '@vendure/core';
+
+export class RequestService {
+
+    constructor(private channelService: ChannelService) {}
+
+    async create(ctx: RequestContext, input: CreateRequestInput): Promise<ProductRequest> {
+        const request = new ProductRequest(input);
+        // Now we need to assign the request to the current channel (+ default channel)
+// highlight-next-line
+        await this.channelService.assignToCurrentChannel(input, ctx);
+        
+        return await this.connection.getRepository(ProductRequest).save(request);
+    }
+}
+```
+For [Translatable entities](/guides/developer-guide/translations/), the best place to assign the channels is inside the `beforeSave` input of the [TranslateableSave](/reference/typescript-api/service-helpers/translatable-saver/) helper class.
+
+
+## Querying channel-aware entities
+
+When querying channel-aware entities, you can use the [ListQueryBuilder](/reference/typescript-api/data-access/list-query-builder/#extendedlistqueryoptions) or
+the [TransactionalConnection](/reference/typescript-api/data-access/transactional-connection/#findoneinchannel) to automatically filter entities based on the provided channel id.
+
+
+```ts title="src/plugins/requests/service/product-request.service.ts"
+import { ChannelService, ListQueryBuilder, TransactionalConnection } from '@vendure/core';
+
+export class RequestService {
+
+    constructor(
+        private connection: TransactionalConnection,
+        private listQueryBuilder: ListQueryBuilder,
+        private channelService: ChannelService) {}
+
+    findOne(ctx: RequestContext,
+            requestId: ID,
+            relations?: RelationPaths<ProductRequest>) {
+// highlight-start
+        return this.connection.findOneInChannel(ctx, ProductRequest, requestId, ctx.channelId, {
+            relations: unique(effectiveRelations)
+        });
+// highlight-end
+    }
+
+    findAll(
+        ctx: RequestContext,
+        options?: ProductRequestListOptions,
+        relations?: RelationPaths<ProductRequest>,
+    ): Promise<PaginatedList<ProductRequest>> {
+        return this.listQueryBuilder
+            .build(ProductRequest, options, {
+                ctx,
+                relations,
+// highlight-next-line
+                channelId: ctx.channelId,
+            })
+            .getManyAndCount()
+            .then(([items, totalItems]) => {
+                return {
+                    items,
+                    totalItems,
+                };
+            });
+    }
+}
+```

+ 1 - 0
docs/sidebars.js

@@ -91,6 +91,7 @@ const sidebars = {
                     value: 'Advanced Topics',
                     className: 'sidebar-section-header',
                 },
+                'guides/developer-guide/channel-aware/index',
                 'guides/developer-guide/cache/index',
                 'guides/developer-guide/dataloaders/index',
                 'guides/developer-guide/db-subscribers/index',

+ 3 - 2
packages/core/src/service/services/channel.service.ts

@@ -111,7 +111,8 @@ export class ChannelService {
     /**
      * @description
      * Assigns a ChannelAware entity to the default Channel as well as any channel
-     * specified in the RequestContext.
+     * specified in the RequestContext. This method will not save the entity to the database, but
+     * assigns the `channels` property of the entity.
      */
     async assignToCurrentChannel<T extends ChannelAware & VendureEntity>(
         entity: T,
@@ -171,7 +172,7 @@ export class ChannelService {
 
     /**
      * @description
-     * Assigns the entity to the given Channels and saves.
+     * Assigns the entity to the given Channels and saves all changes to the database.
      */
     async assignToChannels<T extends ChannelAware & VendureEntity>(
         ctx: RequestContext,