Upgrade to ESLint 8 (#3781)

* Upgrade ESLint

* Add eslint-nibble

* Move typescript to dev deps

* Update ESLint config

* Turn off semi, comma-dangle & quotes rules

* Enable simple sort

* Fix errors in ESLint (#3788)

* Disable rules requiring heavy changes

* Autofix new ESLint rules

* Autofix more-rules

* Fix jsx/generics ambiguity

* Add warnings for broken rules requiring manual fixes

* Remove redundant expected-error

* Add simple-sort

* Add prettier config

* Lint config

* Fix sort plugin

* Fix simple sort plugin

* Fix sort order

* Update src/orders/components/OrderTransaction/components/TransactionEvents/components/PspReferenceLink.tsx

Co-authored-by: Paweł Chyła <chyla1988@gmail.com>

* Remove redundant comment

* Remove chai friendly

* Update package.json

Co-authored-by: Krzysztof Żuraw <9116238+krzysztofzuraw@users.noreply.github.com>

* Remove to-be-checked comment

* Update formatjs plugin

* Lint staged only in src

* Add changeset

* Add tracking issue for new rules

* Resolve auto-fixable warning after merge

* Change sorts to warnings

* Run lint on new files

* Fix errors

---------

Co-authored-by: Paweł Chyła <chyla1988@gmail.com>
Co-authored-by: Krzysztof Żuraw <9116238+krzysztofzuraw@users.noreply.github.com>
This commit is contained in:
Michał Droń 2023-06-30 10:07:13 +02:00 committed by GitHub
parent a1482cc453
commit 3123f04c69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 2973 additions and 1610 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Update to ESLint 8 & use standard-with-typescript ruleset

View file

@ -1,23 +1,32 @@
{
"env": {
"browser": true,
"node": true
"es2021": true
},
"parser": "@typescript-eslint/parser",
"extends": [
"standard-with-typescript",
"plugin:react/recommended",
"prettier"
],
"parserOptions": {
"sourceType": "module"
"ecmaVersion": "latest",
"sourceType": "module",
"project": "./tsconfig.json"
},
"settings": {
"react": {
"version": "detect"
}
},
"extends": ["prettier"],
"plugins": [
"@typescript-eslint",
"react",
"import",
"local-rules",
"simple-import-sort",
"cypress",
"chai-friendly",
"formatjs",
"react-refresh",
"react-hooks",
"react-refresh"
"simple-import-sort"
],
"overrides": [
{
@ -28,179 +37,79 @@
}
],
"rules": {
"@typescript-eslint/semi": ["off"],
"@typescript-eslint/quotes": ["off", "double"],
"import/no-duplicates": "error",
"import/no-extraneous-dependencies": "off", // imports are handled by simple-import-sort/sort
"import/no-internal-modules": "off", // imports are handled by simple-import-sort/sort
"import/order": "off", // imports are handled by simple-import-sort/sort
"sort-imports": "off", // imports are handled by simple-import-sort/sort
"simple-import-sort/imports": "warn",
"simple-import-sort/exports": "warn",
"react-refresh/only-export-components": "warn",
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": [
"error",
{
"default": "array-simple"
}
],
"@typescript-eslint/ban-types": [
"error",
{
"extendDefaults": true,
"types": {
"{}": false
}
}
],
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/indent": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/member-delimiter-style": [
"off",
"error",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/member-ordering": "error",
"@typescript-eslint/no-empty-function": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-this-alias": "error",
"@typescript-eslint/no-use-before-declare": "off",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/quotes": "off",
"@typescript-eslint/semi": ["off", null],
"@typescript-eslint/space-within-parens": ["off", "never"],
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/type-annotation-spacing": "off",
"@typescript-eslint/unified-signatures": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{ "argsIgnorePattern": "^_" }
],
"arrow-body-style": "error",
"arrow-parens": ["off", "as-needed"],
"camelcase": "off",
"capitalized-comments": "off",
"chai-friendly/no-unused-expressions": "error",
"complexity": "off",
"constructor-super": "error",
"curly": "error",
"dot-notation": "error",
"eol-last": "off",
"eqeqeq": ["error", "smart"],
"react-hooks/rules-of-hooks": "error",
"formatjs/enforce-id": [
"error",
{
"idInterpolationPattern": "[sha512:contenthash:base64:6]"
}
],
"guard-for-in": "error",
"id-blacklist": "off",
"import/no-duplicates": "error",
"import/no-extraneous-dependencies": "off", // imports are handled by simple-import-sort/sort
"import/no-internal-modules": "off", // imports are handled by simple-import-sort/sort
"import/order": "off", // imports are handled by simple-import-sort/sort
"linebreak-style": "off",
"local-rules/named-styles": "error",
"max-classes-per-file": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-bitwise": "error",
"no-caller": "error",
"no-cond-assign": "error",
"no-console": [
"error",
{
"allow": [
"warn",
"dir",
"time",
"timeEnd",
"timeLog",
"trace",
"assert",
"clear",
"count",
"countReset",
"group",
"groupEnd",
"table",
"debug",
"info",
"dirxml",
"error",
"groupCollapsed",
"Console",
"profile",
"profileEnd",
"timeStamp",
"context"
]
}
],
"no-debugger": "error",
"no-duplicate-case": "error",
"no-empty": "error",
"no-eval": "error",
"no-extra-bind": "error",
"no-extra-semi": "off",
"no-fallthrough": "off",
"no-invalid-this": "off",
"no-irregular-whitespace": "off",
"no-multiple-empty-lines": "off",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-redeclare": "off",
"no-return-await": "error",
"no-sequences": "error",
"no-shadow": [
"off",
{
"hoist": "all"
}
],
"no-sparse-arrays": "error",
"no-template-curly-in-string": "error",
"no-throw-literal": "error",
"no-trailing-spaces": "off",
"no-undef-init": "error",
"no-underscore-dangle": "off",
"no-unsafe-finally": "error",
"no-unused-expressions": "off",
"no-unused-labels": "error",
"no-var": "error",
"object-shorthand": "error",
"one-var": ["error", "never"],
"prefer-const": "error",
"prefer-object-spread": "error",
"quote-props": "off",
"radix": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"simple-import-sort/sort": ["error"],
"sort-imports": "off", // imports are handled by simple-import-sort/sort
"sort-keys": "off",
"space-before-function-paren": "off",
"spaced-comment": ["error", "always", { "markers": ["/"] }],
"use-isnan": "error",
"valid-typeof": "off",
"no-restricted-imports": [
"error",
{
"paths": ["lodash", "@material-ui/icons/Delete", "classnames"]
}
]
],
// These rules should be reviewed - tracked in
// Tracked in https://github.com/saleor/saleor-dashboard/issues/3813
"@typescript-eslint/consistent-type-imports": "off",
"@typescript-eslint/indent": "off",
"@typescript-eslint/member-delimiter-style": "off",
"@typescript-eslint/method-signature-style": "off",
"@typescript-eslint/no-confusing-void-expression": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/prefer-reduce-type-parameter": "off",
"@typescript-eslint/promise-function-async": "off",
"@typescript-eslint/return-await": "off",
"@typescript-eslint/space-before-function-paren": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"multiline-ternary": "off",
"no-extra-boolean-cast": "off",
"@typescript-eslint/await-thenable": "warn",
"@typescript-eslint/ban-ts-comment": "warn",
"@typescript-eslint/ban-types": "warn",
"@typescript-eslint/consistent-type-assertions": "warn",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/naming-convention": "warn",
"@typescript-eslint/no-base-to-string": "warn",
"@typescript-eslint/no-dynamic-delete": "warn",
"@typescript-eslint/no-floating-promises": "warn",
"@typescript-eslint/no-invalid-void-type": "warn",
"@typescript-eslint/no-misused-promises": "warn",
"@typescript-eslint/no-non-null-asserted-optional-chain": "warn",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-redeclare": "warn",
"@typescript-eslint/prefer-nullish-coalescing": "warn",
"@typescript-eslint/prefer-optional-chain": "warn",
"@typescript-eslint/restrict-plus-operands": "warn",
"@typescript-eslint/restrict-template-expressions": "warn",
"array-callback-return": "warn",
"import/export": "warn",
"n/no-callback-literal": "warn",
"no-case-declarations": "warn",
"no-empty-pattern": "warn",
"no-fallthrough": "warn",
"no-new": "warn",
"no-prototype-builtins": "warn",
"no-unreachable": "warn",
"no-useless-catch": "warn",
"no-useless-escape": "warn",
"prefer-promise-reject-errors": "warn",
"react/display-name": "warn",
"react/jsx-key": "warn",
"react/prop-types": "warn",
"symbol-description": "warn"
},
"ignorePatterns": ["node_modules/", "**/types/**/*", "type-policies.ts"]
}

