Sfoglia il codice sorgente

docs: Added guide on how to make entities channel aware

Kevin Mattutat 1 anno fa
parent
commit
2bdb21cf66

+ 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/)

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

@@ -0,0 +1,111 @@
+---
+title: "Channel-aware Entities"
+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
+a base entity ([Define a database entity](/guides/developer-guide/database-entity/)) that implements the `ChannelAware` interface.
+This interface requires the entity to have 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 {
+    constructor(input?: DeepPartial<ProductRequest>) {
+        super(input);
+    }
+
+    @ManyToOne(type => Product)
+    product: Product;
+
+    @EntityId()
+    productId: ID;
+
+    @Column()
+    text: string;
+
+    @ManyToMany(() => Channel)
+    @JoinTable()
+    channels: Channel[];
+}
+```
+
+# 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)
+        await this.channelService.assignToCurrentChannel(requestInput, 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/).
+
+
+# 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>) {
+        return this.connection.findOneInChannel(ctx, ProductRequest, requestId, ctx.channelId, {
+            relations: unique(effectiveRelations)
+        });
+    }
+
+    findAll(
+        ctx: RequestContext,
+        options?: ProductRequestListOptions,
+        relations?: RelationPaths<ProductRequest>,
+    ): Promise<PaginatedList<ProductRequest>> {
+        return this.listQueryBuilder
+            .build(ProductRequest, options, {
+                ctx,
+                relations,
+                channelId: ctx.channelId,
+            })
+            .getManyAndCount()
+            .then(([items, totalItems]) => {
+                return {
+                    items,
+                    totalItems,
+                };
+            });
+    }
+}
+```

+ 1 - 0
packages/admin-ui/src/lib/catalog/src/catalog.routes.ts

@@ -1,3 +1,4 @@
+
 import { inject } from '@angular/core';
 import { ActivatedRouteSnapshot, Route } from '@angular/router';
 import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';

+ 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 off 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,