Skip to content

Commit

Permalink
Merge branch 'main' into merx-1386-channels-permissions-discounts
Browse files Browse the repository at this point in the history
  • Loading branch information
poulch authored Jan 7, 2025
2 parents 41d1093 + 763a180 commit e4242c9
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .changeset/orange-pugs-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Batch of sentry errors has been fixed
39 changes: 10 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@dnd-kit/core": "^6.0.8",
"@dnd-kit/sortable": "^7.0.2",
"@dnd-kit/utilities": "^3.2.1",
"@editorjs/editorjs": "^2.24.3",
"@editorjs/editorjs": "^2.30.7",
"@editorjs/header": "^2.6.2",
"@editorjs/list": "^1.7.0",
"@editorjs/paragraph": "^2.8.0",
Expand Down
12 changes: 11 additions & 1 deletion src/auth/hooks/useAuthProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,19 @@ export function useAuthProvider({ intl, notify, apolloClient }: UseAuthProviderO
}
};
const handleRequestExternalLogin = async (pluginId: string, input: RequestExternalLoginInput) => {
let stringifyInput: string;

try {
stringifyInput = JSON.stringify(input);
} catch (error) {
setErrors(["externalLoginError"]);

return;
}

const result = await getExternalAuthUrl({
pluginId,
input: JSON.stringify(input),
input: stringifyInput,
});

return result?.data?.externalAuthenticationUrl;
Expand Down
56 changes: 54 additions & 2 deletions src/components/AddressEdit/useAddressValidation.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useAddressValidationRulesQuery } from "@dashboard/graphql";
import { AddressValidationRulesQuery, useAddressValidationRulesQuery } from "@dashboard/graphql";
import { renderHook } from "@testing-library/react-hooks";

import { useAddressValidation } from "./useAddressValidation";
import { selectRules, useAddressValidation } from "./useAddressValidation";

jest.mock("@dashboard/graphql", () => ({
CountryCode: jest.requireActual("@dashboard/graphql").CountryCode,
useAddressValidationRulesQuery: jest.fn(),
}));

describe("useAddressValidation", () => {
it("skips loading validation rules when country is not provided", () => {
// Arrange
Expand Down Expand Up @@ -139,3 +140,54 @@ describe("useAddressValidation", () => {
expect(displayValue).toEqual("");
});
});

describe("selectRules", () => {
it("should return select rules when available", () => {
// Arrange
const data = {
addressValidationRules: {
countryAreaChoices: [
{ raw: "AL", verbose: "Alabama" },
{ raw: "AN", verbose: "Ancona" },
],
allowedFields: ["country"],
},
} as AddressValidationRulesQuery;

// Act
const rules = selectRules(data);

// Assert
expect(rules).toEqual({
countryAreaChoices: [
{ raw: "AL", verbose: "Alabama" },
{ raw: "AN", verbose: "Ancona" },
],
allowedFields: ["country"],
});
});

it("should return empty array when addressValidationRules is not provided", () => {
// Arrange
const data = {
addressValidationRules: null,
} as AddressValidationRulesQuery;

// Act
const rules = selectRules(data);

// Assert
expect(rules).toEqual({ countryAreaChoices: [], allowedFields: [] });
});

it("should return empty array when data is not provided", () => {
// Arrange
const data = undefined;

// Act
const rules = selectRules(data);

// Assert
expect(rules).toEqual({ countryAreaChoices: [], allowedFields: [] });
});
});
13 changes: 10 additions & 3 deletions src/components/AddressEdit/useAddressValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ const prepareChoices = (values: ChoiceValue[]): AreaChoices[] =>
value: v.verbose,
raw: v.raw,
}));
const selectRules = (data: AddressValidationRulesQuery) =>
data ? data.addressValidationRules : { countryAreaChoices: [], allowedFields: [] };

export const selectRules = (data: AddressValidationRulesQuery | null | undefined) => {
if (!data || !data.addressValidationRules) {
return { countryAreaChoices: [], allowedFields: [] };
}

return data.addressValidationRules;
};

