9101: Added new filters for motifs (#193)
This commit is contained in:
@@ -3,7 +3,18 @@ import { ScopeAccess, Scopes } from '../cognito/access-control';
|
|||||||
import { Category, CategoryLocaleData } from '../types/category-types';
|
import { Category, CategoryLocaleData } from '../types/category-types';
|
||||||
import { DataSourceOptions } from '../types/types';
|
import { DataSourceOptions } from '../types/types';
|
||||||
import { BaseSQLDataSource } from './BaseSQLDataSource';
|
import { BaseSQLDataSource } from './BaseSQLDataSource';
|
||||||
import { createQuestionMarksFromList, MINUTE } from './utils';
|
import { createQuestionMarksFromList, HOUR, MINUTE } from './utils';
|
||||||
|
|
||||||
|
const ROOMS_PARENT_ID = 270;
|
||||||
|
const COLORS_PARENT_ID = 1665;
|
||||||
|
const STYLES_PARENT_ID = 1814;
|
||||||
|
const PATTERNS_PARENT_ID = 1414;
|
||||||
|
const KNOWN_FACET_PARENT_IDS = [
|
||||||
|
ROOMS_PARENT_ID,
|
||||||
|
COLORS_PARENT_ID,
|
||||||
|
STYLES_PARENT_ID,
|
||||||
|
PATTERNS_PARENT_ID,
|
||||||
|
];
|
||||||
|
|
||||||
export class CategoryAPI extends BaseSQLDataSource {
|
export class CategoryAPI extends BaseSQLDataSource {
|
||||||
private categoryLoader: DataLoader<number, Category>;
|
private categoryLoader: DataLoader<number, Category>;
|
||||||
@@ -86,108 +97,93 @@ WHERE product_category.product_id = ?
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getMotifRootIds(): Promise<number[]> {
|
||||||
|
const { rows } = await this.cachedRaw(
|
||||||
|
/* sql */ `
|
||||||
|
SELECT id
|
||||||
|
FROM v_categorytree_v2
|
||||||
|
WHERE depth = 1
|
||||||
|
AND id NOT IN (${createQuestionMarksFromList(KNOWN_FACET_PARENT_IDS)})
|
||||||
|
`,
|
||||||
|
KNOWN_FACET_PARENT_IDS,
|
||||||
|
)
|
||||||
|
// @ts-ignore
|
||||||
|
.cache(HOUR);
|
||||||
|
|
||||||
|
return rows.map((row) => row.id);
|
||||||
|
}
|
||||||
|
|
||||||
async getCategoryBasedFacets(productId: number): Promise<{
|
async getCategoryBasedFacets(productId: number): Promise<{
|
||||||
room: string[];
|
room: string[];
|
||||||
color: string[];
|
color: string[];
|
||||||
style: string[];
|
style: string[];
|
||||||
pattern: string[];
|
pattern: string[];
|
||||||
|
motif: string[];
|
||||||
}> {
|
}> {
|
||||||
ScopeAccess.validate(this.user).some([
|
ScopeAccess.validate(this.user).some([
|
||||||
Scopes.CATEGORIES_READ,
|
Scopes.CATEGORIES_READ,
|
||||||
Scopes.CATEGORIES_PUBLIC_READ,
|
Scopes.CATEGORIES_PUBLIC_READ,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const ROOMS_PARENT_ID = 270;
|
const motifRootIds = await this.getMotifRootIds();
|
||||||
const COLORS_PARENT_ID = 1665;
|
const allFacetParentIds = [...KNOWN_FACET_PARENT_IDS, ...motifRootIds];
|
||||||
const STYLES_PARENT_ID = 1814;
|
|
||||||
const PATTERNS_PARENT_ID = 1414;
|
|
||||||
|
|
||||||
const { rows } = await this.cachedRaw(
|
const { rows } = await this.cachedRaw(
|
||||||
`
|
/* sql */ `
|
||||||
WITH rooms AS (
|
WITH facet_parents AS (
|
||||||
SELECT lft, rgt FROM categories_v2_lft_rgt WHERE id = ?
|
SELECT id, lft, rgt, name,
|
||||||
),
|
CASE
|
||||||
colors AS (
|
WHEN id = ? THEN 'room'
|
||||||
SELECT lft, rgt FROM categories_v2_lft_rgt WHERE id = ?
|
WHEN id = ? THEN 'color'
|
||||||
),
|
WHEN id = ? THEN 'style'
|
||||||
styles AS (
|
WHEN id = ? THEN 'pattern'
|
||||||
SELECT lft, rgt FROM categories_v2_lft_rgt WHERE id = ?
|
ELSE 'motif'
|
||||||
),
|
END AS facet
|
||||||
patterns AS (
|
FROM categories_v2_lft_rgt
|
||||||
SELECT lft, rgt FROM categories_v2_lft_rgt WHERE id = ?
|
WHERE id IN (${createQuestionMarksFromList(allFacetParentIds)})
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
array_remove(
|
array_agg(DISTINCT c.name) FILTER (WHERE fp.facet = 'room') AS room,
|
||||||
array_agg(
|
array_agg(DISTINCT c.name) FILTER (WHERE fp.facet = 'color') AS color,
|
||||||
DISTINCT CASE
|
array_agg(DISTINCT c.name) FILTER (WHERE fp.facet = 'style') AS style,
|
||||||
WHEN c.lft > rooms.lft AND c.rgt < rooms.rgt THEN c.name
|
array_agg(DISTINCT c.name) FILTER (WHERE fp.facet = 'pattern') AS pattern,
|
||||||
END
|
array_agg(DISTINCT fp.name) FILTER (WHERE fp.facet = 'motif') AS motif
|
||||||
),
|
|
||||||
NULL
|
|
||||||
) AS room,
|
|
||||||
array_remove(
|
|
||||||
array_agg(
|
|
||||||
DISTINCT CASE
|
|
||||||
WHEN c.lft > colors.lft AND c.rgt < colors.rgt THEN c.name
|
|
||||||
END
|
|
||||||
),
|
|
||||||
NULL
|
|
||||||
) AS color,
|
|
||||||
array_remove(
|
|
||||||
array_agg(
|
|
||||||
DISTINCT CASE
|
|
||||||
WHEN c.lft > styles.lft AND c.rgt < styles.rgt THEN c.name
|
|
||||||
END
|
|
||||||
),
|
|
||||||
NULL
|
|
||||||
) AS style,
|
|
||||||
array_remove(
|
|
||||||
array_agg(
|
|
||||||
DISTINCT CASE
|
|
||||||
WHEN c.lft > patterns.lft AND c.rgt < patterns.rgt THEN c.name
|
|
||||||
END
|
|
||||||
),
|
|
||||||
NULL
|
|
||||||
) AS pattern
|
|
||||||
FROM product_category pc
|
FROM product_category pc
|
||||||
JOIN categories_v2_lft_rgt c ON c.id = pc.category_id
|
JOIN categories_v2_lft_rgt c ON c.id = pc.category_id
|
||||||
CROSS JOIN rooms
|
JOIN facet_parents fp ON c.lft > fp.lft AND c.rgt < fp.rgt
|
||||||
CROSS JOIN colors
|
|
||||||
CROSS JOIN styles
|
|
||||||
CROSS JOIN patterns
|
|
||||||
WHERE pc.product_id = ?
|
WHERE pc.product_id = ?
|
||||||
AND (
|
|
||||||
(c.lft > rooms.lft AND c.rgt < rooms.rgt)
|
|
||||||
OR
|
|
||||||
(c.lft > colors.lft AND c.rgt < colors.rgt)
|
|
||||||
OR
|
|
||||||
(c.lft > styles.lft AND c.rgt < styles.rgt)
|
|
||||||
OR
|
|
||||||
(c.lft > patterns.lft AND c.rgt < patterns.rgt)
|
|
||||||
)
|
|
||||||
`,
|
`,
|
||||||
[
|
[
|
||||||
ROOMS_PARENT_ID,
|
ROOMS_PARENT_ID,
|
||||||
COLORS_PARENT_ID,
|
COLORS_PARENT_ID,
|
||||||
STYLES_PARENT_ID,
|
STYLES_PARENT_ID,
|
||||||
PATTERNS_PARENT_ID,
|
PATTERNS_PARENT_ID,
|
||||||
|
...allFacetParentIds,
|
||||||
productId,
|
productId,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.cache(MINUTE * 5);
|
.cache(MINUTE * 5);
|
||||||
|
|
||||||
const facetRow = rows[0] ?? { room: [], color: [], style: [], pattern: [] };
|
const facetRow = rows[0] ?? {
|
||||||
|
room: [],
|
||||||
|
color: [],
|
||||||
|
style: [],
|
||||||
|
pattern: [],
|
||||||
|
motif: [],
|
||||||
|
};
|
||||||
const roomCategories: string[] = facetRow.room ?? [];
|
const roomCategories: string[] = facetRow.room ?? [];
|
||||||
const colorCategories: string[] = facetRow.color ?? [];
|
const colorCategories: string[] = facetRow.color ?? [];
|
||||||
const styleCategories: string[] = facetRow.style ?? [];
|
const styleCategories: string[] = facetRow.style ?? [];
|
||||||
const patternCategories: string[] = facetRow.pattern ?? [];
|
const patternCategories: string[] = facetRow.pattern ?? [];
|
||||||
|
const motifCategories: string[] = facetRow.motif ?? [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
room: roomCategories,
|
room: roomCategories,
|
||||||
color: colorCategories,
|
color: colorCategories,
|
||||||
style: styleCategories,
|
style: styleCategories,
|
||||||
pattern: patternCategories,
|
pattern: patternCategories,
|
||||||
|
motif: motifCategories,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
type InputType = string | undefined | null;
|
type InputType = string | undefined | null;
|
||||||
|
|
||||||
export const MINUTE = 60;
|
export const MINUTE = 60;
|
||||||
|
export const HOUR = 3600;
|
||||||
|
|
||||||
function isNumeric(n: InputType) {
|
function isNumeric(n: InputType) {
|
||||||
return !isNaN(parseFloat(n));
|
return !isNaN(parseFloat(n));
|
||||||
@@ -82,6 +83,9 @@ export const createQuestionMarksFromList = (arr: unknown[]): string => {
|
|||||||
return '?,'.repeat(arr.length).slice(0, -1);
|
return '?,'.repeat(arr.length).slice(0, -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const sanitizeFacetValues = (values: string[]): string[] =>
|
||||||
|
values.map((v) => v.toLowerCase().replace(/,/g, ''));
|
||||||
|
|
||||||
export const isRepeatingPattern = (product: Product): boolean => {
|
export const isRepeatingPattern = (product: Product): boolean => {
|
||||||
const found = product.printProducts.find(
|
const found = product.printProducts.find(
|
||||||
(pr) => pr.groupId === ProductGroup.WALLPAPER,
|
(pr) => pr.groupId === ProductGroup.WALLPAPER,
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ import { DesignerAPI } from '../datasources/designer-api';
|
|||||||
import { PrintProductDefaultsAPI } from '../datasources/printproduct-defaults-api';
|
import { PrintProductDefaultsAPI } from '../datasources/printproduct-defaults-api';
|
||||||
import { PrintProductDefaults } from '../types/printproduct-defaults-types';
|
import { PrintProductDefaults } from '../types/printproduct-defaults-types';
|
||||||
import { GraphQLError } from 'graphql';
|
import { GraphQLError } from 'graphql';
|
||||||
import { getOrientationString, isRepeatingPattern } from '../datasources/utils';
|
import {
|
||||||
|
getOrientationString,
|
||||||
|
isRepeatingPattern,
|
||||||
|
sanitizeFacetValues,
|
||||||
|
} from '../datasources/utils';
|
||||||
import { sendMessage } from '../aws/sqs';
|
import { sendMessage } from '../aws/sqs';
|
||||||
import { sendProductUpdatedEvent } from '../bernard/client';
|
import { sendProductUpdatedEvent } from '../bernard/client';
|
||||||
|
|
||||||
@@ -117,16 +121,13 @@ const Product = {
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const patterns = product.printProducts.some(
|
const patterns = isRepeating ? categoryBasedFacets.pattern : [];
|
||||||
(pp) => pp.groupId === ProductGroup.WALLPAPER,
|
const motifs = isRepeating ? [] : categoryBasedFacets.motif;
|
||||||
)
|
|
||||||
? categoryBasedFacets.pattern
|
|
||||||
: [];
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
attribute: 'color',
|
attribute: 'color',
|
||||||
values: [...colors],
|
values: sanitizeFacetValues([...colors]),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
attribute: 'orientation',
|
attribute: 'orientation',
|
||||||
@@ -141,10 +142,20 @@ const Product = {
|
|||||||
return value.toLowerCase();
|
return value.toLowerCase();
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{ attribute: 'type', values: types },
|
{ attribute: 'type', values: sanitizeFacetValues(types) },
|
||||||
{ attribute: 'room', values: categoryBasedFacets.room },
|
{
|
||||||
{ attribute: 'style', values: categoryBasedFacets.style },
|
attribute: 'room',
|
||||||
{ attribute: 'pattern', values: patterns },
|
values: sanitizeFacetValues(categoryBasedFacets.room),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attribute: 'style',
|
||||||
|
values: sanitizeFacetValues(categoryBasedFacets.style),
|
||||||
|
},
|
||||||
|
{ attribute: 'pattern', values: sanitizeFacetValues(patterns) },
|
||||||
|
{
|
||||||
|
attribute: 'motif',
|
||||||
|
values: sanitizeFacetValues(motifs),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user