4051
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -143,7 +143,7 @@
"@types/react-sortable-tree": "^0.3.15",
"@types/url-join": "^4.0.1",
"@types/webappsec-credential-management": "^0.5.1",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.41.0",
"@vitejs/plugin-react-swc": "^3.2.0",
"babel-core": "^7.0.0-bridge.0",
@ -159,6 +159,21 @@
"dotenv": "^10.0.0",
"env-var": "^7.3.0",
"esbuild-loader": "^2.18.0",
"eslint": "^8.43.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^35.0.0",
"eslint-nibble": "^8.1.0",
"eslint-plugin-cypress": "^2.11.2",
"eslint-plugin-formatjs": "^4.10.3",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-local-rules": "^0.1.1",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-prefer-arrow": "^1.1.6",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.1",
"eslint-plugin-simple-import-sort": "^10.0.0",
"graphql-request": "^3.7.0",
"identity-obj-proxy": "^3.0.0",
"is-ci": "^3.0.1",
@ -169,7 +184,7 @@
"rimraf": "^3.0.0",
"rollup-plugin-polyfill-node": "^0.11.0",
"start-server-and-test": "^1.11.0",
"typescript": "^5.0.2",
"typescript": "^5.0.4",
"typescript-strict-plugin": "^2.1.0",
"vite": "^3.2.4",
"vite-plugin-html": "^3.2.0",
@ -211,17 +226,6 @@
"cypress-multi-reporters": "^1.5.0",
"cypress-repeat": "^2.3.3",
"cypress-timings": "^1.0.0",
"eslint": "^7.4.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-chai-friendly": "^0.6.0",
"eslint-plugin-cypress": "^2.11.2",
"eslint-plugin-formatjs": "^2.18.0",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-local-rules": "^0.1.1",
"eslint-plugin-prefer-arrow": "^1.1.6",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.1",
"eslint-plugin-simple-import-sort": "^5.0.3",
"fsevents": "^1.2.9",
"husky": "^8.0.3",
"jest": "^27.5.1",
@ -284,11 +288,7 @@
"resolve": "1.20.0"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{js,jsx}": [
"./src/*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
]
@ -322,6 +322,7 @@
"test": "jest src/",
"test:watch": "jest --watch src/",
"lint": "eslint \"src/**/*.@(tsx|ts|jsx|js)\" --fix",
"lint:check-progress": "eslint-nibble \"src/**/*.@(tsx|ts|jsx|js)\"",
"postbuild": "node scripts/removeSourcemaps.js",
"postinstall": "node scripts/patchReactVirtualized.js",
"predev": "npm run build-types",

View file

@ -48,7 +48,7 @@ jest
.mockImplementation(() => "http://localhost:3000");
jest.spyOn(ReactIntl, "useIntl").mockImplementation(
// @ts-ignore - only mock required method
// @ts-expect-error - only mock required method
(): Pick<IntlShape, "formatMessage"> => ({
formatMessage: jest.fn(),
}),
@ -72,7 +72,7 @@ describe("AppActionsHandler", function () {
*/
beforeEach((): void => {
delete window.location;
// @ts-ignore
// @ts-expect-error
window.location = {
href: "http://localhost:3000",
hostname: "localhost",

View file

@ -6,9 +6,7 @@ interface State {
error?: Error;
}
interface Cache {
[url: string]: AppstoreApi.SaleorApp[];
}
type Cache = Record<string, AppstoreApi.SaleorApp[]>;
// discriminated union type
type Action =

View file

@ -1,4 +1,4 @@
export * from "./AppInstallView";
export * from "./AppView";
export * from "./AppListView";
export * from "./AppManageView";
export * from "./AppView";

View file

@ -2,8 +2,8 @@ import { PermissionEnum } from "@dashboard/graphql";
import React from "react";
import { Route, RouteProps } from "react-router-dom";
import { useUser } from "..";
import NotFound from "../../NotFound";
import { useUser } from "..";
import { hasAllPermissions, hasAnyPermissions } from "../misc";
type MatchPermissionType = "all" | "any";

View file

@ -130,8 +130,6 @@ export function useAuthProvider({
navigate("/");
}
}
return;
};
const handleLogin = async (email: string, password: string) => {

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 === false;
const isSimpleProduct = !(productData.productType?.hasVariants);
const haveVariantsChannelListings = productData.variants.some(variant =>
variant.channelListings.some(
listing => listing.channel.id === channel.id,

View file

@ -111,7 +111,7 @@ const CardMenu: React.FC<CardMenuProps> = props => {
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current === true && open === false) {
if (prevOpen.current && !open) {
anchorRef.current!.focus();
}

View file

@ -237,7 +237,7 @@ export const ChannelAvailabilityItemContent: React.FC<ChannelContentProps> = ({
)
: ""
}
value={availableForPurchase ? availableForPurchase : ""}
value={availableForPurchase || ""}
onChange={e =>
onChange(id, {
...formData,

View file

@ -14,7 +14,7 @@ import { FilterContainer } from "../useFilterContainer";
const getFilterElement = (value: any, index: number): FilterElement => {
const possibleFilterElement = value[index];
return typeof possibleFilterElement != "string"
return typeof possibleFilterElement !== "string"
? possibleFilterElement
: null;
};

View file

@ -16,9 +16,7 @@ interface Props {
collection?: string[];
channel?: string[];
producttype?: string[];
attribute?: {
[attribute: string]: string[];
};
attribute?: Record<string, string[]>;
}
export const useInitialAPIState = ({

View file

@ -39,6 +39,7 @@ export class ConditionOptions extends Array<ConditionItem> {
return new ConditionOptions(options);
}
public static fromStaticElementName(name: StaticElementName) {
const options = STATIC_CONDITIONS[name];

View file

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

View file

@ -14,7 +14,7 @@ import {
} from "./fetchingParams";
const toFlatUrlTokens = (p: UrlToken[], c: TokenArray[number]) => {
if (typeof c == "string") {
if (typeof c === "string") {
return p;
}

View file

@ -8,6 +8,7 @@ type TokenType = "a" | "s";
// export type UrlEntry = Record<string, string | string[]>
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class UrlEntry {
constructor(key: string, value: string | string[]) {
this[key] = value;

View file

@ -109,7 +109,7 @@ const FiltersArea = ({ provider, onConfirm }) => {
<Box>
<_ExperimentalFilters
leftOptions={operands}
// @ts-ignore
// @ts-expect-error
value={value}
onChange={handleStateChange}
>
@ -134,7 +134,6 @@ export const ConditionalFilters = () => {
{provider.loading ? (
<Text>Loading...</Text>
) : (
// @ts-ignore
<FiltersArea provider={provider.value} onConfirm={provider.persist} />
)}
</Box>

View file

@ -36,7 +36,7 @@ export const useFilterContainer = (initialValue: FilterContainer) => {
const index = parseInt(position, 10);
setValue(v =>
v.map((el, elIndex) => {
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) {
el.updateLeftOperator(leftOperator);
}
@ -49,7 +49,7 @@ export const useFilterContainer = (initialValue: FilterContainer) => {
const index = parseInt(position, 10);
setValue(v =>
v.map((el, elIndex) => {
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) {
el.updateLeftLoadingState(loading);
}
@ -62,7 +62,7 @@ export const useFilterContainer = (initialValue: FilterContainer) => {
const index = parseInt(position, 10);
setValue(v =>
v.map((el, elIndex) => {
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) {
el.updateRightOperator(leftOperator);
}
@ -75,7 +75,7 @@ export const useFilterContainer = (initialValue: FilterContainer) => {
const index = parseInt(position, 10);
setValue(v =>
v.map((el, elIndex) => {
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) {
el.updateRightOptions(options);
}
@ -88,7 +88,7 @@ export const useFilterContainer = (initialValue: FilterContainer) => {
const index = parseInt(position, 10);
setValue(v =>
v.map((el, elIndex) => {
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) {
el.updateRightLoadingState(loading);
}
@ -102,7 +102,7 @@ export const useFilterContainer = (initialValue: FilterContainer) => {
setValue(v =>
v.map((el, elIndex) => {
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) {
el.updateCondition(conditionValue);
}

View file

@ -62,7 +62,7 @@ export const ControlledSwitch: React.FC<ControlledSwitchProps> = props => {
) : (
label
)}
<div>{secondLabel ? secondLabel : null}</div>
<div>{secondLabel || null}</div>
</div>
}
disabled={disabled}

View file

@ -1,2 +1,2 @@
export * from "./MoneyDiscountedCell";
export * from "./MoneyCell";
export * from "./MoneyDiscountedCell";

View file

@ -1,4 +1,4 @@
export { default } from "./Date";
export * from "./Date";
export * from "./DateTime";
export * from "./DateProvider";
export * from "./DateTime";

View file

@ -1,4 +1,3 @@
// @ts-strict-ignore
/* tslint:disable:no-submodule-imports */
import Dropzone from "react-dropzone/dist/index";
export default Dropzone;

View file

@ -17,7 +17,7 @@ const useStyles = makeStyles(
);
export type FilterGroupLabelProps<
K extends string = string
K extends string = string,
> = FilterFieldBaseProps<K>;
const FilterGroupLabel: React.FC<FilterGroupLabelProps> = ({

View file

@ -34,19 +34,17 @@ const useStyles = makeStyles(
}),
{ name: "FilterKeyValueField" },
);
const getUpdateArrayFn = <T,>(key: "key" | "value") => (
array: T[],
index: number,
value: string,
) => {
// @eslint-ignore-next-line
const getUpdateArrayFn =
<T,>(key: "key" | "value") =>
(array: T[], index: number, value: string) => {
const item = array[index];
return [
...array.slice(0, index),
{ ...item, [key]: value },
...array.slice(index + 1),
];
};
};
const updateKeyFn = getUpdateArrayFn<KeyValue>("key");
const updateValueFn = getUpdateArrayFn<KeyValue>("value");

View file

@ -46,7 +46,7 @@ export type IFilterElementMutableData = FilterElementCommonData &
FilterElementValueData;
export type IFilterElementMutableDataGeneric<
T extends FieldType
T extends FieldType,
> = T extends FieldType.keyValue
? KeyValueFilterElementData & FilterElementCommonData
: RegularFilterElementData & FilterElementCommonData;
@ -69,16 +69,16 @@ export type FilterElement<K extends string = string> = FilterElementCommon<K> &
Partial<UnknownFilterElementData>;
export type FilterElementRegular<
K extends string = string
K extends string = string,
> = FilterElementCommon<K> & RegularFilterElementData;
export type FilterElementKeyValue<
K extends string = string
K extends string = string,
> = FilterElementCommon<K> & KeyValueFilterElementData;
export type FilterElementGeneric<
K extends string,
T extends FieldType
T extends FieldType,
> = T extends FieldType.keyValue
? FilterElementKeyValue<K> & { type: T }
: FilterElementRegular<K> & { type: T };
@ -100,7 +100,7 @@ export const isFilterType = <T extends FieldType, K extends string = string>(
export interface FilterFieldBaseProps<
K extends string = string,
T extends FieldType | unknown = unknown
T extends FieldType | unknown = unknown,
> {
filter: T extends FieldType ? FilterElementGeneric<K, T> : FilterElement<K>;
onFilterPropertyChange: FilterDispatchFunction<K>;
@ -115,7 +115,7 @@ export type FilterErrorMessages<T extends string> = Record<
export type IFilter<
K extends string = string,
T extends FieldType | unknown = unknown
T extends FieldType | unknown = unknown,
> = T extends unknown
? Array<FilterElement<K>>
: T extends FieldType.keyValue

View file

@ -149,7 +149,7 @@ export function GraphiQL({
variables={variables}
>
<GraphiQLInterface
showPersistHeadersSettings={shouldPersistHeaders !== false}
showPersistHeadersSettings={shouldPersistHeaders}
{...props}
/>
</GraphiQLProvider>

View file

@ -19,7 +19,7 @@ const _IconButton: React.FC<any> = React.forwardRef(
);
export const IconButton = _IconButton as <
T extends React.ElementType = "button"
T extends React.ElementType = "button",
>(
props: IconButtonProps<T>,
) => ReturnType<typeof _IconButton>;

View file

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

View file

@ -110,7 +110,7 @@ const MultiAutocompleteSelectFieldComponent: React.FC<
// this is to prevent unwanted state updates when the dropdown is closed with an empty value,
// which downshift interprets as the value being updated with an empty string, causing side-effects
stateReducer={(state, changes) => {
if (changes.isOpen === false && state.inputValue === "") {
if (!changes.isOpen && state.inputValue === "") {
delete changes.inputValue;
}
return changes;

View file

@ -343,7 +343,7 @@ const MultiAutocompleteSelectFieldContent: React.FC<
className={clsx(classes.arrowInnerContainer, {
// Needs to be explicitely compared to false because
// scrolledToBottom can be either true, false or undefined
[classes.hide]: scrolledToBottom !== false,
[classes.hide]: scrolledToBottom,
})}
>
<SVG src={chevronDown} />

View file

@ -93,7 +93,7 @@ const Navigator: React.FC<NavigatorProps> = ({ visible, setVisibility }) => {
},
{
keyboardShortcut:
navigator.platform.toLowerCase().indexOf("mac") >= 0
navigator.platform.toLowerCase().includes("mac")
? "⌘+K"
: "Ctrl+K",
},

View file

@ -65,7 +65,7 @@ export const RadioSwitchField: React.FC<RadioSwitchFieldProps> = props => {
onChange({
target: {
name: event.target.name,
value: event.target.value === "true" ? true : false,
value: event.target.value === "true",
},
} as any);
};

View file

@ -22,7 +22,6 @@ export const SingleItem: React.FC<Props> = ({ menuItem }) => {
const extension = getMenuItemExtension(extensions, menuItem.id);
if (extension) {
extension.open();
return;
}
};
return (

View file

@ -108,7 +108,7 @@ const SingleAutocompleteSelectFieldComponent: React.FC<
// this is to prevent unwanted state updates when the dropdown is closed with an empty value,
// which downshift interprets as the value being updated with an empty string, causing side-effects
stateReducer={(_, changes) => {
if (changes.isOpen === false) {
if (!changes.isOpen) {
delete changes.inputValue;
}
return changes;

View file

@ -333,7 +333,7 @@ const SingleAutocompleteSelectFieldContent: React.FC<
className={clsx(classes.arrowInnerContainer, {
// Needs to be explicitly compared to false because
// scrolledToBottom can be either true, false or undefined
[classes.hide]: scrolledToBottom !== false,
[classes.hide]: scrolledToBottom,
})}
>
<SVG src={chevronDown} />

View file

@ -81,7 +81,7 @@ export const SingleSelectField: React.FC<SingleSelectFieldProps> = props => {
} = props;
const classes = useStyles(props);
const choicesByKey: { [key: string]: string } =
const choicesByKey: Record<string, string> =
choices === undefined
? {}
: choices.reduce((prev, curr) => {

View file

@ -1,5 +1,4 @@
export * from "./SortableTableBody";
export { default as SortableTableBody } from "./SortableTableBody";
export * from "./SortableTableRow";
export { default as SortableTableRow } from "./SortableTableRow";

View file

@ -1,3 +1,3 @@
export * from "./FilterTab";
export { default } from "./FilterTabs";
export * from "./FilterTabs";
export * from "./FilterTab";

View file

@ -96,7 +96,7 @@ const TableHead: React.FC<TableHeadProps> = props => {
>
<Checkbox
indeterminate={items && items.length > selected && selected > 0}
checked={selected === 0 ? false : true}
checked={selected !== 0}
disabled={disabled}
onChange={() => toggleAll(items, selected)}
/>

View file

@ -181,7 +181,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
type="date"
fullWidth={true}
helperText={getFieldError(errors, "publicationDate")?.message}
value={publicationDate ? publicationDate : ""}
value={publicationDate || ""}
onChange={onChange}
className={classes.date}
InputLabelProps={{
@ -250,7 +250,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
type="date"
fullWidth={true}
helperText={getFieldError(errors, "startDate")?.message}
value={availableForPurchase ? availableForPurchase : ""}
value={availableForPurchase || ""}
onChange={onChange}
className={classes.date}
InputLabelProps={{

View file

@ -94,9 +94,7 @@ const DiscountCountrySelectDialog: React.FC<
<TextField
name="query"
value={data.query}
onChange={event =>
change(event /* TO BE CHECKED: () => fetch(data.query)*/)
}
onChange={event => change(event)}
label={intl.formatMessage({
id: "8EGagh",
defaultMessage: "Filter Countries",

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./SaleListPage";
export * from "./SaleListPage";
export * from "./filters";

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./VoucherListPage";
export * from "./VoucherListPage";
export * from "./filters";

View file

@ -8,7 +8,7 @@ import { reduceFlagListArray } from "./reduceFlagListArray";
export class FlagsResolver {
private results: Promise<AvailableFlags.FlagList[]>;
private strategies: Strategy[];
private readonly strategies: Strategy[];
constructor(
strategies: Strategy[],

View file

@ -1,5 +1,5 @@
export type { FlagList } from "./availableFlags";
export { FeatureFlagsProvider } from "./FeatureFlagsProvider";
export { EnvVarsStrategy, LocalStorageStrategy } from "./strategies";
export { useFlag } from "./useFlag";
export { useAllFlags } from "./useAllFlags";
export type { FlagList } from "./availableFlags";
export { useFlag } from "./useFlag";

View file

@ -68,7 +68,7 @@ const GiftCardResendCodeDialog: React.FC<DialogProps> = ({ open, onClose }) => {
variables: {
input: {
id,
email: email ? email : null,
email: email || null,
channel: channelSlug,
},
},

View file

@ -1,5 +1,5 @@
export * from "./extendedTypes";
export * from "./hooks.generated";
export * from "./types.generated";
export * from "./typePolicies.generated";
export { default as introspectionQueryResultData } from "./fragmentTypes.generated";
export * from "./hooks.generated";
export * from "./typePolicies.generated";
export * from "./types.generated";

View file

@ -1,2 +1,2 @@
export * from "../makeQuery";
export * from "../makeMutation";
export * from "../makeQuery";

View file

@ -166,7 +166,6 @@ function useForm<T extends FormData, TErrors>(
if (!(name in data)) {
console.error(`Unknown form field: ${name}`);
return;
} else {
if (data[name] !== value) {
handleSetChanged(true);

View file

@ -12,8 +12,8 @@ const ErrorExclamationCircle = createSvgIcon(
>
<circle cx="12" cy="12" r="12" fill="#FE6D76" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M12.75 6H11.25V15H12.75V6ZM12.75 16.5H11.25V18H12.75V16.5Z"
fill="white"
/>

View file

@ -4,26 +4,26 @@ import React from "react";
const Miscellaneous = createSvgIcon(
<>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M4.00037 2.375C3.1029 2.375 2.37537 3.10254 2.37537 4L2.37537 9C2.37537 9.89746 3.1029 10.625 4.00037 10.625H9.00037C9.89783 10.625 10.6254 9.89746 10.6254 9V4C10.6254 3.10254 9.89783 2.375 9.00037 2.375L4.00037 2.375ZM3.62537 4C3.62537 3.79289 3.79326 3.625 4.00037 3.625L9.00037 3.625C9.20747 3.625 9.37537 3.79289 9.37537 4V9C9.37537 9.20711 9.20747 9.375 9.00037 9.375H4.00037C3.79326 9.375 3.62537 9.20711 3.62537 9L3.62537 4Z"
fill="currentColor"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M15.0004 2.375C14.1029 2.375 13.3754 3.10254 13.3754 4V9C13.3754 9.89746 14.1029 10.625 15.0004 10.625H20.0004C20.8978 10.625 21.6254 9.89746 21.6254 9L21.6254 4C21.6254 3.10254 20.8978 2.375 20.0004 2.375L15.0004 2.375ZM14.6254 4C14.6254 3.79289 14.7933 3.625 15.0004 3.625L20.0004 3.625C20.2075 3.625 20.3754 3.79289 20.3754 4L20.3754 9C20.3754 9.20711 20.2075 9.375 20.0004 9.375H15.0004C14.7933 9.375 14.6254 9.20711 14.6254 9V4Z"
fill="currentColor"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M2.37537 15C2.37537 14.1025 3.1029 13.375 4.00037 13.375H9.00037C9.89783 13.375 10.6254 14.1025 10.6254 15V20C10.6254 20.8975 9.89783 21.625 9.00037 21.625H4.00037C3.1029 21.625 2.37537 20.8975 2.37537 20L2.37537 15ZM4.00037 14.625C3.79326 14.625 3.62537 14.7929 3.62537 15L3.62537 20C3.62537 20.2071 3.79326 20.375 4.00037 20.375H9.00037C9.20747 20.375 9.37537 20.2071 9.37537 20V15C9.37537 14.7929 9.20747 14.625 9.00037 14.625H4.00037Z"
fill="currentColor"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M15.0004 13.375C14.1029 13.375 13.3754 14.1025 13.3754 15V20C13.3754 20.8975 14.1029 21.625 15.0004 21.625H20.0004C20.8978 21.625 21.6254 20.8975 21.6254 20L21.6254 15C21.6254 14.1025 20.8978 13.375 20.0004 13.375H15.0004ZM14.6254 15C14.6254 14.7929 14.7933 14.625 15.0004 14.625H20.0004C20.2075 14.625 20.3754 14.7929 20.3754 15L20.3754 20C20.3754 20.2071 20.2075 20.375 20.0004 20.375H15.0004C14.7933 20.375 14.6254 20.2071 14.6254 20V15Z"
fill="currentColor"
/>

View file

@ -54,8 +54,8 @@ export const OrderChangeWarehouseDialog: React.FC<
const intl = useIntl();
const { anchor, position, setAnchor } = useElementScroll();
const topShadow = isScrolledToTop(anchor, position, 20) === false;
const bottomShadow = isScrolledToBottom(anchor, position, 20) === false;
const topShadow = !isScrolledToTop(anchor, position, 20);
const bottomShadow = !isScrolledToBottom(anchor, position, 20);
const [query, setQuery] = React.useState<string>("");
const [selectedWarehouseId, setSelectedWarehouseId] = React.useState<

View file

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

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./OrderDraftListPage";
export * from "./OrderDraftListPage";
export * from "./filters";

View file

@ -115,7 +115,7 @@ export const OrderListDatagrid: React.FC<OrderListDatagridProps> = ({
columnSelect="single"
hasRowHover={hasRowHover}
freezeColumns={2}
verticalBorder={col => (col > 1 ? true : false)}
verticalBorder={col => col > 1}
availableColumns={visibleColumns}
onHeaderClicked={handleHeaderClick}
emptyText={intl.formatMessage(messages.emptyText)}

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./OrderListPage";
export * from "./OrderListPage";
export * from "./filters";

View file

@ -1,4 +1,4 @@
export * from "./ItemsCard";
export * from "./MaximalButton";
export * from "./ProductErrorCell";
export * from "./SubmitCard";
export * from "./MaximalButton";

View file

@ -26,7 +26,7 @@ export const PspReferenceLink: React.FC<PspRerefenceLinkProps> = ({
<a
href={href}
target="_blank"
rel="noopener noreferer"
rel="noopener noreferrer"
className={classes.link}
>
{children}

View file

@ -1,4 +1,4 @@
export * from "./EventStatus";
export * from "./EventItem";
export * from "./EventStatus";
export * from "./EventTime";
export * from "./PspReference";

View file

@ -53,7 +53,7 @@ const orderBase: OrderDetailsFragment = {
number: "19",
paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED,
status: OrderStatus.FULFILLED,
// @ts-ignore
// @ts-expect-error
total: {
__typename: "TaxedMoney",
gross: {

View file

@ -13,9 +13,9 @@ import {
} from "@dashboard/orders/components/OrderReturnPage/form";
class ReturnFormDataParser {
private order: OrderDetailsFragment;
private formData: OrderReturnFormData;
private refundsEnabled: boolean;
private readonly order: OrderDetailsFragment;
private readonly formData: OrderReturnFormData;
private readonly refundsEnabled: boolean;
constructor(data: {
order: OrderDetailsFragment;
@ -71,13 +71,13 @@ class ReturnFormDataParser {
};
};
private getAmountToRefund = (): number | undefined =>
private readonly getAmountToRefund = (): number | undefined =>
this.formData.amountCalculationMode ===
OrderRefundAmountCalculationMode.MANUAL
? this.formData.amount
: undefined;
private getParsedLineData = <
private readonly getParsedLineData = <
T extends OrderReturnFulfillmentLineInput | OrderReturnLineInput,
>(
itemsQuantities: FormsetQuantityData,
@ -99,7 +99,7 @@ class ReturnFormDataParser {
}, []);
};
private getShouldRefund = (
private readonly getShouldRefund = (
orderLines: OrderReturnLineInput[],
fulfillmentLines: OrderReturnFulfillmentLineInput[],
) => {
@ -122,7 +122,7 @@ class ReturnFormDataParser {
};
// eslint-disable-next-line @typescript-eslint/member-ordering
private static isLineRefundable = function <
private static readonly isLineRefundable = function <
T extends OrderReturnLineInput | OrderReturnFulfillmentLineInput,
>({ replace }: T) {
return !replace;

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./PluginsListPage";
export * from "./PluginsListPage";
export * from "./filters";

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./ProductTypeListPage";
export * from "./ProductTypeListPage";
export * from "./filters";

View file

@ -10,7 +10,7 @@ import { useIntl } from "react-intl";
interface ProductCategoryAndCollectionsFormProps {
categories?: Array<{ value: string; label: string }>;
collections?: Array<{ value: string; label: string }>;
errors: { [key: string]: string };
errors: Record<string, string>;
productCollections?: string[];
category?: string;
loading?: boolean;

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 === false;
const isSimpleProduct = !(data.productType?.hasVariants);
const errors = [...apiErrors, ...validationErrors];

View file

@ -1,3 +1,3 @@
export * from "./form";
export { default } from "./ProductCreatePage";
export * from "./ProductCreatePage";
export * from "./form";

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./ProductListPage";
export * from "./ProductListPage";
export * from "./filters";

View file

@ -371,7 +371,6 @@ export const ProductStocks: React.FC<ProductStocksProps> = ({
/>
</Box>
)}
{/* @ts-ignore */}
<Box __alignSelf="end">
<Button
name="hasPreorderEndDate"

View file

@ -83,7 +83,7 @@ const ProductVariantMediaSelectDialog: React.FC<
classes.imageContainer,
{
[classes.selectedImageContainer]:
selectedMedia.indexOf(mediaObj.id) !== -1,
selectedMedia.includes(mediaObj.id),
},
])}
onClick={() => handleMediaSelect(mediaObj.id)}

View file

@ -257,5 +257,5 @@ export const getSelectedMedia = <
selectedMediaIds: string[],
) =>
media
.filter(image => selectedMediaIds.indexOf(image.id) !== -1)
.filter(image => selectedMediaIds.includes(image.id))
.sort((prev, next) => (prev.sortOrder > next.sortOrder ? 1 : -1));

View file

@ -1,3 +1,3 @@
export * from "./filters";
export { default } from "./StaffListPage";
export * from "./StaffListPage";
export * from "./filters";

View file

@ -1,2 +1,2 @@
export * from "./useStaffUserOperations";
export * from "./useProfileOperations";
export * from "./useStaffUserOperations";

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

@ -31,7 +31,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
const navigate = useNavigator();
const shop = useShop();
if (Object.keys(TranslatableEntities).indexOf(params.tab) === -1) {
if (!Object.keys(TranslatableEntities).includes(params.tab)) {
navigate(
"?" +
stringifyQs({

View file

@ -1,5 +1,4 @@
export * from "./storage";
export { default as createFilterTabUtils } from "./storage";
export * from "./filters";
export { default as createFilterUtils } from "./filters";
export * from "./storage";
export { default as createFilterTabUtils } from "./storage";