@propeller-commerce/propeller-v2-react-ui 0.15.7 → 0.15.9
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 +49 -0
- package/dist/index.cjs +51 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -5
- package/dist/index.d.ts +32 -5
- package/dist/index.js +51 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,55 @@ once it reaches 1.0. Until then (the `0.x` line) the public API may change
|
|
|
8
8
|
between minor versions; breaking changes are called out below and in
|
|
9
9
|
[MIGRATION.md](./MIGRATION.md).
|
|
10
10
|
|
|
11
|
+
## [0.15.9] - 2026-08-11
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **The product specifications table emptied out in a language the catalogue is
|
|
16
|
+
only partly translated into** (PWP-928). A localized list carries only the
|
|
17
|
+
languages someone authored, so asking for one nobody wrote returns nothing —
|
|
18
|
+
it does not fall back. `ProductSpecifications` matched strictly on
|
|
19
|
+
`language === props.language`, which failed twice over: the label fell through
|
|
20
|
+
to `attributeDescription.name` and printed the raw PIM code
|
|
21
|
+
(`QUANTORE_70001706`) at the user, and the value resolved to `''` — and since
|
|
22
|
+
`getAttributes()` drops rows with an empty value, the row disappeared
|
|
23
|
+
entirely. On a Dutch-only catalogue browsed in English the whole table went
|
|
24
|
+
blank. Both now prefer the active language and fall back to whichever
|
|
25
|
+
translation exists, matching `GridFilters`, `ProductDescription` and the menu.
|
|
26
|
+
Empty localized rows the backend really does return
|
|
27
|
+
(`{ language: 'FR', values: [] }`) are skipped rather than winning the
|
|
28
|
+
fallback. Language matching is now case-insensitive: with `language="en"` the
|
|
29
|
+
component previously rendered nothing at all.
|
|
30
|
+
|
|
31
|
+
## [0.15.8] - 2026-08-11
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- **Quick order could add products from outside the user's catalogue.** Both the
|
|
36
|
+
row typeahead and the XLSX upload resolved codes through the flat `products`
|
|
37
|
+
resolver with no catalog scope and no user context. Orderlist (contract)
|
|
38
|
+
scoping is honoured by `category.products` but **silently ignored** on the flat
|
|
39
|
+
resolver, so quick order surfaced the full catalogue while the grid and the
|
|
40
|
+
search preview stayed scoped — the same bug fixed for the SearchBar preview in
|
|
41
|
+
0.4.28. `searchProducts` now queries `category.getCategory` over
|
|
42
|
+
`configuration.baseCategoryId` and passes `userId` / `companyId` /
|
|
43
|
+
`applyOrderlists`, plus `hidden: false`, matching `ProductGrid`, the SearchBar
|
|
44
|
+
and the WordPress plugin's quick-order flow. Codes outside the catalogue are
|
|
45
|
+
reported through `onMissingCodes` instead of being added.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **`QuickOrder` needs `configuration.baseCategoryId`.** Without it the
|
|
50
|
+
typeahead and the upload resolve nothing rather than falling back to an
|
|
51
|
+
unscoped search — failing closed is the point of the fix. Apps already
|
|
52
|
+
resolving a base category for `ProductGrid` / `SearchBar` should pass the same
|
|
53
|
+
value.
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- `QuickOrder` accepts `taxZone` (defaults to `'NL'`), `orderlistIds` and
|
|
58
|
+
`applyOrderlists`, forwarded to the scoped search.
|
|
59
|
+
|
|
11
60
|
## [0.15.7] - 2026-08-10
|
|
12
61
|
|
|
13
62
|
### Fixed
|
package/dist/index.cjs
CHANGED
|
@@ -2596,21 +2596,33 @@ function useQuickOrder(options) {
|
|
|
2596
2596
|
} = options;
|
|
2597
2597
|
const language = options.language || "NL";
|
|
2598
2598
|
const searchLimit = options.searchLimit ?? 8;
|
|
2599
|
+
const taxZone = options.taxZone || "NL";
|
|
2600
|
+
const { orderlistIds, applyOrderlists } = options;
|
|
2599
2601
|
const [submitting, setSubmitting] = React6.useState(false);
|
|
2600
2602
|
const [error, setError] = React6.useState(null);
|
|
2601
2603
|
const searchProducts = React6.useCallback(
|
|
2602
2604
|
async (term) => {
|
|
2603
2605
|
const trimmed = term.trim();
|
|
2604
2606
|
if (!trimmed || !graphqlClient) return [];
|
|
2607
|
+
const catId = configuration.baseCategoryId ?? 0;
|
|
2608
|
+
if (!catId) return [];
|
|
2605
2609
|
try {
|
|
2606
|
-
const service = propellerV2CoreUi.createServices(graphqlClient).
|
|
2610
|
+
const service = propellerV2CoreUi.createServices(graphqlClient).category;
|
|
2611
|
+
const orderlistScope = orderlistIds && orderlistIds.length > 0 ? { applyOrderlists: applyOrderlists !== false, orderlistIds } : { applyOrderlists: false };
|
|
2612
|
+
const userId = user && "contactId" in user ? user.contactId : user && "customerId" in user ? user.customerId : void 0;
|
|
2613
|
+
const contactId = user && "contactId" in user ? user.contactId : void 0;
|
|
2614
|
+
const customerId = user && "customerId" in user ? user.customerId : void 0;
|
|
2607
2615
|
const input = {
|
|
2608
2616
|
term: trimmed,
|
|
2609
2617
|
language,
|
|
2610
2618
|
page: 1,
|
|
2611
2619
|
offset: searchLimit,
|
|
2612
2620
|
statuses: [propellerSdkV2.ProductStatus.A, propellerSdkV2.ProductStatus.P, propellerSdkV2.ProductStatus.T, propellerSdkV2.ProductStatus.S],
|
|
2621
|
+
hidden: false,
|
|
2613
2622
|
sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
|
|
2623
|
+
...companyId && { companyId },
|
|
2624
|
+
...userId !== void 0 && { userId },
|
|
2625
|
+
...orderlistScope,
|
|
2614
2626
|
searchFields: [
|
|
2615
2627
|
{
|
|
2616
2628
|
fieldNames: [
|
|
@@ -2634,18 +2646,36 @@ function useQuickOrder(options) {
|
|
|
2634
2646
|
]
|
|
2635
2647
|
};
|
|
2636
2648
|
const variables = {
|
|
2637
|
-
|
|
2649
|
+
categoryId: catId,
|
|
2638
2650
|
language,
|
|
2651
|
+
categoryProductSearchInput: input,
|
|
2652
|
+
priceCalculateProductInput: {
|
|
2653
|
+
taxZone,
|
|
2654
|
+
...companyId && { companyId },
|
|
2655
|
+
...contactId !== void 0 && { contactId },
|
|
2656
|
+
...customerId !== void 0 && { customerId }
|
|
2657
|
+
},
|
|
2658
|
+
imageSearchFilters: configuration.imageSearchFiltersGrid,
|
|
2639
2659
|
imageVariantFilters: configuration.imageVariantFiltersSmall
|
|
2640
2660
|
};
|
|
2641
|
-
const
|
|
2642
|
-
const items =
|
|
2661
|
+
const response = await service.getCategory(variables);
|
|
2662
|
+
const items = response?.products?.items ?? [];
|
|
2643
2663
|
return items.map((it) => toMatch(it, language));
|
|
2644
2664
|
} catch {
|
|
2645
2665
|
return [];
|
|
2646
2666
|
}
|
|
2647
2667
|
},
|
|
2648
|
-
[
|
|
2668
|
+
[
|
|
2669
|
+
graphqlClient,
|
|
2670
|
+
language,
|
|
2671
|
+
searchLimit,
|
|
2672
|
+
configuration,
|
|
2673
|
+
user,
|
|
2674
|
+
companyId,
|
|
2675
|
+
taxZone,
|
|
2676
|
+
orderlistIds,
|
|
2677
|
+
applyOrderlists
|
|
2678
|
+
]
|
|
2649
2679
|
);
|
|
2650
2680
|
const submit = React6.useCallback(
|
|
2651
2681
|
async (lines) => {
|
|
@@ -14160,6 +14190,9 @@ function QuickOrderInner(props) {
|
|
|
14160
14190
|
companyId,
|
|
14161
14191
|
language,
|
|
14162
14192
|
configuration,
|
|
14193
|
+
taxZone: props.taxZone,
|
|
14194
|
+
orderlistIds: props.orderlistIds,
|
|
14195
|
+
applyOrderlists: props.applyOrderlists,
|
|
14163
14196
|
onCartCreated,
|
|
14164
14197
|
afterAddToCart
|
|
14165
14198
|
});
|
|
@@ -16456,19 +16489,27 @@ function ProductSpecifications(rawProps) {
|
|
|
16456
16489
|
(a) => (a.attributeDescription?.group || "") === group
|
|
16457
16490
|
);
|
|
16458
16491
|
}
|
|
16492
|
+
function pickLocalized(rows, isUsable) {
|
|
16493
|
+
const list = (rows || []).filter(isUsable);
|
|
16494
|
+
const lang = (props.language || "NL").toUpperCase();
|
|
16495
|
+
return list.find((row) => (row.language || "").toUpperCase() === lang) || list[0];
|
|
16496
|
+
}
|
|
16459
16497
|
function getAttributeLabel(attr) {
|
|
16460
|
-
const
|
|
16461
|
-
|
|
16462
|
-
|
|
16498
|
+
const match = pickLocalized(
|
|
16499
|
+
attr.attributeDescription?.descriptions,
|
|
16500
|
+
(d) => !!d.value
|
|
16501
|
+
);
|
|
16463
16502
|
return match?.value || attr.attributeDescription?.name || "";
|
|
16464
16503
|
}
|
|
16465
16504
|
function getAttributeValue(attr) {
|
|
16466
16505
|
const v = attr.value;
|
|
16467
16506
|
if (!v) return "";
|
|
16468
|
-
const lang = props.language || "NL";
|
|
16469
16507
|
if (v.type === propellerSdkV2.AttributeType.TEXT) {
|
|
16470
16508
|
const tv = v;
|
|
16471
|
-
const entry =
|
|
16509
|
+
const entry = pickLocalized(
|
|
16510
|
+
tv.textValues,
|
|
16511
|
+
(row) => (row?.values || []).some(Boolean)
|
|
16512
|
+
);
|
|
16472
16513
|
const vals = (entry?.values || []).filter(Boolean);
|
|
16473
16514
|
return vals.join(", ");
|
|
16474
16515
|
}
|