瀏覽代碼

chore: Migrate from TSLint to ESLint

Michael Bromley 2 年之前
父節點
當前提交
0441a0338a
共有 100 個文件被更改,包括 819 次插入571 次删除
  1. 288 0
      .eslintrc.js
  2. 10 2
      package.json
  3. 1 1
      packages/admin-ui-plugin/build.ts
  4. 1 1
      packages/admin-ui-plugin/package.json
  5. 11 9
      packages/admin-ui-plugin/src/plugin.ts
  6. 80 0
      packages/admin-ui/.eslintrc.json
  7. 18 2
      packages/admin-ui/angular.json
  8. 12 3
      packages/admin-ui/package.json
  9. 4 8
      packages/admin-ui/src/lib/catalog/src/catalog.routes.ts
  10. 1 0
      packages/admin-ui/src/lib/catalog/src/components/assets/assets.component.ts
  11. 4 6
      packages/admin-ui/src/lib/catalog/src/components/assign-products-to-channel-dialog/assign-products-to-channel-dialog.component.ts
  12. 1 1
      packages/admin-ui/src/lib/catalog/src/components/assign-to-channel-dialog/assign-to-channel-dialog.component.ts
  13. 4 8
      packages/admin-ui/src/lib/catalog/src/components/collection-detail/collection-detail.component.ts
  14. 2 4
      packages/admin-ui/src/lib/catalog/src/components/collection-list/collection-list.component.ts
  15. 1 1
      packages/admin-ui/src/lib/catalog/src/components/collection-tree/array-to-tree.ts
  16. 2 4
      packages/admin-ui/src/lib/catalog/src/components/facet-detail/facet-detail.component.ts
  17. 11 21
      packages/admin-ui/src/lib/catalog/src/components/product-detail/product-detail.component.ts
  18. 1 1
      packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.ts
  19. 1 1
      packages/admin-ui/src/lib/catalog/src/components/product-options-editor/product-options-editor.component.ts
  20. 9 17
      packages/admin-ui/src/lib/catalog/src/components/product-variants-editor/product-variants-editor.component.ts
  21. 1 3
      packages/admin-ui/src/lib/catalog/src/components/variant-price-detail/variant-price-detail.component.ts
  22. 5 11
      packages/admin-ui/src/lib/catalog/src/providers/product-detail/product-detail.service.ts
  23. 4 8
      packages/admin-ui/src/lib/core/src/app.component.ts
  24. 1 1
      packages/admin-ui/src/lib/core/src/common/base-list.component.ts
  25. 1 1
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  26. 1 1
      packages/admin-ui/src/lib/core/src/common/introspection-result.ts
  27. 2 4
      packages/admin-ui/src/lib/core/src/common/utilities/configurable-operation-utils.ts
  28. 1 1
      packages/admin-ui/src/lib/core/src/common/utilities/create-updated-translatable.spec.ts
  29. 1 3
      packages/admin-ui/src/lib/core/src/common/utilities/string-to-color.ts
  30. 4 5
      packages/admin-ui/src/lib/core/src/components/breadcrumb/breadcrumb.component.spec.ts
  31. 23 23
      packages/admin-ui/src/lib/core/src/components/breadcrumb/breadcrumb.component.ts
  32. 2 4
      packages/admin-ui/src/lib/core/src/components/channel-switcher/channel-switcher.component.ts
  33. 1 1
      packages/admin-ui/src/lib/core/src/components/notification/notification.component.ts
  34. 10 14
      packages/admin-ui/src/lib/core/src/data/client-state/client-resolvers.ts
  35. 2 4
      packages/admin-ui/src/lib/core/src/data/providers/fetch-adapter.ts
  36. 1 1
      packages/admin-ui/src/lib/core/src/data/utils/add-custom-fields.spec.ts
  37. 4 8
      packages/admin-ui/src/lib/core/src/data/utils/add-custom-fields.ts
  38. 1 1
      packages/admin-ui/src/lib/core/src/providers/bulk-action-registry/bulk-action-registry.service.ts
  39. 5 9
      packages/admin-ui/src/lib/core/src/providers/dashboard-widget/dashboard-widget.service.ts
  40. 1 3
      packages/admin-ui/src/lib/core/src/providers/health-check/health-check.service.ts
  41. 1 1
      packages/admin-ui/src/lib/core/src/providers/i18n/custom-message-format-compiler.ts
  42. 1 1
      packages/admin-ui/src/lib/core/src/providers/local-storage/local-storage.service.ts
  43. 1 1
      packages/admin-ui/src/lib/core/src/providers/nav-builder/nav-builder.service.spec.ts
  44. 1 1
      packages/admin-ui/src/lib/core/src/providers/nav-builder/nav-builder.service.ts
  45. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/asset-preview-dialog/asset-preview-dialog.component.ts
  46. 3 6
      packages/admin-ui/src/lib/core/src/shared/components/asset-search-input/asset-search-input.component.ts
  47. 4 4
      packages/admin-ui/src/lib/core/src/shared/components/bulk-action-menu/bulk-action-menu.component.ts
  48. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/dropdown/dropdown-item.directive.ts
  49. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/form-field/form-field-control.directive.ts
  50. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/modal-dialog/modal-dialog.component.ts
  51. 3 6
      packages/admin-ui/src/lib/core/src/shared/components/product-search-input/product-search-input.component.ts
  52. 4 4
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.service.ts
  53. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/inputrules.ts
  54. 2 2
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/keymap.ts
  55. 3 3
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/menu/menu.ts
  56. 59 61
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/plugins/image-plugin.ts
  57. 2 2
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/plugins/raw-editor-plugin.ts
  58. 65 70
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/plugins/tables-plugin.ts
  59. 3 1
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/prosemirror.service.ts
  60. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/raw-html-dialog/raw-html-dialog.component.ts
  61. 4 4
      packages/admin-ui/src/lib/core/src/shared/directives/if-default-channel-active.directive.ts
  62. 16 18
      packages/admin-ui/src/lib/core/src/shared/directives/if-multichannel.directive.spec.ts
  63. 4 4
      packages/admin-ui/src/lib/core/src/shared/directives/if-multichannel.directive.ts
  64. 2 6
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/code-editor-form-input/html-editor-form-input.component.ts
  65. 1 1
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/dynamic-form-input/dynamic-form-input.component.ts
  66. 4 4
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/customer/relation-customer-input.component.ts
  67. 4 4
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product-variant/relation-product-variant-input.component.ts
  68. 4 4
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product/relation-product-input.component.ts
  69. 1 0
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/relation-card/relation-card.component.ts
  70. 4 4
      packages/admin-ui/src/lib/customer/src/components/add-customer-to-group-dialog/add-customer-to-group-dialog.component.ts
  71. 4 4
      packages/admin-ui/src/lib/customer/src/components/customer-detail/customer-detail.component.ts
  72. 1 3
      packages/admin-ui/src/lib/customer/src/components/customer-group-member-list/customer-group-member-list.component.ts
  73. 8 10
      packages/admin-ui/src/lib/dashboard/src/widgets/order-summary-widget/order-summary-widget.component.ts
  74. 7 9
      packages/admin-ui/src/lib/marketing/src/components/promotion-detail/promotion-detail.component.ts
  75. 4 3
      packages/admin-ui/src/lib/order/src/components/cancel-order-dialog/cancel-order-dialog.component.ts
  76. 1 1
      packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.ts
  77. 8 8
      packages/admin-ui/src/lib/order/src/components/draft-order-detail/draft-order-detail.component.ts
  78. 4 7
      packages/admin-ui/src/lib/order/src/components/fulfillment-detail/fulfillment-detail.component.ts
  79. 8 6
      packages/admin-ui/src/lib/order/src/components/modification-detail/modification-detail.component.ts
  80. 8 8
      packages/admin-ui/src/lib/order/src/components/order-detail/order-detail.component.ts
  81. 3 3
      packages/admin-ui/src/lib/order/src/components/order-editor/order-editor.component.ts
  82. 1 1
      packages/admin-ui/src/lib/order/src/components/order-edits-preview-dialog/order-edits-preview-dialog.component.ts
  83. 4 4
      packages/admin-ui/src/lib/order/src/components/order-list/order-list.component.ts
  84. 1 3
      packages/admin-ui/src/lib/order/src/components/order-table/order-table.component.ts
  85. 4 10
      packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.ts
  86. 0 1
      packages/admin-ui/src/lib/order/src/components/select-shipping-method-dialog/select-shipping-method-dialog.component.ts
  87. 1 1
      packages/admin-ui/src/lib/order/src/providers/routing/order-resolver.ts
  88. 3 3
      packages/admin-ui/src/lib/settings/src/components/admin-detail/admin-detail.component.ts
  89. 1 1
      packages/admin-ui/src/lib/settings/src/components/channel-detail/channel-detail.component.ts
  90. 1 1
      packages/admin-ui/src/lib/settings/src/components/channel-list/channel-list.component.ts
  91. 2 4
      packages/admin-ui/src/lib/settings/src/components/country-list/country-list.component.ts
  92. 2 4
      packages/admin-ui/src/lib/settings/src/components/permission-grid/permission-grid.component.ts
  93. 3 3
      packages/admin-ui/src/lib/settings/src/components/shipping-method-detail/shipping-method-detail.component.ts
  94. 1 3
      packages/admin-ui/src/lib/settings/src/components/zone-member-list/zone-member-list.component.ts
  95. 1 1
      packages/admin-ui/src/lib/static/polyfills.ts
  96. 1 3
      packages/admin-ui/src/lib/system/src/components/job-list/job-list.component.ts
  97. 1 1
      packages/admin-ui/src/main.ts
  98. 1 1
      packages/admin-ui/src/test.ts
  99. 0 17
      packages/admin-ui/src/tslint.json
  100. 0 33
      packages/admin-ui/tslint.json

+ 288 - 0
.eslintrc.js

