diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index df9920bacf..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -src/core/cover-service-api/model/ -src/core/cover-service-api/cover-service.ts -src/core/dpl-cms/model -src/core/dpl-cms/dpl-cms.ts -src/core/fbs/fbs.ts -src/core/publizon/publizon.ts -*.test.ts -*.test.tsx diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index d707ae7fad..0000000000 --- a/.eslintrc +++ /dev/null @@ -1,152 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "extends": [ - "airbnb", - "airbnb-typescript", - "airbnb/hooks", - "plugin:@typescript-eslint/recommended", - "prettier", - "plugin:prettier/recommended", - "plugin:cypress/recommended" - ], - "plugins": ["no-only-tests"], - "settings": { - "react": { - "version": "16.11.0" - }, - // Since we use vitest alongside our production code we have to instruct eslint - // not to throw the import/no-extraneous-dependencies error when doing so. - "import/core-modules": ["vitest"] - }, - "env": { - "browser": true, - "es6": true - }, - "parserOptions": { - "sourceType": "module", - "allowImportExportEverywhere": false, - "ecmaFeatures": { - "jsx": true, - "globalReturn": false - }, - "project": "./tsconfig.json" - }, - "rules": { - "prefer-arrow-callback": [ - "error", - { - "allowNamedFunctions": false, - "allowUnboundThis": true - } - ], - "no-param-reassign": [ - "error", - { - "props": true, - "ignorePropertyModificationsFor": ["state"] - } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": [ - "/**/*.dev.jsx", - "/**/*.dev.tsx", - "/**/*.test.js", - "/**/*.test.jsx", - "/**/*.test.ts", - "/**/*.test.tsx", - "vitest.config.ts", - "webpack.config.js", - "webpack.helpers.js", - "postcss.config.js", - "orval.config.ts", - "cypress/plugins/index.js", - "cypress/support/index.ts", - "scripts/postcss-node-sass.js", - "scripts/post-process-generated-graphql.ts", - "cypress/utils/graphql-test-utils.ts" - ] - } - ], - // We like to use arrow function syntax also for functional components. - "react/function-component-definition": "off", - // No complaints about missing trailing comma - "@typescript-eslint/comma-dangle": "off", - "react-hooks/exhaustive-deps": [ - "warn", - { - "additionalHooks": "useDeepCompareEffect" - } - ], - "no-only-tests/no-only-tests": "warn" - }, - "overrides": [ - { - "files": ["*.js", "*.jsx"], - "parserOptions": { - "project": null - }, - "rules": { - // These rules were triggered on the former non-typescript codebase. - // We are planning to use only ts/tsx in the future - // Therefor we can seperate them by only being ignored on js/jsx files. - // Start - ddb-react former code - "react/jsx-no-bind": "off", - "react/function-component-definition": "off", - "react/forbid-prop-types": "off", - "react/destructuring-assignment": "off", - "@typescript-eslint/return-await": "off", - "no-param-reassign": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/naming-convention": "off", - "@typescript-eslint/dot-notation": "off", - "@typescript-eslint/no-implied-eval": "off", - "@typescript-eslint/no-throw-literal": "off" - // End - ddb-react former code - } - }, - { - "files": ["*.tsx", "*.ts"], - "rules": { - // We do not use prop-types in ts. - "react/prop-types": "off", - "react/require-default-props": "off", - "react/no-unused-prop-types": "off", - "no-underscore-dangle": [ - "error", - { - "allow": ["__typename"] - } - ], - "react/forbid-elements": [ - 1, - { - "forbid": [ - { - "element": "main", - "message": "dpl-cms provide a
to render react in, therefore you must use
to avoid duplicate main" - } - ] - } - ] - } - }, - { - "files": ["*.dev.jsx", "*.dev.tsx"], - "rules": { - // We need a simple way of passing args in stories via object spreading. - "react/jsx-props-no-spreading": "off" - } - }, - { - "files": ["*.entry.tsx"], - "rules": { - // Since we use High Order Functional Component in entries for text props - // and want to show the props being used we disable this rule. - "@typescript-eslint/no-unused-vars": "off" - } - } - ] -} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 03054ddad5..14381560db 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -3,7 +3,6 @@ name: Build and test on: pull_request jobs: - stylelint: name: Lint .scss if: '!github.event.deleted' @@ -71,7 +70,7 @@ jobs: with: github_token: ${{ secrets.github_token }} reporter: github-pr-check - eslint_flags: '--ext .js --ext .jsx ./src/' + eslint_flags: './src/' - name: Lint Javascript run: yarn lint:js diff --git a/.prettierignore b/.prettierignore index fc56054d73..1ba20b67bb 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ +.github/workflows/ .version.json.ejs diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000..12aded192c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,216 @@ +const prettier = require("eslint-config-prettier"); +const airbnbBase = require("eslint-config-airbnb"); +const airbnbTypeScript = require("eslint-config-airbnb-typescript"); +const airbnbHooks = require("eslint-config-airbnb/hooks"); +const prettierRecommended = require("eslint-plugin-prettier").configs + .recommended; +const cypress = require("eslint-plugin-cypress").configs.recommended; +// Include the recommended settings for @typescript-eslint +const typescriptRecommended = { + plugins: { + "@typescript-eslint": require("@typescript-eslint/eslint-plugin") + }, + rules: { + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/explicit-module-boundary-types": "off" + } +}; +const jsxA11yRecommended = require("eslint-plugin-jsx-a11y").configs + .recommended; + +// ESLint configuration using flat config +module.exports = [ + { + files: ["**/*.{ts,tsx,js,jsx}"], + languageOptions: { + parser: require("@typescript-eslint/parser"), + parserOptions: { + project: "./tsconfig.json", // Specify the TypeScript project configuration + sourceType: "module", + ecmaFeatures: { + jsx: true // Enable JSX support + } + } + }, + settings: { + react: { + version: "16.11.0" // React version for linting + }, + // Since we use vitest alongside our production code, we have to instruct ESLint + // not to throw the import/no-extraneous-dependencies error when doing so. + "import/core-modules": ["vitest"] + }, + plugins: { + "@typescript-eslint": require("@typescript-eslint/eslint-plugin"), + cypress: require("eslint-plugin-cypress"), + "react-hooks": require("eslint-plugin-react-hooks"), + react: require("eslint-plugin-react"), + import: require("eslint-plugin-import"), + "jsx-a11y": require("eslint-plugin-jsx-a11y"), + "no-only-tests": require("eslint-plugin-no-only-tests"), + prettier: require("eslint-plugin-prettier") + }, + rules: { + // Extend rules from airbnb, prettier, cypress, and @typescript-eslint plugins + ...airbnbBase.rules, + ...airbnbTypeScript.rules, + ...airbnbHooks.rules, + ...prettier.rules, + ...cypress.rules, + ...typescriptRecommended.rules, + ...jsxA11yRecommended.rules, + ...prettierRecommended.rules, + // Custom rules + "@typescript-eslint/consistent-type-imports": "off", + "prefer-arrow-callback": [ + "error", + { + allowNamedFunctions: false, + allowUnboundThis: true + } + ], + "no-param-reassign": [ + "error", + { + props: true, + ignorePropertyModificationsFor: ["state"] // Ignore state reassignment + } + ], + "import/no-extraneous-dependencies": [ + "error", + { + devDependencies: [ + "/**/*.dev.jsx", + "/**/*.dev.tsx", + "/**/*.test.js", + "/**/*.test.jsx", + "/**/*.test.ts", + "/**/*.test.tsx", + "vitest.config.ts", + "webpack.config.js", + "webpack.helpers.js", + "postcss.config.js", + "orval.config.ts", + "cypress/plugins/index.js", + "cypress/support/index.ts", + "scripts/postcss-node-sass.js", + "scripts/post-process-generated-graphql.ts", + "cypress/utils/graphql-test-utils.ts" + ] + } + ], + // Needed until new TypeScript versions are supported + "@typescript-eslint/no-empty-function": "off", + // We like to use arrow function syntax also for functional components. + "react/function-component-definition": "off", + // No complaints about missing trailing commas + "@typescript-eslint/comma-dangle": "off", + "react-hooks/exhaustive-deps": [ + "warn", + { + additionalHooks: "useDeepCompareEffect" + } + ], + "no-only-tests/no-only-tests": "warn", // Warn on `.only` in tests + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-ignore": true, // flag all `@ts-ignore` comments + "ts-expect-error": true, // flag all `@ts-expect-error` comments + "ts-nocheck": true, // flag all `@ts-nocheck` comments + "ts-check": true // flag all `@ts-check` comments + } + ], + "prettier/prettier": [ + "error", + { + // Needed to avoid conflicts with Prettier + "parser": "flow" + } + ] + } + }, + // JS/JSX-specific rules + { + files: ["*.js", "*.jsx"], + rules: { + // These rules were triggered on the former non-TypeScript codebase. + // We are planning to use only ts/tsx in the future. + // Therefore, we can separate them by only being ignored on js/jsx files. + // Start - ddb-react former code + "react/jsx-no-bind": "off", + "react/function-component-definition": "off", + "react/forbid-prop-types": "off", + "react/destructuring-assignment": "off", + "@typescript-eslint/return-await": "off", + "no-param-reassign": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/naming-convention": "off", + "@typescript-eslint/dot-notation": "off", + "@typescript-eslint/no-implied-eval": "off", + "@typescript-eslint/no-throw-literal": "off" + // End - ddb-react former code + } + }, + // TS/TSX-specific rules + { + files: ["*.tsx", "*.ts"], + rules: { + // We do not use prop-types in TypeScript. + "react/prop-types": "off", + "react/require-default-props": "off", + "react/no-unused-prop-types": "off", + "no-underscore-dangle": [ + "error", + { + allow: ["__typename"] // Allow specific underscores + } + ], + "react/forbid-elements": [ + 1, + { + forbid: [ + { + element: "main", + message: + "dpl-cms provides a
to render React in, therefore you must use
to avoid duplicate
" + } + ] + } + ] + } + }, + // Storybook development rules + { + files: ["*.dev.jsx", "*.dev.tsx"], + rules: { + // Allow spreading props in stories + "react/jsx-props-no-spreading": "off" + } + }, + // Entry point rules + { + files: ["*.entry.tsx"], + rules: { + // Disable unused vars rule for entry points + "@typescript-eslint/no-unused-vars": "off" + } + }, + // Ignore specific files + { + ignores: [ + "src/core/cover-service-api/model/*", + "src/core/cover-service-api/cover-service.ts", + "src/core/dpl-cms/model/*", + "src/core/dpl-cms/dpl-cms.ts", + "src/core/fbs/fbs.ts", + "src/core/publizon/publizon.ts", + "src/**/*.test.ts", + "src/**/*.test.tsx", + "eslint.config.js" + ] + } +]; diff --git a/package.json b/package.json index c8a5ec5994..5ff10796d8 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ }, "scripts": { "fmt": "prettier --config ./.prettierrc --write \"src/**/*.{js,jsx,ts,tsx}\"", - "lint:js": "eslint --ext .js --ext .jsx --ext .ts --ext .tsx --max-warnings 0 --cache --cache-location \".cache/eslint/\" ./src", - "lint:js:fix": "eslint --ext .js --ext .jsx --ext .ts --ext .tsx --fix ./src", + "lint:js": "eslint --max-warnings 0 --cache --cache-location \".cache/eslint/\" ./src", + "lint:js:fix": "eslint --fix ./src", "lint:markdown": "markdownlint-cli2", "lint:markdown:fix": "markdownlint-cli2-fix", "lint:scss": "stylelint \"./src/**/*.scss\"", @@ -23,10 +23,10 @@ "build": "npx concurrently --raw \"yarn clean\" \"yarn lint:scss:fix\" \"yarn build:js:prod\" \"yarn build:css:prod\"", "build:js:dev": "webpack --mode=development --config webpack.config.js", "build:js:prod": "NODE_ENV=production webpack --mode=production --config webpack.config.js", - "build:css:dev": "postcss ./src/apps/**/*.scss ./src/components/components.scss --ext css --dir ./dist", - "build:css:prod": "postcss ./src/apps/**/*.scss ./src/components/components.scss --no-map --ext css --dir ./dist --env production", + "build:css:dev": "postcss ./src/apps/**/*.scss ./src/components/components.scss --dir ./dist", + "build:css:prod": "postcss ./src/apps/**/*.scss ./src/components/components.scss --no-map --dir ./dist --env production", "watch": "npx concurrently --raw \"yarn watch:lint:js\" \"yarn watch:lint:scss\"", - "watch:css": "postcss ./src/apps/**/*.scss ./src/components/components.scss --ext css --dir ./dist --watch", + "watch:css": "postcss ./src/apps/**/*.scss ./src/components/components.scss --dir ./dist --watch", "watch:lint:scss": "chokidar \"./src/**/*.scss\" -c \"yarn lint:scss:fix\"", "watch:lint:js": "chokidar \"./src/**/*.{js,jsx,ts,tsx}\" -c \"yarn lint:js\"", "build:storybook": "storybook build -c .storybook -o dev", @@ -80,8 +80,8 @@ "@types/react-dom": "^18.3.1", "@types/react-flatpickr": "^3.8.11", "@types/react-redux": "^7.1.24", - "@typescript-eslint/eslint-plugin": "^5.23.0", - "@typescript-eslint/parser": "^7.16.0", + "@typescript-eslint/eslint-plugin": "^8.19.0", + "@typescript-eslint/parser": "^8.19.0", "@vitest/coverage-istanbul": "^2.1.8", "autoprefixer": "^10.4.20", "babel-loader": "^9.2.1", @@ -97,7 +97,7 @@ "cssnano": "^7.0.6", "cypress": "^13.17.0", "dotenv": "^16.4.7", - "eslint": "^8.57.0", + "eslint": "^9.17.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^18.0.0", "eslint-config-prettier": "^9.1.0", @@ -106,7 +106,7 @@ "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-no-only-tests": "^3.3.0", - "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.3", "eslint-plugin-react-hooks": "^5.1.0", "eslint-webpack-plugin": "^4.2.0", @@ -121,16 +121,16 @@ "postcss-cli": "^11.0.0", "postcss-loader": "^8.1.1", "postcss-scss": "^4.0.9", - "prettier": "^2.6.2", + "prettier": "^3.4.2", "replace-in-file": "^6.3.2", "sass": "^1.83.1", "source-map-support": "^0.5.21", "storybook": "^8.4.7", "style-loader": "^4.0.0", - "stylelint": "^15.11.0", + "stylelint": "^16.12.0", "stylelint-config-prettier": "^9.0.5", "stylelint-config-recommended-scss": "^14.1.0", - "stylelint-prettier": "^2.0.0", + "stylelint-prettier": "^5.0.2", "stylelint-scss": "^6.10.0", "stylelint-webpack-plugin": "^5.0.1", "svg-url-loader": "^8.0.0", diff --git a/src/apps/advanced-search/types.ts b/src/apps/advanced-search/types.ts index 0ac4bb359a..697b1ded83 100644 --- a/src/apps/advanced-search/types.ts +++ b/src/apps/advanced-search/types.ts @@ -34,7 +34,7 @@ export const advancedSearchIndexTranslations = { "term.isbn": "advancedSearchIdentifierText" } as const; -export type AdvancedSearchIndex = typeof advancedSearchIndexes[number]; +export type AdvancedSearchIndex = (typeof advancedSearchIndexes)[number]; export type AdvancedSearchClause = { value: "AND" | "OR" | "NOT"; diff --git a/src/apps/demo-modal/demo-modal.entry.tsx b/src/apps/demo-modal/demo-modal.entry.tsx index 93ecb96dc2..492b32c88e 100644 --- a/src/apps/demo-modal/demo-modal.entry.tsx +++ b/src/apps/demo-modal/demo-modal.entry.tsx @@ -1,16 +1,12 @@ import React from "react"; import { withText } from "../../core/utils/text"; import DemoModal from "./demo-modal"; -import { GlobalEntryTextProps } from "../../core/storybook/globalTextArgs"; - export interface DemoModalEntryProps { ariaLabelModalOneText: string; ariaLabelModalTwoText: string; screenReaderModalDescriptionText: string; } -const DemoModalEntry: React.FC = ( - props: DemoModalEntryProps -) => ; +const DemoModalEntry: React.FC = () => ; export default withText(DemoModalEntry); diff --git a/src/apps/loan-list/materials/manifestation.graphql b/src/apps/loan-list/materials/manifestation.graphql index 08ecaaa99e..729c7d0503 100644 --- a/src/apps/loan-list/materials/manifestation.graphql +++ b/src/apps/loan-list/materials/manifestation.graphql @@ -26,7 +26,6 @@ fragment ManifestationBasicDetails on Manifestation { } } - query getManifestationViaMaterialByFaust($faust: String!) { manifestation(faust: $faust) { ...ManifestationBasicDetails diff --git a/src/apps/loan-list/materials/selectable-material/selectable-material.tsx b/src/apps/loan-list/materials/selectable-material/selectable-material.tsx index 6e38800959..68b5bf9119 100644 --- a/src/apps/loan-list/materials/selectable-material/selectable-material.tsx +++ b/src/apps/loan-list/materials/selectable-material/selectable-material.tsx @@ -1,5 +1,3 @@ -/* eslint-disable jsx-a11y/no-noninteractive-tabindex */ -/* eslint-disable jsx-a11y/no-static-element-interactions */ import React, { FC, ReactNode } from "react"; import clsx from "clsx"; import { useText } from "../../../../core/utils/text"; diff --git a/src/apps/loan-list/materials/utils/digital-material-fetch-hoc.tsx b/src/apps/loan-list/materials/utils/digital-material-fetch-hoc.tsx index 0d854c404a..eaa0e91750 100644 --- a/src/apps/loan-list/materials/utils/digital-material-fetch-hoc.tsx +++ b/src/apps/loan-list/materials/utils/digital-material-fetch-hoc.tsx @@ -18,13 +18,7 @@ const fetchDigitalMaterial = // If this is a physical book, another HOC fetches the data and this // HOC just returns the component if (item.faust) { - return ( - - ); + return ; } if (item.identifier) { @@ -59,12 +53,7 @@ const fetchDigitalMaterial = if (!digitalMaterial) return null; return ( - + ); } return null; diff --git a/src/apps/loan-list/materials/utils/material-fetch-hoc.tsx b/src/apps/loan-list/materials/utils/material-fetch-hoc.tsx index d03baf9da9..fa2ade6441 100644 --- a/src/apps/loan-list/materials/utils/material-fetch-hoc.tsx +++ b/src/apps/loan-list/materials/utils/material-fetch-hoc.tsx @@ -27,13 +27,7 @@ const fetchMaterial = // If this is a digital book, another HOC fetches the data and this // HOC just returns the component if (item?.identifier) { - return ( - - ); + return ; } if (item?.faust) { @@ -77,14 +71,7 @@ const fetchMaterial = // in cases where the material is not found we return null, else we would load forever if (!material) return null; - return ( - - ); + return ; } return null; }; diff --git a/src/apps/material-grid/MaterialGrid.tsx b/src/apps/material-grid/MaterialGrid.tsx index 8f5f741341..6fd23f7606 100644 --- a/src/apps/material-grid/MaterialGrid.tsx +++ b/src/apps/material-grid/MaterialGrid.tsx @@ -60,7 +60,6 @@ const MaterialGrid: React.FC = ({ } if (!materials.length) { - // eslint-disable-next-line no-console console.warn(`No materials to show for MaterialGrid: ${title}`); return null; } diff --git a/src/apps/material-search/MaterialSearch.stories.tsx b/src/apps/material-search/MaterialSearch.stories.tsx index ec1c26a577..4233734033 100644 --- a/src/apps/material-search/MaterialSearch.stories.tsx +++ b/src/apps/material-search/MaterialSearch.stories.tsx @@ -76,7 +76,6 @@ const MaterialSearchHiddenInputs = ({ /> - {/* eslint-disable-next-line react/jsx-props-no-spreading */} ); @@ -247,7 +246,6 @@ export const WithPreviouslySelectedValues: Story = { const defaultMaterialType = previouslySelectedMaterialType; const modifiedProps = { ...args, defaultWorkId, defaultMaterialType }; - // eslint-disable-next-line react/jsx-props-no-spreading return ; } }; @@ -261,7 +259,6 @@ export const materialWithInvalidType: Story = { const defaultMaterialType = "invalid-type"; const modifiedProps = { ...args, defaultWorkId, defaultMaterialType }; - // eslint-disable-next-line react/jsx-props-no-spreading return ; } }; @@ -275,7 +272,6 @@ export const materialWithInvalidWorkId: Story = { const defaultMaterialType = previouslySelectedMaterialType; const modifiedProps = { ...args, defaultWorkId, defaultMaterialType }; - // eslint-disable-next-line react/jsx-props-no-spreading return ; } }; diff --git a/src/apps/material-search/useGetHiddenInputs.tsx b/src/apps/material-search/useGetHiddenInputs.tsx index d70fd53cdf..4309cb5df8 100644 --- a/src/apps/material-search/useGetHiddenInputs.tsx +++ b/src/apps/material-search/useGetHiddenInputs.tsx @@ -24,7 +24,6 @@ const useGetHiddenInputs = (uniqueIdentifier: string): HiddenInputsResult => { ) as HTMLInputElement | null; if (!workElement) { - // eslint-disable-next-line no-console console.debug( `Could not find input for work ID with unique identifier: ${uniqueIdentifier}` ); @@ -34,7 +33,6 @@ const useGetHiddenInputs = (uniqueIdentifier: string): HiddenInputsResult => { } if (!materialElement) { - // eslint-disable-next-line no-console console.debug( `Could not find input for material type with unique identifier: ${uniqueIdentifier}` ); diff --git a/src/apps/material-search/useUpdateFields.ts b/src/apps/material-search/useUpdateFields.ts index 13d9259c2f..c6cc7f32ed 100644 --- a/src/apps/material-search/useUpdateFields.ts +++ b/src/apps/material-search/useUpdateFields.ts @@ -41,7 +41,7 @@ const useUpdateFields = ({ } // Leaving a debug message hif the input element is not found. - // eslint-disable-next-line no-console + console.debug( `Could not find input element to update with ID: ${uniqueIdentifier}` ); diff --git a/src/apps/material/material.graphql b/src/apps/material/material.graphql index 63a1e41d1e..d198dc53fb 100644 --- a/src/apps/material/material.graphql +++ b/src/apps/material/material.graphql @@ -10,8 +10,7 @@ query getMaterialGlobally($wid: String!) { } } - -query getInfomedia ($id: String!) { +query getInfomedia($id: String!) { infomedia(id: $id) { error article { @@ -21,7 +20,7 @@ query getInfomedia ($id: String!) { } } -query getReviewManifestations ($pid: [String!]!) { +query getReviewManifestations($pid: [String!]!) { manifestations(pid: $pid) { ...ManifestationReviewFields } diff --git a/src/apps/menu/menu.stories.tsx b/src/apps/menu/menu.stories.tsx index 897b819bc7..21123c7806 100644 --- a/src/apps/menu/menu.stories.tsx +++ b/src/apps/menu/menu.stories.tsx @@ -218,7 +218,6 @@ export const UserMenu: Story = { searchHeaderFavoritesText: "Liked" }, render: (args) => { - // eslint-disable-next-line react/jsx-props-no-spreading const menu = ; // We use the Header component as context to the search bar. // It is the Header that creates the Search bar's design - diff --git a/src/apps/opening-hours-editor/DialogFormEdit.tsx b/src/apps/opening-hours-editor/DialogFormEdit.tsx index 42e9e204cd..b779029a6d 100644 --- a/src/apps/opening-hours-editor/DialogFormEdit.tsx +++ b/src/apps/opening-hours-editor/DialogFormEdit.tsx @@ -45,7 +45,6 @@ const DialogFormEdit: React.FC = ({ endTime }: EventFormOnSubmitType) => { if (!eventInfo.start || !eventInfo.end) { - // eslint-disable-next-line no-alert alert(t("openingHoursInvalidEventText")); return; } @@ -120,7 +119,6 @@ const DialogFormEdit: React.FC = ({ }; if (!eventInfo.start || !eventInfo.end) { - // eslint-disable-next-line no-alert alert(t("openingHoursInvalidEventText")); return null; } diff --git a/src/apps/opening-hours-editor/EventForm.tsx b/src/apps/opening-hours-editor/EventForm.tsx index 0606fe767b..99bce79108 100644 --- a/src/apps/opening-hours-editor/EventForm.tsx +++ b/src/apps/opening-hours-editor/EventForm.tsx @@ -1,6 +1,6 @@ // I dont know why eslint is complaining about label-has-associated-control // as the label is associated with the input field. I will disable it for now. -/* eslint-disable jsx-a11y/label-has-associated-control */ + import React, { useEffect, useState } from "react"; import { OpeningHoursCategoriesType } from "./types"; import { useText } from "../../core/utils/text"; diff --git a/src/apps/opening-hours-editor/helper.ts b/src/apps/opening-hours-editor/helper.ts index 99936dfc21..8688bd6b84 100644 --- a/src/apps/opening-hours-editor/helper.ts +++ b/src/apps/opening-hours-editor/helper.ts @@ -187,7 +187,7 @@ export const getInitialDateFromUrl = (): Date | null => { if (!Number.isNaN(date.getTime())) { return date; } - // eslint-disable-next-line no-console + console.debug( "Invalid date format in URL parameter: initialDate =", initialDateString diff --git a/src/apps/opening-hours-editor/useOpeningHoursEditor.tsx b/src/apps/opening-hours-editor/useOpeningHoursEditor.tsx index b4d72ead79..12355d039d 100644 --- a/src/apps/opening-hours-editor/useOpeningHoursEditor.tsx +++ b/src/apps/opening-hours-editor/useOpeningHoursEditor.tsx @@ -56,7 +56,6 @@ const useOpeningHoursEditor = () => { }; const onError = (message: string) => { - // eslint-disable-next-line no-alert alert(message); // reload page to get the latest data window.location.reload(); diff --git a/src/apps/opening-hours-sidebar/OpeningHoursSidebar.stories.tsx b/src/apps/opening-hours-sidebar/OpeningHoursSidebar.stories.tsx index 58837fcae5..8b5c7fa1ff 100644 --- a/src/apps/opening-hours-sidebar/OpeningHoursSidebar.stories.tsx +++ b/src/apps/opening-hours-sidebar/OpeningHoursSidebar.stories.tsx @@ -56,6 +56,5 @@ export default meta; type Story = StoryObj; export const App: Story = { - // eslint-disable-next-line react/jsx-props-no-spreading render: (args) => }; diff --git a/src/apps/opening-hours-sidebar/OpeningHoursSidebarDetails.tsx b/src/apps/opening-hours-sidebar/OpeningHoursSidebarDetails.tsx index 040853a3d1..34fd5fbfba 100644 --- a/src/apps/opening-hours-sidebar/OpeningHoursSidebarDetails.tsx +++ b/src/apps/opening-hours-sidebar/OpeningHoursSidebarDetails.tsx @@ -10,7 +10,6 @@ const OpeningHoursSidebarDetails: FC<
{openingHoursData.map(({ term, description }, i) => ( - // eslint-disable-next-line react/no-array-index-key
{term}
diff --git a/src/apps/recommendation/recommendation.stories.tsx b/src/apps/recommendation/recommendation.stories.tsx index f3b4556a7f..8a68485f29 100644 --- a/src/apps/recommendation/recommendation.stories.tsx +++ b/src/apps/recommendation/recommendation.stories.tsx @@ -60,6 +60,5 @@ export const Skeleton: Story = { ...Default.args }, - // eslint-disable-next-line react/jsx-props-no-spreading render: (args) => }; diff --git a/src/apps/recommender/recommender.graphql b/src/apps/recommender/recommender.graphql index b224b5015e..80fcd2cdd7 100644 --- a/src/apps/recommender/recommender.graphql +++ b/src/apps/recommender/recommender.graphql @@ -2,8 +2,8 @@ query recommendFromFaust($faust: String!, $limit: Int!) { recommend(faust: $faust, limit: $limit) { result { work { - ...WorkSmall + ...WorkSmall } } } -} \ No newline at end of file +} diff --git a/src/apps/reservation-list/list/reservation-list.stories.tsx b/src/apps/reservation-list/list/reservation-list.stories.tsx index 25a90d9aae..923149c37e 100644 --- a/src/apps/reservation-list/list/reservation-list.stories.tsx +++ b/src/apps/reservation-list/list/reservation-list.stories.tsx @@ -24,7 +24,7 @@ const meta: Meta = { title: "Apps / Reservation list", component: ReservationList, // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore: can't figure out how to type serviceUrlArgTypes, deleteReservationModalArgTypes, reservationMaterialDetailsPropTypes, blockedArgTypes, reservationListArgTypes, globalTextArgTypes and globalTextArgTypes + // @ts-ignore: can't figure out how to type serviceUrlArgTypes, deleteReservationModalArgTypes, reservationMaterialDetailsPropTypes,blockedArgTypes, reservationListArgTypes, globalTextArgTypes and globalTextArgTypes argTypes: { // Config ...serviceUrlArgTypes, diff --git a/src/apps/reservation-list/modal/reservation-details/helper.ts b/src/apps/reservation-list/modal/reservation-details/helper.ts index 6f8a52f171..93d95f1bb2 100644 --- a/src/apps/reservation-list/modal/reservation-details/helper.ts +++ b/src/apps/reservation-list/modal/reservation-details/helper.ts @@ -46,7 +46,7 @@ export const getReservationsForSaving = ({ selectedBranch: string; }) => { const getSelectedExpiryDate = (value: FormSelectValue) => - typeof value === "number" ? getFutureDateString(value) : expiryDate ?? ""; + typeof value === "number" ? getFutureDateString(value) : (expiryDate ?? ""); const getSelectedPickupBranch = (value: FormSelectValue) => typeof value === "string" ? value : selectedBranch; diff --git a/src/apps/reservation-list/modal/reservation-details/physical-list-details.tsx b/src/apps/reservation-list/modal/reservation-details/physical-list-details.tsx index 7d8137c678..83821f3a3a 100644 --- a/src/apps/reservation-list/modal/reservation-details/physical-list-details.tsx +++ b/src/apps/reservation-list/modal/reservation-details/physical-list-details.tsx @@ -83,7 +83,7 @@ const PhysicalListDetails: FC = ({ const saveChanges = (formSelectValue: FormSelectValue) => { setReservationStatus("pending"); if (!reservationIds || reservationIds.length === 0 || !selectedBranch) { - console.error("Missing reservationId or selectedBranch"); // eslint-disable-line no-console + console.error("Missing reservationId or selectedBranch"); setReservationStatus("error"); return; } diff --git a/src/apps/search-header/search-header.stories.tsx b/src/apps/search-header/search-header.stories.tsx index 2c9aad429f..752fc6a678 100644 --- a/src/apps/search-header/search-header.stories.tsx +++ b/src/apps/search-header/search-header.stories.tsx @@ -151,7 +151,6 @@ export const Search: Story = { // It is the Header that creates the Search bar's design - // - without it, the Search bar loses its shape. render: (args: SearchHeaderEntryProps) => ( - // eslint-disable-next-line react/jsx-props-no-spreading } /> ) }; diff --git a/src/apps/search-header/search-header.tsx b/src/apps/search-header/search-header.tsx index d0a0350444..7fb72bb73c 100644 --- a/src/apps/search-header/search-header.tsx +++ b/src/apps/search-header/search-header.tsx @@ -326,7 +326,6 @@ const SearchHeader: React.FC = () => { return (
{/* The downshift combobox uses prop spreading by design */} - {/* eslint-disable-next-line react/jsx-props-no-spreading */}
= ({ const t = useText(); return ( <> - {/* eslint-disable react/jsx-props-no-spreading */} {/* The downshift combobox works this way by design (line 43) */} {categoryData.map((item, incorrectIndex) => { // incorrectIndex because in the whole of autosuggest dropdown it is diff --git a/src/components/autosuggest-material/autosuggest-material.tsx b/src/components/autosuggest-material/autosuggest-material.tsx index 7f5ac7dd90..27aa83e394 100644 --- a/src/components/autosuggest-material/autosuggest-material.tsx +++ b/src/components/autosuggest-material/autosuggest-material.tsx @@ -31,7 +31,6 @@ const AutosuggestMaterial: React.FC = ({ const t = useText(); return ( <> - {/* eslint-disable react/jsx-props-no-spreading */} {/* The downshift combobox works this way by design (line 54) */} {materialData.map((item, incorrectIndex) => { // incorrectIndex because in the whole of autosuggest dropdown it is @@ -71,7 +70,6 @@ const AutosuggestMaterial: React.FC = ({ {...getItemProps({ item, index })} data-cy={dataCy} > - {/* eslint-enable react/jsx-props-no-spreading */}
= ({ const t = useText(); return ( <> - {/* eslint-disable react/jsx-props-no-spreading */} {/* The downshift combobox works this way by design */}
  • = ({ lang={isoLang} >

    - {/* eslint-enable react/jsx-props-no-spreading */} {item.type === SuggestionTypeEnum.Creator ? `${item.term} (${t("stringSuggestionAuthorText")})` : null} diff --git a/src/components/autosuggest/autosuggest.tsx b/src/components/autosuggest/autosuggest.tsx index b5b67c4212..01e884813a 100644 --- a/src/components/autosuggest/autosuggest.tsx +++ b/src/components/autosuggest/autosuggest.tsx @@ -43,7 +43,6 @@ export const Autosuggest: React.FC = ({ return ( <> - {/* eslint-disable react/jsx-props-no-spreading */} {/* The downshift combobox works this way by design */}

      = ({ style={!isOpen ? { display: "none" } : {}} data-cy={dataCy} > - {/* eslint-enable react/jsx-props-no-spreading */} - ; export const favourite: Story = { - // eslint-disable-next-line react/jsx-props-no-spreading render: (args: ButtonFavouriteProps) => { const addToListRequest = () => {}; return ( - // eslint-disable-next-line react/jsx-props-no-spreading ); } diff --git a/src/components/cover/cover.stories.tsx b/src/components/cover/cover.stories.tsx index e5afad5f47..07110d4c9c 100644 --- a/src/components/cover/cover.stories.tsx +++ b/src/components/cover/cover.stories.tsx @@ -60,7 +60,7 @@ type Story = StoryObj; export const Item: Story = { render: (args) => { const WrappedCover = withUrls(Cover); - // eslint-disable-next-line react/jsx-props-no-spreading + return ; } }; diff --git a/src/components/date-inputs/DateRangeInput.tsx b/src/components/date-inputs/DateRangeInput.tsx index 8da3ea3df2..09d4983a55 100644 --- a/src/components/date-inputs/DateRangeInput.tsx +++ b/src/components/date-inputs/DateRangeInput.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { FC } from "react"; // Do not understand why eslint is complaining about this import // It is for sure listed in the dependencies of package.json. -// eslint-disable-next-line import/no-extraneous-dependencies + import Flatpickr from "react-flatpickr"; // eslint-disable-next-line import/no-extraneous-dependencies import "flatpickr/dist/flatpickr.css"; diff --git a/src/components/dialog/Dialog.tsx b/src/components/dialog/Dialog.tsx index 50b598724d..18b02b15fd 100644 --- a/src/components/dialog/Dialog.tsx +++ b/src/components/dialog/Dialog.tsx @@ -1,6 +1,5 @@ // The dialog element allready has keyboard support -/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ -/* eslint-disable jsx-a11y/click-events-have-key-events */ + import React, { forwardRef } from "react"; import clsx from "clsx"; import iconCross from "@danskernesdigitalebibliotek/dpl-design-system/build/icons/basic/icon-cross.svg"; @@ -16,6 +15,7 @@ const Dialog = forwardRef( ({ children, closeDialog, isSidebar }, ref) => { useEscapeKey({ closeDialog }); return ( + // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions ( { // We just want to confirm that the click handler works and show it in storybook. - // eslint-disable-next-line no-alert + alert("Close button clicked!"); }} /> diff --git a/src/components/facet-line/intelligent-facets-search.graphql b/src/components/facet-line/intelligent-facets-search.graphql index b132226ae0..a026ede8b3 100644 --- a/src/components/facet-line/intelligent-facets-search.graphql +++ b/src/components/facet-line/intelligent-facets-search.graphql @@ -1,4 +1,9 @@ -query intelligentFacets ($q: SearchQueryInput!, $facetsLimit: Int!, $valuesLimit: Int!, $filters: SearchFiltersInput!) { +query intelligentFacets( + $q: SearchQueryInput! + $facetsLimit: Int! + $valuesLimit: Int! + $filters: SearchFiltersInput! +) { search(q: $q, filters: $filters) { intelligentFacets(limit: $facetsLimit) { name diff --git a/src/components/find-on-shelf/FindOnShelfModal.stories.tsx b/src/components/find-on-shelf/FindOnShelfModal.stories.tsx index 54ff5e0f7a..e382e3c8ca 100644 --- a/src/components/find-on-shelf/FindOnShelfModal.stories.tsx +++ b/src/components/find-on-shelf/FindOnShelfModal.stories.tsx @@ -93,7 +93,7 @@ const meta: Meta = { ...args, selectedPeriodical: storySelectedPeriodical }; - /* eslint-enable no-param-reassign */ + const { manifestations: [{ pid }] } = args; @@ -101,12 +101,10 @@ const meta: Meta = { return ( <> - {/* eslint-disable-next-line react/jsx-props-no-spreading */} ); diff --git a/src/components/guarded-app.tsx b/src/components/guarded-app.tsx index 6242032e71..1e602d4253 100644 --- a/src/components/guarded-app.tsx +++ b/src/components/guarded-app.tsx @@ -31,7 +31,7 @@ const GuardedApp = ({ app, children }: GuardedAppProps) => { const didAuthenticate = getUrlQueryParam(AUTH_PARAM); // We'll leave this debugging here temporarily also in the testing phase for troubleshooting. - // eslint-disable-next-line no-console + console.debug("PERSISTED REQUEST:", persistedRequest); useEffect(() => { @@ -40,11 +40,11 @@ const GuardedApp = ({ app, children }: GuardedAppProps) => { } // We'll leave this debugging here temporarily also in the testing phase for troubleshooting. - // eslint-disable-next-line no-console + console.debug("HAS REQUEST EXPIRED?", hasRequestExpired(persistedRequest)); - // eslint-disable-next-line no-console + console.debug("CURRENT TIMESTAMP", getCurrentUnixTime()); - // eslint-disable-next-line no-console + console.debug("EXPIRE TIMESTAMP", persistedRequest.expire); // If request has expired remove it. @@ -83,7 +83,7 @@ const GuardedApp = ({ app, children }: GuardedAppProps) => { // This is a special case. We need to return a JSX element // and children is not a JSX element. - // eslint-disable-next-line react/jsx-no-useless-fragment + return <>{children}; }; diff --git a/src/components/material/ReviewInfomedia.tsx b/src/components/material/ReviewInfomedia.tsx index fa1737af2d..c2041c78fd 100644 --- a/src/components/material/ReviewInfomedia.tsx +++ b/src/components/material/ReviewInfomedia.tsx @@ -123,7 +123,6 @@ const ReviewInfomedia: React.FC = ({ )} {/* We consider infomedia to be a trustworthy source & decided not to sanitize the text data that we render as HTML. */} - {/* eslint-disable react/no-danger */} {infomedia.article?.text && (

      = ({

      {headline}

      diff --git a/src/components/material/reserve-button.md b/src/components/material/reserve-button.md index bdeae1ced9..c6ab54f1e9 100644 --- a/src/components/material/reserve-button.md +++ b/src/components/material/reserve-button.md @@ -35,3 +35,4 @@ CannotbeReserved[The button says 'Cannot be reserved' + Is disabled] --yes--> DigitalArticle[The button says: 'Order digital copy'] 6{Does the manifestation have an issn digital article id?} --No--> InfomediaArticle[The button says 'See online'] +``` diff --git a/src/components/message/modal-message/ModalMessage.stories.tsx b/src/components/message/modal-message/ModalMessage.stories.tsx index 32e7464a0d..130927bb49 100644 --- a/src/components/message/modal-message/ModalMessage.stories.tsx +++ b/src/components/message/modal-message/ModalMessage.stories.tsx @@ -21,7 +21,6 @@ const Template: StoryFn = (props) => { classNames="modal-cta modal-padding" > @@ -49,7 +48,6 @@ const meta: Meta = { subTitle: "This is a subtitle" }, render: (args) => { - // eslint-disable-next-line react/jsx-props-no-spreading return