Add prettier command and run it inside src folder (#3892)

This commit is contained in:
Krzysztof Żuraw 2023-07-11 08:34:08 +02:00 committed by GitHub
parent de098fd520
commit 03d9e92c97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 342 additions and 350 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Run prettier against source folder

View file

@ -330,7 +330,8 @@
"dep-status": "depcruise --config .dependency-cruiser.js src",
"chromatic": "chromatic --exit-zero-on-changes",
"change:add": "changeset add",
"release:prepare-main": "./scripts/prepare-main-after-release.sh"
"release:prepare-main": "./scripts/prepare-main-after-release.sh",
"format:code": "prettier --ignore-unknown --write src/*"
},
"description": "![Saleor Dashboard](https://user-images.githubusercontent.com/44495184/185379472-2a204c0b-9b7a-4a3e-93c0-2cb85205ed5e.png)"
}

View file

@ -13,7 +13,9 @@ export interface ResetPasswordSuccessPageProps {
onBack: () => void;
}
const ResetPasswordSuccessPage: React.FC<ResetPasswordSuccessPageProps> = props => {
const ResetPasswordSuccessPage: React.FC<
ResetPasswordSuccessPageProps
> = props => {
const { onBack } = props;
const classes = useStyles(props);

View file

@ -26,7 +26,8 @@ export const UserContextError = {
unknownLoginError: "unknownLoginError",
} as const;
export type UserContextError = typeof UserContextError[keyof typeof UserContextError];
export type UserContextError =
(typeof UserContextError)[keyof typeof UserContextError];
export interface UserContext {
login: (username: string, password: string) => Promise<LoginData>;

View file

@ -307,7 +307,7 @@ export const createChannelsDataFromProduct = (productData?: ProductFragment) =>
listing => listing.channel.id === channel.id,
);
// Comparing explicitly to false because `hasVariants` can be undefined
const isSimpleProduct = !(productData.productType?.hasVariants);
const isSimpleProduct = !productData.productType?.hasVariants;
const haveVariantsChannelListings = productData.variants.some(variant =>
variant.channelListings.some(
listing => listing.channel.id === channel.id,

View file

@ -2,10 +2,12 @@ import { AddressTypeInput } from "@dashboard/customers/types";
import { FormChange } from "@dashboard/hooks/useForm";
import { ChangeEvent } from "react";
export const createCountryHandler = (
currentHandler: FormChange,
set: (dataSet: Partial<AddressTypeInput>) => void,
) => (event: ChangeEvent<any>) => {
currentHandler(event);
set({ countryArea: "" });
};
export const createCountryHandler =
(
currentHandler: FormChange,
set: (dataSet: Partial<AddressTypeInput>) => void,
) =>
(event: ChangeEvent<any>) => {
currentHandler(event);
set({ countryArea: "" });
};

View file

@ -13,7 +13,7 @@ export const Backlink = ({
return (
<MacawBacklink<LinkType>
{...props}
component={(Link as unknown) as LinkType}
component={Link as unknown as LinkType}
to={href}
/>
);

View file

@ -19,7 +19,9 @@ export interface ChannelsAvailabilityContentProps {
toggleAll?: (items: Channel[], selected: number) => void;
}
export const ChannelsAvailabilityContent: React.FC<ChannelsAvailabilityContentProps> = ({
export const ChannelsAvailabilityContent: React.FC<
ChannelsAvailabilityContentProps
> = ({
isSelected,
channels,
contentType = "",

View file

@ -1,7 +1,7 @@
import { filter } from "fuzzaldrin";
import React from "react";
export const useChannelsSearch = function<T extends { name: string }>(
export const useChannelsSearch = function <T extends { name: string }>(
channels: T[],
) {
const [query, onQueryChange] = React.useState("");

View file

@ -28,11 +28,9 @@ export interface ChannelsAvailabilityContentProps {
onChange: (option: Channel) => void;
}
const ChannelsAvailabilityContent: React.FC<ChannelsAvailabilityContentProps> = ({
isChannelSelected,
channels,
onChange,
}) => {
const ChannelsAvailabilityContent: React.FC<
ChannelsAvailabilityContentProps
> = ({ isChannelSelected, channels, onChange }) => {
const classes = useStyles({});
return (

View file

@ -86,7 +86,9 @@ export interface ChannelsAvailabilityContentProps {
hasAllSelected: boolean;
}
export const ChannelsAvailabilityContentWrapper: React.FC<ChannelsAvailabilityContentProps> = ({
export const ChannelsAvailabilityContentWrapper: React.FC<
ChannelsAvailabilityContentProps
> = ({
contentType = "",
toggleAll,
toggleAllLabel,

View file

@ -5,7 +5,9 @@
<img width="977" alt="image" src="https://user-images.githubusercontent.com/41952692/233042483-d2cb30f3-26b7-40b5-9d08-2ea42f7f0242.png">
### Column types
In datagrid views various types of columns are available. We can split them into two groups:
- static columns - e. g. `id`, `name`, `created_at`. These columns are simple to set up as a static object.
- dynamic columns - e.g. stocks, attributes, channels. These column values are not known in advance and must be fetched from the API.
@ -16,13 +18,17 @@ For dynamic columns, the naming convetion is as follows:
```
column_name:column_id
```
For example:
```
attribute:QXR0cmlidXRlOjIx
```
### useColumns hook
`useColumns` is a custom hook that is used as single source of truth for both Datagrid and Column Picker. It returns an object with the following properties:
- visible columns - array of visible columns for the datagrid
- static columns - array of static columns for the column picker
- dynamic columns - array of dynamic columns for the column picker
@ -37,6 +43,7 @@ attribute:QXR0cmlidXRlOjIx
- dynamic column selection handler (for column picker)
In order to use this hook, you need to provide four things:
- `staticColumns` - array of static columns in datagrid-ready format (`AvailableColumns[]`)
- `columnCategories` - array of column categories
- state & setter of column settings which we get from `useListSettings`
@ -45,31 +52,32 @@ In order to use this hook, you need to provide four things:
## Adapting new views
### Column picker settings
Firstly, in the view file, we need to provide two settings object, one for the selected columns and one for the dynamic column settings. We should use `useColumnPickerSettings` and `useListSettings` hook for that. The first settings object manages columns selected for the datagrid (visible columns). The second manages state of seleceted dynamic columns (if we pick a value from left side of column picked, it is then displayed on the right side of the picker as dynamic column with togglable visibility). Toggling the visiblity saves the column in the first settings object.
The reason why column picker settings object needs to be in the view file and cannot be integrated into internal logic of useColumns is because we use column picker settings in the query. We need to know which columns are selected in order to fetch the correct data from the API.
```tsx
```tsx
const { columnPickerSettings, setDynamicColumnsSettings } =
useColumnPickerSettings("PRODUCT_LIST");
useColumnPickerSettings("PRODUCT_LIST");
// Translates columnIDs to api IDs
const filteredColumnIds = columnPickerSettings
.filter(isAttributeColumnValue)
.map(getAttributeIdFromColumnValue);
.filter(isAttributeColumnValue)
.map(getAttributeIdFromColumnValue);
const gridAttributes = useGridAttributesQuery({
variables: { ids: filteredColumnIds },
skip: filteredColumnIds.length === 0,
variables: { ids: filteredColumnIds },
skip: filteredColumnIds.length === 0,
});
```
```
### Static columns adapter
Writing an adapter for static columns is an easy task. We need to provide an array of static columns in datagrid-ready format (`AvailableColumns[]`).
For example:
```tsx
export const parseStaticColumnsForProductListView = (intl, emptyColumn, sort) =>
[
@ -94,17 +102,19 @@ export const parseStaticColumnsForProductListView = (intl, emptyColumn, sort) =>
Empty column is a special column that is used to add padding in the datagrid. It is filtered out by the column picker.
### Dynamic column adapter
This function creates ColumnCategory[] object from available data.
This function creates ColumnCategory[] object from available data.
Creating a column category requires two queries per category. Let's say we want to have custom attributes as columns. We need
- query which fetches all attributes
- query which fetches selected attributes
We cannot rely on single query, because searching through attributes would influence already selected columns which are visible in the datagrid.
Example:
```tsx
export const parseDynamicColumnsForProductListView = ({
attributesData,
@ -138,9 +148,11 @@ export const parseDynamicColumnsForProductListView = ({
},
];
```
Here we only have 1 column category, attributes. `attributesData` is the result of the first query, `gridAttributesData` is the result of the second query. We also provide pagination props, which are used in the column picker.
Queries which are used in this case are for categories. Let's look at the first query:
```tsx
export const availableColumnAttribues = gql`
query AvailableColumnAttributes(
@ -170,9 +182,11 @@ export const availableColumnAttribues = gql`
}
`;
```
This query is used to fetch all **available** attributes. It is paginated and has a search filter and results are displayed in the left part of the column picker.
The second query is similar, but it has a filter of IDs, which come from local storage settings (useColumnPickerSettngs):
```tsx
export const gridAttributes = gql`
query GridAttributes($ids: [ID!]!) {
@ -187,10 +201,11 @@ export const gridAttributes = gql`
}
`;
```
Data of this query is displayed in the right part of the column picker, below the static columns.
Here is the adapter for the dynamic columns inside the category:
```tsx
export const parseAttributesColumns = (
attributes: RelayToFlat<
@ -210,4 +225,4 @@ export const parseAttributesColumns = (
}));
```
With the dynamic column adapter written, we can now use the `useColumns` hook.
With the dynamic column adapter written, we can now use the `useColumns` hook.

View file

@ -1,2 +1,2 @@
export { Condition } from "./Condition"
export { type FilterContainer,FilterElement } from "./FilterElement"
export { Condition } from "./Condition";
export { type FilterContainer, FilterElement } from "./FilterElement";

View file

@ -1,8 +1,8 @@
import { FilterContainer } from "./FilterElement";
type QueryVars =
| { OR: QueryVars, current?: FilterContainer[number] }
| { AND: QueryVars, current?: FilterContainer[number] }
| { OR: QueryVars; current?: FilterContainer[number] }
| { AND: QueryVars; current?: FilterContainer[number] };
export interface FilterValueProvider {
value: FilterContainer;
@ -11,21 +11,24 @@ export interface FilterValueProvider {
persist: (newValue: FilterContainer) => void;
}
const toNested = (p: QueryVars, current: FilterContainer[number]): QueryVars => {
const toNested = (
p: QueryVars,
current: FilterContainer[number],
): QueryVars => {
if (typeof current !== "string") {
return { ...p, current }
return { ...p, current };
}
if (current === "AND") {
return { AND: p }
return { AND: p };
}
if (current === "OR") {
return { OR: p }
return { OR: p };
}
return p
}
return p;
};
export const createVariables = (filter: FilterContainer) =>
filter.reduceRight(toNested, {} as QueryVars)
filter.reduceRight(toNested, {} as QueryVars);

View file

@ -8,7 +8,7 @@ export interface FetchingParams {
attribute: Record<string, string[]>;
}
type FetchingParamsKeys = keyof Omit<FetchingParams, "attribute">
type FetchingParamsKeys = keyof Omit<FetchingParams, "attribute">;
export const emptyFetchingParams: FetchingParams = {
category: [],
@ -21,10 +21,10 @@ export const emptyFetchingParams: FetchingParams = {
const unique = <T>(array: Iterable<T>) => Array.from(new Set(array));
export const toFetchingParams = (p: FetchingParams, c: UrlToken) => {
const key = c.name as FetchingParamsKeys
const key = c.name as FetchingParamsKeys;
if (!c.isAttribute() && !p[key]) {
p[key] = []
p[key] = [];
}
if (c.isAttribute() && !p.attribute[c.name]) {

View file

@ -35,9 +35,7 @@ const mapToTokens = (urlEntries: Array<ParsedQs | string>): TokenArray =>
return mapToTokens(entry);
}
return UrlToken.fromUrlEntry(
UrlEntry.fromQs(entry)
);
return UrlToken.fromUrlEntry(UrlEntry.fromQs(entry));
}) as TokenArray;
const tokenizeUrl = (urlParams: string) => {

View file

@ -9,11 +9,10 @@ const STATIC_TO_LOAD = ["category", "collection", "channel", "producttype"];
export const TokenType = {
ATTRIBUTE: "a",
STATIC: "s"
} as const
export type TokenTypeValue = (typeof TokenType)[keyof typeof TokenType]
STATIC: "s",
} as const;
export type TokenTypeValue = (typeof TokenType)[keyof typeof TokenType];
export class UrlEntry {
constructor(key: string, value: string | string[]) {
@ -21,49 +20,54 @@ export class UrlEntry {
}
public static fromQs(entry: ParsedQs) {
const key = Object.keys(entry)[0]
const value = entry[key] as string | string[]
const key = Object.keys(entry)[0];
const value = entry[key] as string | string[];
return new UrlEntry(key, value)
return new UrlEntry(key, value);
}
public static forAttribute (condition: ConditionSelected, paramName: string) {
return UrlEntry.fromConditionSelected(condition, paramName, TokenType.ATTRIBUTE)
public static forAttribute(condition: ConditionSelected, paramName: string) {
return UrlEntry.fromConditionSelected(
condition,
paramName,
TokenType.ATTRIBUTE,
);
}
public static forStatic (condition: ConditionSelected, paramName: string) {
return UrlEntry.fromConditionSelected(condition, paramName, TokenType.STATIC)
public static forStatic(condition: ConditionSelected, paramName: string) {
return UrlEntry.fromConditionSelected(
condition,
paramName,
TokenType.STATIC,
);
}
public getInfo () {
const [key, value] = Object.entries(this)[0] as [
string,
string | string[],
];
public getInfo() {
const [key, value] = Object.entries(this)[0] as [string, string | string[]];
const [identifier, entryName] = key.split(".");
const [type, control] = identifier.split("") as [TokenTypeValue, number];
const conditionKid = CONDITIONS[control]
const conditionKid = CONDITIONS[control];
return { key, value, entryName, type, conditionKid }
return { key, value, entryName, type, conditionKid };
}
private static fromConditionSelected (
private static fromConditionSelected(
condition: ConditionSelected,
paramName: string,
tokenSlug: TokenTypeValue
tokenSlug: TokenTypeValue,
) {
const { conditionValue } = condition;
const slug = slugFromConditionValue(condition.value)
const slug = slugFromConditionValue(condition.value);
if (!conditionValue) {
return new UrlEntry(tokenSlug, slug)
return new UrlEntry(tokenSlug, slug);
}
const conditionIndex = CONDITIONS.findIndex(
el => el === conditionValue.label,
);
return new UrlEntry(`${tokenSlug}${conditionIndex}.${paramName}`, slug)
return new UrlEntry(`${tokenSlug}${conditionIndex}.${paramName}`, slug);
}
}
@ -76,12 +80,7 @@ export class UrlToken {
) {}
public static fromUrlEntry(entry: UrlEntry) {
const {
entryName,
value,
type,
conditionKid
} = entry.getInfo()
const { entryName, value, type, conditionKid } = entry.getInfo();
return new UrlToken(entryName, value, type, conditionKid);
}

View file

@ -3,11 +3,11 @@ import useRouter from "use-react-router";
import { useInitialAPIState } from "../API/initialState/useInitalAPIState";
import { FilterContainer } from "../FilterElement";
import { createVariables,FilterValueProvider } from "../FilterValueProvider";
import { createVariables, FilterValueProvider } from "../FilterValueProvider";
import { useTokenArray } from "./TokenArray";
import { UrlEntry } from "./UrlToken";
type Structure = Array<string | UrlEntry | Structure>
type Structure = Array<string | UrlEntry | Structure>;
const prepareStructure = (filterValue: FilterContainer): Structure =>
filterValue.map(f => {

View file

@ -1,29 +1,34 @@
import { useState } from "react";
import { FilterContainer,FilterElement } from "./FilterElement";
import { FilterContainer, FilterElement } from "./FilterElement";
type StateCallback = (el: FilterElement) => void
type Element = FilterContainer[number]
type StateCallback = (el: FilterElement) => void;
type Element = FilterContainer[number];
export const useContainerState = (initialValue: FilterContainer) => {
const [value, setValue] = useState(initialValue);
const isFilterElement = (elIndex: number, index: number, el: Element): el is FilterElement => {
return elIndex === index && typeof el !== "string" && !Array.isArray(el)
}
const isFilterElement = (
elIndex: number,
index: number,
el: Element,
): el is FilterElement => {
return elIndex === index && typeof el !== "string" && !Array.isArray(el);
};
const updateFilterElement = (index: number, cb: StateCallback) => (el: Element, elIndex: number) => {
if (isFilterElement(elIndex, index, el)) {
cb(el);
}
const updateFilterElement =
(index: number, cb: StateCallback) => (el: Element, elIndex: number) => {
if (isFilterElement(elIndex, index, el)) {
cb(el);
}
return el;
}
return el;
};
const updateAt = (position: string, cb: StateCallback) => {
const index = parseInt(position, 10);
setValue(v => v.map(updateFilterElement(index, cb)));
}
};
const removeAt = (position: string) => {
const index = parseInt(position, 10);
@ -50,11 +55,10 @@ export const useContainerState = (initialValue: FilterContainer) => {
setValue(v => v.concat(newValue));
};
return {
createEmpty,
updateAt,
removeAt,
value,
}
}
};
};

View file

@ -19,15 +19,8 @@ interface ExternalLinkProps extends React.HTMLProps<HTMLAnchorElement> {
}
const ExternalLink: React.FC<ExternalLinkProps> = props => {
const {
className,
children,
href,
typographyProps,
target,
rel,
...rest
} = props;
const { className, children, href, typographyProps, target, rel, ...rest } =
props;
const classes = useStyles(props);

View file

@ -16,9 +16,8 @@ const useStyles = makeStyles(
{ name: "FilterGroupLabel" },
);
export type FilterGroupLabelProps<
K extends string = string,
> = FilterFieldBaseProps<K>;
export type FilterGroupLabelProps<K extends string = string> =
FilterFieldBaseProps<K>;
const FilterGroupLabel: React.FC<FilterGroupLabelProps> = ({
filter,

View file

@ -45,11 +45,10 @@ export type FilterElementValueData =
export type IFilterElementMutableData = FilterElementCommonData &
FilterElementValueData;
export type IFilterElementMutableDataGeneric<
T extends FieldType,
> = T extends FieldType.keyValue
? KeyValueFilterElementData & FilterElementCommonData
: RegularFilterElementData & FilterElementCommonData;
export type IFilterElementMutableDataGeneric<T extends FieldType> =
T extends FieldType.keyValue
? KeyValueFilterElementData & FilterElementCommonData
: RegularFilterElementData & FilterElementCommonData;
type FilterElementCommon<K extends string = string> = {
autocomplete?: boolean;
@ -68,13 +67,11 @@ type FilterElementCommon<K extends string = string> = {
export type FilterElement<K extends string = string> = FilterElementCommon<K> &
Partial<UnknownFilterElementData>;
export type FilterElementRegular<
K extends string = string,
> = FilterElementCommon<K> & RegularFilterElementData;
export type FilterElementRegular<K extends string = string> =
FilterElementCommon<K> & RegularFilterElementData;
export type FilterElementKeyValue<
K extends string = string,
> = FilterElementCommon<K> & KeyValueFilterElementData;
export type FilterElementKeyValue<K extends string = string> =
FilterElementCommon<K> & KeyValueFilterElementData;
export type FilterElementGeneric<
K extends string,

View file

@ -20,7 +20,10 @@ export interface MetadataFormData {
privateMetadata: MetadataInput[];
}
export type MetadataIdSchema = Record<string, {
export type MetadataIdSchema = Record<
string,
{
metadata: MetadataInput[];
privateMetadata: MetadataInput[];
}>;
}
>;

View file

@ -92,10 +92,9 @@ const Navigator: React.FC<NavigatorProps> = ({ visible, setVisibility }) => {
description: "navigator notification",
},
{
keyboardShortcut:
navigator.platform.toLowerCase().includes("mac")
? "⌘+K"
: "Ctrl+K",
keyboardShortcut: navigator.platform.toLowerCase().includes("mac")
? "⌘+K"
: "Ctrl+K",
},
),
title: intl.formatMessage({

View file

@ -8,9 +8,10 @@ import { findPriceSeparator, getCurrencyDecimalPoints } from "./utils";
export function usePriceField(currency: string, onChange: FormChange) {
const minValue = 0;
const maxDecimalLength = useMemo(() => getCurrencyDecimalPoints(currency), [
currency,
]);
const maxDecimalLength = useMemo(
() => getCurrencyDecimalPoints(currency),
[currency],
);
const handleChange: FormChange = e => {
let value = e.target.value;

View file

@ -48,14 +48,8 @@ export interface SortableChipsFieldProps extends SortableContainerProps {
}
const SortableChipsField: React.FC<SortableChipsFieldProps> = props => {
const {
loading,
values,
error,
helperText,
onValueDelete,
onValueReorder,
} = props;
const { loading, values, error, helperText, onValueDelete, onValueReorder } =
props;
const classes = useStyles(props);
const handleSortStart = () => {

View file

@ -12,12 +12,9 @@ interface DeleteWarningDialogConsentContentProps {
onConsentChange: (value: boolean) => void;
}
const DeleteWarningDialogConsentContent: React.FC<DeleteWarningDialogConsentContentProps> = ({
description,
consentLabel,
isConsentChecked,
onConsentChange,
}) => {
const DeleteWarningDialogConsentContent: React.FC<
DeleteWarningDialogConsentContentProps
> = ({ description, consentLabel, isConsentChecked, onConsentChange }) => {
const classes = useStyles();
const handleConsentChange = ({ target }: ChangeEvent<any>) =>

View file

@ -51,10 +51,8 @@ export const customerAddUrl = customerAddPath;
export const customerAddressesPath = (id: string) =>
urlJoin(customerPath(id), "addresses");
export type CustomerAddressesUrlDialog = "add" | "edit" | "remove";
export type CustomerAddressesUrlQueryParams = Dialog<
CustomerAddressesUrlDialog
> &
SingleAction;
export type CustomerAddressesUrlQueryParams =
Dialog<CustomerAddressesUrlDialog> & SingleAction;
export const customerAddressesUrl = (
id: string,
params?: CustomerAddressesUrlQueryParams,

View file

@ -23,13 +23,12 @@ const getChannelMinAmountSpent = (
return channel.minSpent;
};
const mapChannelToChannelInput = (formData: VoucherDetailsPageFormData) => (
channel: ChannelVoucherData,
) => ({
channelId: channel.id,
discountValue: getChannelDiscountValue(channel, formData),
minAmountSpent: getChannelMinAmountSpent(channel, formData),
});
const mapChannelToChannelInput =
(formData: VoucherDetailsPageFormData) => (channel: ChannelVoucherData) => ({
channelId: channel.id,
discountValue: getChannelDiscountValue(channel, formData),
minAmountSpent: getChannelMinAmountSpent(channel, formData),
});
const filterNotDiscountedChannel = (
channelInput: VoucherChannelListingAddInput,

View file

@ -12,10 +12,9 @@ type GiftCardCreateRequiresActivationSectionProps = Pick<
"checked" | "onChange"
>;
const GiftCardCreateRequiresActivationSection: React.FC<GiftCardCreateRequiresActivationSectionProps> = ({
checked,
onChange,
}) => (
const GiftCardCreateRequiresActivationSection: React.FC<
GiftCardCreateRequiresActivationSectionProps
> = ({ checked, onChange }) => (
<ControlledCheckbox
name="requiresActivation"
label={

View file

@ -48,32 +48,30 @@ const useGiftCardActivateToggle = ({
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
});
const [
giftCardDeactivate,
giftCardDeactivateOpts,
] = useGiftCardDeactivateMutation({
onCompleted: data => {
const errors = data?.giftCardDeactivate?.errors;
const [giftCardDeactivate, giftCardDeactivateOpts] =
useGiftCardDeactivateMutation({
onCompleted: data => {
const errors = data?.giftCardDeactivate?.errors;
if (!!errors?.length) {
notify({
status: "error",
text: intl.formatMessage(commonErrorMessages.unknownError),
});
return;
}
if (!!errors?.length) {
notify({
status: "error",
text: intl.formatMessage(commonErrorMessages.unknownError),
status: "success",
text: intl.formatMessage(messages.successfullyDisabledTitle),
});
return;
}
notify({
status: "success",
text: intl.formatMessage(messages.successfullyDisabledTitle),
});
if (!!onDeactivateActionComplete) {
onDeactivateActionComplete();
}
},
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
});
if (!!onDeactivateActionComplete) {
onDeactivateActionComplete();
}
},
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
});
const currentOpts = isActive ? giftCardDeactivateOpts : giftCardActivateOpts;

View file

@ -6,8 +6,7 @@ export enum GiftCardUpdatePageActionParamsEnum {
RESEND_CODE = "resend-code",
}
export type GiftCardUpdatePageUrlQueryParams = Dialog<
GiftCardUpdatePageActionParamsEnum
>;
export type GiftCardUpdatePageUrlQueryParams =
Dialog<GiftCardUpdatePageActionParamsEnum>;
export const PLACEHOLDER = "-";

View file

@ -13,10 +13,9 @@ interface GiftCardsListHeaderAlertContentProps {
giftCardProductsExist: boolean;
}
const GiftCardsListHeaderAlertContent: React.FC<GiftCardsListHeaderAlertContentProps> = ({
giftCardProductTypesExist,
giftCardProductsExist,
}) => {
const GiftCardsListHeaderAlertContent: React.FC<
GiftCardsListHeaderAlertContentProps
> = ({ giftCardProductTypesExist, giftCardProductsExist }) => {
const classes = useStyles({});
const giftCardProductTypeUrl = productTypeAddUrl({

View file

@ -18,9 +18,9 @@ interface CustomerGiftCardsCardListItemProps {
giftCard: ExtendedGiftCard<CustomerGiftCardFragment>;
}
const CustomerGiftCardsCardListItem: React.FC<CustomerGiftCardsCardListItemProps> = ({
giftCard,
}) => {
const CustomerGiftCardsCardListItem: React.FC<
CustomerGiftCardsCardListItemProps
> = ({ giftCard }) => {
const intl = useIntl();
const classes = useListWrapperStyles();
const [openDeleteGiftCard, setOpenDeleteGiftCard] = useState(false);

View file

@ -33,13 +33,11 @@ const GiftCardDeleteDialog: React.FC<GiftCardDeleteDialogProps> = ({
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
});
const {
onBulkDeleteGiftCards,
bulkDeleteGiftCardOpts,
} = useGiftCardBulkDelete({
onClose,
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
});
const { onBulkDeleteGiftCards, bulkDeleteGiftCardOpts } =
useGiftCardBulkDelete({
onClose,
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
});
const dialogProps: Pick<
ActionDialogProps,

View file

@ -1,6 +1,6 @@
import { PermissionEnum } from "./types.generated";
export interface Node {
id: string
id: string;
}
export type PrefixedPermissions = `PERMISSION_${PermissionEnum}`;

View file

@ -3,7 +3,7 @@ import { FetchMoreProps, Search, SearchProps } from "@dashboard/types";
import { filter } from "fuzzaldrin";
import React from "react";
export const useChannelsSearch = function<T extends { name: string }>(
export const useChannelsSearch = function <T extends { name: string }>(
channels: T[],
) {
const [query, onQueryChange] = React.useState("");

View file

@ -6,11 +6,11 @@ export const useServiceWorker = (timeout: number) => {
const registrationRef = useRef<ServiceWorkerRegistration>();
useEffect(() => {
const interval = (setInterval(() => {
const interval = setInterval(() => {
if (registrationRef.current) {
registrationRef.current.update();
}
}, timeout) as unknown) as number;
}, timeout) as unknown as number;
return () => clearInterval(interval);
}, [timeout]);

View file

@ -9,9 +9,12 @@
<meta name="robots" content="noindex" />
<title>Sign in to the Saleor Dashboard</title>
<meta name="description" content="Sign in to the Saleor Dashboard to manage your orders, payments, products and more.">
<meta
name="description"
content="Sign in to the Saleor Dashboard to manage your orders, payments, products and more."
/>
<%- injectOgTags %>
<%- injectOgTags %>
<script>
window.__SALEOR_CONFIG__ = {

View file

@ -213,4 +213,4 @@ export const OrderChangeWarehouseDialog: React.FC<
);
};
OrderChangeWarehouseDialog.displayName = "OrderChangeWarehouseDialog";
export default OrderChangeWarehouseDialog;
export default OrderChangeWarehouseDialog;

View file

@ -11,9 +11,9 @@ export interface OrderChannelSectionCardProps {
channel?: Pick<ChannelFragment, "id" | "name">;
}
export const OrderChannelSectionCard: React.FC<OrderChannelSectionCardProps> = ({
channel,
}) => {
export const OrderChannelSectionCard: React.FC<
OrderChannelSectionCardProps
> = ({ channel }) => {
const intl = useIntl();
return (

View file

@ -11,9 +11,8 @@ export interface OrderCustomerChangeData {
changeActionOption: CustomerChangeActionEnum;
}
type UseOrderCustomerChangeFormResult = CommonUseFormResult<
OrderCustomerChangeData
>;
type UseOrderCustomerChangeFormResult =
CommonUseFormResult<OrderCustomerChangeData>;
export interface OrderCustomerChangeFormProps {
children: (props: UseOrderCustomerChangeFormResult) => React.ReactNode;

View file

@ -82,7 +82,10 @@ export interface OrderDetailsPageProps {
onInvoiceClick: (invoiceId: string) => any;
onInvoiceGenerate: () => any;
onInvoiceSend: (invoiceId: string) => any;
onTransactionAction: (transactionId: string, actionType: TransactionActionEnum) => any;
onTransactionAction: (
transactionId: string,
actionType: TransactionActionEnum,
) => any;
onAddManualTransaction: () => any;
onSubmit: (data: MetadataIdSchema) => SubmitPromise;
}

View file

@ -137,7 +137,7 @@ export const OrderDraftDetailsDatagrid = ({
rowMarkers="none"
columnSelect="none"
freezeColumns={2}
verticalBorder={col => (col > 1)}
verticalBorder={col => col > 1}
availableColumns={columns}
emptyText={intl.formatMessage(messages.emptyText)}
getCellContent={getCellContent}

View file

@ -14,7 +14,10 @@ import { OrderTransactionsWrapper } from "./OrderTransactionsWrapper";
export interface OrderPaymentOrTransactionProps {
order: OrderDetailsFragment;
shop: OrderDetailsQuery["shop"];
onTransactionAction: (transactionId: string, actionType: TransactionActionEnum) => any;
onTransactionAction: (
transactionId: string,
actionType: TransactionActionEnum,
) => any;
onPaymentCapture: () => any;
onPaymentVoid: () => any;
onPaymentRefund: () => any;

View file

@ -20,7 +20,10 @@ import { getFilteredPayments } from "./utils";
interface OrderTransactionsWrapper {
order: OrderDetailsFragment;
shop: OrderDetailsQuery["shop"];
onTransactionAction: (transactionId: string, actionType: TransactionActionEnum) => any;
onTransactionAction: (
transactionId: string,
actionType: TransactionActionEnum,
) => any;
onPaymentCapture: () => any;
onMarkAsPaid: () => any;
onPaymentVoid: () => any;

View file

@ -16,9 +16,8 @@ export interface OrderSettingsFormData {
automaticallyFulfillNonShippableGiftCard: boolean;
}
export type UseOrderSettingsFormResult = CommonUseFormResult<
OrderSettingsFormData
>;
export type UseOrderSettingsFormResult =
CommonUseFormResult<OrderSettingsFormData>;
export interface OrderSettingsFormProps {
children: (props: UseOrderSettingsFormResult) => React.ReactNode;
orderSettings: OrderSettingsFragment;

View file

@ -20,16 +20,10 @@ export function getFilterVariables(
};
}
export const {
deleteFilterTab,
getFilterTabs,
saveFilterTab,
} = createFilterTabUtils<PageTypeListUrlFilters>(PAGE_TYPE_FILTERS_KEY);
export const { deleteFilterTab, getFilterTabs, saveFilterTab } =
createFilterTabUtils<PageTypeListUrlFilters>(PAGE_TYPE_FILTERS_KEY);
export const {
areFiltersApplied,
getActiveFilters,
getFiltersCurrentTab,
} = createFilterUtils<PageTypeListUrlQueryParams, PageTypeListUrlFilters>(
PageTypeListUrlFiltersEnum,
);
export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } =
createFilterUtils<PageTypeListUrlQueryParams, PageTypeListUrlFilters>(
PageTypeListUrlFiltersEnum,
);

View file

@ -18,12 +18,11 @@ export enum PermissionGroupListUrlSortField {
name = "name",
}
export type PermissionGroupListUrlSort = Sort<PermissionGroupListUrlSortField>;
export type PermissionGroupListUrlQueryParams = Dialog<
PermissionGroupListUrlDialog
> &
Pagination &
PermissionGroupListUrlSort &
SingleAction;
export type PermissionGroupListUrlQueryParams =
Dialog<PermissionGroupListUrlDialog> &
Pagination &
PermissionGroupListUrlSort &
SingleAction;
export const permissionGroupListUrl = (
params?: PermissionGroupListUrlQueryParams,
) => permissionGroupListPath + "?" + stringifyQs(params);

View file

@ -8,7 +8,9 @@ import PluginDetailsChannelsCardContent, {
PluginDetailsChannelsCardProps,
} from "./PluginDetailsChannelsCardContent";
const PluginDetailsChannelsCard: React.FC<PluginDetailsChannelsCardProps> = props => {
const PluginDetailsChannelsCard: React.FC<
PluginDetailsChannelsCardProps
> = props => {
const intl = useIntl();
return (

View file

@ -10,9 +10,9 @@ interface PluginChannelAvailabilityCellProps {
plugin: PluginBaseFragment;
}
const PluginChannelAvailabilityCell: React.FC<PluginChannelAvailabilityCellProps> = ({
plugin,
}) => {
const PluginChannelAvailabilityCell: React.FC<
PluginChannelAvailabilityCellProps
> = ({ plugin }) => {
const [isPopupOpen, setIsPopupOpen] = useState(false);
const popupAnchor = useRef<HTMLTableCellElement>(null);

View file

@ -34,14 +34,8 @@ export interface PluginListProps
const totalColSpan = 10;
const PluginList: React.FC<PluginListProps> = props => {
const {
settings,
plugins,
disabled,
sort,
onSort,
onUpdateListSettings,
} = props;
const { settings, plugins, disabled, sort, onSort, onUpdateListSettings } =
props;
const classes = useStyles(props);
const navigate = useNavigator();
const intl = useIntl();

View file

@ -4,8 +4,7 @@ export const isPluginGlobal = (
globalConfiguration: PluginConfigurationBaseFragment,
) => !!globalConfiguration;
export const getConfigByChannelId = (channelIdToCompare: string) => ({
channel,
}: {
channel: { id: string };
}) => channel.id === channelIdToCompare;
export const getConfigByChannelId =
(channelIdToCompare: string) =>
({ channel }: { channel: { id: string } }) =>
channel.id === channelIdToCompare;

View file

@ -1,14 +1,13 @@
import { ProductTypeKindEnum, TaxClassBaseFragment } from "@dashboard/graphql";
import { ChangeEvent, FormChange } from "@dashboard/hooks/useForm";
export const makeProductTypeKindChangeHandler = (
onChange: FormChange,
onKindChange: (kind: ProductTypeKindEnum) => void,
) => (event: React.ChangeEvent<any>) => {
const kind = event.target.value as ProductTypeKindEnum;
onKindChange(kind);
onChange(event);
};
export const makeProductTypeKindChangeHandler =
(onChange: FormChange, onKindChange: (kind: ProductTypeKindEnum) => void) =>
(event: React.ChangeEvent<any>) => {
const kind = event.target.value as ProductTypeKindEnum;
onKindChange(kind);
onChange(event);
};
export function handleTaxClassChange(
event: ChangeEvent,

View file

@ -225,7 +225,7 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
attributeRichTextGetters,
}) => {
// Comparing explicitly to false because `hasVariants` can be undefined
const isSimpleProduct = !(data.productType?.hasVariants);
const isSimpleProduct = !data.productType?.hasVariants;
const errors = [...apiErrors, ...validationErrors];

View file

@ -62,26 +62,25 @@ const ExportDialogSettings: React.FC<ExportDialogSettingsProps> = ({
const formErrors = getFormErrors(formFields, errors);
const productExportTypeChoices: Array<RadioGroupFieldChoice<
FileTypesEnum
>> = [
{
label: intl.formatMessage({
id: "9Tl/bT",
defaultMessage: "Spreadsheet for Excel, Numbers etc.",
description: "export items as spreadsheet",
}),
value: FileTypesEnum.XLSX,
},
{
label: intl.formatMessage({
id: "li1BBk",
defaultMessage: "Plain CSV file",
description: "export items as csv file",
}),
value: FileTypesEnum.CSV,
},
];
const productExportTypeChoices: Array<RadioGroupFieldChoice<FileTypesEnum>> =
[
{
label: intl.formatMessage({
id: "9Tl/bT",
defaultMessage: "Spreadsheet for Excel, Numbers etc.",
description: "export items as spreadsheet",
}),
value: FileTypesEnum.XLSX,
},
{
label: intl.formatMessage({
id: "li1BBk",
defaultMessage: "Plain CSV file",
description: "export items as csv file",
}),
value: FileTypesEnum.CSV,
},
];
const exportScopeChoices = [
{

View file

@ -11,10 +11,9 @@ interface VariantDetailsChannelsAvailabilityCardContainerProps {
cardTitle?: React.ReactNode;
}
const VariantDetailsChannelsAvailabilityCardContainer: React.FC<VariantDetailsChannelsAvailabilityCardContainerProps> = ({
children,
cardTitle,
}) => (
const VariantDetailsChannelsAvailabilityCardContainer: React.FC<
VariantDetailsChannelsAvailabilityCardContainerProps
> = ({ children, cardTitle }) => (
<>
<Card>
{cardTitle || (

View file

@ -19,7 +19,9 @@ interface ProductVariantCheckoutSettingsProps {
onChange: FormChange;
}
const ProductVariantCheckoutSettings: React.FC<ProductVariantCheckoutSettingsProps> = props => {
const ProductVariantCheckoutSettings: React.FC<
ProductVariantCheckoutSettingsProps
> = props => {
const { data, disabled, errors, onChange } = props;
const intl = useIntl();

View file

@ -82,8 +82,9 @@ const ProductVariantMediaSelectDialog: React.FC<
className={clsx([
classes.imageContainer,
{
[classes.selectedImageContainer]:
selectedMedia.includes(mediaObj.id),
[classes.selectedImageContainer]: selectedMedia.includes(
mediaObj.id,
),
},
])}
onClick={() => handleMediaSelect(mediaObj.id)}

View file

@ -33,7 +33,9 @@ export interface ShippingZoneSettingsCardProps {
loading: boolean;
}
export const ShippingZoneSettingsCard: React.FC<ShippingZoneSettingsCardProps> = ({
export const ShippingZoneSettingsCard: React.FC<
ShippingZoneSettingsCardProps
> = ({
formData,
warehousesDisplayValues,
hasMoreWarehouses,

View file

@ -31,9 +31,9 @@ const ShippingZonesList: React.FC<RouteComponentProps<{}>> = ({ location }) => {
interface ShippingZoneDetailsRouteProps {
id: string;
}
const ShippingZoneDetails: React.FC<RouteComponentProps<
ShippingZoneDetailsRouteProps
>> = ({ location, match }) => {
const ShippingZoneDetails: React.FC<
RouteComponentProps<ShippingZoneDetailsRouteProps>
> = ({ location, match }) => {
const qs = parseQs(location.search.substr(1));
const params: ShippingZoneUrlQueryParams = qs;
return (
@ -58,10 +58,12 @@ const RateCreate: React.FC<RouteComponentProps<{ id: string }>> = ({
);
};
const RateUpdate: React.FC<RouteComponentProps<{
id: string;
rateId: string;
}>> = ({ match }) => {
const RateUpdate: React.FC<
RouteComponentProps<{
id: string;
rateId: string;
}>
> = ({ match }) => {
const qs = parseQs(location.search.substr(1));
const params: ShippingRateUrlQueryParams = qs;

View file

@ -51,13 +51,12 @@ export type ShippingRateUrlQueryParams = Dialog<ShippingRateUrlDialog> &
SingleAction &
BulkAction;
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions | ChannelsAction;
export type ShippingRateCreateUrlQueryParams = Dialog<
ShippingRateCreateUrlDialog
> &
SingleAction &
Partial<{
type: ShippingMethodTypeEnum;
}>;
export type ShippingRateCreateUrlQueryParams =
Dialog<ShippingRateCreateUrlDialog> &
SingleAction &
Partial<{
type: ShippingMethodTypeEnum;
}>;
export const shippingRateCreatePath = (id: string) =>
urlJoin(shippingZonePath(id), "add");

View file

@ -39,9 +39,8 @@ export type StaffMemberDetailsUrlDialog =
| "change-password"
| "remove"
| "remove-avatar";
export type StaffMemberDetailsUrlQueryParams = Dialog<
StaffMemberDetailsUrlDialog
>;
export type StaffMemberDetailsUrlQueryParams =
Dialog<StaffMemberDetailsUrlDialog>;
export const staffMemberDetailsUrl = (
id: string,

View file

@ -231,12 +231,12 @@ const TranslationFields: React.FC<TranslationFieldsProps> = props => {
onDiscard={onDiscard}
onSubmit={data => onSubmit(field, data)}
/>
) // FIXME
) : // FIXME
// For now this is the only way to fix the issue
// of initializing the editor with fetched data.
// Without this the editor doesn't get the saved data
// and is empty
: disabled ? (
disabled ? (
<Skeleton />
) : (
<TranslationFieldsRich

View file

@ -10,16 +10,11 @@ export function useRichTextSubmit(
) {
const { setIsDirty, setExitDialogSubmitRef } = useExitFormDialog();
const {
defaultValue,
editorRef,
isReadyForMount,
handleChange,
getValue,
} = useRichText({
initial,
triggerChange: () => setIsDirty(true),
});
const { defaultValue, editorRef, isReadyForMount, handleChange, getValue } =
useRichText({
initial,
triggerChange: () => setIsDirty(true),
});
const handleSubmit = React.useCallback(async () => {
const result = onSubmit(await getValue());
@ -34,10 +29,10 @@ export function useRichTextSubmit(
return errors;
}, [getValue, onSubmit, setIsDirty]);
React.useEffect(() => setExitDialogSubmitRef(handleSubmit), [
handleSubmit,
setExitDialogSubmitRef,
]);
React.useEffect(
() => setExitDialogSubmitRef(handleSubmit),
[handleSubmit, setExitDialogSubmitRef],
);
return {
defaultValue,

View file

@ -25,7 +25,7 @@ describe("Multiple file upload handler", () => {
return promise;
}, cbs);
handle((testFiles as unknown) as FileList).then(() => {
handle(testFiles as unknown as FileList).then(() => {
expect(cbs.onAfterUpload).toBeCalledTimes(testFiles.length);
expect(cbs.onBeforeUpload).toBeCalledTimes(testFiles.length);
expect(cbs.onCompleted).toBeCalledTimes(1);
@ -56,7 +56,7 @@ describe("Multiple file upload handler", () => {
return promise;
}, cbs);
handle((testFiles as unknown) as FileList).then(() => {
handle(testFiles as unknown as FileList).then(() => {
expect(cbs.onAfterUpload).toBeCalledTimes(testFiles.length - 1);
expect(cbs.onBeforeUpload).toBeCalledTimes(testFiles.length);
expect(cbs.onCompleted).toBeCalledTimes(1);

View file

@ -3,20 +3,18 @@ import { useState } from "react";
function useMetadataChangeTrigger() {
const [isMetadataModified, setMetadataModified] = useState(false);
const [isPrivateMetadataModified, setPrivateMetadataModified] = useState(
false,
);
const [isPrivateMetadataModified, setPrivateMetadataModified] =
useState(false);
const makeChangeHandler: (
onChange: FormChange,
) => FormChange = onChange => event => {
if (event.target.name === "metadata") {
setMetadataModified(true);
} else {
setPrivateMetadataModified(true);
}
onChange(event);
};
const makeChangeHandler: (onChange: FormChange) => FormChange =
onChange => event => {
if (event.target.name === "metadata") {
setMetadataModified(true);
} else {
setPrivateMetadataModified(true);
}
onChange(event);
};
const resetMetadataChanged = () => {
setMetadataModified(false);

View file

@ -20,16 +20,10 @@ export function getFilterVariables(
};
}
export const {
deleteFilterTab,
getFilterTabs,
saveFilterTab,
} = createFilterTabUtils<WarehouseListUrlFilters>(WAREHOUSE_FILTERS_KEY);
export const { deleteFilterTab, getFilterTabs, saveFilterTab } =
createFilterTabUtils<WarehouseListUrlFilters>(WAREHOUSE_FILTERS_KEY);
export const {
areFiltersApplied,
getActiveFilters,
getFiltersCurrentTab,
} = createFilterUtils<WarehouseListUrlQueryParams, WarehouseListUrlFilters>(
WarehouseListUrlFiltersEnum,
);
export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } =
createFilterUtils<WarehouseListUrlQueryParams, WarehouseListUrlFilters>(
WarehouseListUrlFiltersEnum,
);