@@ -0,0 +1,288 @@
+/*
+👋 Hi! This file was autogenerated by tslint-to-eslint-config.
+https://github.com/typescript-eslint/tslint-to-eslint-config
+
+It represents the closest reasonable ESLint configuration to this
+project's original TSLint configuration.
+
+We recommend eventually switching this configuration to extend from
+the recommended rulesets in typescript-eslint.
+https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md
+
+Happy linting! 💖
+*/
+module.exports = {
+    env: {
+        es6: true,
+        node: true,
+    },
+    extends: [
+        'plugin:@typescript-eslint/recommended',
+        'plugin:@typescript-eslint/recommended-requiring-type-checking',
+        'prettier',
+    ],
+    ignorePatterns: ['**/generated*', '**/*.js', '**/*.d.ts', '/packages/ui-devkit/scaffold/**/*'],
+    parser: '@typescript-eslint/parser',
+    parserOptions: {
+        project: 'tsconfig.json',
+        sourceType: 'module',
+    },
+    plugins: [
+        'eslint-plugin-import',
+        'eslint-plugin-jsdoc',
+        'eslint-plugin-prefer-arrow',
+        '@typescript-eslint',
+    ],
+    root: true,
+    overrides: [
+        {
+            files: ['./packages/ui-devkit/src/client/**/*'],
+            parserOptions: {
+                project: 'tsconfig.json',
+                sourceType: 'module',
+            },
+        },
+        {
+            files: ['./packages/ui-devkit/src/compiler/**/*'],
+            parserOptions: {
+                project: 'tsconfig.compiler.json',
+                sourceType: 'module',
+            },
+        },
+    ],
+    rules: {
+        '@typescript-eslint/adjacent-overload-signatures': 'error',
+        '@typescript-eslint/array-type': [
+            'error',
+            {
+                default: 'array-simple',
+            },
+        ],
+        '@typescript-eslint/await-thenable': 'error',
+        '@typescript-eslint/ban-ts-comment': 'off',
+        '@typescript-eslint/ban-types': [
+            'error',
+            {
+                types: {
+                    Object: {
+                        message: 'Avoid using the `Object` type. Did you mean `object`?',
+                    },
+                    Function: {
+                        message:
+                            'Avoid using the `Function` type. Prefer a specific function type, like `() => void`.',
+                    },
+                    Boolean: {
+                        message: 'Avoid using the `Boolean` type. Did you mean `boolean`?',
+                    },
+                    Number: {
+                        message: 'Avoid using the `Number` type. Did you mean `number`?',
+                    },
+                    String: {
+                        message: 'Avoid using the `String` type. Did you mean `string`?',
+                    },
+                    Symbol: {
+                        message: 'Avoid using the `Symbol` type. Did you mean `symbol`?',
+                    },
+                },
+            },
+        ],
+        '@typescript-eslint/consistent-type-assertions': 'error',
+        '@typescript-eslint/consistent-type-definitions': 'off',
+        '@typescript-eslint/dot-notation': 'error',
+        '@typescript-eslint/explicit-function-return-type': 'off',
+        '@typescript-eslint/explicit-member-accessibility': [
+            'off',
+            {
+                accessibility: 'explicit',
+            },
+        ],
+        '@typescript-eslint/explicit-module-boundary-types': 'off',
+        '@typescript-eslint/indent': 'off',
+        '@typescript-eslint/member-ordering': 'off',
+        '@typescript-eslint/naming-convention': [
+            'off',
+            {
+                selector: 'variable',
+                format: ['camelCase', 'UPPER_CASE'],
+                leadingUnderscore: 'forbid',
+                trailingUnderscore: 'forbid',
+            },
+        ],
+        '@typescript-eslint/no-array-constructor': 'error',
+        '@typescript-eslint/no-empty-function': 'error',
+        '@typescript-eslint/no-empty-interface': 'off',
+        '@typescript-eslint/no-explicit-any': 'off',
+        '@typescript-eslint/no-extra-non-null-assertion': 'error',
+        '@typescript-eslint/no-extra-semi': 'error',
+        '@typescript-eslint/no-floating-promises': 'error',
+        '@typescript-eslint/no-for-in-array': 'error',
+        '@typescript-eslint/no-implied-eval': 'error',
+        '@typescript-eslint/no-inferrable-types': [
+            'error',
+            {
+                ignoreParameters: true,
+            },
+        ],
+        '@typescript-eslint/no-loss-of-precision': 'error',
+        '@typescript-eslint/no-misused-new': 'error',
+        '@typescript-eslint/no-misused-promises': 'warn',
+        '@typescript-eslint/no-namespace': 'error',
+        '@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
+        '@typescript-eslint/no-non-null-assertion': 'error',
+        '@typescript-eslint/no-parameter-properties': 'off',
+        '@typescript-eslint/no-shadow': [
+            'error',
+            {
+                hoist: 'all',
+            },
+        ],
+        '@typescript-eslint/no-this-alias': 'error',
+        '@typescript-eslint/no-unnecessary-type-assertion': 'error',
+        '@typescript-eslint/no-unnecessary-type-constraint': 'error',
+        '@typescript-eslint/no-unsafe-argument': 'off',
+        '@typescript-eslint/no-unsafe-assignment': 'off',
+        '@typescript-eslint/no-unsafe-call': 'off',
+        '@typescript-eslint/no-unsafe-member-access': 'off',
+        '@typescript-eslint/no-unsafe-return': 'off',
+        '@typescript-eslint/no-unused-expressions': 'error',
+        '@typescript-eslint/no-unused-vars': 'off',
+        '@typescript-eslint/no-use-before-define': 'off',
+        '@typescript-eslint/no-var-requires': 'error',
+        '@typescript-eslint/prefer-as-const': 'error',
+        '@typescript-eslint/prefer-for-of': 'error',
+        '@typescript-eslint/prefer-function-type': 'error',
+        '@typescript-eslint/prefer-namespace-keyword': 'error',
+        '@typescript-eslint/quotes': ['error', 'single'],
+        '@typescript-eslint/require-await': 'warn',
+        '@typescript-eslint/restrict-plus-operands': 'error',
+        '@typescript-eslint/restrict-template-expressions': 'error',
+        '@typescript-eslint/triple-slash-reference': [
+            'error',
+            {
+                path: 'always',
+                types: 'prefer-import',
+                lib: 'always',
+            },
+        ],
+        '@typescript-eslint/typedef': 'off',
+        '@typescript-eslint/unbound-method': 'error',
+        '@typescript-eslint/unified-signatures': 'error',
+        'arrow-parens': ['off', 'always'],
+        complexity: 'off',
+        'constructor-super': 'error',
+        'dot-notation': 'off',
+        eqeqeq: ['error', 'smart'],
+        'guard-for-in': 'error',
+        'id-denylist': 'off',
+        'id-match': 'off',
+        'import/order': [
+            'error',
+            {
+                alphabetize: {
+                    caseInsensitive: true,
+                    order: 'asc',
+                },
+                'newlines-between': 'always',
+                groups: [
+                    ['builtin', 'external', 'internal', 'unknown', 'object', 'type'],
+                    'parent',
+                    ['sibling', 'index'],
+                ],
+                distinctGroup: false,
+                pathGroupsExcludedImportTypes: [],
+                pathGroups: [
+                    {
+                        pattern: './',
+                        patternOptions: {
+                            nocomment: true,
+                            dot: true,
+                        },
+                        group: 'sibling',
+                        position: 'before',
+                    },
+                    {
+                        pattern: '.',
+                        patternOptions: {
+                            nocomment: true,
+                            dot: true,
+                        },
+                        group: 'sibling',
+                        position: 'before',
+                    },
+                    {
+                        pattern: '..',
+                        patternOptions: {
+                            nocomment: true,
+                            dot: true,
+                        },
+                        group: 'parent',
+                        position: 'before',
+                    },
+                    {
+                        pattern: '../',
+                        patternOptions: {
+                            nocomment: true,
+                            dot: true,
+                        },
+                        group: 'parent',
+                        position: 'before',
+                    },
+                ],
+            },
+        ],
+        indent: 'off',
+        'jsdoc/check-alignment': 'off',
+        'jsdoc/check-indentation': 'off',
+        'jsdoc/newline-after-description': 'off',
+        'max-classes-per-file': 'off',
+        'max-len': [
+            'error',
+            {
+                code: 170,
+            },
+        ],
+        'new-parens': 'error',
+        'no-array-constructor': 'off',
+        'no-bitwise': 'error',
+        'no-caller': 'error',
+        'no-cond-assign': 'error',
+        'no-console': 'error',
+        'no-debugger': 'error',
+        'no-empty': 'error',
+        'no-empty-function': 'off',
+        'no-eval': 'error',
+        'no-extra-semi': 'off',
+        'no-fallthrough': 'error',
+        'no-implied-eval': 'off',
+        'no-invalid-this': 'off',
+        'no-loss-of-precision': 'off',
+        'no-new-wrappers': 'error',
+        'no-shadow': 'off',
+        'no-throw-literal': 'error',
+        'no-trailing-spaces': 'error',
+        'no-undef-init': 'error',
+        'no-underscore-dangle': 'off',
+        'no-unsafe-finally': 'error',
+        'no-unused-expressions': 'off',
+        'no-unused-labels': 'error',
+        'no-unused-vars': 'off',
+        'no-use-before-define': 'off',
+        'no-var': 'error',
+        'object-shorthand': 'error',
+        'one-var': ['error', 'never'],
+        'prefer-arrow/prefer-arrow-functions': 'off',
+        'prefer-const': 'error',
+        quotes: 'off',
+        radix: 'error',
+        'require-await': 'off',
+        'spaced-comment': [
+            'error',
+            'always',
+            {
+                markers: ['/'],
+            },
+        ],
+        'use-isnan': 'error',
+        'valid-typeof': 'off',
+    },
+};

+ 10 - 2
package.json

@@ -8,7 +8,7 @@
   "scripts": {
     "watch": "lerna run watch --parallel",
     "watch:core-common": "lerna run --scope @vendure/common --scope @vendure/core watch --parallel",
-    "lint": "yarn tslint --fix",
+    "lint": "yarn eslint --fix",
     "format": "prettier --write --html-whitespace-sensitivity ignore",
     "bootstrap": "lerna bootstrap",
     "docs:generate-typescript-docs": "ts-node scripts/docs/generate-typescript-docs.ts",
@@ -52,7 +52,6 @@
     "lint-staged": "^10.5.4",
     "prettier": "^2.2.1",
     "ts-node": "^10.9.1",
-    "tslint": "^6.1.3",
     "typescript": "4.9.5",
     "unplugin-swc": "^1.3.2",
     "vitest": "^0.29.2"
@@ -91,5 +90,14 @@
       "pre-commit": "lint-staged",
       "pre-push": "yarn check-imports && yarn check-angular-versions && yarn build && yarn test && yarn e2e"
     }
+  },
+  "dependencies": {
+    "@typescript-eslint/eslint-plugin": "^5.54.1",
+    "@typescript-eslint/parser": "^5.54.1",
+    "eslint": "^8.35.0",
+    "eslint-config-prettier": "^8.7.0",
+    "eslint-plugin-import": "^2.27.5",
+    "eslint-plugin-jsdoc": "^40.0.1",
+    "eslint-plugin-prefer-arrow": "^1.2.3"
   }
 }

+ 1 - 1
packages/admin-ui-plugin/build.ts

@@ -1,4 +1,4 @@
-/* tslint:disable:no-console */
+/* eslint-disable no-console */
 import { execSync, spawn } from 'child_process';
 import fs from 'fs-extra';
 import path from 'path';

+ 1 - 1
packages/admin-ui-plugin/package.json

@@ -10,7 +10,7 @@
   "scripts": {
     "build": "rimraf lib && node -r ts-node/register build.ts && yarn compile",
     "watch": "tsc -p ./tsconfig.build.json --watch",
-    "lint": "tslint --fix --project ./",
+    "lint": "eslint --fix .",
     "compile": "tsc -p ./tsconfig.build.json"
   },
   "homepage": "https://www.vendure.io/",

+ 11 - 9
packages/admin-ui-plugin/src/plugin.ts

@@ -163,13 +163,13 @@ export class AdminUiPlugin implements NestModule {
                 )
                 .forRoutes('sockjs-node');
 
-            Logger.info(`Compiling Admin UI app in development mode`, loggerCtx);
+            Logger.info('Compiling Admin UI app in development mode', loggerCtx);
             app.compile().then(
                 () => {
-                    Logger.info(`Admin UI compiling and watching for changes...`, loggerCtx);
+                    Logger.info('Admin UI compiling and watching for changes...', loggerCtx);
                 },
                 (err: any) => {
-                    Logger.error(`Failed to compile: ${err}`, loggerCtx, err.stack);
+                    Logger.error(`Failed to compile: ${JSON.stringify(err)}`, loggerCtx, err.stack);
                 },
             );
             await overwriteConfig();
@@ -178,15 +178,15 @@ export class AdminUiPlugin implements NestModule {
             consumer.apply(await this.createStaticServer(app)).forRoutes(route);
 
             if (app && typeof app.compile === 'function') {
-                Logger.info(`Compiling Admin UI app in production mode...`, loggerCtx);
+                Logger.info('Compiling Admin UI app in production mode...', loggerCtx);
                 app.compile()
                     .then(overwriteConfig)
                     .then(
                         () => {
-                            Logger.info(`Admin UI successfully compiled`, loggerCtx);
+                            Logger.info('Admin UI successfully compiled', loggerCtx);
                         },
                         (err: any) => {
-                            Logger.error(`Failed to compile: ${err}`, loggerCtx, err.stack);
+                            Logger.error(`Failed to compile: ${JSON.stringify(err)}`, loggerCtx, err.stack);
                         },
                     );
             } else {
@@ -265,9 +265,11 @@ export class AdminUiPlugin implements NestModule {
         try {
             await fs.writeFile(adminUiConfigPath, JSON.stringify(config, null, 2));
         } catch (e: any) {
-            throw new Error('[AdminUiPlugin] Could not write vendure-ui-config.json file:\n' + e.message);
+            throw new Error(
+                '[AdminUiPlugin] Could not write vendure-ui-config.json file:\n' + JSON.stringify(e.message),
+            );
         }
-        Logger.verbose(`Applied configuration to vendure-ui-config.json file`, loggerCtx);
+        Logger.verbose('Applied configuration to vendure-ui-config.json file', loggerCtx);
     }
 
     /**
@@ -289,7 +291,7 @@ export class AdminUiPlugin implements NestModule {
             );
             await fs.writeFile(indexHtmlPath, withCustomBaseHref);
         } catch (e: any) {
-            throw new Error('[AdminUiPlugin] Could not write index.html file:\n' + e.message);
+            throw new Error('[AdminUiPlugin] Could not write index.html file:\n' + JSON.stringify(e.message));
         }
         Logger.verbose(`Applied baseHref "/${baseHref}/" to index.html file`, loggerCtx);
     }

+ 80 - 0
packages/admin-ui/.eslintrc.json

@@ -0,0 +1,80 @@
+{
+    "root": true,
+    "ignorePatterns": ["projects/**/*"],
+    "overrides": [
+        {
+            "files": ["*.ts"],
+            "parserOptions": {
+                "project": ["tsconfig.json"],
+                "createDefaultProgram": true
+            },
+            "extends": [
+                "plugin:@angular-eslint/ng-cli-compat",
+                "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
+                "plugin:@angular-eslint/template/process-inline-templates"
+            ],
+            "rules": {
+                "@angular-eslint/directive-selector": [
+                    "error",
+                    {
+                        "type": "attribute",
+                        "prefix": "vdr",
+                        "style": "camelCase"
+                    }
+                ],
+                "@angular-eslint/component-selector": [
+                    "error",
+                    {
+                        "type": "element",
+                        "prefix": "vdr",
+                        "style": "kebab-case"
+                    }
+                ],
+                "@angular-eslint/no-input-rename": "off",
+                "@typescript-eslint/array-type": [
+                    "error",
+                    {
+                        "default": "array-simple"
+                    }
+                ],
+                "@typescript-eslint/naming-convention": "off",
+                "@typescript-eslint/consistent-type-definitions": "off",
+                "@typescript-eslint/dot-notation": "off",
+                "@typescript-eslint/explicit-member-accessibility": [
+                    "off",
+                    {
+                        "accessibility": "explicit"
+                    }
+                ],
+                "@typescript-eslint/member-ordering": "off",
+                "@typescript-eslint/no-empty-function": "error",
+                "@typescript-eslint/no-empty-interface": "off",
+                "@typescript-eslint/no-floating-promises": "off",
+                "@typescript-eslint/no-var-requires": "error",
+                "arrow-parens": ["off", "always"],
+                "id-blacklist": "off",
+                "id-match": "off",
+                "import/order": "error",
+                "jsdoc/check-alignment": "off",
+                "jsdoc/newline-after-description": "off",
+                "max-len": [
+                    "error",
+                    {
+                        "code": 170
+                    }
+                ],
+                "no-empty": "error",
+                "no-underscore-dangle": "off",
+                "prefer-arrow/prefer-arrow-functions": "off"
+            }
+        },
+        {
+            "files": ["*.html"],
+            "extends": ["plugin:@angular-eslint/template/recommended"],
+            "rules": {
+              "@angular-eslint/template/no-negated-async": "off",
+              "@angular-eslint/template/eqeqeq": "off"
+            }
+        }
+    ]
+}

+ 18 - 2
packages/admin-ui/angular.json

@@ -24,7 +24,11 @@
             "polyfills": "src/lib/static/polyfills.ts",
             "tsConfig": "src/tsconfig.app.json",
             "assets": [
-              { "glob": "**/*", "input": "src/lib/static/", "output": "/" }
+              {
+                "glob": "**/*",
+                "input": "src/lib/static/",
+                "output": "/"
+              }
             ],
             "styles": [
               "src/lib/static/styles/styles.scss"
@@ -130,6 +134,15 @@
               ]
             }
           }
+        },
+        "lint": {
+          "builder": "@angular-eslint/builder:lint",
+          "options": {
+            "lintFilePatterns": [
+              "src/**/*.ts",
+              "src/**/*.html"
+            ]
+          }
         }
       }
     },
@@ -162,6 +175,9 @@
   },
   "cli": {
     "packageManager": "yarn",
-    "analytics": "61fa89f7-706a-46c0-bcdb-b1d3664195ce"
+    "analytics": "61fa89f7-706a-46c0-bcdb-b1d3664195ce",
+    "schematicCollections": [
+      "@angular-eslint/schematics"
+    ]
   }
 }

+ 12 - 3
packages/admin-ui/package.json

@@ -9,7 +9,7 @@
     "build": "node scripts/copy-package-json.js && node scripts/set-version.js && node scripts/build-public-api.js && yarn ng build vendure-admin-lib --configuration production && node scripts/compile-styles.js",
     "watch": "ng build --watch=true",
     "test": "ng test --watch=false --browsers=ChromeHeadlessCI --progress=false",
