@graphcommerce/magento-product 9.0.0-canary.57 → 9.0.0-canary.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 9.0.0-canary.58
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2328](https://github.com/graphcommerce-org/graphcommerce/pull/2328) [`ee04368`](https://github.com/graphcommerce-org/graphcommerce/commit/ee04368444f732e5541a595db6e2ef66d15add68) - Move to attributesList to get a list of filterable attributes instead of using an introspection query. `productFiltersProSectionRenderer` and `productFiltersProChipRenderer` keys now now one of `AttributeFrontendInputEnum`. ([@paales](https://github.com/paales))
8
+
3
9
  ## 9.0.0-canary.57
4
10
 
5
11
  ## 9.0.0-canary.56
@@ -1,3 +1,4 @@
1
+ import { AttributeFrontendInputEnum } from '@graphcommerce/graphql-mesh'
1
2
  import { ProductListFiltersFragment } from '../ProductListFilters/ProductListFilters.gql'
2
3
  import { ProductFilterEqualChip } from './ProductFilterEqualChip'
3
4
  import { ProductFilterEqualSection } from './ProductFilterEqualSection'
@@ -11,20 +12,24 @@ export type FilterProps = {
11
12
  aggregation: NonNullable<NonNullable<ProductListFiltersFragment['aggregations']>[number]>
12
13
  }
13
14
 
14
- export type FilterRenderer = Record<string, React.FC<FilterProps>>
15
+ export type FilterRenderer = Record<AttributeFrontendInputEnum, React.FC<FilterProps>>
15
16
 
16
17
  export type ProductFiltersProAggregationsProps = {
17
- renderer?: FilterRenderer
18
+ renderer?: Partial<FilterRenderer>
18
19
  }
19
20
 
20
- export const productFiltersProSectionRenderer = {
21
- FilterRangeTypeInput: ProductFilterRangeSection,
22
- FilterEqualTypeInput: ProductFilterEqualSection,
21
+ export const productFiltersProSectionRenderer: Partial<FilterRenderer> = {
22
+ SELECT: ProductFilterEqualSection,
23
+ MULTISELECT: ProductFilterEqualSection,
24
+ BOOLEAN: ProductFilterEqualSection,
25
+ PRICE: ProductFilterRangeSection,
23
26
  }
24
27
 
25
- export const productFiltersProChipRenderer = {
26
- FilterEqualTypeInput: ProductFilterEqualChip,
27
- FilterRangeTypeInput: ProductFilterRangeChip,
28
+ export const productFiltersProChipRenderer: Partial<FilterRenderer> = {
29
+ SELECT: ProductFilterEqualChip,
30
+ MULTISELECT: ProductFilterEqualChip,
31
+ BOOLEAN: ProductFilterEqualChip,
32
+ PRICE: ProductFilterRangeChip,
28
33
  }
29
34
 
30
35
  export function ProductFiltersProAggregations(props: ProductFiltersProAggregationsProps) {
@@ -36,7 +41,10 @@ export function ProductFiltersProAggregations(props: ProductFiltersProAggregatio
36
41
  {excludeCategory(applyAggregationCount(aggregations, appliedAggregations, params)).map(
37
42
  (aggregation) => {
38
43
  const filterType = filterTypes[aggregation.attribute_code]
39
- if (!filterType) return null
44
+ if (!filterType) {
45
+ console.log('Filter not recognized', aggregation.attribute_code, filterTypes)
46
+ return null
47
+ }
40
48
 
41
49
  const Component = renderer?.[filterType]
42
50
  if (!Component) {
@@ -1,5 +1,5 @@
1
1
  import { ChipMenuProps } from '@graphcommerce/next-ui'
2
- import { FilterTypes } from '../ProductListItems/filterTypes'
2
+ import { FilterTypes } from '../ProductListItems/getFilterTypes'
3
3
  import { FilterCheckboxType } from './FilterCheckboxType'
4
4
  import { FilterEqualType } from './FilterEqualType'
5
5
  import { FilterRangeType } from './FilterRangeType'
@@ -23,22 +23,16 @@ export function ProductListFilters(props: ProductFiltersProps) {
23
23
  return null
24
24
 
25
25
  switch (filterTypes[aggregation.attribute_code]) {
26
- case 'FilterEqualTypeInput':
27
- if (
28
- aggregation.options?.[0]?.label === '0' ||
29
- aggregation.options?.[1]?.label === '0' ||
30
- aggregation.options?.[0]?.label === '1' ||
31
- aggregation.options?.[1]?.label === '1'
32
- ) {
33
- return (
34
- <FilterCheckboxType
35
- key={aggregation.attribute_code}
36
- {...aggregation}
37
- {...chipMenuProps}
38
- />
39
- )
40
- }
41
-
26
+ case 'BOOLEAN':
27
+ return (
28
+ <FilterCheckboxType
29
+ key={aggregation.attribute_code}
30
+ {...aggregation}
31
+ {...chipMenuProps}
32
+ />
33
+ )
34
+ case 'SELECT':
35
+ case 'MULTISELECT':
42
36
  return (
43
37
  <FilterEqualType
44
38
  key={aggregation.attribute_code}
@@ -46,8 +40,7 @@ export function ProductListFilters(props: ProductFiltersProps) {
46
40
  {...chipMenuProps}
47
41
  />
48
42
  )
49
-
50
- case 'FilterRangeTypeInput':
43
+ case 'PRICE':
51
44
  return (
52
45
  <FilterRangeType
53
46
  key={aggregation.attribute_code}
@@ -56,6 +49,7 @@ export function ProductListFilters(props: ProductFiltersProps) {
56
49
  />
57
50
  )
58
51
  }
52
+
59
53
  // console.log(
60
54
  // 'Filter not recognized',
61
55
  // aggregation.attribute_code,
@@ -0,0 +1,8 @@
1
+ query ProductFilterTypes($filters: AttributeFilterInput!) {
2
+ attributesList(entityType: CATALOG_PRODUCT, filters: $filters) {
3
+ items {
4
+ code
5
+ frontend_input
6
+ }
7
+ }
8
+ }
@@ -67,8 +67,6 @@ export function isFilterTypeRange(filter: AnyFilterType): filter is FilterRangeT
67
67
  )
68
68
  }
69
69
 
70
- export type FilterTypes = Partial<Record<string, string>>
71
-
72
70
  export function toProductListParams(params: ProductFilterParams): ProductListParams {
73
71
  const { sort, dir, filters, ...rest } = params
74
72
 
@@ -1,13 +1,13 @@
1
1
  import type {
2
2
  FilterEqualTypeInput,
3
- FilterMatchTypeInput,
4
3
  FilterRangeTypeInput,
5
4
  SortEnum,
6
5
  } from '@graphcommerce/graphql-mesh'
7
- import { useRouter } from 'next/router'
8
- import { FilterTypes, ProductListParams } from './filterTypes'
9
6
  // eslint-disable-next-line import/no-extraneous-dependencies
10
7
  import { equal } from '@wry/equality'
8
+ import { useRouter } from 'next/router'
9
+ import { ProductListParams } from './filterTypes'
10
+ import { FilterTypes } from './getFilterTypes'
11
11
 
12
12
  export function parseParams(
13
13
  url: string,
@@ -44,20 +44,20 @@ export function parseParams(
44
44
 
45
45
  const [from, to] = value.split('-')
46
46
  switch (typeMap[param]) {
47
- case 'FilterMatchTypeInput':
48
- categoryVariables.filters[param] = { match: value } as FilterMatchTypeInput
47
+ case 'BOOLEAN':
48
+ case 'SELECT':
49
+ case 'MULTISELECT':
50
+ categoryVariables.filters[param] = { in: value.split(',') } as FilterEqualTypeInput
49
51
  return undefined
50
- case 'FilterRangeTypeInput':
52
+ case 'PRICE':
51
53
  categoryVariables.filters[param] = {
52
54
  ...(from !== '*' && { from }),
53
55
  ...(to !== '*' && { to }),
54
56
  } as FilterRangeTypeInput
55
57
  return undefined
56
- case 'FilterEqualTypeInput':
57
- categoryVariables.filters[param] = { in: value.split(',') } as FilterEqualTypeInput
58
- return undefined
59
58
  }
60
59
 
60
+ // console.log('Filter not recognized', param, typeMap[param])
61
61
  error = true
62
62
  return undefined
63
63
  }, undefined)
@@ -1,5 +1,7 @@
1
1
  import { gql, ApolloClient, NormalizedCacheObject, TypedDocumentNode } from '@graphcommerce/graphql'
2
- import type { Exact } from '@graphcommerce/graphql-mesh'
2
+ import type { AttributeFrontendInputEnum, Exact } from '@graphcommerce/graphql-mesh'
3
+ import { filterNonNullableKeys, nonNullable } from '@graphcommerce/next-ui'
4
+ import { ProductFilterTypesDocument } from './ProductFilterTypes.gql'
3
5
 
4
6
  type FilterInputTypesQueryVariables = Exact<{ [key: string]: never }>
5
7
 
@@ -25,13 +27,40 @@ const FilterInputTypesDocument = gql`
25
27
  }
26
28
  ` as TypedDocumentNode<FilterInputTypesQuery, FilterInputTypesQueryVariables>
27
29
 
30
+ export type FilterTypes = Partial<Record<string, AttributeFrontendInputEnum>>
31
+
28
32
  export async function getFilterTypes(
29
33
  client: ApolloClient<NormalizedCacheObject>,
30
- ): Promise<Record<string, string | undefined>> {
34
+ isSearch: boolean = false,
35
+ ): Promise<FilterTypes> {
36
+ if (import.meta.graphCommerce.magentoVersion >= 247) {
37
+ const types = await client.query({
38
+ query: ProductFilterTypesDocument,
39
+ variables: {
40
+ filters: isSearch ? { is_filterable_in_search: true } : {},
41
+ },
42
+ })
43
+
44
+ const typeMap: FilterTypes = Object.fromEntries(
45
+ filterNonNullableKeys(types.data.attributesList?.items, ['frontend_input'])
46
+ .map((i) => [i.code, i.frontend_input])
47
+ .filter(nonNullable),
48
+ )
49
+
50
+ return typeMap
51
+ }
52
+
31
53
  const filterInputTypes = await client.query({ query: FilterInputTypesDocument })
32
54
 
33
- const typeMap: Record<string, string | undefined> = Object.fromEntries(
34
- filterInputTypes.data?.__type.inputFields.map(({ name, type }) => [name, type.name]),
55
+ const typeMap: FilterTypes = Object.fromEntries(
56
+ filterInputTypes.data?.__type.inputFields
57
+ .map<[string, AttributeFrontendInputEnum] | undefined>((field) => {
58
+ if (field.type.name === 'FilterEqualTypeInput') return [field.name, 'SELECT']
59
+ if (field.type.name === 'FilterRangeTypeInput') return [field.name, 'PRICE']
60
+ if (field.type.name === 'FilterMatchTypeInput') return [field.name, 'TEXT']
61
+ return undefined
62
+ })
63
+ .filter(nonNullable),
35
64
  )
36
65
 
37
66
  return typeMap
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-product",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "9.0.0-canary.57",
5
+ "version": "9.0.0-canary.58",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -18,19 +18,19 @@
18
18
  "typescript": "5.5.3"
19
19
  },
20
20
  "peerDependencies": {
21
- "@graphcommerce/ecommerce-ui": "^9.0.0-canary.57",
22
- "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.57",
23
- "@graphcommerce/framer-next-pages": "^9.0.0-canary.57",
24
- "@graphcommerce/framer-scroller": "^9.0.0-canary.57",
25
- "@graphcommerce/graphql": "^9.0.0-canary.57",
26
- "@graphcommerce/graphql-mesh": "^9.0.0-canary.57",
27
- "@graphcommerce/image": "^9.0.0-canary.57",
28
- "@graphcommerce/magento-cart": "^9.0.0-canary.57",
29
- "@graphcommerce/magento-category": "^9.0.0-canary.57",
30
- "@graphcommerce/magento-store": "^9.0.0-canary.57",
31
- "@graphcommerce/next-ui": "^9.0.0-canary.57",
32
- "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.57",
33
- "@graphcommerce/typescript-config-pwa": "^9.0.0-canary.57",
21
+ "@graphcommerce/ecommerce-ui": "^9.0.0-canary.58",
22
+ "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.58",
23
+ "@graphcommerce/framer-next-pages": "^9.0.0-canary.58",
24
+ "@graphcommerce/framer-scroller": "^9.0.0-canary.58",
25
+ "@graphcommerce/graphql": "^9.0.0-canary.58",
26
+ "@graphcommerce/graphql-mesh": "^9.0.0-canary.58",
27
+ "@graphcommerce/image": "^9.0.0-canary.58",
28
+ "@graphcommerce/magento-cart": "^9.0.0-canary.58",
29
+ "@graphcommerce/magento-category": "^9.0.0-canary.58",
30
+ "@graphcommerce/magento-store": "^9.0.0-canary.58",
31
+ "@graphcommerce/next-ui": "^9.0.0-canary.58",
32
+ "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.58",
33
+ "@graphcommerce/typescript-config-pwa": "^9.0.0-canary.58",
34
34
  "@lingui/core": "^4.2.1",
35
35
  "@lingui/macro": "^4.2.1",
36
36
  "@lingui/react": "^4.2.1",