Skip to content

Commit

Permalink
feat(core): Implement facet duplicator
Browse files Browse the repository at this point in the history
Relates to #627
  • Loading branch information
michaelbromley committed Feb 20, 2024
1 parent d457851 commit 8d20847
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 14 deletions.
67 changes: 67 additions & 0 deletions packages/core/e2e/duplicate-entity.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
CREATE_ROLE,
GET_COLLECTION,
GET_COLLECTIONS,
GET_FACET_WITH_VALUES,
GET_PRODUCT_WITH_VARIANTS,
UPDATE_PRODUCT_VARIANTS,
} from './graphql/shared-definitions';
Expand Down Expand Up @@ -645,6 +646,72 @@ describe('Duplicating entities', () => {
expect(collection?.filters).toEqual(testCollection.filters);
});
});

describe('Facet duplicator', () => {
let newFacetId: string;

it('duplicate facet', async () => {
const { duplicateEntity } = await adminClient.query<
Codegen.DuplicateEntityMutation,
Codegen.DuplicateEntityMutationVariables
>(DUPLICATE_ENTITY, {
input: {
entityName: 'Facet',
entityId: 'T_1',
duplicatorInput: {
code: 'facet-duplicator',
arguments: [
{
name: 'includeFacetValues',
value: 'true',
},
],
},
},
});

duplicateEntityGuard.assertSuccess(duplicateEntity);

expect(duplicateEntity.newEntityId).toBe('T_2');
newFacetId = duplicateEntity.newEntityId;
});

it('facet name is suffixed', async () => {
const { facet } = await adminClient.query<
Codegen.GetFacetWithValuesQuery,
Codegen.GetFacetWithValuesQueryVariables
>(GET_FACET_WITH_VALUES, {
id: newFacetId,
});

expect(facet?.name).toBe('category (copy)');
});

it('is initially private', async () => {
const { facet } = await adminClient.query<
Codegen.GetFacetWithValuesQuery,
Codegen.GetFacetWithValuesQueryVariables
>(GET_FACET_WITH_VALUES, {
id: newFacetId,
});

expect(facet?.isPrivate).toBe(true);
});

it('facet values are duplicated', async () => {
const { facet } = await adminClient.query<
Codegen.GetFacetWithValuesQuery,
Codegen.GetFacetWithValuesQueryVariables
>(GET_FACET_WITH_VALUES, {
id: newFacetId,
});

expect(facet?.values.map(v => v.name).sort()).toEqual([
'computers (copy)',
'electronics (copy)',
]);
});
});
});
});

Expand Down
15 changes: 3 additions & 12 deletions packages/core/e2e/facet.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ import path from 'path';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';

import { initialData } from '../../../e2e-common/e2e-initial-data';
import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';

import { FACET_VALUE_FRAGMENT, FACET_WITH_VALUES_FRAGMENT } from './graphql/fragments';
import { FACET_VALUE_FRAGMENT } from './graphql/fragments';
import * as Codegen from './graphql/generated-e2e-admin-types';
import {
ChannelFragment,
CurrencyCode,
DeletionResult,
FacetWithValuesFragment,
GetFacetWithValueListDocument,
GetFacetWithValuesDocument,
LanguageCode,
} from './graphql/generated-e2e-admin-types';
import {
Expand All @@ -24,6 +23,7 @@ import {
CREATE_FACET,
GET_FACET_LIST,
GET_FACET_LIST_SIMPLE,
GET_FACET_WITH_VALUES,
GET_PRODUCT_WITH_VARIANTS,
UPDATE_FACET,
UPDATE_PRODUCT,
Expand Down Expand Up @@ -810,15 +810,6 @@ describe('Facet resolver', () => {
});
});

export const GET_FACET_WITH_VALUES = gql`
query GetFacetWithValues($id: ID!) {
facet(id: $id) {
...FacetWithValues
}
}
${FACET_WITH_VALUES_FRAGMENT}
`;

export const GET_FACET_WITH_VALUE_LIST = gql`
query GetFacetWithValueList($id: ID!) {
facet(id: $id) {
Expand Down
9 changes: 9 additions & 0 deletions packages/core/e2e/graphql/shared-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1054,3 +1054,12 @@ export const GET_COLLECTION = gql`
}
${COLLECTION_FRAGMENT}
`;

export const GET_FACET_WITH_VALUES = gql`
query GetFacetWithValues($id: ID!) {
facet(id: $id) {
...FacetWithValues
}
}
${FACET_WITH_VALUES_FRAGMENT}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const collectionDuplicator = new EntityDuplicator({
connection = injector.get(TransactionalConnection);
collectionService = injector.get(CollectionService);
},
async duplicate({ ctx, id, args }) {
async duplicate({ ctx, id }) {
const collection = await connection.getEntityOrThrow(ctx, Collection, id, {
relations: {
featuredAsset: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
CreateFacetInput,
FacetTranslationInput,
LanguageCode,
Permission,
} from '@vendure/common/lib/generated-types';

import { Injector } from '../../../common/index';
import { TransactionalConnection } from '../../../connection/index';
import { Facet } from '../../../entity/index';
import { FacetService, FacetValueService } from '../../../service/index';
import { EntityDuplicator } from '../entity-duplicator';

let connection: TransactionalConnection;
let facetService: FacetService;
let facetValueService: FacetValueService;

/**
* @description
* Duplicates a Facet
*/
export const facetDuplicator = new EntityDuplicator({
code: 'facet-duplicator',
description: [
{
languageCode: LanguageCode.en,
value: 'Default duplicator for Facets',
},
],
requiresPermission: [Permission.CreateFacet, Permission.CreateCatalog],
forEntities: ['Facet'],
args: {
includeFacetValues: {
type: 'boolean',
defaultValue: true,
label: [{ languageCode: LanguageCode.en, value: 'Include facet values' }],
},
},
init(injector: Injector) {
connection = injector.get(TransactionalConnection);
facetService = injector.get(FacetService);
facetValueService = injector.get(FacetValueService);
},
async duplicate({ ctx, id, args }) {
const facet = await connection.getEntityOrThrow(ctx, Facet, id, {
relations: {
values: true,
},
});
const translations: FacetTranslationInput[] = facet.translations.map(translation => {
return {
name: translation.name + ' (copy)',
languageCode: translation.languageCode,
customFields: translation.customFields,
};
});
const facetInput: CreateFacetInput = {
isPrivate: true,
translations,
customFields: facet.customFields,
code: facet.code + '-copy',
};

const duplicatedFacet = await facetService.create(ctx, facetInput);
if (args.includeFacetValues) {
if (facet.values.length) {
for (const value of facet.values) {
const newValue = await facetValueService.create(ctx, duplicatedFacet, {
code: value.code + '-copy',
translations: value.translations.map(translation => ({
name: translation.name + ' (copy)',
languageCode: translation.languageCode,
customFields: translation.customFields,
})),
facetId: duplicatedFacet.id,
customFields: value.customFields,
});
duplicatedFacet.values.push(newValue);
}
}
}
return duplicatedFacet;
},
});
3 changes: 2 additions & 1 deletion packages/core/src/config/entity/entity-duplicators/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { collectionDuplicator } from './collection-duplicator';
import { facetDuplicator } from './facet-duplicator';
import { productDuplicator } from './product-duplicator';

export const defaultEntityDuplicators = [productDuplicator, collectionDuplicator];
export const defaultEntityDuplicators = [productDuplicator, collectionDuplicator, facetDuplicator];

0 comments on commit 8d20847

Please sign in to comment.