-    "lint": "tslint --fix",
+    "lint": "ng lint --fix",
     "extract-translations": "node scripts/extract-translations.js",
     "ngcc": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points"
   },
@@ -68,15 +68,25 @@
   },
   "devDependencies": {
     "@angular-devkit/build-angular": "^15.2.1",
+    "@angular-eslint/builder": "15.2.1",
+    "@angular-eslint/eslint-plugin": "15.2.1",
+    "@angular-eslint/eslint-plugin-template": "15.2.1",
+    "@angular-eslint/schematics": "15.2.1",
+    "@angular-eslint/template-parser": "15.2.1",
     "@angular/cli": "15.2.1",
     "@angular/compiler": "15.2.1",
     "@angular/compiler-cli": "15.2.1",
     "@types/jasmine": "~3.6.0",
     "@types/jasminewd2": "~2.0.6",
     "@types/node": "^14.14.31",
+    "@typescript-eslint/eslint-plugin": "5.48.2",
+    "@typescript-eslint/parser": "5.48.2",
     "@vendure/ngx-translate-extract": "^8.0.5",
-    "codelyzer": "^6.0.0",
     "cross-spawn": "^7.0.3",
+    "eslint": "^8.33.0",
+    "eslint-plugin-import": "latest",
+    "eslint-plugin-jsdoc": "latest",
+    "eslint-plugin-prefer-arrow": "latest",
     "fs-extra": "^10.0.0",
     "jasmine-core": "~3.99.1",
     "jasmine-spec-reporter": "~7.0.0",
@@ -89,7 +99,6 @@
     "ng-packagr": "15.2.2",
     "puppeteer": "^19.7.3",
     "rimraf": "^3.0.2",
-    "tslint": "~6.1.3",
     "typescript": "4.9.5"
   }
 }

+ 4 - 8
packages/admin-ui/src/lib/catalog/src/catalog.routes.ts

@@ -123,8 +123,7 @@ export function productBreadcrumb(data: any, params: any) {
 
 export function productVariantEditorBreadcrumb(data: any, params: any) {
     return data.entity.pipe(
-        map((entity: any) => {
-            return [
+        map((entity: any) => [
                 {
                     label: _('breadcrumb.products'),
                     link: ['../', 'products'],
@@ -137,15 +136,13 @@ export function productVariantEditorBreadcrumb(data: any, params: any) {
                     label: _('breadcrumb.manage-variants'),
                     link: ['manage-variants'],
                 },
-            ];
-        }),
+            ]),
     );
 }
 
 export function productOptionsEditorBreadcrumb(data: any, params: any) {
     return data.entity.pipe(
-        map((entity: any) => {
-            return [
+        map((entity: any) => [
                 {
                     label: _('breadcrumb.products'),
                     link: ['../', 'products'],
@@ -158,8 +155,7 @@ export function productOptionsEditorBreadcrumb(data: any, params: any) {
                     label: _('breadcrumb.product-options'),
                     link: ['options'],
                 },
-            ];
-        }),
+            ]),
     );
 }
 

+ 1 - 0
packages/admin-ui/src/lib/catalog/src/components/assets/assets.component.ts

@@ -45,6 +45,7 @@ export class AssetsComponent {
     @HostBinding('class.compact')
     @Input()
     compact = false;
+    // eslint-disable-next-line @angular-eslint/no-output-native
     @Output() change = new EventEmitter<AssetChange>();
 
     public assets: Asset[] = [];

+ 4 - 6
packages/admin-ui/src/lib/catalog/src/components/assign-products-to-channel-dialog/assign-products-to-channel-dialog.component.ts

@@ -46,7 +46,7 @@ export class AssignProductsToChannelDialogComponent implements OnInit, Dialog<an
         const allChannels$ = this.dataService.settings.getChannels().mapSingle(data => data.channels);
 
         combineLatest(activeChannelId$, allChannels$).subscribe(([activeChannelId, channels]) => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             this.currentChannel = channels.find(c => c.id === activeChannelId)!;
             this.availableChannels = channels;
         });
@@ -59,14 +59,12 @@ export class AssignProductsToChannelDialogComponent implements OnInit, Dialog<an
             from(this.getTopVariants(10)),
             this.priceFactorControl.valueChanges.pipe(startWith(1)),
         ).pipe(
-            map(([variants, factor]) => {
-                return variants.map(v => ({
+            map(([variants, factor]) => variants.map(v => ({
                     id: v.id,
                     name: v.name,
                     price: v.price,
                     pricePreview: v.price * +factor,
-                }));
-            }),
+                }))),
         );
     }
 
@@ -101,7 +99,7 @@ export class AssignProductsToChannelDialogComponent implements OnInit, Dialog<an
                     .subscribe(() => {
                         this.notificationService.success(_('catalog.assign-variant-to-channel-success'), {
                             channel: selectedChannel.code,
-                            // tslint:disable-next-line:no-non-null-assertion
+                            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                             count: this.productVariantIds!.length,
                         });
                         this.resolveWith(true);

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/assign-to-channel-dialog/assign-to-channel-dialog.component.ts

@@ -29,7 +29,7 @@ export class AssignToChannelDialogComponent implements OnInit, Dialog<Channel> {
         const allChannels$ = this.dataService.settings.getChannels().mapSingle(data => data.channels);
 
         combineLatest(activeChannelId$, allChannels$).subscribe(([activeChannelId, channels]) => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             this.currentChannel = channels.find(c => c.id === activeChannelId)!;
             this.availableChannels = channels;
         });

+ 4 - 8
packages/admin-ui/src/lib/catalog/src/components/collection-detail/collection-detail.component.ts

@@ -341,16 +341,12 @@ export class CollectionDetailComponent
         operations: ConfigurableOperation[],
         formValueOperations: any,
     ): ConfigurableOperationInput[] {
-        return operations.map((o, i) => {
-            return {
+        return operations.map((o, i) => ({
                 code: o.code,
-                arguments: Object.entries(formValueOperations[i].args).map(([name, value], j) => {
-                    return {
+                arguments: Object.entries(formValueOperations[i].args).map(([name, value], j) => ({
                         name,
                         value: encodeConfigArgValue(value),
-                    };
-                }),
-            };
-        });
+                    })),
+            }));
     }
 }

+ 2 - 4
packages/admin-ui/src/lib/catalog/src/components/collection-list/collection-list.component.ts

@@ -147,8 +147,7 @@ export class CollectionListComponent implements OnInit, OnDestroy {
             .pipe(
                 take(1),
                 map(items => -1 < items.findIndex(i => i.parent && i.parent.id === id)),
-                switchMap(hasChildren => {
-                    return this.modalService.dialog({
+                switchMap(hasChildren => this.modalService.dialog({
                         title: _('catalog.confirm-delete-collection'),
                         body: hasChildren
                             ? _('catalog.confirm-delete-collection-and-children-body')
@@ -157,8 +156,7 @@ export class CollectionListComponent implements OnInit, OnDestroy {
                             { type: 'secondary', label: _('common.cancel') },
                             { type: 'danger', label: _('common.delete'), returnValue: true },
                         ],
-                    });
-                }),
+                    })),
                 switchMap(response => (response ? this.dataService.collection.deleteCollection(id) : EMPTY)),
             )
             .subscribe(

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/collection-tree/array-to-tree.ts

@@ -41,7 +41,7 @@ export function arrayToTree<T extends HasParent>(
             }
         }
     }
-    // tslint:disable-next-line:no-non-null-assertion
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     const rootId = topLevelNodes.length ? topLevelNodes[0].parent!.id : undefined;
     return { id: rootId, children: topLevelNodes };
 }

+ 2 - 4
packages/admin-ui/src/lib/catalog/src/components/facet-detail/facet-detail.component.ts

@@ -430,8 +430,7 @@ export class FacetDetailComponent
             throw new Error(_(`error.facet-value-form-values-do-not-match`));
         }
         return dirtyValues
-            .map((value, i) => {
-                return createUpdatedTranslatable({
+            .map((value, i) => createUpdatedTranslatable({
                     translatable: value,
                     updatedFields: dirtyValueValues[i],
                     customFieldConfig: this.customValueFields,
@@ -440,8 +439,7 @@ export class FacetDetailComponent
                         languageCode,
                         name: '',
                     },
-                });
-            })
+                }))
             .filter(notNullOrUndefined);
     }
 }

+ 11 - 21
packages/admin-ui/src/lib/catalog/src/components/product-detail/product-detail.component.ts

@@ -148,8 +148,7 @@ export class ProductDetailComponent
             skipUntil(initialVariants$),
             skip(1),
             debounceTime(100),
-            switchMap(([term, currentPage, itemsPerPage]) => {
-                return this.dataService.product
+            switchMap(([term, currentPage, itemsPerPage]) => this.dataService.product
                     .getProductVariants(
                         {
                             skip: (currentPage - 1) * itemsPerPage,
@@ -161,8 +160,7 @@ export class ProductDetailComponent
                         },
                         this.id,
                     )
-                    .mapStream(({ productVariants }) => productVariants);
-            }),
+                    .mapStream(({ productVariants }) => productVariants)),
             shareReplay({ bufferSize: 1, refCount: true }),
         );
         const updatedVariants$ = variantsList$.pipe(map(result => result.items));
@@ -195,7 +193,7 @@ export class ProductDetailComponent
 
         const productFacetValues$ = this.product$.pipe(map(product => product.facetValues));
         const productGroup = this.getProductFormGroup();
-        // tslint:disable-next-line:no-non-null-assertion
+        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
         const formFacetValueIdChanges$ = productGroup.get('facetValueIds')!.valueChanges.pipe(
             skip(1),
             distinctUntilChanged(),
@@ -250,15 +248,13 @@ export class ProductDetailComponent
         this.productChannels$
             .pipe(
                 take(1),
-                switchMap(channels => {
-                    return this.modalService.fromComponent(AssignProductsToChannelDialogComponent, {
+                switchMap(channels => this.modalService.fromComponent(AssignProductsToChannelDialogComponent, {
                         size: 'lg',
                         locals: {
                             productIds: [this.id],
                             currentChannelIds: channels.map(c => c.id),
                         },
-                    });
-                }),
+                    })),
             )
             .subscribe();
     }
