Przeglądaj źródła

feat(core): Create APIs & resolver for Tag operations

Relates to #316.
Michael Bromley 5 lat temu
rodzic
commit
6630063f12

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

@@ -71,6 +71,8 @@ export type Query = {
   shippingEligibilityCheckers: Array<ConfigurableOperationDefinition>;
   shippingMethod?: Maybe<ShippingMethod>;
   shippingMethods: ShippingMethodList;
+  tag: Tag;
+  tags: TagList;
   taxCategories: Array<TaxCategory>;
   taxCategory?: Maybe<TaxCategory>;
   taxRate?: Maybe<TaxRate>;
@@ -256,6 +258,16 @@ export type QueryShippingMethodsArgs = {
 };
 
 
+export type QueryTagArgs = {
+  id: Scalars['ID'];
+};
+
+
+export type QueryTagsArgs = {
+  options?: Maybe<TagListOptions>;
+};
+
+
 export type QueryTaxCategoryArgs = {
   id: Scalars['ID'];
 };
@@ -346,6 +358,8 @@ export type Mutation = {
   createRole: Role;
   /** Create a new ShippingMethod */
   createShippingMethod: ShippingMethod;
+  /** Create a new Tag */
+  createTag: Tag;
   /** Create a new TaxCategory */
   createTaxCategory: TaxCategory;
   /** Create a new TaxRate */
@@ -385,6 +399,8 @@ export type Mutation = {
   deleteRole: DeletionResponse;
   /** Delete a ShippingMethod */
   deleteShippingMethod: DeletionResponse;
+  /** Delete an existing Tag */
+  deleteTag: DeletionResponse;
   /** Deletes a TaxCategory */
   deleteTaxCategory: DeletionResponse;
   /** Delete a TaxRate */
@@ -468,6 +484,8 @@ export type Mutation = {
   updateRole: Role;
   /** Update an existing ShippingMethod */
   updateShippingMethod: ShippingMethod;
+  /** Update an existing Tag */
+  updateTag: Tag;
   /** Update an existing TaxCategory */
   updateTaxCategory: TaxCategory;
   /** Update an existing TaxRate */
@@ -635,6 +653,11 @@ export type MutationCreateShippingMethodArgs = {
 };
 
 
+export type MutationCreateTagArgs = {
+  input: CreateTagInput;
+};
+
+
 export type MutationCreateTaxCategoryArgs = {
   input: CreateTaxCategoryInput;
 };
@@ -744,6 +767,11 @@ export type MutationDeleteShippingMethodArgs = {
 };
 
 
+export type MutationDeleteTagArgs = {
+  id: Scalars['ID'];
+};
+
+
 export type MutationDeleteTaxCategoryArgs = {
   id: Scalars['ID'];
 };
@@ -977,6 +1005,11 @@ export type MutationUpdateShippingMethodArgs = {
 };
 
 
+export type MutationUpdateTagArgs = {
+  input: UpdateTagInput;
+};
+
+
 export type MutationUpdateTaxCategoryArgs = {
   input: UpdateTaxCategoryInput;
 };
@@ -2337,6 +2370,15 @@ export type StockMovementList = {
   totalItems: Scalars['Int'];
 };
 
+export type CreateTagInput = {
+  value: Scalars['String'];
+};
+
+export type UpdateTagInput = {
+  id: Scalars['ID'];
+  value?: Maybe<Scalars['String']>;
+};
+
 export type CreateTaxCategoryInput = {
   name: Scalars['String'];
 };
@@ -4107,6 +4149,12 @@ export type Tag = Node & {
   value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+  __typename?: 'TagList';
+  items: Array<Tag>;
+  totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
   __typename?: 'TaxCategory';
   id: Scalars['ID'];
@@ -4255,6 +4303,13 @@ export type ShippingMethodListOptions = {
   filter?: Maybe<ShippingMethodFilterParameter>;
 };
 
+export type TagListOptions = {
+  skip?: Maybe<Scalars['Int']>;
+  take?: Maybe<Scalars['Int']>;
+  sort?: Maybe<TagSortParameter>;
+  filter?: Maybe<TagFilterParameter>;
+};
+
 export type TaxRateListOptions = {
   skip?: Maybe<Scalars['Int']>;
   take?: Maybe<Scalars['Int']>;
@@ -4551,6 +4606,19 @@ export type ShippingMethodSortParameter = {
   fulfillmentHandlerCode?: Maybe<SortOrder>;
 };
 
+export type TagFilterParameter = {
+  createdAt?: Maybe<DateOperators>;
+  updatedAt?: Maybe<DateOperators>;
+  value?: Maybe<StringOperators>;
+};
+
+export type TagSortParameter = {
+  id?: Maybe<SortOrder>;
+  createdAt?: Maybe<SortOrder>;
+  updatedAt?: Maybe<SortOrder>;
+  value?: Maybe<SortOrder>;
+};
+
 export type TaxRateFilterParameter = {
   createdAt?: Maybe<DateOperators>;
   updatedAt?: Maybe<DateOperators>;

+ 1 - 0
packages/admin-ui/src/lib/core/src/common/introspection-result.ts

@@ -85,6 +85,7 @@ const result: PossibleTypesResultData = {
             'PromotionList',
             'RoleList',
             'ShippingMethodList',
+            'TagList',
             'TaxRateList',
         ],
         Node: [

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

@@ -70,6 +70,8 @@ export type Query = {
     fulfillmentHandlers: Array<ConfigurableOperationDefinition>;
     testShippingMethod: TestShippingMethodResult;
     testEligibleShippingMethods: Array<ShippingMethodQuote>;
+    tag: Tag;
+    tags: TagList;
     taxCategories: Array<TaxCategory>;
     taxCategory?: Maybe<TaxCategory>;
     taxRates: TaxRateList;
@@ -224,6 +226,14 @@ export type QueryTestEligibleShippingMethodsArgs = {
     input: TestEligibleShippingMethodsInput;
 };
 
+export type QueryTagArgs = {
+    id: Scalars['ID'];
+};
+
+export type QueryTagsArgs = {
+    options?: Maybe<TagListOptions>;
+};
+
 export type QueryTaxCategoryArgs = {
     id: Scalars['ID'];
 };
@@ -399,6 +409,12 @@ export type Mutation = {
     updateShippingMethod: ShippingMethod;
     /** Delete a ShippingMethod */
     deleteShippingMethod: DeletionResponse;
+    /** Create a new Tag */
+    createTag: Tag;
+    /** Update an existing Tag */
+    updateTag: Tag;
+    /** Delete an existing Tag */
+    deleteTag: DeletionResponse;
     /** Create a new TaxCategory */
     createTaxCategory: TaxCategory;
     /** Update an existing TaxCategory */
@@ -776,6 +792,18 @@ export type MutationDeleteShippingMethodArgs = {
     id: Scalars['ID'];
 };
 
+export type MutationCreateTagArgs = {
+    input: CreateTagInput;
+};
+
+export type MutationUpdateTagArgs = {
+    input: UpdateTagInput;
+};
+
+export type MutationDeleteTagArgs = {
+    id: Scalars['ID'];
+};
+
 export type MutationCreateTaxCategoryArgs = {
     input: CreateTaxCategoryInput;
 };
@@ -2139,6 +2167,15 @@ export type StockMovementList = {
     totalItems: Scalars['Int'];
 };
 
+export type CreateTagInput = {
+    value: Scalars['String'];
+};
+
+export type UpdateTagInput = {
+    id: Scalars['ID'];
+    value?: Maybe<Scalars['String']>;
+};
+
 export type CreateTaxCategoryInput = {
     name: Scalars['String'];
 };
@@ -3836,6 +3873,11 @@ export type Tag = Node & {
     value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+    items: Array<Tag>;
+    totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
@@ -3978,6 +4020,13 @@ export type ShippingMethodListOptions = {
     filter?: Maybe<ShippingMethodFilterParameter>;
 };
 
+export type TagListOptions = {
+    skip?: Maybe<Scalars['Int']>;
+    take?: Maybe<Scalars['Int']>;
+    sort?: Maybe<TagSortParameter>;
+    filter?: Maybe<TagFilterParameter>;
+};
+
 export type TaxRateListOptions = {
     skip?: Maybe<Scalars['Int']>;
     take?: Maybe<Scalars['Int']>;
@@ -4274,6 +4323,19 @@ export type ShippingMethodSortParameter = {
     fulfillmentHandlerCode?: Maybe<SortOrder>;
 };
 
+export type TagFilterParameter = {
+    createdAt?: Maybe<DateOperators>;
+    updatedAt?: Maybe<DateOperators>;
+    value?: Maybe<StringOperators>;
+};
+
+export type TagSortParameter = {
+    id?: Maybe<SortOrder>;
+    createdAt?: Maybe<SortOrder>;
+    updatedAt?: Maybe<SortOrder>;
+    value?: Maybe<SortOrder>;
+};
+
 export type TaxRateFilterParameter = {
     createdAt?: Maybe<DateOperators>;
     updatedAt?: Maybe<DateOperators>;

+ 6 - 0
packages/common/src/generated-shop-types.ts

@@ -2248,6 +2248,12 @@ export type Tag = Node & {
     value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+    __typename?: 'TagList';
+    items: Array<Tag>;
+    totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
     __typename?: 'TaxCategory';
     id: Scalars['ID'];

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

@@ -71,6 +71,8 @@ export type Query = {
   fulfillmentHandlers: Array<ConfigurableOperationDefinition>;
   testShippingMethod: TestShippingMethodResult;
   testEligibleShippingMethods: Array<ShippingMethodQuote>;
+  tag: Tag;
+  tags: TagList;
   taxCategories: Array<TaxCategory>;
   taxCategory?: Maybe<TaxCategory>;
   taxRates: TaxRateList;
@@ -262,6 +264,16 @@ export type QueryTestEligibleShippingMethodsArgs = {
 };
 
 
+export type QueryTagArgs = {
+  id: Scalars['ID'];
+};
+
+
+export type QueryTagsArgs = {
+  options?: Maybe<TagListOptions>;
+};
+
+
 export type QueryTaxCategoryArgs = {
   id: Scalars['ID'];
 };
@@ -441,6 +453,12 @@ export type Mutation = {
   updateShippingMethod: ShippingMethod;
   /** Delete a ShippingMethod */
   deleteShippingMethod: DeletionResponse;
+  /** Create a new Tag */
+  createTag: Tag;
+  /** Update an existing Tag */
+  updateTag: Tag;
+  /** Delete an existing Tag */
+  deleteTag: DeletionResponse;
   /** Create a new TaxCategory */
   createTaxCategory: TaxCategory;
   /** Update an existing TaxCategory */
@@ -903,6 +921,21 @@ export type MutationDeleteShippingMethodArgs = {
 };
 
 
+export type MutationCreateTagArgs = {
+  input: CreateTagInput;
+};
+
+
+export type MutationUpdateTagArgs = {
+  input: UpdateTagInput;
+};
+
+
+export type MutationDeleteTagArgs = {
+  id: Scalars['ID'];
+};
+
+
 export type MutationCreateTaxCategoryArgs = {
   input: CreateTaxCategoryInput;
 };
@@ -2300,6 +2333,15 @@ export type StockMovementList = {
   totalItems: Scalars['Int'];
 };
 
+export type CreateTagInput = {
+  value: Scalars['String'];
+};
+
+export type UpdateTagInput = {
+  id: Scalars['ID'];
+  value?: Maybe<Scalars['String']>;
+};
+
 export type CreateTaxCategoryInput = {
   name: Scalars['String'];
 };
@@ -4069,6 +4111,12 @@ export type Tag = Node & {
   value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+  __typename?: 'TagList';
+  items: Array<Tag>;
+  totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
   __typename?: 'TaxCategory';
   id: Scalars['ID'];
@@ -4217,6 +4265,13 @@ export type ShippingMethodListOptions = {
   filter?: Maybe<ShippingMethodFilterParameter>;
 };
 
+export type TagListOptions = {
+  skip?: Maybe<Scalars['Int']>;
+  take?: Maybe<Scalars['Int']>;
+  sort?: Maybe<TagSortParameter>;
+  filter?: Maybe<TagFilterParameter>;
+};
+
 export type TaxRateListOptions = {
   skip?: Maybe<Scalars['Int']>;
   take?: Maybe<Scalars['Int']>;
@@ -4513,6 +4568,19 @@ export type ShippingMethodSortParameter = {
   fulfillmentHandlerCode?: Maybe<SortOrder>;
 };
 
+export type TagFilterParameter = {
+  createdAt?: Maybe<DateOperators>;
+  updatedAt?: Maybe<DateOperators>;
+  value?: Maybe<StringOperators>;
+};
+
+export type TagSortParameter = {
+  id?: Maybe<SortOrder>;
+  createdAt?: Maybe<SortOrder>;
+  updatedAt?: Maybe<SortOrder>;
+  value?: Maybe<SortOrder>;
+};
+
 export type TaxRateFilterParameter = {
   createdAt?: Maybe<DateOperators>;
   updatedAt?: Maybe<DateOperators>;

+ 125 - 0
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -70,6 +70,8 @@ export type Query = {
     fulfillmentHandlers: Array<ConfigurableOperationDefinition>;
     testShippingMethod: TestShippingMethodResult;
     testEligibleShippingMethods: Array<ShippingMethodQuote>;
+    tag: Tag;
+    tags: TagList;
     taxCategories: Array<TaxCategory>;
     taxCategory?: Maybe<TaxCategory>;
     taxRates: TaxRateList;
@@ -224,6 +226,14 @@ export type QueryTestEligibleShippingMethodsArgs = {
     input: TestEligibleShippingMethodsInput;
 };
 
+export type QueryTagArgs = {
+    id: Scalars['ID'];
+};
+
+export type QueryTagsArgs = {
+    options?: Maybe<TagListOptions>;
+};
+
 export type QueryTaxCategoryArgs = {
     id: Scalars['ID'];
 };
@@ -399,6 +409,12 @@ export type Mutation = {
     updateShippingMethod: ShippingMethod;
     /** Delete a ShippingMethod */
     deleteShippingMethod: DeletionResponse;
+    /** Create a new Tag */
+    createTag: Tag;
+    /** Update an existing Tag */
+    updateTag: Tag;
+    /** Delete an existing Tag */
+    deleteTag: DeletionResponse;
     /** Create a new TaxCategory */
     createTaxCategory: TaxCategory;
     /** Update an existing TaxCategory */
@@ -776,6 +792,18 @@ export type MutationDeleteShippingMethodArgs = {
     id: Scalars['ID'];
 };
 
+export type MutationCreateTagArgs = {
+    input: CreateTagInput;
+};
+
+export type MutationUpdateTagArgs = {
+    input: UpdateTagInput;
+};
+
+export type MutationDeleteTagArgs = {
+    id: Scalars['ID'];
+};
+
 export type MutationCreateTaxCategoryArgs = {
     input: CreateTaxCategoryInput;
 };
@@ -2139,6 +2167,15 @@ export type StockMovementList = {
     totalItems: Scalars['Int'];
 };
 
+export type CreateTagInput = {
+    value: Scalars['String'];
+};
+
+export type UpdateTagInput = {
+    id: Scalars['ID'];
+    value?: Maybe<Scalars['String']>;
+};
+
 export type CreateTaxCategoryInput = {
     name: Scalars['String'];
 };
@@ -3836,6 +3873,11 @@ export type Tag = Node & {
     value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+    items: Array<Tag>;
+    totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
@@ -3978,6 +4020,13 @@ export type ShippingMethodListOptions = {
     filter?: Maybe<ShippingMethodFilterParameter>;
 };
 
+export type TagListOptions = {
+    skip?: Maybe<Scalars['Int']>;
+    take?: Maybe<Scalars['Int']>;
+    sort?: Maybe<TagSortParameter>;
+    filter?: Maybe<TagFilterParameter>;
+};
+
 export type TaxRateListOptions = {
     skip?: Maybe<Scalars['Int']>;
     take?: Maybe<Scalars['Int']>;
@@ -4274,6 +4323,19 @@ export type ShippingMethodSortParameter = {
     fulfillmentHandlerCode?: Maybe<SortOrder>;
 };
 
+export type TagFilterParameter = {
+    createdAt?: Maybe<DateOperators>;
+    updatedAt?: Maybe<DateOperators>;
+    value?: Maybe<StringOperators>;
+};
+
+export type TagSortParameter = {
+    id?: Maybe<SortOrder>;
+    createdAt?: Maybe<SortOrder>;
+    updatedAt?: Maybe<SortOrder>;
+    value?: Maybe<SortOrder>;
+};
+
 export type TaxRateFilterParameter = {
     createdAt?: Maybe<DateOperators>;
     updatedAt?: Maybe<DateOperators>;
@@ -6143,6 +6205,38 @@ export type UpdateStockMutationVariables = Exact<{
 
 export type UpdateStockMutation = { updateProductVariants: Array<Maybe<VariantWithStockFragment>> };
 
+export type GetTagListQueryVariables = Exact<{
+    options?: Maybe<TagListOptions>;
+}>;
+
+export type GetTagListQuery = {
+    tags: Pick<TagList, 'totalItems'> & { items: Array<Pick<Tag, 'id' | 'value'>> };
+};
+
+export type GetTagQueryVariables = Exact<{
+    id: Scalars['ID'];
+}>;
+
+export type GetTagQuery = { tag: Pick<Tag, 'id' | 'value'> };
+
+export type CreateTagMutationVariables = Exact<{
+    input: CreateTagInput;
+}>;
+
+export type CreateTagMutation = { createTag: Pick<Tag, 'id' | 'value'> };
+
+export type UpdateTagMutationVariables = Exact<{
+    input: UpdateTagInput;
+}>;
+
+export type UpdateTagMutation = { updateTag: Pick<Tag, 'id' | 'value'> };
+
+export type DeleteTagMutationVariables = Exact<{
+    id: Scalars['ID'];
+}>;
+
+export type DeleteTagMutation = { deleteTag: Pick<DeletionResponse, 'message' | 'result'> };
+
 export type GetTaxCategoryListQueryVariables = Exact<{ [key: string]: never }>;
 
 export type GetTaxCategoryListQuery = { taxCategories: Array<Pick<TaxCategory, 'id' | 'name'>> };
@@ -8213,6 +8307,37 @@ export namespace UpdateStock {
     >;
 }
 
+export namespace GetTagList {
+    export type Variables = GetTagListQueryVariables;
+    export type Query = GetTagListQuery;
+    export type Tags = NonNullable<GetTagListQuery['tags']>;
+    export type Items = NonNullable<NonNullable<NonNullable<GetTagListQuery['tags']>['items']>[number]>;
+}
+
+export namespace GetTag {
+    export type Variables = GetTagQueryVariables;
+    export type Query = GetTagQuery;
+    export type Tag = NonNullable<GetTagQuery['tag']>;
+}
+
+export namespace CreateTag {
+    export type Variables = CreateTagMutationVariables;
+    export type Mutation = CreateTagMutation;
+    export type CreateTag = NonNullable<CreateTagMutation['createTag']>;
+}
+
+export namespace UpdateTag {
+    export type Variables = UpdateTagMutationVariables;
+    export type Mutation = UpdateTagMutation;
+    export type UpdateTag = NonNullable<UpdateTagMutation['updateTag']>;
+}
+
+export namespace DeleteTag {
+    export type Variables = DeleteTagMutationVariables;
+    export type Mutation = DeleteTagMutation;
+    export type DeleteTag = NonNullable<DeleteTagMutation['deleteTag']>;
+}
+
 export namespace GetTaxCategoryList {
     export type Variables = GetTaxCategoryListQueryVariables;
     export type Query = GetTaxCategoryListQuery;

+ 5 - 0
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -2162,6 +2162,11 @@ export type Tag = Node & {
     value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+    items: Array<Tag>;
+    totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];

+ 129 - 0
packages/core/e2e/tag.e2e-spec.ts

@@ -0,0 +1,129 @@
+import gql from 'graphql-tag';
+import path from 'path';
+
+import { initialData } from '../../../e2e-common/e2e-initial-data';
+import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
+import { createTestEnvironment } from '../../testing/lib/create-test-environment';
+
+import { CreateTag, GetTag, GetTagList, UpdateTag } from './graphql/generated-e2e-admin-types';
+
+describe('Tag resolver', () => {
+    const { server, adminClient } = createTestEnvironment(testConfig);
+
+    beforeAll(async () => {
+        await server.init({
+            initialData,
+            productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
+            customerCount: 1,
+        });
+        await adminClient.asSuperAdmin();
+    }, TEST_SETUP_TIMEOUT_MS);
+
+    afterAll(async () => {
+        await server.destroy();
+    });
+
+    it('create', async () => {
+        const { createTag } = await adminClient.query<CreateTag.Mutation, CreateTag.Variables>(CREATE_TAG, {
+            input: { value: 'tag1' },
+        });
+
+        expect(createTag).toEqual({
+            id: 'T_1',
+            value: 'tag1',
+        });
+    });
+
+    it('create with existing value returns existing tag', async () => {
+        const { createTag } = await adminClient.query<CreateTag.Mutation, CreateTag.Variables>(CREATE_TAG, {
+            input: { value: 'tag1' },
+        });
+
+        expect(createTag).toEqual({
+            id: 'T_1',
+            value: 'tag1',
+        });
+    });
+
+    it('update', async () => {
+        const { updateTag } = await adminClient.query<UpdateTag.Mutation, UpdateTag.Variables>(UPDATE_TAG, {
+            input: { id: 'T_1', value: 'tag1-updated' },
+        });
+
+        expect(updateTag).toEqual({
+            id: 'T_1',
+            value: 'tag1-updated',
+        });
+    });
+
+    it('tag', async () => {
+        const { tag } = await adminClient.query<GetTag.Query, GetTag.Variables>(GET_TAG, { id: 'T_1' });
+
+        expect(tag).toEqual({
+            id: 'T_1',
+            value: 'tag1-updated',
+        });
+    });
+
+    it('tags', async () => {
+        const { tags } = await adminClient.query<GetTagList.Query, GetTagList.Variables>(GET_TAG_LIST);
+
+        expect(tags).toEqual({
+            items: [
+                {
+                    id: 'T_1',
+                    value: 'tag1-updated',
+                },
+            ],
+            totalItems: 1,
+        });
+    });
+});
+
+const GET_TAG_LIST = gql`
+    query GetTagList($options: TagListOptions) {
+        tags(options: $options) {
+            items {
+                id
+                value
+            }
+            totalItems
+        }
+    }
+`;
+
+const GET_TAG = gql`
+    query GetTag($id: ID!) {
+        tag(id: $id) {
+            id
+            value
+        }
+    }
+`;
+
+const CREATE_TAG = gql`
+    mutation CreateTag($input: CreateTagInput!) {
+        createTag(input: $input) {
+            id
+            value
+        }
+    }
+`;
+
+const UPDATE_TAG = gql`
+    mutation UpdateTag($input: UpdateTagInput!) {
+        updateTag(input: $input) {
+            id
+            value
+        }
+    }
+`;
+
+const DELETE_TAG = gql`
+    mutation DeleteTag($id: ID!) {
+        deleteTag(id: $id) {
+            message
+            result
+        }
+    }
+`;

+ 2 - 0
packages/core/src/api/api-internal-modules.ts

@@ -28,6 +28,7 @@ import { PromotionResolver } from './resolvers/admin/promotion.resolver';
 import { RoleResolver } from './resolvers/admin/role.resolver';
 import { SearchResolver } from './resolvers/admin/search.resolver';
 import { ShippingMethodResolver } from './resolvers/admin/shipping-method.resolver';
+import { TagResolver } from './resolvers/admin/tag.resolver';
 import { TaxCategoryResolver } from './resolvers/admin/tax-category.resolver';
 import { TaxRateResolver } from './resolvers/admin/tax-rate.resolver';
 import { ZoneResolver } from './resolvers/admin/zone.resolver';
@@ -90,6 +91,7 @@ const adminResolvers = [
     RoleResolver,
     SearchResolver,
     ShippingMethodResolver,
+    TagResolver,
     TaxCategoryResolver,
     TaxRateResolver,
     ZoneResolver,

+ 59 - 0
packages/core/src/api/resolvers/admin/tag.resolver.ts

@@ -0,0 +1,59 @@
+import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
+import {
+    DeletionResponse,
+    MutationCreateTagArgs,
+    MutationDeleteTagArgs,
+    MutationUpdateTagArgs,
+    Permission,
+    QueryTagArgs,
+    QueryTagsArgs,
+    TagList,
+} from '@vendure/common/lib/generated-types';
+
+import { Tag } from '../../../entity/tag/tag.entity';
+import { TagService } from '../../../service/services/tag.service';
+import { RequestContext } from '../../common/request-context';
+import { Allow } from '../../decorators/allow.decorator';
+import { Ctx } from '../../decorators/request-context.decorator';
+import { Transaction } from '../../decorators/transaction.decorator';
+
+@Resolver('Tag')
+export class TagResolver {
+    constructor(private tagService: TagService) {}
+
+    @Query()
+    @Allow(Permission.ReadSettings)
+    async tags(@Ctx() ctx: RequestContext, @Args() args: QueryTagsArgs): Promise<TagList> {
+        return this.tagService.findAll(ctx, args.options);
+    }
+
+    @Query()
+    @Allow(Permission.ReadSettings)
+    async tag(@Ctx() ctx: RequestContext, @Args() args: QueryTagArgs): Promise<Tag | undefined> {
+        return this.tagService.findOne(ctx, args.id);
+    }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.CreateSettings)
+    async createTag(@Ctx() ctx: RequestContext, @Args() args: MutationCreateTagArgs): Promise<Tag> {
+        return this.tagService.create(ctx, args.input);
+    }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.UpdateSettings)
+    async updateTag(@Ctx() ctx: RequestContext, @Args() args: MutationUpdateTagArgs): Promise<Tag> {
+        return this.tagService.update(ctx, args.input);
+    }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.DeleteSettings)
+    async deleteTag(
+        @Ctx() ctx: RequestContext,
+        @Args() args: MutationDeleteTagArgs,
+    ): Promise<DeletionResponse> {
+        return this.tagService.delete(ctx, args.id);
+    }
+}

+ 25 - 0
packages/core/src/api/schema/admin-api/tag.api.graphql

@@ -0,0 +1,25 @@
+type Query {
+  tag(id: ID!): Tag!
+  tags(options: TagListOptions): TagList!
+}
+
+type Mutation {
+  "Create a new Tag"
+  createTag(input: CreateTagInput!): Tag!
+  "Update an existing Tag"
+  updateTag(input: UpdateTagInput!): Tag!
+  "Delete an existing Tag"
+  deleteTag(id: ID!): DeletionResponse!
+}
+
+# generated by generateListOptions function
+input TagListOptions
+
+input CreateTagInput {
+    value: String!
+}
+
+input UpdateTagInput {
+    id: ID!
+    value: String
+}

+ 5 - 0
packages/core/src/api/schema/common/tag.type.graphql

@@ -4,3 +4,8 @@ type Tag implements Node {
     updatedAt: DateTime!
     value: String!
 }
+
+type TagList implements PaginatedList {
+    items: [Tag!]!
+    totalItems: Int!
+}

+ 45 - 3
packages/core/src/service/services/tag.service.ts

@@ -1,16 +1,58 @@
 import { Injectable } from '@nestjs/common';
-import { ID, Type } from '@vendure/common/lib/shared-types';
+import {
+    CreateTagInput,
+    DeletionResponse,
+    DeletionResult,
+    UpdateTagInput,
+} from '@vendure/common/lib/generated-types';
+import { ID, PaginatedList, Type } from '@vendure/common/lib/shared-types';
 import { unique } from '@vendure/common/lib/unique';
 
 import { RequestContext } from '../../api/common/request-context';
-import { Taggable } from '../../common/types/common-types';
+import { ListQueryOptions, Taggable } from '../../common/types/common-types';
 import { VendureEntity } from '../../entity/base/base.entity';
 import { Tag } from '../../entity/tag/tag.entity';
+import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { TransactionalConnection } from '../transaction/transactional-connection';
 
 @Injectable()
 export class TagService {
-    constructor(private connection: TransactionalConnection) {}
+    constructor(private connection: TransactionalConnection, private listQueryBuilder: ListQueryBuilder) {}
+
+    findAll(ctx: RequestContext, options?: ListQueryOptions<Tag>): Promise<PaginatedList<Tag>> {
+        return this.listQueryBuilder
+            .build(Tag, options, { ctx })
+            .getManyAndCount()
+            .then(([items, totalItems]) => ({
+                items,
+                totalItems,
+            }));
+    }
+
+    findOne(ctx: RequestContext, tagId: ID): Promise<Tag | undefined> {
+        return this.connection.getRepository(ctx, Tag).findOne(tagId);
+    }
+
+    create(ctx: RequestContext, input: CreateTagInput) {
+        return this.tagValueToTag(ctx, input.value);
+    }
+
+    async update(ctx: RequestContext, input: UpdateTagInput) {
+        const tag = await this.connection.getEntityOrThrow(ctx, Tag, input.id);
+        if (input.value) {
+            tag.value = input.value;
+            await this.connection.getRepository(ctx, Tag).save(tag);
+        }
+        return tag;
+    }
+
+    async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
+        const tag = await this.connection.getEntityOrThrow(ctx, Tag, id);
+        await this.connection.getRepository(ctx, Tag).remove(tag);
+        return {
+            result: DeletionResult.DELETED,
+        };
+    }
 
     async valuesToTags(ctx: RequestContext, values: string[]): Promise<Tag[]> {
         const tags: Tag[] = [];

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

@@ -70,6 +70,8 @@ export type Query = {
     fulfillmentHandlers: Array<ConfigurableOperationDefinition>;
     testShippingMethod: TestShippingMethodResult;
     testEligibleShippingMethods: Array<ShippingMethodQuote>;
+    tag: Tag;
+    tags: TagList;
     taxCategories: Array<TaxCategory>;
     taxCategory?: Maybe<TaxCategory>;
     taxRates: TaxRateList;
@@ -224,6 +226,14 @@ export type QueryTestEligibleShippingMethodsArgs = {
     input: TestEligibleShippingMethodsInput;
 };
 
+export type QueryTagArgs = {
+    id: Scalars['ID'];
+};
+
+export type QueryTagsArgs = {
+    options?: Maybe<TagListOptions>;
+};
+
 export type QueryTaxCategoryArgs = {
     id: Scalars['ID'];
 };
@@ -399,6 +409,12 @@ export type Mutation = {
     updateShippingMethod: ShippingMethod;
     /** Delete a ShippingMethod */
     deleteShippingMethod: DeletionResponse;
+    /** Create a new Tag */
+    createTag: Tag;
+    /** Update an existing Tag */
+    updateTag: Tag;
+    /** Delete an existing Tag */
+    deleteTag: DeletionResponse;
     /** Create a new TaxCategory */
     createTaxCategory: TaxCategory;
     /** Update an existing TaxCategory */
@@ -776,6 +792,18 @@ export type MutationDeleteShippingMethodArgs = {
     id: Scalars['ID'];
 };
 
+export type MutationCreateTagArgs = {
+    input: CreateTagInput;
+};
+
+export type MutationUpdateTagArgs = {
+    input: UpdateTagInput;
+};
+
+export type MutationDeleteTagArgs = {
+    id: Scalars['ID'];
+};
+
 export type MutationCreateTaxCategoryArgs = {
     input: CreateTaxCategoryInput;
 };
@@ -2139,6 +2167,15 @@ export type StockMovementList = {
     totalItems: Scalars['Int'];
 };
 
+export type CreateTagInput = {
+    value: Scalars['String'];
+};
+
+export type UpdateTagInput = {
+    id: Scalars['ID'];
+    value?: Maybe<Scalars['String']>;
+};
+
 export type CreateTaxCategoryInput = {
     name: Scalars['String'];
 };
@@ -3836,6 +3873,11 @@ export type Tag = Node & {
     value: Scalars['String'];
 };
 
+export type TagList = PaginatedList & {
+    items: Array<Tag>;
+    totalItems: Scalars['Int'];
+};
+
 export type TaxCategory = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
@@ -3978,6 +4020,13 @@ export type ShippingMethodListOptions = {
     filter?: Maybe<ShippingMethodFilterParameter>;
 };
 
+export type TagListOptions = {
+    skip?: Maybe<Scalars['Int']>;
+    take?: Maybe<Scalars['Int']>;
+    sort?: Maybe<TagSortParameter>;
+    filter?: Maybe<TagFilterParameter>;
+};
+
 export type TaxRateListOptions = {
     skip?: Maybe<Scalars['Int']>;
     take?: Maybe<Scalars['Int']>;
@@ -4274,6 +4323,19 @@ export type ShippingMethodSortParameter = {
     fulfillmentHandlerCode?: Maybe<SortOrder>;
 };
 
+export type TagFilterParameter = {
+    createdAt?: Maybe<DateOperators>;
+    updatedAt?: Maybe<DateOperators>;
+    value?: Maybe<StringOperators>;
+};
+
+export type TagSortParameter = {
+    id?: Maybe<SortOrder>;
+    createdAt?: Maybe<SortOrder>;
+    updatedAt?: Maybe<SortOrder>;
+    value?: Maybe<SortOrder>;
+};
+
 export type TaxRateFilterParameter = {
     createdAt?: Maybe<DateOperators>;
     updatedAt?: Maybe<DateOperators>;

Plik diff jest za duży
+ 0 - 0
schema-admin.json


Plik diff jest za duży
+ 0 - 0
schema-shop.json


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików