Add prettier command and run it inside src folder (#3892)
This commit is contained in:
parent
de098fd520
commit
03d9e92c97
68 changed files with 342 additions and 350 deletions
5
.changeset/flat-roses-live.md
Normal file
5
.changeset/flat-roses-live.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"saleor-dashboard": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Run prettier against source folder
|
|
@ -330,7 +330,8 @@
|
||||||
"dep-status": "depcruise --config .dependency-cruiser.js src",
|
"dep-status": "depcruise --config .dependency-cruiser.js src",
|
||||||
"chromatic": "chromatic --exit-zero-on-changes",
|
"chromatic": "chromatic --exit-zero-on-changes",
|
||||||
"change:add": "changeset add",
|
"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": ""
|
"description": ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@ export interface ResetPasswordSuccessPageProps {
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ResetPasswordSuccessPage: React.FC<ResetPasswordSuccessPageProps> = props => {
|
const ResetPasswordSuccessPage: React.FC<
|
||||||
|
ResetPasswordSuccessPageProps
|
||||||
|
> = props => {
|
||||||
const { onBack } = props;
|
const { onBack } = props;
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
|
@ -26,7 +26,8 @@ export const UserContextError = {
|
||||||
unknownLoginError: "unknownLoginError",
|
unknownLoginError: "unknownLoginError",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type UserContextError = typeof UserContextError[keyof typeof UserContextError];
|
export type UserContextError =
|
||||||
|
(typeof UserContextError)[keyof typeof UserContextError];
|
||||||
|
|
||||||
export interface UserContext {
|
export interface UserContext {
|
||||||
login: (username: string, password: string) => Promise<LoginData>;
|
login: (username: string, password: string) => Promise<LoginData>;
|
||||||
|
|
|
@ -307,7 +307,7 @@ export const createChannelsDataFromProduct = (productData?: ProductFragment) =>
|
||||||
listing => listing.channel.id === channel.id,
|
listing => listing.channel.id === channel.id,
|
||||||
);
|
);
|
||||||
// Comparing explicitly to false because `hasVariants` can be undefined
|
// 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 =>
|
const haveVariantsChannelListings = productData.variants.some(variant =>
|
||||||
variant.channelListings.some(
|
variant.channelListings.some(
|
||||||
listing => listing.channel.id === channel.id,
|
listing => listing.channel.id === channel.id,
|
||||||
|
|
|
@ -2,10 +2,12 @@ import { AddressTypeInput } from "@dashboard/customers/types";
|
||||||
import { FormChange } from "@dashboard/hooks/useForm";
|
import { FormChange } from "@dashboard/hooks/useForm";
|
||||||
import { ChangeEvent } from "react";
|
import { ChangeEvent } from "react";
|
||||||
|
|
||||||
export const createCountryHandler = (
|
export const createCountryHandler =
|
||||||
currentHandler: FormChange,
|
(
|
||||||
set: (dataSet: Partial<AddressTypeInput>) => void,
|
currentHandler: FormChange,
|
||||||
) => (event: ChangeEvent<any>) => {
|
set: (dataSet: Partial<AddressTypeInput>) => void,
|
||||||
currentHandler(event);
|
) =>
|
||||||
set({ countryArea: "" });
|
(event: ChangeEvent<any>) => {
|
||||||
};
|
currentHandler(event);
|
||||||
|
set({ countryArea: "" });
|
||||||
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const Backlink = ({
|
||||||
return (
|
return (
|
||||||
<MacawBacklink<LinkType>
|
<MacawBacklink<LinkType>
|
||||||
{...props}
|
{...props}
|
||||||
component={(Link as unknown) as LinkType}
|
component={Link as unknown as LinkType}
|
||||||
to={href}
|
to={href}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,7 +19,9 @@ export interface ChannelsAvailabilityContentProps {
|
||||||
toggleAll?: (items: Channel[], selected: number) => void;
|
toggleAll?: (items: Channel[], selected: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChannelsAvailabilityContent: React.FC<ChannelsAvailabilityContentProps> = ({
|
export const ChannelsAvailabilityContent: React.FC<
|
||||||
|
ChannelsAvailabilityContentProps
|
||||||
|
> = ({
|
||||||
isSelected,
|
isSelected,
|
||||||
channels,
|
channels,
|
||||||
contentType = "",
|
contentType = "",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { filter } from "fuzzaldrin";
|
import { filter } from "fuzzaldrin";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export const useChannelsSearch = function<T extends { name: string }>(
|
export const useChannelsSearch = function <T extends { name: string }>(
|
||||||
channels: T[],
|
channels: T[],
|
||||||
) {
|
) {
|
||||||
const [query, onQueryChange] = React.useState("");
|
const [query, onQueryChange] = React.useState("");
|
||||||
|
|
|
@ -28,11 +28,9 @@ export interface ChannelsAvailabilityContentProps {
|
||||||
onChange: (option: Channel) => void;
|
onChange: (option: Channel) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChannelsAvailabilityContent: React.FC<ChannelsAvailabilityContentProps> = ({
|
const ChannelsAvailabilityContent: React.FC<
|
||||||
isChannelSelected,
|
ChannelsAvailabilityContentProps
|
||||||
channels,
|
> = ({ isChannelSelected, channels, onChange }) => {
|
||||||
onChange,
|
|
||||||
}) => {
|
|
||||||
const classes = useStyles({});
|
const classes = useStyles({});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -86,7 +86,9 @@ export interface ChannelsAvailabilityContentProps {
|
||||||
hasAllSelected: boolean;
|
hasAllSelected: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChannelsAvailabilityContentWrapper: React.FC<ChannelsAvailabilityContentProps> = ({
|
export const ChannelsAvailabilityContentWrapper: React.FC<
|
||||||
|
ChannelsAvailabilityContentProps
|
||||||
|
> = ({
|
||||||
contentType = "",
|
contentType = "",
|
||||||
toggleAll,
|
toggleAll,
|
||||||
toggleAllLabel,
|
toggleAllLabel,
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
<img width="977" alt="image" src="https://user-images.githubusercontent.com/41952692/233042483-d2cb30f3-26b7-40b5-9d08-2ea42f7f0242.png">
|
<img width="977" alt="image" src="https://user-images.githubusercontent.com/41952692/233042483-d2cb30f3-26b7-40b5-9d08-2ea42f7f0242.png">
|
||||||
|
|
||||||
### Column types
|
### Column types
|
||||||
|
|
||||||
In datagrid views various types of columns are available. We can split them into two groups:
|
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.
|
- 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.
|
- 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
|
column_name:column_id
|
||||||
```
|
```
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
attribute:QXR0cmlidXRlOjIx
|
attribute:QXR0cmlidXRlOjIx
|
||||||
```
|
```
|
||||||
|
|
||||||
### useColumns hook
|
### 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:
|
`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
|
- visible columns - array of visible columns for the datagrid
|
||||||
- static columns - array of static columns for the column picker
|
- static columns - array of static columns for the column picker
|
||||||
- dynamic columns - array of dynamic 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)
|
- dynamic column selection handler (for column picker)
|
||||||
|
|
||||||
In order to use this hook, you need to provide four things:
|
In order to use this hook, you need to provide four things:
|
||||||
|
|
||||||
- `staticColumns` - array of static columns in datagrid-ready format (`AvailableColumns[]`)
|
- `staticColumns` - array of static columns in datagrid-ready format (`AvailableColumns[]`)
|
||||||
- `columnCategories` - array of column categories
|
- `columnCategories` - array of column categories
|
||||||
- state & setter of column settings which we get from `useListSettings`
|
- 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
|
## Adapting new views
|
||||||
|
|
||||||
### Column picker settings
|
### 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.
|
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.
|
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 } =
|
const { columnPickerSettings, setDynamicColumnsSettings } =
|
||||||
useColumnPickerSettings("PRODUCT_LIST");
|
useColumnPickerSettings("PRODUCT_LIST");
|
||||||
|
|
||||||
// Translates columnIDs to api IDs
|
// Translates columnIDs to api IDs
|
||||||
const filteredColumnIds = columnPickerSettings
|
const filteredColumnIds = columnPickerSettings
|
||||||
.filter(isAttributeColumnValue)
|
.filter(isAttributeColumnValue)
|
||||||
.map(getAttributeIdFromColumnValue);
|
.map(getAttributeIdFromColumnValue);
|
||||||
|
|
||||||
const gridAttributes = useGridAttributesQuery({
|
const gridAttributes = useGridAttributesQuery({
|
||||||
variables: { ids: filteredColumnIds },
|
variables: { ids: filteredColumnIds },
|
||||||
skip: filteredColumnIds.length === 0,
|
skip: filteredColumnIds.length === 0,
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Static columns adapter
|
### 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[]`).
|
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:
|
For example:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export const parseStaticColumnsForProductListView = (intl, emptyColumn, sort) =>
|
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.
|
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
|
### 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
|
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 all attributes
|
||||||
- query which fetches selected 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.
|
We cannot rely on single query, because searching through attributes would influence already selected columns which are visible in the datagrid.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export const parseDynamicColumnsForProductListView = ({
|
export const parseDynamicColumnsForProductListView = ({
|
||||||
attributesData,
|
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.
|
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:
|
Queries which are used in this case are for categories. Let's look at the first query:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export const availableColumnAttribues = gql`
|
export const availableColumnAttribues = gql`
|
||||||
query AvailableColumnAttributes(
|
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.
|
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):
|
The second query is similar, but it has a filter of IDs, which come from local storage settings (useColumnPickerSettngs):
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export const gridAttributes = gql`
|
export const gridAttributes = gql`
|
||||||
query GridAttributes($ids: [ID!]!) {
|
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.
|
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:
|
Here is the adapter for the dynamic columns inside the category:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export const parseAttributesColumns = (
|
export const parseAttributesColumns = (
|
||||||
attributes: RelayToFlat<
|
attributes: RelayToFlat<
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
export { Condition } from "./Condition"
|
export { Condition } from "./Condition";
|
||||||
export { type FilterContainer,FilterElement } from "./FilterElement"
|
export { type FilterContainer, FilterElement } from "./FilterElement";
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { FilterContainer } from "./FilterElement";
|
import { FilterContainer } from "./FilterElement";
|
||||||
|
|
||||||
type QueryVars =
|
type QueryVars =
|
||||||
| { OR: QueryVars, current?: FilterContainer[number] }
|
| { OR: QueryVars; current?: FilterContainer[number] }
|
||||||
| { AND: QueryVars, current?: FilterContainer[number] }
|
| { AND: QueryVars; current?: FilterContainer[number] };
|
||||||
|
|
||||||
export interface FilterValueProvider {
|
export interface FilterValueProvider {
|
||||||
value: FilterContainer;
|
value: FilterContainer;
|
||||||
|
@ -11,21 +11,24 @@ export interface FilterValueProvider {
|
||||||
persist: (newValue: FilterContainer) => void;
|
persist: (newValue: FilterContainer) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toNested = (p: QueryVars, current: FilterContainer[number]): QueryVars => {
|
const toNested = (
|
||||||
|
p: QueryVars,
|
||||||
|
current: FilterContainer[number],
|
||||||
|
): QueryVars => {
|
||||||
if (typeof current !== "string") {
|
if (typeof current !== "string") {
|
||||||
return { ...p, current }
|
return { ...p, current };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current === "AND") {
|
if (current === "AND") {
|
||||||
return { AND: p }
|
return { AND: p };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current === "OR") {
|
if (current === "OR") {
|
||||||
return { OR: p }
|
return { OR: p };
|
||||||
}
|
}
|
||||||
|
|
||||||
return p
|
return p;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const createVariables = (filter: FilterContainer) =>
|
export const createVariables = (filter: FilterContainer) =>
|
||||||
filter.reduceRight(toNested, {} as QueryVars)
|
filter.reduceRight(toNested, {} as QueryVars);
|
||||||
|
|
|
@ -8,7 +8,7 @@ export interface FetchingParams {
|
||||||
attribute: Record<string, string[]>;
|
attribute: Record<string, string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type FetchingParamsKeys = keyof Omit<FetchingParams, "attribute">
|
type FetchingParamsKeys = keyof Omit<FetchingParams, "attribute">;
|
||||||
|
|
||||||
export const emptyFetchingParams: FetchingParams = {
|
export const emptyFetchingParams: FetchingParams = {
|
||||||
category: [],
|
category: [],
|
||||||
|
@ -21,10 +21,10 @@ export const emptyFetchingParams: FetchingParams = {
|
||||||
const unique = <T>(array: Iterable<T>) => Array.from(new Set(array));
|
const unique = <T>(array: Iterable<T>) => Array.from(new Set(array));
|
||||||
|
|
||||||
export const toFetchingParams = (p: FetchingParams, c: UrlToken) => {
|
export const toFetchingParams = (p: FetchingParams, c: UrlToken) => {
|
||||||
const key = c.name as FetchingParamsKeys
|
const key = c.name as FetchingParamsKeys;
|
||||||
|
|
||||||
if (!c.isAttribute() && !p[key]) {
|
if (!c.isAttribute() && !p[key]) {
|
||||||
p[key] = []
|
p[key] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.isAttribute() && !p.attribute[c.name]) {
|
if (c.isAttribute() && !p.attribute[c.name]) {
|
||||||
|
|
|
@ -35,9 +35,7 @@ const mapToTokens = (urlEntries: Array<ParsedQs | string>): TokenArray =>
|
||||||
return mapToTokens(entry);
|
return mapToTokens(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return UrlToken.fromUrlEntry(
|
return UrlToken.fromUrlEntry(UrlEntry.fromQs(entry));
|
||||||
UrlEntry.fromQs(entry)
|
|
||||||
);
|
|
||||||
}) as TokenArray;
|
}) as TokenArray;
|
||||||
|
|
||||||
const tokenizeUrl = (urlParams: string) => {
|
const tokenizeUrl = (urlParams: string) => {
|
||||||
|
|
|
@ -9,11 +9,10 @@ const STATIC_TO_LOAD = ["category", "collection", "channel", "producttype"];
|
||||||
|
|
||||||
export const TokenType = {
|
export const TokenType = {
|
||||||
ATTRIBUTE: "a",
|
ATTRIBUTE: "a",
|
||||||
STATIC: "s"
|
STATIC: "s",
|
||||||
} as const
|
} as const;
|
||||||
|
|
||||||
export type TokenTypeValue = (typeof TokenType)[keyof typeof TokenType]
|
|
||||||
|
|
||||||
|
export type TokenTypeValue = (typeof TokenType)[keyof typeof TokenType];
|
||||||
|
|
||||||
export class UrlEntry {
|
export class UrlEntry {
|
||||||
constructor(key: string, value: string | string[]) {
|
constructor(key: string, value: string | string[]) {
|
||||||
|
@ -21,49 +20,54 @@ export class UrlEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static fromQs(entry: ParsedQs) {
|
public static fromQs(entry: ParsedQs) {
|
||||||
const key = Object.keys(entry)[0]
|
const key = Object.keys(entry)[0];
|
||||||
const value = entry[key] as string | string[]
|
const value = entry[key] as string | string[];
|
||||||
|
|
||||||
return new UrlEntry(key, value)
|
return new UrlEntry(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static forAttribute (condition: ConditionSelected, paramName: string) {
|
public static forAttribute(condition: ConditionSelected, paramName: string) {
|
||||||
return UrlEntry.fromConditionSelected(condition, paramName, TokenType.ATTRIBUTE)
|
return UrlEntry.fromConditionSelected(
|
||||||
|
condition,
|
||||||
|
paramName,
|
||||||
|
TokenType.ATTRIBUTE,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static forStatic (condition: ConditionSelected, paramName: string) {
|
public static forStatic(condition: ConditionSelected, paramName: string) {
|
||||||
return UrlEntry.fromConditionSelected(condition, paramName, TokenType.STATIC)
|
return UrlEntry.fromConditionSelected(
|
||||||
|
condition,
|
||||||
|
paramName,
|
||||||
|
TokenType.STATIC,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getInfo () {
|
public getInfo() {
|
||||||
const [key, value] = Object.entries(this)[0] as [
|
const [key, value] = Object.entries(this)[0] as [string, string | string[]];
|
||||||
string,
|
|
||||||
string | string[],
|
|
||||||
];
|
|
||||||
const [identifier, entryName] = key.split(".");
|
const [identifier, entryName] = key.split(".");
|
||||||
const [type, control] = identifier.split("") as [TokenTypeValue, number];
|
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,
|
condition: ConditionSelected,
|
||||||
paramName: string,
|
paramName: string,
|
||||||
tokenSlug: TokenTypeValue
|
tokenSlug: TokenTypeValue,
|
||||||
) {
|
) {
|
||||||
const { conditionValue } = condition;
|
const { conditionValue } = condition;
|
||||||
const slug = slugFromConditionValue(condition.value)
|
const slug = slugFromConditionValue(condition.value);
|
||||||
|
|
||||||
if (!conditionValue) {
|
if (!conditionValue) {
|
||||||
return new UrlEntry(tokenSlug, slug)
|
return new UrlEntry(tokenSlug, slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditionIndex = CONDITIONS.findIndex(
|
const conditionIndex = CONDITIONS.findIndex(
|
||||||
el => el === conditionValue.label,
|
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) {
|
public static fromUrlEntry(entry: UrlEntry) {
|
||||||
const {
|
const { entryName, value, type, conditionKid } = entry.getInfo();
|
||||||
entryName,
|
|
||||||
value,
|
|
||||||
type,
|
|
||||||
conditionKid
|
|
||||||
} = entry.getInfo()
|
|
||||||
|
|
||||||
return new UrlToken(entryName, value, type, conditionKid);
|
return new UrlToken(entryName, value, type, conditionKid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ import useRouter from "use-react-router";
|
||||||
|
|
||||||
import { useInitialAPIState } from "../API/initialState/useInitalAPIState";
|
import { useInitialAPIState } from "../API/initialState/useInitalAPIState";
|
||||||
import { FilterContainer } from "../FilterElement";
|
import { FilterContainer } from "../FilterElement";
|
||||||
import { createVariables,FilterValueProvider } from "../FilterValueProvider";
|
import { createVariables, FilterValueProvider } from "../FilterValueProvider";
|
||||||
import { useTokenArray } from "./TokenArray";
|
import { useTokenArray } from "./TokenArray";
|
||||||
import { UrlEntry } from "./UrlToken";
|
import { UrlEntry } from "./UrlToken";
|
||||||
|
|
||||||
type Structure = Array<string | UrlEntry | Structure>
|
type Structure = Array<string | UrlEntry | Structure>;
|
||||||
|
|
||||||
const prepareStructure = (filterValue: FilterContainer): Structure =>
|
const prepareStructure = (filterValue: FilterContainer): Structure =>
|
||||||
filterValue.map(f => {
|
filterValue.map(f => {
|
||||||
|
|
|
@ -1,29 +1,34 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { FilterContainer,FilterElement } from "./FilterElement";
|
import { FilterContainer, FilterElement } from "./FilterElement";
|
||||||
|
|
||||||
type StateCallback = (el: FilterElement) => void
|
type StateCallback = (el: FilterElement) => void;
|
||||||
type Element = FilterContainer[number]
|
type Element = FilterContainer[number];
|
||||||
|
|
||||||
export const useContainerState = (initialValue: FilterContainer) => {
|
export const useContainerState = (initialValue: FilterContainer) => {
|
||||||
const [value, setValue] = useState(initialValue);
|
const [value, setValue] = useState(initialValue);
|
||||||
|
|
||||||
const isFilterElement = (elIndex: number, index: number, el: Element): el is FilterElement => {
|
const isFilterElement = (
|
||||||
return elIndex === index && typeof el !== "string" && !Array.isArray(el)
|
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) => {
|
const updateFilterElement =
|
||||||
if (isFilterElement(elIndex, index, el)) {
|
(index: number, cb: StateCallback) => (el: Element, elIndex: number) => {
|
||||||
cb(el);
|
if (isFilterElement(elIndex, index, el)) {
|
||||||
}
|
cb(el);
|
||||||
|
}
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
}
|
};
|
||||||
|
|
||||||
const updateAt = (position: string, cb: StateCallback) => {
|
const updateAt = (position: string, cb: StateCallback) => {
|
||||||
const index = parseInt(position, 10);
|
const index = parseInt(position, 10);
|
||||||
setValue(v => v.map(updateFilterElement(index, cb)));
|
setValue(v => v.map(updateFilterElement(index, cb)));
|
||||||
}
|
};
|
||||||
|
|
||||||
const removeAt = (position: string) => {
|
const removeAt = (position: string) => {
|
||||||
const index = parseInt(position, 10);
|
const index = parseInt(position, 10);
|
||||||
|
@ -50,11 +55,10 @@ export const useContainerState = (initialValue: FilterContainer) => {
|
||||||
setValue(v => v.concat(newValue));
|
setValue(v => v.concat(newValue));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createEmpty,
|
createEmpty,
|
||||||
updateAt,
|
updateAt,
|
||||||
removeAt,
|
removeAt,
|
||||||
value,
|
value,
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
|
@ -19,15 +19,8 @@ interface ExternalLinkProps extends React.HTMLProps<HTMLAnchorElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExternalLink: React.FC<ExternalLinkProps> = props => {
|
const ExternalLink: React.FC<ExternalLinkProps> = props => {
|
||||||
const {
|
const { className, children, href, typographyProps, target, rel, ...rest } =
|
||||||
className,
|
props;
|
||||||
children,
|
|
||||||
href,
|
|
||||||
typographyProps,
|
|
||||||
target,
|
|
||||||
rel,
|
|
||||||
...rest
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,8 @@ const useStyles = makeStyles(
|
||||||
{ name: "FilterGroupLabel" },
|
{ name: "FilterGroupLabel" },
|
||||||
);
|
);
|
||||||
|
|
||||||
export type FilterGroupLabelProps<
|
export type FilterGroupLabelProps<K extends string = string> =
|
||||||
K extends string = string,
|
FilterFieldBaseProps<K>;
|
||||||
> = FilterFieldBaseProps<K>;
|
|
||||||
|
|
||||||
const FilterGroupLabel: React.FC<FilterGroupLabelProps> = ({
|
const FilterGroupLabel: React.FC<FilterGroupLabelProps> = ({
|
||||||
filter,
|
filter,
|
||||||
|
|
|
@ -45,11 +45,10 @@ export type FilterElementValueData =
|
||||||
export type IFilterElementMutableData = FilterElementCommonData &
|
export type IFilterElementMutableData = FilterElementCommonData &
|
||||||
FilterElementValueData;
|
FilterElementValueData;
|
||||||
|
|
||||||
export type IFilterElementMutableDataGeneric<
|
export type IFilterElementMutableDataGeneric<T extends FieldType> =
|
||||||
T extends FieldType,
|
T extends FieldType.keyValue
|
||||||
> = T extends FieldType.keyValue
|
? KeyValueFilterElementData & FilterElementCommonData
|
||||||
? KeyValueFilterElementData & FilterElementCommonData
|
: RegularFilterElementData & FilterElementCommonData;
|
||||||
: RegularFilterElementData & FilterElementCommonData;
|
|
||||||
|
|
||||||
type FilterElementCommon<K extends string = string> = {
|
type FilterElementCommon<K extends string = string> = {
|
||||||
autocomplete?: boolean;
|
autocomplete?: boolean;
|
||||||
|
@ -68,13 +67,11 @@ type FilterElementCommon<K extends string = string> = {
|
||||||
export type FilterElement<K extends string = string> = FilterElementCommon<K> &
|
export type FilterElement<K extends string = string> = FilterElementCommon<K> &
|
||||||
Partial<UnknownFilterElementData>;
|
Partial<UnknownFilterElementData>;
|
||||||
|
|
||||||
export type FilterElementRegular<
|
export type FilterElementRegular<K extends string = string> =
|
||||||
K extends string = string,
|
FilterElementCommon<K> & RegularFilterElementData;
|
||||||
> = FilterElementCommon<K> & RegularFilterElementData;
|
|
||||||
|
|
||||||
export type FilterElementKeyValue<
|
export type FilterElementKeyValue<K extends string = string> =
|
||||||
K extends string = string,
|
FilterElementCommon<K> & KeyValueFilterElementData;
|
||||||
> = FilterElementCommon<K> & KeyValueFilterElementData;
|
|
||||||
|
|
||||||
export type FilterElementGeneric<
|
export type FilterElementGeneric<
|
||||||
K extends string,
|
K extends string,
|
||||||
|
|
|
@ -20,7 +20,10 @@ export interface MetadataFormData {
|
||||||
privateMetadata: MetadataInput[];
|
privateMetadata: MetadataInput[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MetadataIdSchema = Record<string, {
|
export type MetadataIdSchema = Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
metadata: MetadataInput[];
|
metadata: MetadataInput[];
|
||||||
privateMetadata: MetadataInput[];
|
privateMetadata: MetadataInput[];
|
||||||
}>;
|
}
|
||||||
|
>;
|
||||||
|
|
|
@ -92,10 +92,9 @@ const Navigator: React.FC<NavigatorProps> = ({ visible, setVisibility }) => {
|
||||||
description: "navigator notification",
|
description: "navigator notification",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keyboardShortcut:
|
keyboardShortcut: navigator.platform.toLowerCase().includes("mac")
|
||||||
navigator.platform.toLowerCase().includes("mac")
|
? "⌘+K"
|
||||||
? "⌘+K"
|
: "Ctrl+K",
|
||||||
: "Ctrl+K",
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: intl.formatMessage({
|
title: intl.formatMessage({
|
||||||
|
|
|
@ -8,9 +8,10 @@ import { findPriceSeparator, getCurrencyDecimalPoints } from "./utils";
|
||||||
export function usePriceField(currency: string, onChange: FormChange) {
|
export function usePriceField(currency: string, onChange: FormChange) {
|
||||||
const minValue = 0;
|
const minValue = 0;
|
||||||
|
|
||||||
const maxDecimalLength = useMemo(() => getCurrencyDecimalPoints(currency), [
|
const maxDecimalLength = useMemo(
|
||||||
currency,
|
() => getCurrencyDecimalPoints(currency),
|
||||||
]);
|
[currency],
|
||||||
|
);
|
||||||
|
|
||||||
const handleChange: FormChange = e => {
|
const handleChange: FormChange = e => {
|
||||||
let value = e.target.value;
|
let value = e.target.value;
|
||||||
|
|
|
@ -48,14 +48,8 @@ export interface SortableChipsFieldProps extends SortableContainerProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortableChipsField: React.FC<SortableChipsFieldProps> = props => {
|
const SortableChipsField: React.FC<SortableChipsFieldProps> = props => {
|
||||||
const {
|
const { loading, values, error, helperText, onValueDelete, onValueReorder } =
|
||||||
loading,
|
props;
|
||||||
values,
|
|
||||||
error,
|
|
||||||
helperText,
|
|
||||||
onValueDelete,
|
|
||||||
onValueReorder,
|
|
||||||
} = props;
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
||||||
const handleSortStart = () => {
|
const handleSortStart = () => {
|
||||||
|
|
|
@ -12,12 +12,9 @@ interface DeleteWarningDialogConsentContentProps {
|
||||||
onConsentChange: (value: boolean) => void;
|
onConsentChange: (value: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteWarningDialogConsentContent: React.FC<DeleteWarningDialogConsentContentProps> = ({
|
const DeleteWarningDialogConsentContent: React.FC<
|
||||||
description,
|
DeleteWarningDialogConsentContentProps
|
||||||
consentLabel,
|
> = ({ description, consentLabel, isConsentChecked, onConsentChange }) => {
|
||||||
isConsentChecked,
|
|
||||||
onConsentChange,
|
|
||||||
}) => {
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const handleConsentChange = ({ target }: ChangeEvent<any>) =>
|
const handleConsentChange = ({ target }: ChangeEvent<any>) =>
|
||||||
|
|
|
@ -51,10 +51,8 @@ export const customerAddUrl = customerAddPath;
|
||||||
export const customerAddressesPath = (id: string) =>
|
export const customerAddressesPath = (id: string) =>
|
||||||
urlJoin(customerPath(id), "addresses");
|
urlJoin(customerPath(id), "addresses");
|
||||||
export type CustomerAddressesUrlDialog = "add" | "edit" | "remove";
|
export type CustomerAddressesUrlDialog = "add" | "edit" | "remove";
|
||||||
export type CustomerAddressesUrlQueryParams = Dialog<
|
export type CustomerAddressesUrlQueryParams =
|
||||||
CustomerAddressesUrlDialog
|
Dialog<CustomerAddressesUrlDialog> & SingleAction;
|
||||||
> &
|
|
||||||
SingleAction;
|
|
||||||
export const customerAddressesUrl = (
|
export const customerAddressesUrl = (
|
||||||
id: string,
|
id: string,
|
||||||
params?: CustomerAddressesUrlQueryParams,
|
params?: CustomerAddressesUrlQueryParams,
|
||||||
|
|
|
@ -23,13 +23,12 @@ const getChannelMinAmountSpent = (
|
||||||
return channel.minSpent;
|
return channel.minSpent;
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapChannelToChannelInput = (formData: VoucherDetailsPageFormData) => (
|
const mapChannelToChannelInput =
|
||||||
channel: ChannelVoucherData,
|
(formData: VoucherDetailsPageFormData) => (channel: ChannelVoucherData) => ({
|
||||||
) => ({
|
channelId: channel.id,
|
||||||
channelId: channel.id,
|
discountValue: getChannelDiscountValue(channel, formData),
|
||||||
discountValue: getChannelDiscountValue(channel, formData),
|
minAmountSpent: getChannelMinAmountSpent(channel, formData),
|
||||||
minAmountSpent: getChannelMinAmountSpent(channel, formData),
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const filterNotDiscountedChannel = (
|
const filterNotDiscountedChannel = (
|
||||||
channelInput: VoucherChannelListingAddInput,
|
channelInput: VoucherChannelListingAddInput,
|
||||||
|
|
|
@ -12,10 +12,9 @@ type GiftCardCreateRequiresActivationSectionProps = Pick<
|
||||||
"checked" | "onChange"
|
"checked" | "onChange"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const GiftCardCreateRequiresActivationSection: React.FC<GiftCardCreateRequiresActivationSectionProps> = ({
|
const GiftCardCreateRequiresActivationSection: React.FC<
|
||||||
checked,
|
GiftCardCreateRequiresActivationSectionProps
|
||||||
onChange,
|
> = ({ checked, onChange }) => (
|
||||||
}) => (
|
|
||||||
<ControlledCheckbox
|
<ControlledCheckbox
|
||||||
name="requiresActivation"
|
name="requiresActivation"
|
||||||
label={
|
label={
|
||||||
|
|
|
@ -48,32 +48,30 @@ const useGiftCardActivateToggle = ({
|
||||||
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
|
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
|
||||||
});
|
});
|
||||||
|
|
||||||
const [
|
const [giftCardDeactivate, giftCardDeactivateOpts] =
|
||||||
giftCardDeactivate,
|
useGiftCardDeactivateMutation({
|
||||||
giftCardDeactivateOpts,
|
onCompleted: data => {
|
||||||
] = useGiftCardDeactivateMutation({
|
const errors = data?.giftCardDeactivate?.errors;
|
||||||
onCompleted: data => {
|
|
||||||
const errors = data?.giftCardDeactivate?.errors;
|
if (!!errors?.length) {
|
||||||
|
notify({
|
||||||
|
status: "error",
|
||||||
|
text: intl.formatMessage(commonErrorMessages.unknownError),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!!errors?.length) {
|
|
||||||
notify({
|
notify({
|
||||||
status: "error",
|
status: "success",
|
||||||
text: intl.formatMessage(commonErrorMessages.unknownError),
|
text: intl.formatMessage(messages.successfullyDisabledTitle),
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
notify({
|
if (!!onDeactivateActionComplete) {
|
||||||
status: "success",
|
onDeactivateActionComplete();
|
||||||
text: intl.formatMessage(messages.successfullyDisabledTitle),
|
}
|
||||||
});
|
},
|
||||||
|
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
|
||||||
if (!!onDeactivateActionComplete) {
|
});
|
||||||
onDeactivateActionComplete();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
|
|
||||||
});
|
|
||||||
|
|
||||||
const currentOpts = isActive ? giftCardDeactivateOpts : giftCardActivateOpts;
|
const currentOpts = isActive ? giftCardDeactivateOpts : giftCardActivateOpts;
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ export enum GiftCardUpdatePageActionParamsEnum {
|
||||||
RESEND_CODE = "resend-code",
|
RESEND_CODE = "resend-code",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GiftCardUpdatePageUrlQueryParams = Dialog<
|
export type GiftCardUpdatePageUrlQueryParams =
|
||||||
GiftCardUpdatePageActionParamsEnum
|
Dialog<GiftCardUpdatePageActionParamsEnum>;
|
||||||
>;
|
|
||||||
|
|
||||||
export const PLACEHOLDER = "-";
|
export const PLACEHOLDER = "-";
|
||||||
|
|
|
@ -13,10 +13,9 @@ interface GiftCardsListHeaderAlertContentProps {
|
||||||
giftCardProductsExist: boolean;
|
giftCardProductsExist: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GiftCardsListHeaderAlertContent: React.FC<GiftCardsListHeaderAlertContentProps> = ({
|
const GiftCardsListHeaderAlertContent: React.FC<
|
||||||
giftCardProductTypesExist,
|
GiftCardsListHeaderAlertContentProps
|
||||||
giftCardProductsExist,
|
> = ({ giftCardProductTypesExist, giftCardProductsExist }) => {
|
||||||
}) => {
|
|
||||||
const classes = useStyles({});
|
const classes = useStyles({});
|
||||||
|
|
||||||
const giftCardProductTypeUrl = productTypeAddUrl({
|
const giftCardProductTypeUrl = productTypeAddUrl({
|
||||||
|
|
|
@ -18,9 +18,9 @@ interface CustomerGiftCardsCardListItemProps {
|
||||||
giftCard: ExtendedGiftCard<CustomerGiftCardFragment>;
|
giftCard: ExtendedGiftCard<CustomerGiftCardFragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomerGiftCardsCardListItem: React.FC<CustomerGiftCardsCardListItemProps> = ({
|
const CustomerGiftCardsCardListItem: React.FC<
|
||||||
giftCard,
|
CustomerGiftCardsCardListItemProps
|
||||||
}) => {
|
> = ({ giftCard }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const classes = useListWrapperStyles();
|
const classes = useListWrapperStyles();
|
||||||
const [openDeleteGiftCard, setOpenDeleteGiftCard] = useState(false);
|
const [openDeleteGiftCard, setOpenDeleteGiftCard] = useState(false);
|
||||||
|
|
|
@ -33,13 +33,11 @@ const GiftCardDeleteDialog: React.FC<GiftCardDeleteDialogProps> = ({
|
||||||
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
|
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { onBulkDeleteGiftCards, bulkDeleteGiftCardOpts } =
|
||||||
onBulkDeleteGiftCards,
|
useGiftCardBulkDelete({
|
||||||
bulkDeleteGiftCardOpts,
|
onClose,
|
||||||
} = useGiftCardBulkDelete({
|
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
|
||||||
onClose,
|
});
|
||||||
refetchQueries: [GIFT_CARD_LIST_QUERY, ...refetchQueries],
|
|
||||||
});
|
|
||||||
|
|
||||||
const dialogProps: Pick<
|
const dialogProps: Pick<
|
||||||
ActionDialogProps,
|
ActionDialogProps,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { PermissionEnum } from "./types.generated";
|
import { PermissionEnum } from "./types.generated";
|
||||||
|
|
||||||
export interface Node {
|
export interface Node {
|
||||||
id: string
|
id: string;
|
||||||
}
|
}
|
||||||
export type PrefixedPermissions = `PERMISSION_${PermissionEnum}`;
|
export type PrefixedPermissions = `PERMISSION_${PermissionEnum}`;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { FetchMoreProps, Search, SearchProps } from "@dashboard/types";
|
||||||
import { filter } from "fuzzaldrin";
|
import { filter } from "fuzzaldrin";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export const useChannelsSearch = function<T extends { name: string }>(
|
export const useChannelsSearch = function <T extends { name: string }>(
|
||||||
channels: T[],
|
channels: T[],
|
||||||
) {
|
) {
|
||||||
const [query, onQueryChange] = React.useState("");
|
const [query, onQueryChange] = React.useState("");
|
||||||
|
|
|
@ -6,11 +6,11 @@ export const useServiceWorker = (timeout: number) => {
|
||||||
const registrationRef = useRef<ServiceWorkerRegistration>();
|
const registrationRef = useRef<ServiceWorkerRegistration>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = (setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
if (registrationRef.current) {
|
if (registrationRef.current) {
|
||||||
registrationRef.current.update();
|
registrationRef.current.update();
|
||||||
}
|
}
|
||||||
}, timeout) as unknown) as number;
|
}, timeout) as unknown as number;
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [timeout]);
|
}, [timeout]);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
<title>Sign in to the Saleor Dashboard</title>
|
<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 %>
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ export interface OrderChannelSectionCardProps {
|
||||||
channel?: Pick<ChannelFragment, "id" | "name">;
|
channel?: Pick<ChannelFragment, "id" | "name">;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OrderChannelSectionCard: React.FC<OrderChannelSectionCardProps> = ({
|
export const OrderChannelSectionCard: React.FC<
|
||||||
channel,
|
OrderChannelSectionCardProps
|
||||||
}) => {
|
> = ({ channel }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -11,9 +11,8 @@ export interface OrderCustomerChangeData {
|
||||||
changeActionOption: CustomerChangeActionEnum;
|
changeActionOption: CustomerChangeActionEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
type UseOrderCustomerChangeFormResult = CommonUseFormResult<
|
type UseOrderCustomerChangeFormResult =
|
||||||
OrderCustomerChangeData
|
CommonUseFormResult<OrderCustomerChangeData>;
|
||||||
>;
|
|
||||||
|
|
||||||
export interface OrderCustomerChangeFormProps {
|
export interface OrderCustomerChangeFormProps {
|
||||||
children: (props: UseOrderCustomerChangeFormResult) => React.ReactNode;
|
children: (props: UseOrderCustomerChangeFormResult) => React.ReactNode;
|
||||||
|
|
|
@ -82,7 +82,10 @@ export interface OrderDetailsPageProps {
|
||||||
onInvoiceClick: (invoiceId: string) => any;
|
onInvoiceClick: (invoiceId: string) => any;
|
||||||
onInvoiceGenerate: () => any;
|
onInvoiceGenerate: () => any;
|
||||||
onInvoiceSend: (invoiceId: string) => any;
|
onInvoiceSend: (invoiceId: string) => any;
|
||||||
onTransactionAction: (transactionId: string, actionType: TransactionActionEnum) => any;
|
onTransactionAction: (
|
||||||
|
transactionId: string,
|
||||||
|
actionType: TransactionActionEnum,
|
||||||
|
) => any;
|
||||||
onAddManualTransaction: () => any;
|
onAddManualTransaction: () => any;
|
||||||
onSubmit: (data: MetadataIdSchema) => SubmitPromise;
|
onSubmit: (data: MetadataIdSchema) => SubmitPromise;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ export const OrderDraftDetailsDatagrid = ({
|
||||||
rowMarkers="none"
|
rowMarkers="none"
|
||||||
columnSelect="none"
|
columnSelect="none"
|
||||||
freezeColumns={2}
|
freezeColumns={2}
|
||||||
verticalBorder={col => (col > 1)}
|
verticalBorder={col => col > 1}
|
||||||
availableColumns={columns}
|
availableColumns={columns}
|
||||||
emptyText={intl.formatMessage(messages.emptyText)}
|
emptyText={intl.formatMessage(messages.emptyText)}
|
||||||
getCellContent={getCellContent}
|
getCellContent={getCellContent}
|
||||||
|
|
|
@ -14,7 +14,10 @@ import { OrderTransactionsWrapper } from "./OrderTransactionsWrapper";
|
||||||
export interface OrderPaymentOrTransactionProps {
|
export interface OrderPaymentOrTransactionProps {
|
||||||
order: OrderDetailsFragment;
|
order: OrderDetailsFragment;
|
||||||
shop: OrderDetailsQuery["shop"];
|
shop: OrderDetailsQuery["shop"];
|
||||||
onTransactionAction: (transactionId: string, actionType: TransactionActionEnum) => any;
|
onTransactionAction: (
|
||||||
|
transactionId: string,
|
||||||
|
actionType: TransactionActionEnum,
|
||||||
|
) => any;
|
||||||
onPaymentCapture: () => any;
|
onPaymentCapture: () => any;
|
||||||
onPaymentVoid: () => any;
|
onPaymentVoid: () => any;
|
||||||
onPaymentRefund: () => any;
|
onPaymentRefund: () => any;
|
||||||
|
|
|
@ -20,7 +20,10 @@ import { getFilteredPayments } from "./utils";
|
||||||
interface OrderTransactionsWrapper {
|
interface OrderTransactionsWrapper {
|
||||||
order: OrderDetailsFragment;
|
order: OrderDetailsFragment;
|
||||||
shop: OrderDetailsQuery["shop"];
|
shop: OrderDetailsQuery["shop"];
|
||||||
onTransactionAction: (transactionId: string, actionType: TransactionActionEnum) => any;
|
onTransactionAction: (
|
||||||
|
transactionId: string,
|
||||||
|
actionType: TransactionActionEnum,
|
||||||
|
) => any;
|
||||||
onPaymentCapture: () => any;
|
onPaymentCapture: () => any;
|
||||||
onMarkAsPaid: () => any;
|
onMarkAsPaid: () => any;
|
||||||
onPaymentVoid: () => any;
|
onPaymentVoid: () => any;
|
||||||
|
|
|
@ -16,9 +16,8 @@ export interface OrderSettingsFormData {
|
||||||
automaticallyFulfillNonShippableGiftCard: boolean;
|
automaticallyFulfillNonShippableGiftCard: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UseOrderSettingsFormResult = CommonUseFormResult<
|
export type UseOrderSettingsFormResult =
|
||||||
OrderSettingsFormData
|
CommonUseFormResult<OrderSettingsFormData>;
|
||||||
>;
|
|
||||||
export interface OrderSettingsFormProps {
|
export interface OrderSettingsFormProps {
|
||||||
children: (props: UseOrderSettingsFormResult) => React.ReactNode;
|
children: (props: UseOrderSettingsFormResult) => React.ReactNode;
|
||||||
orderSettings: OrderSettingsFragment;
|
orderSettings: OrderSettingsFragment;
|
||||||
|
|
|
@ -20,16 +20,10 @@ export function getFilterVariables(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const {
|
export const { deleteFilterTab, getFilterTabs, saveFilterTab } =
|
||||||
deleteFilterTab,
|
createFilterTabUtils<PageTypeListUrlFilters>(PAGE_TYPE_FILTERS_KEY);
|
||||||
getFilterTabs,
|
|
||||||
saveFilterTab,
|
|
||||||
} = createFilterTabUtils<PageTypeListUrlFilters>(PAGE_TYPE_FILTERS_KEY);
|
|
||||||
|
|
||||||
export const {
|
export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } =
|
||||||
areFiltersApplied,
|
createFilterUtils<PageTypeListUrlQueryParams, PageTypeListUrlFilters>(
|
||||||
getActiveFilters,
|
PageTypeListUrlFiltersEnum,
|
||||||
getFiltersCurrentTab,
|
);
|
||||||
} = createFilterUtils<PageTypeListUrlQueryParams, PageTypeListUrlFilters>(
|
|
||||||
PageTypeListUrlFiltersEnum,
|
|
||||||
);
|
|
||||||
|
|
|
@ -18,12 +18,11 @@ export enum PermissionGroupListUrlSortField {
|
||||||
name = "name",
|
name = "name",
|
||||||
}
|
}
|
||||||
export type PermissionGroupListUrlSort = Sort<PermissionGroupListUrlSortField>;
|
export type PermissionGroupListUrlSort = Sort<PermissionGroupListUrlSortField>;
|
||||||
export type PermissionGroupListUrlQueryParams = Dialog<
|
export type PermissionGroupListUrlQueryParams =
|
||||||
PermissionGroupListUrlDialog
|
Dialog<PermissionGroupListUrlDialog> &
|
||||||
> &
|
Pagination &
|
||||||
Pagination &
|
PermissionGroupListUrlSort &
|
||||||
PermissionGroupListUrlSort &
|
SingleAction;
|
||||||
SingleAction;
|
|
||||||
export const permissionGroupListUrl = (
|
export const permissionGroupListUrl = (
|
||||||
params?: PermissionGroupListUrlQueryParams,
|
params?: PermissionGroupListUrlQueryParams,
|
||||||
) => permissionGroupListPath + "?" + stringifyQs(params);
|
) => permissionGroupListPath + "?" + stringifyQs(params);
|
||||||
|
|
|
@ -8,7 +8,9 @@ import PluginDetailsChannelsCardContent, {
|
||||||
PluginDetailsChannelsCardProps,
|
PluginDetailsChannelsCardProps,
|
||||||
} from "./PluginDetailsChannelsCardContent";
|
} from "./PluginDetailsChannelsCardContent";
|
||||||
|
|
||||||
const PluginDetailsChannelsCard: React.FC<PluginDetailsChannelsCardProps> = props => {
|
const PluginDetailsChannelsCard: React.FC<
|
||||||
|
PluginDetailsChannelsCardProps
|
||||||
|
> = props => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -10,9 +10,9 @@ interface PluginChannelAvailabilityCellProps {
|
||||||
plugin: PluginBaseFragment;
|
plugin: PluginBaseFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PluginChannelAvailabilityCell: React.FC<PluginChannelAvailabilityCellProps> = ({
|
const PluginChannelAvailabilityCell: React.FC<
|
||||||
plugin,
|
PluginChannelAvailabilityCellProps
|
||||||
}) => {
|
> = ({ plugin }) => {
|
||||||
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
||||||
const popupAnchor = useRef<HTMLTableCellElement>(null);
|
const popupAnchor = useRef<HTMLTableCellElement>(null);
|
||||||
|
|
||||||
|
|
|
@ -34,14 +34,8 @@ export interface PluginListProps
|
||||||
const totalColSpan = 10;
|
const totalColSpan = 10;
|
||||||
|
|
||||||
const PluginList: React.FC<PluginListProps> = props => {
|
const PluginList: React.FC<PluginListProps> = props => {
|
||||||
const {
|
const { settings, plugins, disabled, sort, onSort, onUpdateListSettings } =
|
||||||
settings,
|
props;
|
||||||
plugins,
|
|
||||||
disabled,
|
|
||||||
sort,
|
|
||||||
onSort,
|
|
||||||
onUpdateListSettings,
|
|
||||||
} = props;
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
|
@ -4,8 +4,7 @@ export const isPluginGlobal = (
|
||||||
globalConfiguration: PluginConfigurationBaseFragment,
|
globalConfiguration: PluginConfigurationBaseFragment,
|
||||||
) => !!globalConfiguration;
|
) => !!globalConfiguration;
|
||||||
|
|
||||||
export const getConfigByChannelId = (channelIdToCompare: string) => ({
|
export const getConfigByChannelId =
|
||||||
channel,
|
(channelIdToCompare: string) =>
|
||||||
}: {
|
({ channel }: { channel: { id: string } }) =>
|
||||||
channel: { id: string };
|
channel.id === channelIdToCompare;
|
||||||
}) => channel.id === channelIdToCompare;
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { ProductTypeKindEnum, TaxClassBaseFragment } from "@dashboard/graphql";
|
import { ProductTypeKindEnum, TaxClassBaseFragment } from "@dashboard/graphql";
|
||||||
import { ChangeEvent, FormChange } from "@dashboard/hooks/useForm";
|
import { ChangeEvent, FormChange } from "@dashboard/hooks/useForm";
|
||||||
|
|
||||||
export const makeProductTypeKindChangeHandler = (
|
export const makeProductTypeKindChangeHandler =
|
||||||
onChange: FormChange,
|
(onChange: FormChange, onKindChange: (kind: ProductTypeKindEnum) => void) =>
|
||||||
onKindChange: (kind: ProductTypeKindEnum) => void,
|
(event: React.ChangeEvent<any>) => {
|
||||||
) => (event: React.ChangeEvent<any>) => {
|
const kind = event.target.value as ProductTypeKindEnum;
|
||||||
const kind = event.target.value as ProductTypeKindEnum;
|
onKindChange(kind);
|
||||||
onKindChange(kind);
|
onChange(event);
|
||||||
onChange(event);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
export function handleTaxClassChange(
|
export function handleTaxClassChange(
|
||||||
event: ChangeEvent,
|
event: ChangeEvent,
|
||||||
|
|
|
@ -225,7 +225,7 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
attributeRichTextGetters,
|
attributeRichTextGetters,
|
||||||
}) => {
|
}) => {
|
||||||
// Comparing explicitly to false because `hasVariants` can be undefined
|
// Comparing explicitly to false because `hasVariants` can be undefined
|
||||||
const isSimpleProduct = !(data.productType?.hasVariants);
|
const isSimpleProduct = !data.productType?.hasVariants;
|
||||||
|
|
||||||
const errors = [...apiErrors, ...validationErrors];
|
const errors = [...apiErrors, ...validationErrors];
|
||||||
|
|
||||||
|
|
|
@ -62,26 +62,25 @@ const ExportDialogSettings: React.FC<ExportDialogSettingsProps> = ({
|
||||||
|
|
||||||
const formErrors = getFormErrors(formFields, errors);
|
const formErrors = getFormErrors(formFields, errors);
|
||||||
|
|
||||||
const productExportTypeChoices: Array<RadioGroupFieldChoice<
|
const productExportTypeChoices: Array<RadioGroupFieldChoice<FileTypesEnum>> =
|
||||||
FileTypesEnum
|
[
|
||||||
>> = [
|
{
|
||||||
{
|
label: intl.formatMessage({
|
||||||
label: intl.formatMessage({
|
id: "9Tl/bT",
|
||||||
id: "9Tl/bT",
|
defaultMessage: "Spreadsheet for Excel, Numbers etc.",
|
||||||
defaultMessage: "Spreadsheet for Excel, Numbers etc.",
|
description: "export items as spreadsheet",
|
||||||
description: "export items as spreadsheet",
|
}),
|
||||||
}),
|
value: FileTypesEnum.XLSX,
|
||||||
value: FileTypesEnum.XLSX,
|
},
|
||||||
},
|
{
|
||||||
{
|
label: intl.formatMessage({
|
||||||
label: intl.formatMessage({
|
id: "li1BBk",
|
||||||
id: "li1BBk",
|
defaultMessage: "Plain CSV file",
|
||||||
defaultMessage: "Plain CSV file",
|
description: "export items as csv file",
|
||||||
description: "export items as csv file",
|
}),
|
||||||
}),
|
value: FileTypesEnum.CSV,
|
||||||
value: FileTypesEnum.CSV,
|
},
|
||||||
},
|
];
|
||||||
];
|
|
||||||
|
|
||||||
const exportScopeChoices = [
|
const exportScopeChoices = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,10 +11,9 @@ interface VariantDetailsChannelsAvailabilityCardContainerProps {
|
||||||
cardTitle?: React.ReactNode;
|
cardTitle?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VariantDetailsChannelsAvailabilityCardContainer: React.FC<VariantDetailsChannelsAvailabilityCardContainerProps> = ({
|
const VariantDetailsChannelsAvailabilityCardContainer: React.FC<
|
||||||
children,
|
VariantDetailsChannelsAvailabilityCardContainerProps
|
||||||
cardTitle,
|
> = ({ children, cardTitle }) => (
|
||||||
}) => (
|
|
||||||
<>
|
<>
|
||||||
<Card>
|
<Card>
|
||||||
{cardTitle || (
|
{cardTitle || (
|
||||||
|
|
|
@ -19,7 +19,9 @@ interface ProductVariantCheckoutSettingsProps {
|
||||||
onChange: FormChange;
|
onChange: FormChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductVariantCheckoutSettings: React.FC<ProductVariantCheckoutSettingsProps> = props => {
|
const ProductVariantCheckoutSettings: React.FC<
|
||||||
|
ProductVariantCheckoutSettingsProps
|
||||||
|
> = props => {
|
||||||
const { data, disabled, errors, onChange } = props;
|
const { data, disabled, errors, onChange } = props;
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
|
@ -82,8 +82,9 @@ const ProductVariantMediaSelectDialog: React.FC<
|
||||||
className={clsx([
|
className={clsx([
|
||||||
classes.imageContainer,
|
classes.imageContainer,
|
||||||
{
|
{
|
||||||
[classes.selectedImageContainer]:
|
[classes.selectedImageContainer]: selectedMedia.includes(
|
||||||
selectedMedia.includes(mediaObj.id),
|
mediaObj.id,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
onClick={() => handleMediaSelect(mediaObj.id)}
|
onClick={() => handleMediaSelect(mediaObj.id)}
|
||||||
|
|
|
@ -33,7 +33,9 @@ export interface ShippingZoneSettingsCardProps {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShippingZoneSettingsCard: React.FC<ShippingZoneSettingsCardProps> = ({
|
export const ShippingZoneSettingsCard: React.FC<
|
||||||
|
ShippingZoneSettingsCardProps
|
||||||
|
> = ({
|
||||||
formData,
|
formData,
|
||||||
warehousesDisplayValues,
|
warehousesDisplayValues,
|
||||||
hasMoreWarehouses,
|
hasMoreWarehouses,
|
||||||
|
|
|
@ -31,9 +31,9 @@ const ShippingZonesList: React.FC<RouteComponentProps<{}>> = ({ location }) => {
|
||||||
interface ShippingZoneDetailsRouteProps {
|
interface ShippingZoneDetailsRouteProps {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
const ShippingZoneDetails: React.FC<RouteComponentProps<
|
const ShippingZoneDetails: React.FC<
|
||||||
ShippingZoneDetailsRouteProps
|
RouteComponentProps<ShippingZoneDetailsRouteProps>
|
||||||
>> = ({ location, match }) => {
|
> = ({ location, match }) => {
|
||||||
const qs = parseQs(location.search.substr(1));
|
const qs = parseQs(location.search.substr(1));
|
||||||
const params: ShippingZoneUrlQueryParams = qs;
|
const params: ShippingZoneUrlQueryParams = qs;
|
||||||
return (
|
return (
|
||||||
|
@ -58,10 +58,12 @@ const RateCreate: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RateUpdate: React.FC<RouteComponentProps<{
|
const RateUpdate: React.FC<
|
||||||
id: string;
|
RouteComponentProps<{
|
||||||
rateId: string;
|
id: string;
|
||||||
}>> = ({ match }) => {
|
rateId: string;
|
||||||
|
}>
|
||||||
|
> = ({ match }) => {
|
||||||
const qs = parseQs(location.search.substr(1));
|
const qs = parseQs(location.search.substr(1));
|
||||||
const params: ShippingRateUrlQueryParams = qs;
|
const params: ShippingRateUrlQueryParams = qs;
|
||||||
|
|
||||||
|
|
|
@ -51,13 +51,12 @@ export type ShippingRateUrlQueryParams = Dialog<ShippingRateUrlDialog> &
|
||||||
SingleAction &
|
SingleAction &
|
||||||
BulkAction;
|
BulkAction;
|
||||||
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions | ChannelsAction;
|
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions | ChannelsAction;
|
||||||
export type ShippingRateCreateUrlQueryParams = Dialog<
|
export type ShippingRateCreateUrlQueryParams =
|
||||||
ShippingRateCreateUrlDialog
|
Dialog<ShippingRateCreateUrlDialog> &
|
||||||
> &
|
SingleAction &
|
||||||
SingleAction &
|
Partial<{
|
||||||
Partial<{
|
type: ShippingMethodTypeEnum;
|
||||||
type: ShippingMethodTypeEnum;
|
}>;
|
||||||
}>;
|
|
||||||
|
|
||||||
export const shippingRateCreatePath = (id: string) =>
|
export const shippingRateCreatePath = (id: string) =>
|
||||||
urlJoin(shippingZonePath(id), "add");
|
urlJoin(shippingZonePath(id), "add");
|
||||||
|
|
|
@ -39,9 +39,8 @@ export type StaffMemberDetailsUrlDialog =
|
||||||
| "change-password"
|
| "change-password"
|
||||||
| "remove"
|
| "remove"
|
||||||
| "remove-avatar";
|
| "remove-avatar";
|
||||||
export type StaffMemberDetailsUrlQueryParams = Dialog<
|
export type StaffMemberDetailsUrlQueryParams =
|
||||||
StaffMemberDetailsUrlDialog
|
Dialog<StaffMemberDetailsUrlDialog>;
|
||||||
>;
|
|
||||||
|
|
||||||
export const staffMemberDetailsUrl = (
|
export const staffMemberDetailsUrl = (
|
||||||
id: string,
|
id: string,
|
||||||
|
|
|
@ -231,12 +231,12 @@ const TranslationFields: React.FC<TranslationFieldsProps> = props => {
|
||||||
onDiscard={onDiscard}
|
onDiscard={onDiscard}
|
||||||
onSubmit={data => onSubmit(field, data)}
|
onSubmit={data => onSubmit(field, data)}
|
||||||
/>
|
/>
|
||||||
) // FIXME
|
) : // FIXME
|
||||||
// For now this is the only way to fix the issue
|
// For now this is the only way to fix the issue
|
||||||
// of initializing the editor with fetched data.
|
// of initializing the editor with fetched data.
|
||||||
// Without this the editor doesn't get the saved data
|
// Without this the editor doesn't get the saved data
|
||||||
// and is empty
|
// and is empty
|
||||||
: disabled ? (
|
disabled ? (
|
||||||
<Skeleton />
|
<Skeleton />
|
||||||
) : (
|
) : (
|
||||||
<TranslationFieldsRich
|
<TranslationFieldsRich
|
||||||
|
|
|
@ -10,16 +10,11 @@ export function useRichTextSubmit(
|
||||||
) {
|
) {
|
||||||
const { setIsDirty, setExitDialogSubmitRef } = useExitFormDialog();
|
const { setIsDirty, setExitDialogSubmitRef } = useExitFormDialog();
|
||||||
|
|
||||||
const {
|
const { defaultValue, editorRef, isReadyForMount, handleChange, getValue } =
|
||||||
defaultValue,
|
useRichText({
|
||||||
editorRef,
|
initial,
|
||||||
isReadyForMount,
|
triggerChange: () => setIsDirty(true),
|
||||||
handleChange,
|
});
|
||||||
getValue,
|
|
||||||
} = useRichText({
|
|
||||||
initial,
|
|
||||||
triggerChange: () => setIsDirty(true),
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSubmit = React.useCallback(async () => {
|
const handleSubmit = React.useCallback(async () => {
|
||||||
const result = onSubmit(await getValue());
|
const result = onSubmit(await getValue());
|
||||||
|
@ -34,10 +29,10 @@ export function useRichTextSubmit(
|
||||||
return errors;
|
return errors;
|
||||||
}, [getValue, onSubmit, setIsDirty]);
|
}, [getValue, onSubmit, setIsDirty]);
|
||||||
|
|
||||||
React.useEffect(() => setExitDialogSubmitRef(handleSubmit), [
|
React.useEffect(
|
||||||
handleSubmit,
|
() => setExitDialogSubmitRef(handleSubmit),
|
||||||
setExitDialogSubmitRef,
|
[handleSubmit, setExitDialogSubmitRef],
|
||||||
]);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
defaultValue,
|
defaultValue,
|
||||||
|
|
|
@ -25,7 +25,7 @@ describe("Multiple file upload handler", () => {
|
||||||
return promise;
|
return promise;
|
||||||
}, cbs);
|
}, cbs);
|
||||||
|
|
||||||
handle((testFiles as unknown) as FileList).then(() => {
|
handle(testFiles as unknown as FileList).then(() => {
|
||||||
expect(cbs.onAfterUpload).toBeCalledTimes(testFiles.length);
|
expect(cbs.onAfterUpload).toBeCalledTimes(testFiles.length);
|
||||||
expect(cbs.onBeforeUpload).toBeCalledTimes(testFiles.length);
|
expect(cbs.onBeforeUpload).toBeCalledTimes(testFiles.length);
|
||||||
expect(cbs.onCompleted).toBeCalledTimes(1);
|
expect(cbs.onCompleted).toBeCalledTimes(1);
|
||||||
|
@ -56,7 +56,7 @@ describe("Multiple file upload handler", () => {
|
||||||
return promise;
|
return promise;
|
||||||
}, cbs);
|
}, cbs);
|
||||||
|
|
||||||
handle((testFiles as unknown) as FileList).then(() => {
|
handle(testFiles as unknown as FileList).then(() => {
|
||||||
expect(cbs.onAfterUpload).toBeCalledTimes(testFiles.length - 1);
|
expect(cbs.onAfterUpload).toBeCalledTimes(testFiles.length - 1);
|
||||||
expect(cbs.onBeforeUpload).toBeCalledTimes(testFiles.length);
|
expect(cbs.onBeforeUpload).toBeCalledTimes(testFiles.length);
|
||||||
expect(cbs.onCompleted).toBeCalledTimes(1);
|
expect(cbs.onCompleted).toBeCalledTimes(1);
|
||||||
|
|
|
@ -3,20 +3,18 @@ import { useState } from "react";
|
||||||
|
|
||||||
function useMetadataChangeTrigger() {
|
function useMetadataChangeTrigger() {
|
||||||
const [isMetadataModified, setMetadataModified] = useState(false);
|
const [isMetadataModified, setMetadataModified] = useState(false);
|
||||||
const [isPrivateMetadataModified, setPrivateMetadataModified] = useState(
|
const [isPrivateMetadataModified, setPrivateMetadataModified] =
|
||||||
false,
|
useState(false);
|
||||||
);
|
|
||||||
|
|
||||||
const makeChangeHandler: (
|
const makeChangeHandler: (onChange: FormChange) => FormChange =
|
||||||
onChange: FormChange,
|
onChange => event => {
|
||||||
) => FormChange = onChange => event => {
|
if (event.target.name === "metadata") {
|
||||||
if (event.target.name === "metadata") {
|
setMetadataModified(true);
|
||||||
setMetadataModified(true);
|
} else {
|
||||||
} else {
|
setPrivateMetadataModified(true);
|
||||||
setPrivateMetadataModified(true);
|
}
|
||||||
}
|
onChange(event);
|
||||||
onChange(event);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const resetMetadataChanged = () => {
|
const resetMetadataChanged = () => {
|
||||||
setMetadataModified(false);
|
setMetadataModified(false);
|
||||||
|
|
|
@ -20,16 +20,10 @@ export function getFilterVariables(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const {
|
export const { deleteFilterTab, getFilterTabs, saveFilterTab } =
|
||||||
deleteFilterTab,
|
createFilterTabUtils<WarehouseListUrlFilters>(WAREHOUSE_FILTERS_KEY);
|
||||||
getFilterTabs,
|
|
||||||
saveFilterTab,
|
|
||||||
} = createFilterTabUtils<WarehouseListUrlFilters>(WAREHOUSE_FILTERS_KEY);
|
|
||||||
|
|
||||||
export const {
|
export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } =
|
||||||
areFiltersApplied,
|
createFilterUtils<WarehouseListUrlQueryParams, WarehouseListUrlFilters>(
|
||||||
getActiveFilters,
|
WarehouseListUrlFiltersEnum,
|
||||||
getFiltersCurrentTab,
|
);
|
||||||
} = createFilterUtils<WarehouseListUrlQueryParams, WarehouseListUrlFilters>(
|
|
||||||
WarehouseListUrlFiltersEnum,
|
|
||||||
);
|
|
||||||
|
|
Loading…
Reference in a new issue