@@ -266,8 +262,7 @@ export class ProductDetailComponent
     removeFromChannel(channelId: string) {
         from(getChannelCodeFromUserStatus(this.dataService, channelId))
             .pipe(
-                switchMap(({ channelCode }) => {
-                    return this.modalService.dialog({
+                switchMap(({ channelCode }) => this.modalService.dialog({
                         title: _('catalog.remove-product-from-channel'),
                         buttons: [
                             { type: 'secondary', label: _('common.cancel') },
@@ -278,8 +273,7 @@ export class ProductDetailComponent
                                 returnValue: true,
                             },
                         ],
-                    });
-                }),
+                    })),
                 switchMap(response =>
                     response
                         ? this.dataService.product.removeProductsFromChannel({
@@ -315,8 +309,7 @@ export class ProductDetailComponent
     removeVariantFromChannel({ channelId, variant }: { channelId: string; variant: ProductVariantFragment }) {
         from(getChannelCodeFromUserStatus(this.dataService, channelId))
             .pipe(
-                switchMap(({ channelCode }) => {
-                    return this.modalService.dialog({
+                switchMap(({ channelCode }) => this.modalService.dialog({
                         title: _('catalog.remove-product-variant-from-channel'),
                         buttons: [
                             { type: 'secondary', label: _('common.cancel') },
@@ -327,8 +320,7 @@ export class ProductDetailComponent
                                 returnValue: true,
                             },
                         ],
-                    });
-                }),
+                    })),
                 switchMap(response =>
                     response
                         ? this.dataService.product.removeVariantsFromChannel({
@@ -423,9 +415,7 @@ export class ProductDetailComponent
     variantsToCreateAreValid(): boolean {
         return (
             0 < this.createVariantsConfig.variants.length &&
-            this.createVariantsConfig.variants.every(v => {
-                return v.sku !== '';
-            })
+            this.createVariantsConfig.variants.every(v => v.sku !== '')
         );
     }
 
@@ -470,7 +460,7 @@ export class ProductDetailComponent
                     this.router.navigate(['../', productId], { relativeTo: this.route });
                 },
                 err => {
-                    // tslint:disable-next-line:no-console
+                    // eslint-disable-next-line no-console
                     console.error(err);
                     this.notificationService.error(_('common.notify-create-error'), {
                         entity: 'Product',

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.ts

@@ -82,7 +82,7 @@ export class ProductListComponent
             (...args: any[]) =>
                 this.dataService.product.searchProducts(this.searchTerm, ...args).refetchOnChannelChange(),
             data => data.search,
-            // tslint:disable-next-line:no-shadowed-variable
+            // eslint-disable-next-line @typescript-eslint/no-shadow
             (skip, take) => ({
                 input: {
                     skip,

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/product-options-editor/product-options-editor.component.ts

@@ -81,7 +81,7 @@ export class ProductOptionsEditorComponent extends BaseDetailComponent<ProductWi
         if (this.detailForm.invalid || this.detailForm.pristine) {
             return;
         }
-        // tslint:disable-next-line:no-non-null-assertion
+        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
         const $product = this.dataService.product.getProduct(this.id).mapSingle(data => data.product!);
         combineLatest(this.entity$, this.languageCode$, $product)
             .pipe(

+ 9 - 17
packages/admin-ui/src/lib/catalog/src/components/product-variants-editor/product-variants-editor.component.ts

@@ -328,12 +328,10 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware {
     }
 
     private checkUniqueSkus() {
-        const withDuplicateSkus = this.generatedVariants.filter((variant, index) => {
-            return (
+        const withDuplicateSkus = this.generatedVariants.filter((variant, index) => (
                 variant.enabled &&
                 this.generatedVariants.find(gv => gv.sku.trim() === variant.sku.trim() && gv !== variant)
-            );
-        });
+            ));
         if (withDuplicateSkus.length) {
             return this.modalService
                 .dialog({
@@ -357,9 +355,7 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware {
                     },
                 })
                 .pipe(
-                    mergeMap(res => {
-                        return res === true ? of(true) : EMPTY;
-                    }),
+                    mergeMap(res => res === true ? of(true) : EMPTY),
                 );
         } else {
             return of(true);
@@ -381,12 +377,10 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware {
     ): Observable<Array<CreateProductOptionGroupMutation['createProductOptionGroup']>> {
         if (createdOptionGroups.length) {
             return forkJoin(
-                createdOptionGroups.map(optionGroup => {
-                    return this.dataService.product.addOptionGroupToProduct({
+                createdOptionGroups.map(optionGroup => this.dataService.product.addOptionGroupToProduct({
                         productId: this.product.id,
                         optionGroupId: optionGroup.id,
-                    });
-                }),
+                    })),
             ).pipe(map(() => createdOptionGroups));
         } else {
             return of([]);
@@ -493,9 +487,9 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware {
 
     initOptionsAndVariants() {
         this.dataService.product
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             .getProductVariantsOptions(this.route.snapshot.paramMap.get('id')!)
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             .mapSingle(({ product }) => product!)
             .subscribe(p => {
                 this.product = p;
@@ -503,8 +497,7 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware {
                 const allUsedOptionGroupIds = p.variants
                     .map(v => v.options.map(option => option.groupId))
                     .flat();
-                this.optionGroups = p.optionGroups.map(og => {
-                    return {
+                this.optionGroups = p.optionGroups.map(og => ({
                         id: og.id,
                         isNew: false,
                         name: og.name,
@@ -514,8 +507,7 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware {
                             name: o.name,
                             locked: allUsedOptionIds.includes(o.id),
                         })),
-                    };
-                });
+                    }));
                 this.generateVariants();
             });
     }

+ 1 - 3
packages/admin-ui/src/lib/catalog/src/components/variant-price-detail/variant-price-detail.component.ts

@@ -50,9 +50,7 @@ export class VariantPriceDetailComponent implements OnInit, OnChanges {
         );
 
         this.grossPrice$ = combineLatest(this.taxRate$, this.priceChange$).pipe(
-            map(([taxRate, price]) => {
-                return Math.round(price * ((100 + taxRate) / 100));
-            }),
+            map(([taxRate, price]) => Math.round(price * ((100 + taxRate) / 100))),
         );
     }
 

+ 5 - 11
packages/admin-ui/src/lib/catalog/src/providers/product-detail/product-detail.service.ts

@@ -53,18 +53,14 @@ export class ProductDetailService {
             mergeMap(([{ createProduct }, optionGroups]) => {
                 const addOptionsToProduct$ = optionGroups.length
                     ? forkJoin(
-                          optionGroups.map(optionGroup => {
-                              return this.dataService.product.addOptionGroupToProduct({
+                          optionGroups.map(optionGroup => this.dataService.product.addOptionGroupToProduct({
                                   productId: createProduct.id,
                                   optionGroupId: optionGroup.id,
-                              });
-                          }),
+                              })),
                       )
                     : of([]);
                 return addOptionsToProduct$.pipe(
-                    map(() => {
-                        return { createProduct, optionGroups };
-                    }),
+                    map(() => ({ createProduct, optionGroups })),
                 );
             }),
             mergeMap(({ createProduct, optionGroups }) => {
@@ -94,8 +90,7 @@ export class ProductDetailService {
     createProductOptionGroups(groups: Array<{ name: string; values: string[] }>, languageCode: LanguageCode) {
         return groups.length
             ? forkJoin(
-                  groups.map(c => {
-                      return this.dataService.product
+                  groups.map(c => this.dataService.product
                           .createProductOptionGroups({
                               code: normalizeString(c.name, '-'),
                               translations: [{ languageCode, name: c.name }],
@@ -104,8 +99,7 @@ export class ProductDetailService {
                                   translations: [{ languageCode, name: v }],
                               })),
                           })
-                          .pipe(map(data => data.createProductOptionGroup));
-                  }),
+                          .pipe(map(data => data.createProductOptionGroup))),
               )
             : of([]);
     }

+ 4 - 8
packages/admin-ui/src/lib/core/src/app.component.ts

@@ -45,14 +45,10 @@ export class AppComponent implements OnInit {
             .mapStream(({ userStatus }) => userStatus.isLoggedIn)
             .pipe(
                 filter(loggedIn => loggedIn === true),
-                switchMap(() => {
-                    return this.dataService.client.uiState().mapStream(data => data.uiState.contentLanguage);
-                }),
-                switchMap(contentLang => {
-                    return this.serverConfigService
+                switchMap(() => this.dataService.client.uiState().mapStream(data => data.uiState.contentLanguage)),
+                switchMap(contentLang => this.serverConfigService
                         .getAvailableLanguages()
-                        .pipe(map(available => [contentLang, available] as const));
-                }),
+                        .pipe(map(available => [contentLang, available] as const))),
             )
             .subscribe({
                 next: ([contentLanguage, availableLanguages]) => {
@@ -64,7 +60,7 @@ export class AppComponent implements OnInit {
             });
 
         if (isDevMode()) {
-            // tslint:disable-next-line:no-console
+            // eslint-disable-next-line no-console
             console.log(
                 `%cVendure Admin UI: Press "ctrl/cmd + u" to view UI extension points`,
                 `color: #17C1FF; font-weight: bold;`,

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/base-list.component.ts

@@ -85,7 +85,7 @@ export type ItemOf<T, K extends keyof T> = T[K] extends { items: infer R }
  * @docsCategory list-detail-views
  */
 @Directive()
-// tslint:disable-next-line:directive-class-suffix
+// eslint-disable-next-line @angular-eslint/directive-class-suffix
 export class BaseListComponent<ResultType, ItemType, VariableType extends Record<string, any> = any>
     implements OnInit, OnDestroy
 {

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -1,4 +1,4 @@
-// tslint:disable
+/* eslint-disable */
 export type Maybe<T> = T | null;
 export type InputMaybe<T> = Maybe<T>;
 export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/introspection-result.ts

@@ -1,4 +1,4 @@
-// tslint:disable
+/* eslint-disable */
 
       export interface PossibleTypesResultData {
         possibleTypes: {

+ 2 - 4
packages/admin-ui/src/lib/core/src/common/utilities/configurable-operation-utils.ts

@@ -33,12 +33,10 @@ export function configurableDefinitionToInstance(
 ): ConfigurableOperation {
     return {
         ...def,
-        args: def.args.map(arg => {
-            return {
+        args: def.args.map(arg => ({
                 ...arg,
                 value: getDefaultConfigArgValue(arg),
-            };
-        }),
+            })),
     } as ConfigurableOperation;
 }
 

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/utilities/create-updated-translatable.spec.ts

@@ -4,7 +4,7 @@ import { CustomFieldConfig, LanguageCode, ProductDetailFragment } from '../gener
 
 import { createUpdatedTranslatable } from './create-updated-translatable';
 
-// tslint:disable:no-non-null-assertion
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
 describe('createUpdatedTranslatable()', () => {
     let product: any;
 

+ 1 - 3
packages/admin-ui/src/lib/core/src/common/utilities/string-to-color.ts

@@ -28,8 +28,6 @@ export function stringToColor(input: string): string {
         '#7A7574',
         '#767676',
     ];
-    const value = input.split('').reduce((prev, curr, index) => {
-        return prev + Math.round(curr.charCodeAt(0) * Math.log(index + 2));
-    }, 0);
+    const value = input.split('').reduce((prev, curr, index) => prev + Math.round(curr.charCodeAt(0) * Math.log(index + 2)), 0);
     return safeColors[value % safeColors.length];
 }

+ 4 - 5
packages/admin-ui/src/lib/core/src/components/breadcrumb/breadcrumb.component.spec.ts

@@ -244,7 +244,7 @@ describe('BeadcrumbsComponent', () => {
         return fakeAsync(() => {
             const fixture = TestBed.createComponent(TestChildComponent);
             // Run in ngZone to prevent warning: https://github.com/angular/angular/issues/25837#issuecomment-445796236
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             fixture.ngZone!.run(() => {
                 router.navigate(route);
             });
@@ -437,8 +437,8 @@ function getBreadcrumbLinks(fixture: ComponentFixture<TestComponent>): string[]
         .filter(notNullOrUndefined);
 }
 
-// tslint:disable component-selector
 @Component({
+    // eslint-disable-next-line @angular-eslint/component-selector
     selector: 'test-root-component',
     template: `
         <vdr-breadcrumb></vdr-breadcrumb>
@@ -448,10 +448,9 @@ function getBreadcrumbLinks(fixture: ComponentFixture<TestComponent>): string[]
 class TestParentComponent {}
 
 @Component({
+    // eslint-disable-next-line @angular-eslint/component-selector
     selector: 'test-child-component',
-    template: `
-        <vdr-breadcrumb></vdr-breadcrumb>
-    `,
+    template: ` <vdr-breadcrumb></vdr-breadcrumb> `,
 })
 class TestChildComponent {}
 

+ 23 - 23
packages/admin-ui/src/lib/core/src/components/breadcrumb/breadcrumb.component.ts

@@ -3,7 +3,6 @@ import { ActivatedRoute, Data, NavigationEnd, Params, PRIMARY_OUTLET, Router } f
 import { flatten } from 'lodash';
 import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subject } from 'rxjs';
 import { filter, map, startWith, switchMap, takeUntil } from 'rxjs/operators';
-
 import { DataService } from '../../data/providers/data.service';
 
 export type BreadcrumbString = string;
@@ -55,28 +54,29 @@ export class BreadcrumbComponent implements OnDestroy {
         rootRoute: ActivatedRoute,
     ): Observable<Array<{ link: Array<string | any>; label: string }>> {
         const breadcrumbParts = this.assembleBreadcrumbParts(rootRoute);
-        const breadcrumbObservables$ = breadcrumbParts.map(({ value$, path }) => {
-            return value$.pipe(
-                map(value => {
-                    if (isBreadcrumbLabelLinkPair(value)) {
-                        return {
-                            label: value.label,
-                            link: this.normalizeRelativeLinks(value.link, path),
-                        };
-                    } else if (isBreadcrumbPairArray(value)) {
-                        return value.map(val => ({
-                            label: val.label,
-                            link: this.normalizeRelativeLinks(val.link, path),
-                        }));
-                    } else {
-                        return {
-                            label: value,
-                            link: '/' + path.join('/'),
-                        };
-                    }
-                }),
-            ) as Observable<BreadcrumbLabelLinkPair | BreadcrumbLabelLinkPair[]>;
-        });
+        const breadcrumbObservables$ = breadcrumbParts.map(
+            ({ value$, path }) =>
+                value$.pipe(
+                    map(value => {
+                        if (isBreadcrumbLabelLinkPair(value)) {
+                            return {
+                                label: value.label,
+                                link: this.normalizeRelativeLinks(value.link, path),
+                            };
+                        } else if (isBreadcrumbPairArray(value)) {
+                            return value.map(val => ({
+                                label: val.label,
+                                link: this.normalizeRelativeLinks(val.link, path),
+                            }));
+                        } else {
+                            return {
+                                label: value,
+                                link: '/' + path.join('/'),
+                            };
+                        }
+                    }),
+                ) as Observable<BreadcrumbLabelLinkPair | BreadcrumbLabelLinkPair[]>,
+        );
 
         return observableCombineLatest(breadcrumbObservables$).pipe(map(links => flatten(links)));
     }

+ 2 - 4
packages/admin-ui/src/lib/core/src/components/channel-switcher/channel-switcher.component.ts

@@ -26,13 +26,11 @@ export class ChannelSwitcherComponent implements OnInit {
         const channels$ = this.dataService.client.userStatus().mapStream(data => data.userStatus.channels);
         const filterTerm$ = this.filterControl.valueChanges.pipe<string>(startWith(''));
         this.channels$ = combineLatest(channels$, filterTerm$).pipe(
-            map(([channels, filterTerm]) => {
-                return filterTerm
+            map(([channels, filterTerm]) => filterTerm
                     ? channels.filter(c =>
                           c.code.toLocaleLowerCase().includes(filterTerm.toLocaleLowerCase()),
                       )
-                    : channels;
-            }),
+                    : channels),
         );
         this.channelCount$ = channels$.pipe(map(channels => channels.length));
         const activeChannel$ = this.dataService.client

+ 1 - 1
packages/admin-ui/src/lib/core/src/components/notification/notification.component.ts

@@ -16,7 +16,7 @@ export class NotificationComponent {
     isVisible = true;
     private onClickFn: () => void = () => {
         /* */
-    }
+    };
 
     registerOnClickFn(fn: () => void): void {
         this.onClickFn = fn;

+ 10 - 14
packages/admin-ui/src/lib/core/src/data/client-state/client-resolvers.ts

@@ -18,17 +18,13 @@ export type ResolverDefinition = {
 
 export const clientResolvers: ResolverDefinition = {
     Mutation: {
-        requestStarted: (_, args, { cache }): number => {
-            return updateRequestsInFlight(cache, 1);
-        },
-        requestCompleted: (_, args, { cache }): number => {
-            return updateRequestsInFlight(cache, -1);
-        },
+        requestStarted: (_, args, { cache }): number => updateRequestsInFlight(cache, 1),
+        requestCompleted: (_, args, { cache }): number => updateRequestsInFlight(cache, -1),
         setAsLoggedIn: (_, args: Codegen.SetAsLoggedInMutationVariables, { cache }): UserStatus => {
             const {
                 input: { username, loginTime, channels, activeChannelId },
             } = args;
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const permissions = channels.find(c => c.id === activeChannelId)!.permissions;
             const data: { userStatus: UserStatus } = {
                 userStatus: {
@@ -60,14 +56,14 @@ export const clientResolvers: ResolverDefinition = {
             return data.userStatus;
         },
         setUiLanguage: (_, args: Codegen.SetUiLanguageMutationVariables, { cache }): LanguageCode => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<Codegen.GetUiStateQuery>({ query: GET_UI_STATE })!;
             const data = updateUiState(previous, 'language', args.languageCode);
             cache.writeQuery({ query: GET_UI_STATE, data });
             return args.languageCode;
         },
         setUiLocale: (_, args: Codegen.SetUiLocaleMutationVariables, { cache }): string | undefined => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<Codegen.GetUiStateQuery>({ query: GET_UI_STATE })!;
             const data = updateUiState(previous, 'locale', args.locale);
             cache.writeQuery({ query: GET_UI_STATE, data });
@@ -78,14 +74,14 @@ export const clientResolvers: ResolverDefinition = {
             args: Codegen.SetContentLanguageMutationVariables,
             { cache },
         ): LanguageCode => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<Codegen.GetUiStateQuery>({ query: GET_UI_STATE })!;
             const data = updateUiState(previous, 'contentLanguage', args.languageCode);
             cache.writeQuery({ query: GET_UI_STATE, data });
             return args.languageCode;
         },
         setUiTheme: (_, args: Codegen.SetUiThemeMutationVariables, { cache }): string => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<Codegen.GetUiStateQuery>({ query: GET_UI_STATE })!;
             const data = updateUiState(previous, 'theme', args.theme);
             cache.writeQuery({ query: GET_UI_STATE, data });
@@ -96,14 +92,14 @@ export const clientResolvers: ResolverDefinition = {
             args: Codegen.SetDisplayUiExtensionPointsMutationVariables,
             { cache },
         ): boolean => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<Codegen.GetUiStateQuery>({ query: GET_UI_STATE })!;
             const data = updateUiState(previous, 'displayUiExtensionPoints', args.display);
             cache.writeQuery({ query: GET_UI_STATE, data });
             return args.display;
         },
         setActiveChannel: (_, args: Codegen.SetActiveChannelMutationVariables, { cache }): UserStatus => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<GetUserStatusQuery>({ query: GET_USER_STATUS })!;
             const activeChannel = previous.userStatus.channels.find(c => c.id === args.channelId);
             if (!activeChannel) {
@@ -121,7 +117,7 @@ export const clientResolvers: ResolverDefinition = {
             return data.userStatus;
         },
         updateUserChannels: (_, args: Codegen.UpdateUserChannelsMutationVariables, { cache }): UserStatus => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             const previous = cache.readQuery<GetUserStatusQuery>({ query: GET_USER_STATUS })!;
             const data = {
                 userStatus: {

+ 2 - 4
packages/admin-ui/src/lib/core/src/data/providers/fetch-adapter.ts

@@ -23,11 +23,9 @@ export class FetchAdapter {
                 responseType: 'json',
                 withCredentials: true,
             }),
-        ).then(result => {
-            return new Response(JSON.stringify(result.body), {
+        ).then(result => new Response(JSON.stringify(result.body), {
                 status: result.status,
                 statusText: result.statusText,
-            });
-        });
+            }));
     };
 }

+ 1 - 1
packages/admin-ui/src/lib/core/src/data/utils/add-custom-fields.spec.ts

@@ -4,7 +4,7 @@ import { CustomFields } from '../../common/generated-types';
 
 import { addCustomFields } from './add-custom-fields';
 
-// tslint:disable:no-non-null-assertion
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
 describe('addCustomFields()', () => {
     let documentNode: DocumentNode;
 

+ 4 - 8
packages/admin-ui/src/lib/core/src/data/utils/add-custom-fields.ts

@@ -38,8 +38,7 @@ export function addCustomFields(documentNode: DocumentNode, customFields: Custom
                 kind: Kind.FIELD,
                 selectionSet: {
                     kind: Kind.SELECTION_SET,
-                    selections: customFieldsForType.map(customField => {
-                        return {
+                    selections: customFieldsForType.map(customField => ({
                             kind: Kind.FIELD,
                             name: {
                                 kind: Kind.NAME,
@@ -60,8 +59,7 @@ export function addCustomFields(documentNode: DocumentNode, customFields: Custom
                                       },
                                   }
                                 : {}),
-                        } as FieldNode;
-                    }),
+                        } as FieldNode)),
                 },
             });
 
@@ -80,15 +78,13 @@ export function addCustomFields(documentNode: DocumentNode, customFields: Custom
                     kind: Kind.FIELD,
                     selectionSet: {
                         kind: Kind.SELECTION_SET,
-                        selections: localeStrings.map(customField => {
-                            return {
+                        selections: localeStrings.map(customField => ({
                                 kind: Kind.FIELD,
                                 name: {
                                     kind: Kind.NAME,
                                     value: customField.name,
                                 },
-                            } as FieldNode;
-                        }),
+                            } as FieldNode)),
                     },
                 });
             }

+ 1 - 1
packages/admin-ui/src/lib/core/src/providers/bulk-action-registry/bulk-action-registry.service.ts

@@ -12,7 +12,7 @@ export class BulkActionRegistryService {
         if (!this.locationBulActionMap.has(bulkAction.location)) {
             this.locationBulActionMap.set(bulkAction.location, new Set([bulkAction]));
         } else {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             this.locationBulActionMap.get(bulkAction.location)!.add(bulkAction);
         }
     }

+ 5 - 9
packages/admin-ui/src/lib/core/src/providers/dashboard-widget/dashboard-widget.service.ts

@@ -29,17 +29,13 @@ export class DashboardWidgetService {
     }
 
     getAvailableIds(currentUserPermissions: Permission[]): string[] {
-        const hasAllPermissions = (requiredPerms: string[], userPerms: string[]): boolean => {
-            return requiredPerms.every(p => userPerms.includes(p));
-        };
+        const hasAllPermissions = (requiredPerms: string[], userPerms: string[]): boolean => requiredPerms.every(p => userPerms.includes(p));
 
         return [...this.registry.entries()]
-            .filter(([id, config]) => {
-                return (
+            .filter(([id, config]) => (
                     !config.requiresPermissions ||
                     hasAllPermissions(config.requiresPermissions, currentUserPermissions)
-                );
-            })
+                ))
             .map(([id]) => id);
     }
 
@@ -70,7 +66,7 @@ export class DashboardWidgetService {
     }
 
     private idNotFound(id: string): undefined {
-        // tslint:disable-next-line:no-console
+        // eslint-disable-next-line no-console
         console.error(
             `No dashboard widget was found with the id "${id}"\nAvailable ids: ${[...this.registry.keys()]
                 .map(_id => `"${_id}"`)
@@ -92,7 +88,7 @@ export class DashboardWidgetService {
             // Fall back to the largest supported width
             const sortedWidths = supportedWidths.sort((a, b) => a - b);
             const fallbackWidth = supportedWidths[sortedWidths.length - 1];
-            // tslint:disable-next-line:no-console
+            // eslint-disable-next-line no-console
             console.error(
                 `The "${id}" widget does not support the specified width (${targetWidth}).\nSupported widths are: [${sortedWidths.join(
                     ', ',

+ 1 - 3
packages/admin-ui/src/lib/core/src/providers/health-check/health-check.service.ts

@@ -47,9 +47,7 @@ export class HealthCheckService {
         this.status$ = result$.pipe(map(res => res.status));
         this.details$ = result$.pipe(
             map(res =>
-                Object.keys(res.details).map(key => {
-                    return { key, result: res.details[key] };
-                }),
+                Object.keys(res.details).map(key => ({ key, result: res.details[key] })),
             ),
         );
         this.lastCheck$ = result$.pipe(map(res => res.lastChecked));

+ 1 - 1
packages/admin-ui/src/lib/core/src/providers/i18n/custom-message-format-compiler.ts

@@ -1,4 +1,4 @@
-/* tslint:disable:no-console */
+/* eslint-disable no-console */
 import { Injectable } from '@angular/core';
 import {
     TranslateMessageFormatCompiler,

+ 1 - 1
packages/admin-ui/src/lib/core/src/providers/local-storage/local-storage.service.ts

@@ -68,7 +68,7 @@ export class LocalStorageService {
         try {
             result = JSON.parse(item || 'null');
         } catch (e: any) {
-            // tslint:disable-next-line:no-console
+            // eslint-disable-next-line no-console
             console.error(`Could not parse the localStorage value for "${key}" (${item})`);
         }
         return result;

+ 1 - 1
packages/admin-ui/src/lib/core/src/providers/nav-builder/nav-builder.service.spec.ts

@@ -1,4 +1,4 @@
-/* tslint:disable:no-non-null-assertion no-console */
+/* eslint-disable @typescript-eslint/no-non-null-assertion, no-console */
 import { TestBed } from '@angular/core/testing';
 import { take } from 'rxjs/operators';
 

+ 1 - 1
packages/admin-ui/src/lib/core/src/providers/nav-builder/nav-builder.service.ts

@@ -241,7 +241,7 @@ export class NavBuilderService {
                 for (const item of additionalItems) {
                     const section = sections.find(s => s.id === item.sectionId);
                     if (!section) {
-                        // tslint:disable-next-line:no-console
+                        // eslint-disable-next-line no-console
                         console.error(
                             `Could not add menu item "${item.config.id}", section "${item.sectionId}" does not exist`,
                         );

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/asset-preview-dialog/asset-preview-dialog.component.ts

@@ -26,7 +26,7 @@ export class AssetPreviewDialogComponent implements Dialog<void>, OnInit {
                 if (this.hasTags(asset)) {
                     return of(asset);
                 } else {
-                    // tslint:disable-next-line:no-non-null-assertion
+                    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                     return this.dataService.product.getAsset(asset.id).mapSingle(data => data.asset!);
                 }
             }),

+ 3 - 6
packages/admin-ui/src/lib/core/src/shared/components/asset-search-input/asset-search-input.component.ts

@@ -40,9 +40,7 @@ export class AssetSearchInputComponent {
             }
         });
 
-        tags.map(tag => {
-            return items?.find(item => this.isTag(item) && item.id === tag.id);
-        })
+        tags.map(tag => items?.find(item => this.isTag(item) && item.id === tag.id))
             .filter(notNullOrUndefined)
             .forEach(item => {
                 const isSelected = this.selectComponent.selectedItems.find(i => {
@@ -104,7 +102,6 @@ export class AssetSearchInputComponent {
         return { label: item };
     }
 
-    private isTag = (input: unknown): input is TagFragment => {
-        return typeof input === 'object' && !!input && input.hasOwnProperty('value');
-    };
+    private isTag = (input: unknown): input is TagFragment =>
+        typeof input === 'object' && !!input && input.hasOwnProperty('value');
 }

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/components/bulk-action-menu/bulk-action-menu.component.ts

@@ -48,8 +48,8 @@ export class BulkActionMenuComponent<T = any> implements OnInit, OnDestroy {
     ngOnInit(): void {
         const actionsForLocation = this.bulkActionRegistryService.getBulkActionsForLocation(this.locationId);
         this.actions$ = this.selectionManager.selectionChanges$.pipe(
-            switchMap(selection => {
-                return Promise.all(
+            switchMap(selection =>
+                Promise.all(
                     actionsForLocation.map(async action => {
                         let display = true;
                         let translationVars = {};
@@ -69,8 +69,8 @@ export class BulkActionMenuComponent<T = any> implements OnInit, OnDestroy {
                         }
                         return { ...action, display, translationVars };
                     }),
-                );
-            }),
+                ),
+            ),
         );
         this.subscription = this.dataService.client
             .userStatus()

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/dropdown/dropdown-item.directive.ts

@@ -4,7 +4,7 @@ import { DropdownComponent } from './dropdown.component';
 
 @Directive({
     selector: '[vdrDropdownItem]',
-    // tslint:disable-next-line
+    // eslint-disable-next-line
     host: { '[class.dropdown-item]': 'true' },
 })
 export class DropdownItemDirective {

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/form-field/form-field-control.directive.ts

@@ -3,7 +3,7 @@ import { NgControl } from '@angular/forms';
 
 type InputElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
 
-// tslint:disable:directive-selector
+/* eslint-disable @angular-eslint/directive-selector */
 @Directive({ selector: 'input, textarea, select' })
 export class FormFieldControlDirective {
     constructor(

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/modal-dialog/modal-dialog.component.ts

@@ -41,7 +41,7 @@ export class ModalDialogComponent<T extends Dialog<any>> {
             this.closeModal(result);
         };
         if (this.options && this.options.locals) {
-            // tslint:disable-next-line
+            // eslint-disable-next-line
             for (const key in this.options.locals) {
                 componentInstance[key] = this.options.locals[key] as T[Extract<keyof T, string>];
             }

+ 3 - 6
packages/admin-ui/src/lib/core/src/shared/components/product-search-input/product-search-input.component.ts

@@ -42,9 +42,7 @@ export class ProductSearchInputComponent {
             }
         });
 
-        ids.map(id => {
-            return items?.find(item => this.isFacetValueItem(item) && item.facetValue.id === id);
-        })
+        ids.map(id => items?.find(item => this.isFacetValueItem(item) && item.facetValue.id === id))
             .filter(notNullOrUndefined)
             .forEach(item => {
                 const isSelected = this.selectComponent.selectedItems.find(i => {
@@ -111,7 +109,6 @@ export class ProductSearchInputComponent {
         return this.selectComponent.itemsList.markedIndex === -1;
     }
 
-    private isFacetValueItem = (input: unknown): input is FacetValueResult => {
-        return typeof input === 'object' && !!input && input.hasOwnProperty('facetValue');
-    };
+    private isFacetValueItem = (input: unknown): input is FacetValueResult =>
+        typeof input === 'object' && !!input && input.hasOwnProperty('facetValue');
 }

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.service.ts

@@ -39,8 +39,8 @@ export class ContextMenuService {
         const source$ = this.setContextMenuConfig$.asObservable();
         const groupedConfig$ = source$.pipe(
             bufferWhen(() => source$.pipe(debounceTime(50))),
-            map(group => {
-                return group.reduce((acc, cur) => {
+            map(group =>
+                group.reduce((acc, cur) => {
                     if (!acc) {
                         return cur;
                     } else {
@@ -53,8 +53,8 @@ export class ContextMenuService {
                         }
                     }
                     return acc;
-                }, undefined as ContextMenuConfig | undefined);
-            }),
+                }, undefined as ContextMenuConfig | undefined),
+            ),
         );
 
         const visible$ = this.menuIsVisible$.pipe(filter(val => val === true));

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/inputrules.ts

@@ -60,7 +60,7 @@ export function headingRule(nodeType, maxLevel) {
 export function buildInputRules(schema: Schema): Plugin {
     const rules = smartQuotes.concat(ellipsis, emDash);
     let type: NodeType;
-    // tslint:disable:no-conditional-assignment
+    /* eslint-disable no-cond-assign */
     if ((type = schema.nodes.blockquote)) {
         rules.push(blockQuoteRule(type));
     }

+ 2 - 2
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/keymap.ts

@@ -74,7 +74,7 @@ export function buildKeymap(schema: Schema, mapKeys?: Keymap) {
     bind('Mod-BracketLeft', lift);
     bind('Escape', selectParentNode);
 
-    // tslint:disable:no-conditional-assignment
+    /* eslint-disable no-cond-assign */
     if ((type = schema.marks.strong)) {
         bind('Mod-b', toggleMark(type));
         bind('Mod-B', toggleMark(type));
@@ -99,7 +99,7 @@ export function buildKeymap(schema: Schema, mapKeys?: Keymap) {
     if ((type = schema.nodes.hard_break)) {
         const br = type;
         const cmd = chainCommands(exitCode, (state, dispatch) => {
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             dispatch!(state.tr.replaceSelectionWith(br.create()).scrollIntoView());
             return true;
         });

+ 3 - 3
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/menu/menu.ts

@@ -34,7 +34,7 @@ function cmdItem(cmd: (...args: any[]) => void, options: CmdItemOptions) {
             ? renderClarityIcon({ shape: options.iconShape, size: IconSize.Large })
             : undefined,
     };
-    // tslint:disable-next-line:forin
+    // eslint-disable-next-line guard-for-in
     for (const prop in options) {
         passedOptions[prop] = options[prop];
     }
@@ -52,7 +52,7 @@ function markItem(markType, options: CmdItemOptions) {
         },
         enable: true,
     };
-    // tslint:disable-next-line:forin
+    // eslint-disable-next-line guard-for-in
     for (const prop in options) {
         passedOptions[prop] = options[prop];
     }
@@ -124,7 +124,7 @@ function wrapListItem(nodeType, options: CmdItemOptions) {
 export function buildMenuItems(schema: Schema, modalService: ModalService) {
     const r: Record<string, any> = {};
     let type: MarkType | NodeType;
-    // tslint:disable:no-conditional-assignment
+    /* eslint-disable no-cond-assign */
     if ((type = schema.marks.strong)) {
         r.toggleStrong = markItem(type, {
             title: 'Toggle strong style',

+ 59 - 61
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/plugins/image-plugin.ts

@@ -49,7 +49,7 @@ export function insertImageItem(nodeType: NodeType, modalService: ModalService)
                 })
                 .subscribe(result => {
                     if (result) {
-                        // tslint:disable-next-line:no-non-null-assertion
+                        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                         view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(result)!));
                     }
                     view.focus();
@@ -60,67 +60,65 @@ export function insertImageItem(nodeType: NodeType, modalService: ModalService)
 
 export const imageContextMenuPlugin = (contextMenuService: ContextMenuService, modalService: ModalService) =>
     new Plugin({
-        view: () => {
-            return {
-                update: view => {
-                    if (!view.hasFocus()) {
-                        return;
+        view: () => ({
+            update: view => {
+                if (!view.hasFocus()) {
+                    return;
+                }
+                const { doc, selection } = view.state;
+                let imageNode: Node | undefined;
+                let imageNodePos = 0;
+                doc.nodesBetween(selection.from, selection.to, (n, pos, parent) => {
+                    if (n.type.name === 'image') {
+                        imageNode = n;
+                        imageNodePos = pos;
+                        return false;
                     }
-                    const { doc, selection } = view.state;
-                    let imageNode: Node | undefined;
-                    let imageNodePos = 0;
-                    doc.nodesBetween(selection.from, selection.to, (n, pos, parent) => {
-                        if (n.type.name === 'image') {
-                            imageNode = n;
-                            imageNodePos = pos;
-                            return false;
-                        }
-                    });
-                    if (imageNode) {
-                        const node = view.nodeDOM(imageNodePos);
-                        if (node instanceof HTMLImageElement) {
-                            contextMenuService.setContextMenu({
-                                ref: selection,
-                                title: 'Image',
-                                iconShape: 'image',
-                                element: node,
-                                coords: view.coordsAtPos(imageNodePos),
-                                items: [
-                                    {
-                                        enabled: true,
-                                        iconShape: 'image',
-                                        label: 'Image properties',
-                                        onClick: () => {
-                                            contextMenuService.clearContextMenu();
-                                            modalService
-                                                .fromComponent(ExternalImageDialogComponent, {
-                                                    closable: true,
-                                                    locals: {
-                                                        // tslint:disable-next-line:no-non-null-assertion
-                                                        existing: imageNode!.attrs as ExternalImageAttrs,
-                                                    },
-                                                })
-                                                .subscribe(result => {
-                                                    if (result) {
-                                                        // tslint:disable-next-line:no-non-null-assertion
-                                                        view.dispatch(
-                                                            view.state.tr.replaceSelectionWith(
-                                                                // tslint:disable-next-line:no-non-null-assertion
-                                                                imageNode!.type.createAndFill(result)!,
-                                                            ),
-                                                        );
-                                                    }
-                                                    view.focus();
-                                                });
-                                        },
+                });
+                if (imageNode) {
+                    const node = view.nodeDOM(imageNodePos);
+                    if (node instanceof HTMLImageElement) {
+                        contextMenuService.setContextMenu({
+                            ref: selection,
+                            title: 'Image',
+                            iconShape: 'image',
+                            element: node,
+                            coords: view.coordsAtPos(imageNodePos),
+                            items: [
+                                {
+                                    enabled: true,
+                                    iconShape: 'image',
+                                    label: 'Image properties',
+                                    onClick: () => {
+                                        contextMenuService.clearContextMenu();
+                                        modalService
+                                            .fromComponent(ExternalImageDialogComponent, {
+                                                closable: true,
+                                                locals: {
+                                                    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+                                                    existing: imageNode!.attrs as ExternalImageAttrs,
+                                                },
+                                            })
+                                            .subscribe(result => {
+                                                if (result) {
+                                                    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+                                                    view.dispatch(
+                                                        view.state.tr.replaceSelectionWith(
+                                                            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+                                                            imageNode!.type.createAndFill(result)!,
+                                                        ),
+                                                    );
+                                                }
+                                                view.focus();
+                                            });
                                     },
-                                ],
-                            });
-                        }
-                    } else {
-                        contextMenuService.clearContextMenu();
+                                },
+                            ],
+                        });
                     }
-                },
-            };
-        },
+                } else {
+                    contextMenuService.clearContextMenu();
+                }
+            },
+        }),
     });

+ 2 - 2
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/plugins/raw-editor-plugin.ts

@@ -46,7 +46,7 @@ export const rawEditorPlugin = (contextMenuService: ContextMenuService, modalSer
                                         onClick: () => {
                                             contextMenuService.clearContextMenu();
                                             const element = domSerializer.serializeNode(
-                                                // tslint:disable-next-line:no-non-null-assertion
+                                                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                                                 topLevelNode!,
                                             ) as HTMLElement;
                                             modalService
@@ -73,7 +73,7 @@ export const rawEditorPlugin = (contextMenuService: ContextMenuService, modalSer
                                                                     parsedNodeSlice,
                                                                 );
                                                             } catch (err: any) {
-                                                                // tslint:disable-next-line:no-console
+                                                                // eslint-disable-next-line no-console
                                                                 console.error(err);
                                                             }
                                                             view.dispatch(tr);

+ 65 - 70
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/plugins/tables-plugin.ts

@@ -26,82 +26,77 @@ import { renderClarityIcon } from '../menu/menu-common';
 
 export const tableContextMenuPlugin = (contextMenuService: ContextMenuService) =>
     new Plugin({
-        view: () => {
-            return {
-                update: view => {
-                    if (!view.hasFocus()) {
-                        return;
+        view: () => ({
+            update: view => {
+                if (!view.hasFocus()) {
+                    return;
+                }
+                const { doc, selection } = view.state;
+                let tableNode: Node | undefined;
+                let tableNodePos = 0;
+                doc.nodesBetween(selection.from, selection.to, (n, pos, parent) => {
+                    if (n.type.name === 'table') {
+                        tableNode = n;
+                        tableNodePos = pos;
+                        return false;
                     }
-                    const { doc, selection } = view.state;
-                    let tableNode: Node | undefined;
-                    let tableNodePos = 0;
-                    doc.nodesBetween(selection.from, selection.to, (n, pos, parent) => {
-                        if (n.type.name === 'table') {
-                            tableNode = n;
-                            tableNodePos = pos;
-                            return false;
-                        }
-                    });
-                    if (tableNode) {
-                        const node = view.nodeDOM(tableNodePos);
-                        if (node instanceof Element) {
-                            function createMenuItem(
-                                label: string,
-                                commandFn: (
-                                    state: EditorState,
-                                    dispatch?: (tr: Transaction) => void,
-                                ) => boolean,
-                                iconClass?: string,
-                            ): ContextMenuItem {
-                                const enabled = commandFn(view.state);
-                                return {
-                                    label,
-                                    enabled,
-                                    iconClass,
-                                    onClick: () => {
-                                        contextMenuService.clearContextMenu();
-                                        view.focus();
-                                        commandFn(view.state, view.dispatch);
-                                    },
-                                };
-                            }
-                            const separator: ContextMenuItem = {
-                                label: '',
-                                separator: true,
-                                enabled: true,
+                });
+                if (tableNode) {
+                    const node = view.nodeDOM(tableNodePos);
+                    if (node instanceof Element) {
+                        function createMenuItem(
+                            label: string,
+                            commandFn: (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean,
+                            iconClass?: string,
+                        ): ContextMenuItem {
+                            const enabled = commandFn(view.state);
+                            return {
+                                label,
+                                enabled,
+                                iconClass,
                                 onClick: () => {
-                                    /**/
+                                    contextMenuService.clearContextMenu();
+                                    view.focus();
+                                    commandFn(view.state, view.dispatch);
                                 },
                             };
-                            contextMenuService.setContextMenu({
-                                ref: selection,
-                                title: 'Table',
-                                iconShape: 'table',
-                                element: node,
-                                coords: view.coordsAtPos(tableNodePos),
-                                items: [
-                                    createMenuItem('Insert column before', addColumnBefore, 'add-column'),
-                                    createMenuItem('Insert column after', addColumnAfter, 'add-column'),
-                                    createMenuItem('Insert row before', addRowBefore, 'add-row'),
-                                    createMenuItem('Insert row after', addRowAfter, 'add-row'),
-                                    createMenuItem('Merge cells', mergeCells),
-                                    createMenuItem('Split cell', splitCell),
-                                    separator,
-                                    createMenuItem('Toggle header column', toggleHeaderColumn),
-                                    createMenuItem('Toggle header row', toggleHeaderRow),
-                                    separator,
-                                    createMenuItem('Delete column', deleteColumn),
-                                    createMenuItem('Delete row', deleteRow),
-                                    createMenuItem('Delete table', deleteTable),
-                                ],
-                            });
                         }
-                    } else {
-                        contextMenuService.clearContextMenu();
+                        const separator: ContextMenuItem = {
+                            label: '',
+                            separator: true,
+                            enabled: true,
+                            onClick: () => {
+                                /**/
+                            },
+                        };
+                        contextMenuService.setContextMenu({
+                            ref: selection,
+                            title: 'Table',
+                            iconShape: 'table',
+                            element: node,
+                            coords: view.coordsAtPos(tableNodePos),
+                            items: [
+                                createMenuItem('Insert column before', addColumnBefore, 'add-column'),
+                                createMenuItem('Insert column after', addColumnAfter, 'add-column'),
+                                createMenuItem('Insert row before', addRowBefore, 'add-row'),
+                                createMenuItem('Insert row after', addRowAfter, 'add-row'),
+                                createMenuItem('Merge cells', mergeCells),
+                                createMenuItem('Split cell', splitCell),
+                                separator,
+                                createMenuItem('Toggle header column', toggleHeaderColumn),
+                                createMenuItem('Toggle header row', toggleHeaderRow),
+                                separator,
+                                createMenuItem('Delete column', deleteColumn),
+                                createMenuItem('Delete row', deleteRow),
+                                createMenuItem('Delete table', deleteTable),
+                            ],
+                        });
                     }
-                },
-            };
-        },
+                } else {
+                    contextMenuService.clearContextMenu();
+                }
+            },
+        }),
     });
 
 export function getTableNodes() {

+ 3 - 1
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/prosemirror.service.ts

@@ -84,7 +84,9 @@ export class ProsemirrorService {
                 let state = this.getStateFromText(text);
                 if (document.body.contains(this.editorView.dom)) {
                     const fix = fixTables(state);
-                    if (fix) state = state.apply(fix.setMeta('addToHistory', false));
+                    if (fix) {
+                        state = state.apply(fix.setMeta('addToHistory', false));
+                    }
                     this.editorView.updateState(state);
                 }
             }

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/raw-html-dialog/raw-html-dialog.component.ts

@@ -42,7 +42,7 @@ export class RawHtmlDialogComponent implements OnInit, Dialog<string> {
         const indentAfter = new Array(level - 1).join('\t');
         let textNode: Text;
 
-        // tslint:disable-next-line:prefer-for-of
+        // eslint-disable-next-line @typescript-eslint/prefer-for-of
         for (let i = 0; i < node.children.length; i++) {
             textNode = document.createTextNode('\n' + indentBefore);
             node.insertBefore(textNode, node.children[i]);

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/directives/if-default-channel-active.directive.ts

@@ -17,12 +17,12 @@ export class IfDefaultChannelActiveDirective extends IfDirectiveBase<[]> {
         private dataService: DataService,
         private changeDetectorRef: ChangeDetectorRef,
     ) {
-        super(_viewContainer, templateRef, () => {
-            return this.dataService.client
+        super(_viewContainer, templateRef, () =>
+            this.dataService.client
                 .userStatus()
                 .mapStream(({ userStatus }) => this.defaultChannelIsActive(userStatus))
-                .pipe(tap(() => this.changeDetectorRef.markForCheck()));
-        });
+                .pipe(tap(() => this.changeDetectorRef.markForCheck())),
+        );
     }
 
     /**

+ 16 - 18
packages/admin-ui/src/lib/core/src/shared/directives/if-multichannel.directive.spec.ts

@@ -1,4 +1,4 @@
-/* tslint:disable:component-class-suffix */
+/* eslint-disable @angular-eslint/component-class-suffix */
 import { Component, Input } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { BehaviorSubject } from 'rxjs';
@@ -21,7 +21,7 @@ describe('vdrIfMultichannel directive', () => {
         });
 
         it('is multichannel', () => {
-            ((fixture.componentInstance.dataService as unknown) as MockDataService).setChannels([1, 2]);
+            (fixture.componentInstance.dataService as unknown as MockDataService).setChannels([1, 2]);
             fixture.detectChanges();
 
             const thenEl = fixture.nativeElement.querySelector('.then');
@@ -29,7 +29,7 @@ describe('vdrIfMultichannel directive', () => {
         });
 
         it('not multichannel', () => {
-            ((fixture.componentInstance.dataService as unknown) as MockDataService).setChannels([1]);
+            (fixture.componentInstance.dataService as unknown as MockDataService).setChannels([1]);
             fixture.detectChanges();
 
             const thenEl = fixture.nativeElement.querySelector('.then');
@@ -49,7 +49,7 @@ describe('vdrIfMultichannel directive', () => {
         });
 
         it('is multichannel', () => {
-            ((fixture.componentInstance.dataService as unknown) as MockDataService).setChannels([1, 2]);
+            (fixture.componentInstance.dataService as unknown as MockDataService).setChannels([1, 2]);
             fixture.detectChanges();
 
             const thenEl = fixture.nativeElement.querySelector('.then');
@@ -59,7 +59,7 @@ describe('vdrIfMultichannel directive', () => {
         });
 
         it('not multichannel', () => {
-            ((fixture.componentInstance.dataService as unknown) as MockDataService).setChannels([1]);
+            (fixture.componentInstance.dataService as unknown as MockDataService).setChannels([1]);
             fixture.detectChanges();
 
             const thenEl = fixture.nativeElement.querySelector('.then');
@@ -101,19 +101,17 @@ class MockDataService {
         this.channels$.next(channels);
     }
     client = {
-        userStatus: () => {
-            return {
-                mapStream: (mapFn: any) =>
-                    this.channels$.pipe(
-                        map(channels =>
-                            mapFn({
-                                userStatus: {
-                                    channels,
-                                },
-                            }),
-                        ),
+        userStatus: () => ({
+            mapStream: (mapFn: any) =>
+                this.channels$.pipe(
+                    map(channels =>
+                        mapFn({
+                            userStatus: {
+                                channels,
+                            },
+                        }),
                     ),
-            };
-        },
+                ),
+        }),
     };
 }

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/directives/if-multichannel.directive.ts

@@ -27,11 +27,11 @@ export class IfMultichannelDirective extends IfDirectiveBase<[]> {
         templateRef: TemplateRef<any>,
         private dataService: DataService,
     ) {
-        super(_viewContainer, templateRef, () => {
-            return this.dataService.client
+        super(_viewContainer, templateRef, () =>
+            this.dataService.client
                 .userStatus()
-                .mapStream(({ userStatus }) => 1 < userStatus.channels.length);
-        });
+                .mapStream(({ userStatus }) => 1 < userStatus.channels.length),
+        );
     }
 
     /**

+ 2 - 6
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/code-editor-form-input/html-editor-form-input.component.ts

@@ -7,9 +7,7 @@ import { FormInputComponent } from '../../../common/component-registry-types';
 import { BaseCodeEditorFormInputComponent } from './base-code-editor-form-input.component';
 
 function htmlValidator(): ValidatorFn {
-    return (control: AbstractControl): ValidationErrors | null => {
-        return null;
-    };
+    return (control: AbstractControl): ValidationErrors | null => null;
 }
 
 const HTML_TAG_RE = /<\/?[^>]+>?/g;
@@ -66,9 +64,7 @@ export class HtmlEditorFormInputComponent
                     );
                 });
             },
-            getErrorMessage: (json: string): string | undefined => {
-                return;
-            },
+            getErrorMessage: (json: string): string | undefined => undefined,
         });
     }
 

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/dynamic-form-input/dynamic-form-input.component.ts

@@ -91,7 +91,7 @@ export class DynamicFormInputComponent
         if (componentType) {
             this.componentType = componentType;
         } else {
-            // tslint:disable-next-line:no-console
+            // eslint-disable-next-line no-console
             console.error(
                 `No form input component registered with the id "${componentId}". Using the default input instead.`,
             );

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/customer/relation-customer-input.component.ts

@@ -36,11 +36,11 @@ export class RelationCustomerInputComponent implements OnInit {
     ngOnInit() {
         this.results$ = this.searchTerm$.pipe(
             debounceTime(200),
-            switchMap(term => {
-                return this.dataService.customer
+            switchMap(term =>
+                this.dataService.customer
                     .getCustomerList(10, 0, term)
-                    .mapSingle(data => data.customers.items);
-            }),
+                    .mapSingle(data => data.customers.items),
+            ),
         );
     }
 

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product-variant/relation-product-variant-input.component.ts

@@ -48,8 +48,8 @@ export class RelationProductVariantInputComponent implements OnInit {
 
         this.results$ = this.searchTerm$.pipe(
             debounceTime(200),
-            switchMap(term => {
-                return this.dataService.product
+            switchMap(term =>
+                this.dataService.product
                     .getProductVariantsSimple({
                         ...(term
                             ? {
@@ -62,8 +62,8 @@ export class RelationProductVariantInputComponent implements OnInit {
                             : {}),
                         take: 10,
                     })
-                    .mapSingle(data => data.productVariants.items);
-            }),
+                    .mapSingle(data => data.productVariants.items),
+            ),
         );
     }
 

+ 4 - 4
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product/relation-product-input.component.ts

@@ -48,8 +48,8 @@ export class RelationProductInputComponent implements OnInit {
 
         this.results$ = this.searchTerm$.pipe(
             debounceTime(200),
-            switchMap(term => {
-                return this.dataService.product
+            switchMap(term =>
+                this.dataService.product
                     .getProducts({
                         ...(term
                             ? {
@@ -62,8 +62,8 @@ export class RelationProductInputComponent implements OnInit {
                             : {}),
                         take: 10,
                     })
-                    .mapSingle(data => data.products.items);
-            }),
+                    .mapSingle(data => data.products.items),
+            ),
         );
     }
 

+ 1 - 0
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/relation-card/relation-card.component.ts

@@ -30,6 +30,7 @@ export class RelationCardComponent {
     @Input() selectLabel: string;
     @Input() readonly: boolean;
     @Input() removable = true;
+    // eslint-disable-next-line @angular-eslint/no-output-native
     @Output() select = new EventEmitter();
     @Output() remove = new EventEmitter();
     @ContentChild(RelationCardPreviewDirective, { read: TemplateRef })

+ 4 - 4
packages/admin-ui/src/lib/customer/src/components/add-customer-to-group-dialog/add-customer-to-group-dialog.component.ts

@@ -35,11 +35,11 @@ export class AddCustomerToGroupDialogComponent implements Dialog<string[]>, OnIn
 
     ngOnInit() {
         const customerResult$ = this.fetchGroupMembers$.pipe(
-            switchMap(({ skip, take, filterTerm }) => {
-                return this.dataService.customer
+            switchMap(({ skip, take, filterTerm }) =>
+                this.dataService.customer
                     .getCustomerList(take, skip, filterTerm)
-                    .mapStream(res => res.customers);
-            }),
+                    .mapStream(res => res.customers),
+            ),
         );
 
         this.customers$ = customerResult$.pipe(map(res => res.items));

+ 4 - 4
packages/admin-ui/src/lib/customer/src/components/customer-detail/customer-detail.component.ts

@@ -116,15 +116,15 @@ export class CustomerDetailComponent
         this.ordersCount$ = this.entity$.pipe(map(customer => customer.orders.totalItems));
         this.history$ = this.fetchHistory.pipe(
             startWith(null),
-            switchMap(() => {
-                return this.dataService.customer
+            switchMap(() =>
+                this.dataService.customer
                     .getCustomerHistory(this.id, {
                         sort: {
                             createdAt: SortOrder.DESC,
                         },
                     })
-                    .mapStream(data => data.customer?.history.items);
-            }),
+                    .mapStream(data => data.customer?.history.items),
+            ),
         );
     }
 

+ 1 - 3
packages/admin-ui/src/lib/customer/src/components/customer-group-member-list/customer-group-member-list.component.ts

@@ -128,7 +128,5 @@ export class CustomerGroupMemberListComponent implements OnInit, OnDestroy {
         }
     }
 
-    isMemberSelected = (member: { id: string }): boolean => {
-        return -1 < this.selectedMemberIds.indexOf(member.id);
-    };
+    isMemberSelected = (member: { id: string }): boolean => -1 < this.selectedMemberIds.indexOf(member.id);
 }

+ 8 - 10
packages/admin-ui/src/lib/dashboard/src/widgets/order-summary-widget/order-summary-widget.component.ts

@@ -29,21 +29,19 @@ export class OrderSummaryWidgetComponent implements OnInit {
     ngOnInit(): void {
         this.dateRange$ = this.selection$.pipe(
             distinctUntilChanged(),
-            map(selection => {
-                return {
-                    start: dayjs(selection.date).startOf(selection.timeframe).toDate(),
-                    end: dayjs(selection.date).endOf(selection.timeframe).toDate(),
-                };
-            }),
+            map(selection => ({
+                start: dayjs(selection.date).startOf(selection.timeframe).toDate(),
+                end: dayjs(selection.date).endOf(selection.timeframe).toDate(),
+            })),
             shareReplay(1),
         );
         const orderSummary$ = this.dateRange$.pipe(
-            switchMap(({ start, end }) => {
-                return this.dataService.order
+            switchMap(({ start, end }) =>
+                this.dataService.order
                     .getOrderSummary(start, end)
                     .refetchOnChannelChange()
-                    .mapStream(data => data.orders);
-            }),
+                    .mapStream(data => data.orders),
+            ),
             shareReplay(1),
         );
         this.totalOrderCount$ = orderSummary$.pipe(map(res => res.totalItems));

+ 7 - 9
packages/admin-ui/src/lib/marketing/src/components/promotion-detail/promotion-detail.component.ts

@@ -268,15 +268,13 @@ export class PromotionDetailComponent
         operations: ConfigurableOperation[],
         formValueOperations: any,
     ): ConfigurableOperationInput[] {
-        return operations.map((o, i) => {
-            return {
-                code: o.code,
-                arguments: Object.values<any>(formValueOperations[i].args).map((value, j) => ({
-                    name: o.args[j].name,
-                    value: encodeConfigArgValue(value),
-                })),
-            };
-        });
+        return operations.map((o, i) => ({
+            code: o.code,
+            arguments: Object.values<any>(formValueOperations[i].args).map((value, j) => ({
+                name: o.args[j].name,
+                value: encodeConfigArgValue(value),
+            })),
+        }));
     }
 
     /**

+ 4 - 3
packages/admin-ui/src/lib/order/src/components/cancel-order-dialog/cancel-order-dialog.component.ts

@@ -35,9 +35,10 @@ export class CancelOrderDialogComponent implements OnInit, Dialog<CancelOrderInp
     }
 
     ngOnInit() {
-        this.lineQuantities = this.order.lines.reduce((result, line) => {
-            return { ...result, [line.id]: line.quantity };
-        }, {});
+        this.lineQuantities = this.order.lines.reduce(
+            (result, line) => ({ ...result, [line.id]: line.quantity }),
+            {},
+        );
     }
 
     radioChanged() {

+ 1 - 1
packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.ts

@@ -30,7 +30,7 @@ export class CouponCodeSelectorComponent implements OnInit {
                         }).single$,
                 ),
                 map(({ promotions }) =>
-                    // tslint:disable-next-line:no-non-null-assertion
+                    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                     promotions.items.map(p => ({ code: p.couponCode!, promotionName: p.name })),
                 ),
                 startWith([]),

+ 8 - 8
packages/admin-ui/src/lib/order/src/components/draft-order-detail/draft-order-detail.component.ts

@@ -126,14 +126,14 @@ export class DraftOrderDetailComponent
         this.entity$
             .pipe(
                 take(1),
-                switchMap(order => {
-                    return this.modalService.fromComponent(SelectAddressDialogComponent, {
+                switchMap(order =>
+                    this.modalService.fromComponent(SelectAddressDialogComponent, {
                         locals: {
                             customerId: order.customer?.id,
                             currentAddress: order.shippingAddress ?? undefined,
                         },
-                    });
-                }),
+                    }),
+                ),
             )
             .subscribe(result => {
                 if (result) {
@@ -146,14 +146,14 @@ export class DraftOrderDetailComponent
         this.entity$
             .pipe(
                 take(1),
-                switchMap(order => {
-                    return this.modalService.fromComponent(SelectAddressDialogComponent, {
+                switchMap(order =>
+                    this.modalService.fromComponent(SelectAddressDialogComponent, {
                         locals: {
                             customerId: order.customer?.id,
                             currentAddress: order.billingAddress ?? undefined,
                         },
-                    });
-                }),
+                    }),
+                ),
             )
             .subscribe(result => {
                 if (result) {

+ 4 - 7
packages/admin-ui/src/lib/order/src/components/fulfillment-detail/fulfillment-detail.component.ts

@@ -32,13 +32,10 @@ export class FulfillmentDetailComponent implements OnInit, OnChanges {
 
     get items(): Array<{ name: string; quantity: number }> {
         return (
-            this.fulfillment?.lines.map(row => {
-                return {
-                    name:
-                        this.order.lines.find(line => line.id === row.orderLineId)?.productVariant.name ?? '',
-                    quantity: row.quantity,
-                };
-            }) ?? []
+            this.fulfillment?.lines.map(row => ({
+                name: this.order.lines.find(line => line.id === row.orderLineId)?.productVariant.name ?? '',
+                quantity: row.quantity,
+            })) ?? []
         );
     }
 

+ 8 - 6
packages/admin-ui/src/lib/order/src/components/modification-detail/modification-detail.component.ts

@@ -24,15 +24,17 @@ export class ModificationDetailComponent implements OnChanges {
     }
 
     getAddedItems() {
-        return [...this.addedItems.entries()].map(([line, count]) => {
-            return { name: line.productVariant.name, quantity: count };
-        });
+        return [...this.addedItems.entries()].map(([line, count]) => ({
+            name: line.productVariant.name,
+            quantity: count,
+        }));
     }
 
     getRemovedItems() {
-        return [...this.removedItems.entries()].map(([line, count]) => {
-            return { name: line.productVariant.name, quantity: count };
-        });
+        return [...this.removedItems.entries()].map(([line, count]) => ({
+            name: line.productVariant.name,
+            quantity: count,
+        }));
     }
 
     private getModifiedLines() {

+ 8 - 8
packages/admin-ui/src/lib/order/src/components/order-detail/order-detail.component.ts

@@ -92,15 +92,15 @@ export class OrderDetailComponent
         this.orderLineCustomFields = this.getCustomFieldConfig('OrderLine');
         this.history$ = this.fetchHistory.pipe(
             startWith(null),
-            switchMap(() => {
-                return this.dataService.order
+            switchMap(() =>
+                this.dataService.order
                     .getOrderHistory(this.id, {
                         sort: {
                             createdAt: SortOrder.DESC,
                         },
                     })
-                    .mapStream(data => data.order?.history.items);
-            }),
+                    .mapStream(data => data.order?.history.items),
+            ),
         );
         this.nextStates$ = this.entity$.pipe(
             map(order => {
@@ -357,14 +357,14 @@ export class OrderDetailComponent
         this.entity$
             .pipe(
                 take(1),
-                switchMap(order => {
-                    return this.modalService.fromComponent(FulfillOrderDialogComponent, {
+                switchMap(order =>
+                    this.modalService.fromComponent(FulfillOrderDialogComponent, {
                         size: 'xl',
                         locals: {
                             order,
                         },
-                    });
-                }),
+                    }),
+                ),
                 switchMap(input => {
                     if (input) {
                         return this.dataService.order.createFulfillment(input);

+ 3 - 3
packages/admin-ui/src/lib/order/src/components/order-editor/order-editor.component.ts

@@ -358,9 +358,9 @@ export class OrderEditorComponent
     previewAndModify(order: OrderDetailFragment) {
         const modifyOrderInput: ModifyOrderData = {
             ...this.modifyOrderInput,
-            adjustOrderLines: this.modifyOrderInput.adjustOrderLines.map(line => {
-                return transformRelationCustomFieldInputs(simpleDeepClone(line), this.orderLineCustomFields);
-            }),
+            adjustOrderLines: this.modifyOrderInput.adjustOrderLines.map(line =>
+                transformRelationCustomFieldInputs(simpleDeepClone(line), this.orderLineCustomFields),
+            ),
         };
         const input: ModifyOrderInput = {
             ...modifyOrderInput,

+ 1 - 1
packages/admin-ui/src/lib/order/src/components/order-edits-preview-dialog/order-edits-preview-dialog.component.ts

@@ -67,7 +67,7 @@ export class OrderEditsPreviewDialogComponent implements OnInit, Dialog<OrderEdi
         } else if (this.priceDifference < 0) {
             this.resolveWith({
                 result: OrderEditResultType.Refund,
-                // tslint:disable-next-line:no-non-null-assertion
+                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                 refundPaymentId: this.selectedPayment!.id,
                 refundNote: this.refundNote,
             });

+ 4 - 4
packages/admin-ui/src/lib/order/src/components/order-list/order-list.component.ts

@@ -103,10 +103,10 @@ export class OrderListComponent
     ) {
         super(router, route);
         super.setQueryFn(
-            // tslint:disable-next-line:no-shadowed-variable
+            // eslint-disable-next-line @typescript-eslint/no-shadow
             (take, skip) => this.dataService.order.getOrders({ take, skip }).refetchOnChannelChange(),
             data => data.orders,
-            // tslint:disable-next-line:no-shadowed-variable
+            // eslint-disable-next-line @typescript-eslint/no-shadow
             (skip, take) =>
                 this.createQueryOptions(
                     skip,
@@ -185,14 +185,14 @@ export class OrderListComponent
     }
 
     private createQueryOptions(
-        // tslint:disable-next-line:no-shadowed-variable
+        // eslint-disable-next-line @typescript-eslint/no-shadow
         skip: number,
         take: number,
         searchTerm: string,
         activeFilterPreset?: string,
     ): { options: OrderListOptions } {
         const filterConfig = this.filterPresets.find(p => p.name === activeFilterPreset);
-        // tslint:disable-next-line:no-shadowed-variable
+        // eslint-disable-next-line @typescript-eslint/no-shadow
         let filter: OrderFilterParameter = {};
         let filterOperator: LogicalOperator = LogicalOperator.AND;
         if (filterConfig) {

+ 1 - 3
packages/admin-ui/src/lib/order/src/components/order-table/order-table.component.ts

@@ -59,9 +59,7 @@ export class OrderTableComponent implements OnInit {
                         value,
                     };
                 })
-                .filter(field => {
-                    return this.orderLineCustomFieldsVisible ? true : field.value != null;
-                });
+                .filter(field => this.orderLineCustomFieldsVisible ? true : field.value != null);
             this.customFieldsForLine[line.id] = result;
         }
     }

+ 4 - 10
packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.ts

@@ -84,16 +84,14 @@ export class RefundOrderDialogComponent
     }
 
     ngOnInit() {
-        this.lineQuantities = this.order.lines.reduce((result, line) => {
-            return {
+        this.lineQuantities = this.order.lines.reduce((result, line) => ({
                 ...result,
                 [line.id]: {
                     quantity: 0,
                     refund: false,
                     cancel: false,
                 },
-            };
-        }, {});
+            }), {});
         this.settledPayments = (this.order.payments || []).filter(p => p.state === 'Settled');
         if (this.settledPayments.length) {
             this.selectedPayment = this.settledPayments[0];
@@ -108,16 +106,12 @@ export class RefundOrderDialogComponent
     }
 
     isRefunding(): boolean {
-        const result = Object.values(this.lineQuantities).reduce((isRefunding, line) => {
-            return isRefunding || (0 < line.quantity && line.refund);
-        }, false);
+        const result = Object.values(this.lineQuantities).reduce((isRefunding, line) => isRefunding || (0 < line.quantity && line.refund), false);
         return result;
     }
 
     isCancelling(): boolean {
-        const result = Object.values(this.lineQuantities).reduce((isCancelling, line) => {
-            return isCancelling || (0 < line.quantity && line.cancel);
-        }, false);
+        const result = Object.values(this.lineQuantities).reduce((isCancelling, line) => isCancelling || (0 < line.quantity && line.cancel), false);
         return result;
     }
 

+ 0 - 1
packages/admin-ui/src/lib/order/src/components/select-shipping-method-dialog/select-shipping-method-dialog.component.ts

@@ -21,7 +21,6 @@ export class SelectShippingMethodDialogComponent implements OnInit, Dialog<strin
     currentSelectionId: string;
     currencyCode: CurrencyCode;
     selectedMethod: ShippingMethodQuote | undefined;
-    constructor() {}
 
     ngOnInit(): void {
         if (this.currentSelectionId) {

+ 1 - 1
packages/admin-ui/src/lib/order/src/providers/routing/order-resolver.ts

@@ -33,7 +33,7 @@ export class OrderResolver implements Resolve<Observable<OrderDetailFragment>> {
         const navigateAway$ = this.router.events.pipe(filter(event => event instanceof ActivationStart));
 
         const stream = this.dataService.order
-            // tslint:disable-next-line:no-non-null-assertion
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             .getOrder(id!)
             .mapStream(data => data.order)
             .pipe(

+ 3 - 3
packages/admin-ui/src/lib/settings/src/components/admin-detail/admin-detail.component.ts

@@ -228,18 +228,18 @@ export class AdminDetailComponent
 
             this.selectedRolePermissions = {} as any;
             for (const channelId of Array.from(channelIdPermissionsMap.keys())) {
-                // tslint:disable-next-line:no-non-null-assertion
+                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                 const permissionSet = channelIdPermissionsMap.get(channelId)!;
                 const permissionsHash: { [K in Permission]: boolean } = {} as any;
                 for (const def of this.serverConfigService.getPermissionDefinitions()) {
                     permissionsHash[def.name] = permissionSet.has(def.name as Permission);
                 }
                 this.selectedRolePermissions[channelId] = {
-                    // tslint:disable:no-non-null-assertion
+                    /* eslint-disable @typescript-eslint/no-non-null-assertion */
                     channelId,
                     channelCode: channelIdCodeMap.get(channelId)!,
                     permissions: permissionsHash,
-                    // tslint:enable:no-non-null-assertion
+                    /* eslint-enable @typescript-eslint/no-non-null-assertion */
                 };
             }
         }

+ 1 - 1
packages/admin-ui/src/lib/settings/src/components/channel-detail/channel-detail.component.ts

@@ -109,7 +109,7 @@ export class ChannelDetailComponent
                     ),
                 ),
                 mergeMap(({ me, createChannel }) =>
-                    // tslint:disable-next-line:no-non-null-assertion
+                    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                     this.dataService.client.updateUserChannels(me!.channels).pipe(map(() => createChannel)),
                 ),
             )

+ 1 - 1
packages/admin-ui/src/lib/settings/src/components/channel-list/channel-list.component.ts

@@ -42,7 +42,7 @@ export class ChannelListComponent {
             .pipe(
                 switchMap(response => (response ? this.dataService.settings.deleteChannel(id) : EMPTY)),
                 mergeMap(() => this.dataService.auth.currentUser().single$),
-                // tslint:disable-next-line:no-non-null-assertion
+                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                 mergeMap(data => this.dataService.client.updateUserChannels(data.me!.channels)),
             )
             .subscribe(

+ 2 - 4
packages/admin-ui/src/lib/settings/src/components/country-list/country-list.component.ts

@@ -62,12 +62,10 @@ export class CountryListComponent implements OnInit, OnDestroy {
         this.zones$ = this.dataService.settings.getZones().mapStream(data => data.zones);
 
         this.countriesWithZones$ = combineLatest(countries$, this.zones$).pipe(
-            map(([countries, zones]) => {
-                return countries.map(country => ({
+            map(([countries, zones]) => countries.map(country => ({
                     ...country,
                     zones: zones.filter(z => !!z.members.find(c => c.id === country.id)),
-                }));
-            }),
+                }))),
         );
 
         this.availableLanguages$ = this.serverConfigService.getAvailableLanguages();

+ 2 - 4
packages/admin-ui/src/lib/settings/src/components/permission-grid/permission-grid.component.ts

@@ -67,13 +67,11 @@ export class PermissionGridComponent implements OnInit {
                 description: d.description,
                 permissions: [d],
             })),
-            ...Array.from(crudGroups.entries()).map(([label, defs]) => {
-                return {
+            ...Array.from(crudGroups.entries()).map(([label, defs]) => ({
                     label,
                     description: this.extractCrudDescription(defs[0]),
                     permissions: defs,
-                };
-            }),
+                })),
         ];
     }
 

+ 3 - 3
packages/admin-ui/src/lib/settings/src/components/shipping-method-detail/shipping-method-detail.component.ts

@@ -123,14 +123,14 @@ export class ShippingMethodDetailComponent
             }),
         );
 
-        // tslint:disable:no-non-null-assertion
+        /* eslint-disable @typescript-eslint/no-non-null-assertion */
         merge(
             this.detailForm.get(['checker'])!.valueChanges,
             this.detailForm.get(['calculator'])!.valueChanges,
         )
             .pipe(takeUntil(this.destroy$))
             .subscribe(() => (this.testDataUpdated = true));
-        // tslint:enable:no-non-null-assertion
+        /* eslint-enable @typescript-eslint/no-non-null-assertion */
     }
 
     ngOnDestroy(): void {
@@ -242,7 +242,7 @@ export class ShippingMethodDetailComponent
                     this.changeDetector.markForCheck();
                 },
                 err => {
-                    // tslint:disable-next-line:no-console
+                    // eslint-disable-next-line no-console
                     console.error(err);
                     this.notificationService.error(_('common.notify-update-error'), {
                         entity: 'ShippingMethod',

+ 1 - 3
packages/admin-ui/src/lib/settings/src/components/zone-member-list/zone-member-list.component.ts

@@ -54,7 +54,5 @@ export class ZoneMemberListComponent {
         }
     }
 
-    isMemberSelected = (member: ZoneMember): boolean => {
-        return -1 < this.selectedMemberIds.indexOf(member.id);
-    };
+    isMemberSelected = (member: ZoneMember): boolean => -1 < this.selectedMemberIds.indexOf(member.id);
 }

+ 1 - 1
packages/admin-ui/src/lib/static/polyfills.ts

@@ -13,7 +13,7 @@
  *
  * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
  */
-// tslint:disable:ordered-imports
+/* eslint-disable import/order */
 /***************************************************************************************************
  * BROWSER POLYFILLS
  */

+ 1 - 3
packages/admin-ui/src/lib/system/src/components/job-list/job-list.component.ts

@@ -75,9 +75,7 @@ export class JobListComponent
             .getJobQueues()
             .mapStream(res => res.jobQueues)
             .pipe(
-                map(queues => {
-                    return [{ name: 'all', running: true }, ...queues];
-                }),
+                map(queues => [{ name: 'all', running: true }, ...queues]),
             );
     }
 

+ 1 - 1
packages/admin-ui/src/main.ts

@@ -12,6 +12,6 @@ if (environment.production) {
 loadAppConfig()
     .then(() => platformBrowserDynamic().bootstrapModule(AppModule))
     .catch(err => {
-        // tslint:disable:no-console
+        /* eslint-disable no-console */
         console.log(err);
     });

+ 1 - 1
packages/admin-ui/src/test.ts

@@ -1,5 +1,5 @@
 // This file is required by karma.conf.js and loads recursively all the .spec and framework files
-// tslint:disable
+/* eslint-disable */
 import 'zone.js/testing';
 import { getTestBed } from '@angular/core/testing';
 import {

+ 0 - 17
packages/admin-ui/src/tslint.json

@@ -1,17 +0,0 @@
-{
-    "extends": "../tslint.json",
-    "rules": {
-        "directive-selector": [
-            true,
-            "attribute",
-            "vdr",
-            "camelCase"
-        ],
-        "component-selector": [
-            true,
-            "element",
-            "vdr",
-            "kebab-case"
-        ]
-    }
-}

+ 0 - 33
packages/admin-ui/tslint.json

@@ -1,33 +0,0 @@
-{
-  "extends": [
-    "../../tslint.json"
-  ],
-  "rulesDirectory": [
-    "./node_modules/codelyzer"
-  ],
-  "rules": {
-    "deprecation": {
-      "severity": "warn"
-    },
-    "import-blacklist": [
-      true,
-      "rxjs/Rx"
-    ],
-    "indent": [
-      true,
-      "spaces"
-    ],
-    "no-string-literal": false,
-    "no-output-on-prefix": true,
-    "use-input-property-decorator": true,
-    "use-output-property-decorator": true,
-    "use-host-property-decorator": true,
-    "no-input-rename": false,
-    "no-output-rename": true,
-    "use-life-cycle-interface": true,
-    "use-pipe-transform-interface": true,
-    "component-class-suffix": true,
-    "directive-class-suffix": true,
-    "no-floating-promises": false
-  }
-}

Some files were not shown because too many files changed in this diff