const useValidationRules = (country?: string) => {
const countryCode = CountryCode[country];
const { data, loading } = useAddressValidationRulesQuery({
Expand All @@ -30,7 +37,7 @@ const useValidationRules = (country?: string) => {
return { data, loading };
};
const useAreas = (data: AddressValidationRulesQuery) => {
const rawChoices = selectRules(data).countryAreaChoices;
const rawChoices = selectRules(data)?.countryAreaChoices ?? [];
const choices = prepareChoices(rawChoices);

return choices;
Expand Down
15 changes: 9 additions & 6 deletions src/components/Datagrid/customCells/PillCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,15 @@ export const pillCellRenderer = (): CustomRenderer<PillCell> => ({
const tileHeight = textHeight * 1.2;

// Draw the tile
ctx.fillStyle = base;
ctx.strokeStyle = border;
ctx.beginPath();
ctx.roundRect(x + 10, y + height / 2 - tileHeight / 2, tileWidth, tileHeight, 5);
ctx.stroke();
ctx.fill();
if ("roundRect" in ctx) {
ctx.fillStyle = base;
ctx.strokeStyle = border;
ctx.beginPath();
ctx.roundRect(x + 10, y + height / 2 - tileHeight / 2, tileWidth, tileHeight, 5);
ctx.stroke();
ctx.fill();
}

// Draw the text
ctx.fillStyle = text;
ctx.fillText(label, x + 15, y + height / 2 + getMiddleCenterBias(ctx, theme));
Expand Down
2 changes: 1 addition & 1 deletion src/components/SortableTree/hooks/useAnnouncement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const useAnnouncement = <T extends DataTypePlaceholder>({

if (!previousItem && nextItem) {
announcement = `${activeId} was ${movedVerb} before ${nextItem.id}.`;
} else if (projected.depth > previousItem.depth) {
} else if (projected?.depth > previousItem?.depth) {
announcement = `${activeId} was ${nestedVerb} under ${previousItem.id}.`;
} else {
const previousSibling = findPreviousSibling(projected, previousItem, sortedItems);
Expand Down
2 changes: 1 addition & 1 deletion src/customers/views/CustomerList/CustomerList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const CustomerList: React.FC<CustomerListProps> = ({ params }) => {
return;
}

const rowsIds = rows.map(row => customers[row].id);
const rowsIds = rows.map(row => customers[row]?.id).filter(id => id !== undefined);
const haveSaveValues = isEqual(rowsIds, selectedRowIds);

if (!haveSaveValues) {
Expand Down
8 changes: 7 additions & 1 deletion src/productTypes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ import ProductTypeListComponent from "./views/ProductTypeList";
import ProductTypeUpdateComponent from "./views/ProductTypeUpdate";

const ProductTypeList: React.FC<RouteComponentProps<{}>> = ({ location }) => {
const qs = parseQs(location.search.substr(1)) as any;
const qs = parseQs(location.search, {
ignoreQueryPrefix: true,
// As a product types list still keeps ids to remove in query params,
// we need to increase the array limit to 100, default 20,
// because qs library return object instead of an array when limit is exceeded
arrayLimit: 100,
}) as any;
const params: ProductTypeListUrlQueryParams = asSortParams(qs, ProductTypeListUrlSortField);

return <ProductTypeListComponent params={params} />;
Expand Down
2 changes: 1 addition & 1 deletion src/products/components/ProductListDatagrid/datagrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ function getProductTypeCellContent(
theme: DefaultTheme,
rowData: RelayToFlat<ProductListQuery["products"]>[number],
) {
const hue = stringToHue(rowData.productType?.name);
const hue = stringToHue(rowData?.productType?.name);
const color = theme === "defaultDark" ? hueToPillColorDark(hue) : hueToPillColorLight(hue);

return pillCell(rowData.productType?.name, color, COMMON_CELL_PROPS);
Expand Down
2 changes: 1 addition & 1 deletion src/products/components/ProductUpdatePage/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function updateVaraintWithPriceFormat(
const channelId = dataChange.column.split(":")[1];
const currencyCode = getChannelCurrencyCodeById(channelId, product.channelListings);

dataChange.data.value = parseCurrency(`${dataChange.data.value}`, locale, currencyCode);
dataChange.data.value = parseCurrency(`${String(dataChange.data.value)}`, locale, currencyCode);

return dataChange;
}
Expand Down
5 changes: 3 additions & 2 deletions src/searches/useAttributeValueSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export default makeSearch<SearchAttributeValuesQuery, SearchAttributeValuesQuery
result.loadMore(
(prev, next) => {
if (
prev.attribute.choices.pageInfo.endCursor === next.attribute.choices.pageInfo.endCursor
prev?.attribute?.choices?.pageInfo?.endCursor ===
next?.attribute?.choices?.pageInfo?.endCursor
) {
return prev;
}
Expand All @@ -64,7 +65,7 @@ export default makeSearch<SearchAttributeValuesQuery, SearchAttributeValuesQuery
attribute: {
...prev.attribute,
choices: {
...prev.attribute.choices,
...prev?.attribute.choices,
edges: [...prev.attribute.choices.edges, ...next.attribute.choices.edges],
pageInfo: next.attribute.choices.pageInfo,
},
Expand Down
16 changes: 16 additions & 0 deletions testUtils/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "@testing-library/jest-dom";

import { configure } from "@testing-library/react";

jest.mock("@sentry/react");
Expand Down Expand Up @@ -40,9 +41,24 @@ configure({ testIdAttribute: "data-test-id" });
* Fixes (hacks) "TextEncoder is not defined" error which is likely bug in jsdom
*/
import { TextDecoder, TextEncoder } from "util";

global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder as typeof global.TextDecoder;

global.CSS = {
supports: () => false,
} as any;

/**
*
* Fixes (hacks) "crypto is not defined" error which is likely missing implementation in jsdom
*/
import nodeCrypto from "crypto";

global.crypto = {
getRandomValues: function (buffer: any) {
return nodeCrypto.randomFillSync(buffer);
},
subtle: {} as SubtleCrypto,
randomUUID: () => nodeCrypto.randomUUID(),
};

0 comments on commit e4242c9

Please sign in to comment.