From 17a6fa6c1d4c60f957e4ca7fce8cacd16b52fd88 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 11 Mar 2026 13:17:08 +0530 Subject: [PATCH] feat: upgrade to eslint 10 --- .eslintrc.js | 256 --- app/javascript/dashboard/api/ApiClient.js | 1 - .../dashboard/api/CacheEnabledApiClient.js | 3 - app/javascript/dashboard/api/changelog.js | 1 - .../api/channel/voice/voiceAPIClient.js | 1 - app/javascript/dashboard/api/contacts.js | 1 - app/javascript/dashboard/api/inboxes.js | 1 - app/javascript/dashboard/api/labels.js | 1 - app/javascript/dashboard/api/reports.js | 1 - app/javascript/dashboard/api/teams.js | 3 - .../LiveChatCampaign/LiveChatCampaignForm.vue | 1 - .../components-next/message/Message.vue | 5 +- .../widgets/WootWriter/FullEditor.vue | 4 +- .../widgets/WootWriter/ReplyBottomPanel.vue | 2 +- .../WootWriter/utils/mp3ConversionUtils.js | 4 +- .../dashboard/helper/actionCable.js | 5 - .../dashboard/helper/automationHelper.js | 3 +- .../dashboard/helper/emailQuoteExtractor.js | 2 +- app/javascript/dashboard/helper/pushHelper.js | 3 - .../helper/specs/templateHelper.spec.js | 3 +- .../settings/inbox/channels/Facebook.vue | 1 - .../shared/helpers/AudioNotificationHelper.js | 3 +- .../helpers/BaseActionCableConnector.js | 2 - app/javascript/shared/helpers/CustomErrors.js | 1 - .../widget/components/UnreadMessage.vue | 1 - app/javascript/widget/helpers/actionCable.js | 1 - app/javascript/widget/helpers/uuid.js | 3 +- eslint.config.js | 246 +++ package.json | 17 +- pnpm-lock.yaml | 1700 +++-------------- 30 files changed, 520 insertions(+), 1756 deletions(-) delete mode 100644 .eslintrc.js create mode 100644 eslint.config.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 6b5205ad7..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,256 +0,0 @@ -module.exports = { - extends: [ - 'airbnb-base/legacy', - 'prettier', - 'plugin:vue/vue3-recommended', - 'plugin:vitest-globals/recommended', - // use recommended-legacy when upgrading the plugin to v4 - 'plugin:@intlify/vue-i18n/recommended', - ], - overrides: [ - { - files: ['**/*.spec.{j,t}s?(x)'], - env: { - 'vitest-globals/env': true, - }, - }, - { - files: ['**/*.story.vue'], - rules: { - 'vue/no-undef-components': [ - 'error', - { - ignorePatterns: ['Variant', 'Story'], - }, - ], - // Story files can have static strings, it doesn't need to handle i18n always. - 'vue/no-bare-strings-in-template': 'off', - 'no-console': 'off', - }, - }, - ], - plugins: ['html', 'prettier'], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - }, - rules: { - 'prettier/prettier': ['error'], - camelcase: 'off', - 'no-param-reassign': 'off', - 'import/no-extraneous-dependencies': 'off', - 'import/prefer-default-export': 'off', - 'import/no-named-as-default': 'off', - 'jsx-a11y/no-static-element-interactions': 'off', - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/label-has-associated-control': 'off', - 'jsx-a11y/label-has-for': 'off', - 'jsx-a11y/anchor-is-valid': 'off', - 'import/no-unresolved': 'off', - 'vue/html-indent': 'off', - 'vue/multi-word-component-names': 'off', - 'vue/next-tick-style': ['error', 'callback'], - 'vue/block-order': [ - 'error', - { - order: ['script', 'template', 'style'], - }, - ], - 'vue/component-name-in-template-casing': [ - 'error', - 'PascalCase', - { - registeredComponentsOnly: true, - }, - ], - 'vue/component-options-name-casing': ['error', 'PascalCase'], - 'vue/custom-event-name-casing': ['error', 'camelCase'], - 'vue/define-emits-declaration': ['error'], - 'vue/define-macros-order': [ - 'error', - { - order: ['defineProps', 'defineEmits'], - defineExposeLast: false, - }, - ], - 'vue/define-props-declaration': ['error', 'runtime'], - 'vue/match-component-import-name': ['error'], - 'vue/no-bare-strings-in-template': [ - 'error', - { - allowlist: [ - '(', - ')', - ',', - '.', - '&', - '+', - '-', - '=', - '*', - '/', - '#', - '%', - '!', - '?', - ':', - '[', - ']', - '{', - '}', - '<', - '>', - '⌘', - '📄', - '🎉', - '🚀', - '💬', - '👥', - '📥', - '🔖', - '❌', - '✅', - '\u00b7', - '\u2022', - '\u2010', - '\u2013', - '\u2014', - '\u2212', - '|', - ], - attributes: { - '/.+/': [ - 'title', - 'aria-label', - 'aria-placeholder', - 'aria-roledescription', - 'aria-valuetext', - ], - input: ['placeholder'], - }, - directives: ['v-text'], - }, - ], - 'vue/no-empty-component-block': 'error', - 'vue/no-multiple-objects-in-class': 'error', - 'vue/no-root-v-if': 'warn', - 'vue/no-static-inline-styles': [ - 'error', - { - allowBinding: false, - }, - ], - 'vue/no-template-target-blank': [ - 'error', - { - allowReferrer: false, - enforceDynamicLinks: 'always', - }, - ], - 'vue/no-required-prop-with-default': [ - 'error', - { - autofix: false, - }, - ], - 'vue/no-this-in-before-route-enter': 'error', - 'vue/no-undef-components': [ - 'error', - { - ignorePatterns: [ - '^woot-', - '^fluent-', - '^multiselect', - '^router-link', - '^router-view', - '^ninja-keys', - '^FormulateForm', - '^FormulateInput', - '^highlightjs', - ], - }, - ], - 'vue/no-unused-emit-declarations': 'error', - 'vue/no-unused-refs': 'error', - 'vue/no-use-v-else-with-v-for': 'error', - 'vue/prefer-true-attribute-shorthand': 'error', - 'vue/no-useless-v-bind': [ - 'error', - { - ignoreIncludesComment: false, - ignoreStringEscape: false, - }, - ], - 'vue/no-v-text': 'error', - 'vue/padding-line-between-blocks': ['error', 'always'], - 'vue/prefer-separate-static-class': 'error', - 'vue/require-explicit-slots': 'error', - 'vue/require-macro-variable-name': [ - 'error', - { - defineProps: 'props', - defineEmits: 'emit', - defineSlots: 'slots', - useSlots: 'slots', - useAttrs: 'attrs', - }, - ], - 'vue/no-unused-properties': [ - 'error', - { - groups: ['props'], - deepData: false, - ignorePublicMembers: false, - unreferencedOptions: [], - }, - ], - 'vue/max-attributes-per-line': [ - 'error', - { - singleline: { - max: 20, - }, - multiline: { - max: 1, - }, - }, - ], - 'vue/html-self-closing': [ - 'error', - { - html: { - void: 'always', - normal: 'always', - component: 'always', - }, - svg: 'always', - math: 'always', - }, - ], - 'vue/no-v-html': 'off', - 'vue/component-definition-name-casing': 'off', - 'vue/singleline-html-element-content-newline': 'off', - 'import/extensions': ['off'], - 'no-console': 'error', - '@intlify/vue-i18n/no-dynamic-keys': 'warn', - '@intlify/vue-i18n/no-unused-keys': [ - 'warn', - { - extensions: ['.js', '.vue'], - }, - ], - }, - settings: { - 'vue-i18n': { - localeDir: './app/javascript/*/i18n/**.json', - }, - }, - env: { - browser: true, - node: true, - }, - globals: { - bus: true, - vi: true, - }, -}; diff --git a/app/javascript/dashboard/api/ApiClient.js b/app/javascript/dashboard/api/ApiClient.js index 6b57d32b6..27d9251fa 100644 --- a/app/javascript/dashboard/api/ApiClient.js +++ b/app/javascript/dashboard/api/ApiClient.js @@ -13,7 +13,6 @@ class ApiClient { return `${this.baseUrl()}/${this.resource}`; } - // eslint-disable-next-line class-methods-use-this get accountIdFromRoute() { const isInsideAccountScopedURLs = window.location.pathname.includes('/app/accounts'); diff --git a/app/javascript/dashboard/api/CacheEnabledApiClient.js b/app/javascript/dashboard/api/CacheEnabledApiClient.js index 9af939c00..8bb5eebb2 100644 --- a/app/javascript/dashboard/api/CacheEnabledApiClient.js +++ b/app/javascript/dashboard/api/CacheEnabledApiClient.js @@ -8,7 +8,6 @@ class CacheEnabledApiClient extends ApiClient { this.dataManager = new DataManager(this.accountIdFromRoute); } - // eslint-disable-next-line class-methods-use-this get cacheModelName() { throw new Error('cacheModelName is not defined'); } @@ -25,12 +24,10 @@ class CacheEnabledApiClient extends ApiClient { return axios.get(this.url); } - // eslint-disable-next-line class-methods-use-this extractDataFromResponse(response) { return response.data.payload; } - // eslint-disable-next-line class-methods-use-this marshallData(dataToParse) { return { data: { payload: dataToParse } }; } diff --git a/app/javascript/dashboard/api/changelog.js b/app/javascript/dashboard/api/changelog.js index 8cf0cdea1..74b389125 100644 --- a/app/javascript/dashboard/api/changelog.js +++ b/app/javascript/dashboard/api/changelog.js @@ -7,7 +7,6 @@ class ChangelogApi extends ApiClient { super('changelog', { apiVersion: 'v1' }); } - // eslint-disable-next-line class-methods-use-this fetchFromHub() { return axios.get(CHANGELOG_API_URL); } diff --git a/app/javascript/dashboard/api/channel/voice/voiceAPIClient.js b/app/javascript/dashboard/api/channel/voice/voiceAPIClient.js index 6e1e548c8..9b8ecd1e9 100644 --- a/app/javascript/dashboard/api/channel/voice/voiceAPIClient.js +++ b/app/javascript/dashboard/api/channel/voice/voiceAPIClient.js @@ -7,7 +7,6 @@ class VoiceAPI extends ApiClient { super('voice', { accountScoped: true }); } - // eslint-disable-next-line class-methods-use-this initiateCall(contactId, inboxId) { return ContactsAPI.initiateCall(contactId, inboxId).then(r => r.data); } diff --git a/app/javascript/dashboard/api/contacts.js b/app/javascript/dashboard/api/contacts.js index bae5623a7..e95f67b96 100644 --- a/app/javascript/dashboard/api/contacts.js +++ b/app/javascript/dashboard/api/contacts.js @@ -72,7 +72,6 @@ class ContactAPI extends ApiClient { return axios.get(requestURL); } - // eslint-disable-next-line default-param-last filter(page = 1, sortAttr = 'name', queryPayload) { let requestURL = `${this.url}/filter?${buildContactParams(page, sortAttr)}`; return axios.post(requestURL, queryPayload); diff --git a/app/javascript/dashboard/api/inboxes.js b/app/javascript/dashboard/api/inboxes.js index 079f21815..1475ea1bd 100644 --- a/app/javascript/dashboard/api/inboxes.js +++ b/app/javascript/dashboard/api/inboxes.js @@ -6,7 +6,6 @@ class Inboxes extends CacheEnabledApiClient { super('inboxes', { accountScoped: true }); } - // eslint-disable-next-line class-methods-use-this get cacheModelName() { return 'inbox'; } diff --git a/app/javascript/dashboard/api/labels.js b/app/javascript/dashboard/api/labels.js index 2b521b058..33ce9546a 100644 --- a/app/javascript/dashboard/api/labels.js +++ b/app/javascript/dashboard/api/labels.js @@ -5,7 +5,6 @@ class LabelsAPI extends CacheEnabledApiClient { super('labels', { accountScoped: true }); } - // eslint-disable-next-line class-methods-use-this get cacheModelName() { return 'label'; } diff --git a/app/javascript/dashboard/api/reports.js b/app/javascript/dashboard/api/reports.js index 00f040f8e..94545c4b3 100644 --- a/app/javascript/dashboard/api/reports.js +++ b/app/javascript/dashboard/api/reports.js @@ -31,7 +31,6 @@ class ReportsAPI extends ApiClient { }); } - // eslint-disable-next-line default-param-last getSummary(since, until, type = 'account', id, groupBy, businessHours) { return axios.get(`${this.url}/summary`, { params: { diff --git a/app/javascript/dashboard/api/teams.js b/app/javascript/dashboard/api/teams.js index 5413af96b..2737c556b 100644 --- a/app/javascript/dashboard/api/teams.js +++ b/app/javascript/dashboard/api/teams.js @@ -7,17 +7,14 @@ export class TeamsAPI extends CacheEnabledApiClient { super('teams', { accountScoped: true }); } - // eslint-disable-next-line class-methods-use-this get cacheModelName() { return 'team'; } - // eslint-disable-next-line class-methods-use-this extractDataFromResponse(response) { return response.data; } - // eslint-disable-next-line class-methods-use-this marshallData(dataToParse) { return { data: dataToParse }; } diff --git a/app/javascript/dashboard/components-next/Campaigns/Pages/CampaignPage/LiveChatCampaign/LiveChatCampaignForm.vue b/app/javascript/dashboard/components-next/Campaigns/Pages/CampaignPage/LiveChatCampaign/LiveChatCampaignForm.vue index 00bd2297f..54f85370b 100644 --- a/app/javascript/dashboard/components-next/Campaigns/Pages/CampaignPage/LiveChatCampaign/LiveChatCampaignForm.vue +++ b/app/javascript/dashboard/components-next/Campaigns/Pages/CampaignPage/LiveChatCampaign/LiveChatCampaignForm.vue @@ -56,7 +56,6 @@ const state = reactive({ ...initialState }); const urlValidators = { shouldBeAValidURLPattern: value => { try { - // eslint-disable-next-line new URLPattern(value); return true; } catch { diff --git a/app/javascript/dashboard/components-next/message/Message.vue b/app/javascript/dashboard/components-next/message/Message.vue index 3de9d2d04..1a6f48348 100644 --- a/app/javascript/dashboard/components-next/message/Message.vue +++ b/app/javascript/dashboard/components-next/message/Message.vue @@ -99,7 +99,6 @@ import { useBranding } from 'shared/composables/useBranding'; * @property {number} inboxId - The ID of the inbox to which the message belongs */ -// eslint-disable-next-line vue/define-macros-order const props = defineProps({ id: { type: Number, required: true }, messageType: { @@ -124,12 +123,12 @@ const props = defineProps({ createdAt: { type: Number, required: true }, // eslint-disable-line vue/no-unused-properties currentUserId: { type: Number, required: true }, // eslint-disable-line vue/no-unused-properties groupWithNext: { type: Boolean, default: false }, - inboxId: { type: Number, default: null }, // eslint-disable-line vue/no-unused-properties + inboxId: { type: Number, default: null }, inboxSupportsReplyTo: { type: Object, default: () => ({}) }, inReplyTo: { type: Object, default: null }, // eslint-disable-line vue/no-unused-properties isEmailInbox: { type: Boolean, default: false }, private: { type: Boolean, default: false }, - additionalAttributes: { type: Object, default: () => ({}) }, // eslint-disable-line vue/no-unused-properties + additionalAttributes: { type: Object, default: () => ({}) }, sender: { type: Object, default: null }, senderId: { type: Number, default: null }, senderType: { type: String, default: null }, diff --git a/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue b/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue index 817f6e2b9..00addbc48 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue @@ -18,9 +18,9 @@ const MAXIMUM_FILE_UPLOAD_SIZE = 4; // in MB const createState = ( content, placeholder, - // eslint-disable-next-line default-param-last + plugins = [], - // eslint-disable-next-line default-param-last + methods = {}, enabledMenuOptions ) => { diff --git a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue index 5f76041dc..1220542f1 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue @@ -36,7 +36,7 @@ export default { }, // inbox prop is used in /mixins/inboxMixin, // remove this props when refactoring to composable if not needed - // eslint-disable-next-line vue/no-unused-properties + inbox: { type: Object, default: () => ({}), diff --git a/app/javascript/dashboard/components/widgets/WootWriter/utils/mp3ConversionUtils.js b/app/javascript/dashboard/components/widgets/WootWriter/utils/mp3ConversionUtils.js index 3ae37911d..2d74223e0 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/utils/mp3ConversionUtils.js +++ b/app/javascript/dashboard/components/widgets/WootWriter/utils/mp3ConversionUtils.js @@ -1,7 +1,6 @@ import lamejs from '@breezystack/lamejs'; const writeString = (view, offset, string) => { - // eslint-disable-next-line no-plusplus for (let i = 0; i < string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } @@ -29,9 +28,8 @@ const bufferToWav = async (buffer, numChannels, sampleRate) => { // WAV Data const offset = 44; - // eslint-disable-next-line no-plusplus + for (let i = 0; i < buffer.length; i++) { - // eslint-disable-next-line no-plusplus for (let channel = 0; channel < numChannels; channel++) { const sample = Math.max( -1, diff --git a/app/javascript/dashboard/helper/actionCable.js b/app/javascript/dashboard/helper/actionCable.js index 991576e66..e460ccaec 100644 --- a/app/javascript/dashboard/helper/actionCable.js +++ b/app/javascript/dashboard/helper/actionCable.js @@ -37,12 +37,10 @@ class ActionCableConnector extends BaseActionCableConnector { }; } - // eslint-disable-next-line class-methods-use-this onReconnect = () => { emitter.emit(BUS_EVENTS.WEBSOCKET_RECONNECT); }; - // eslint-disable-next-line class-methods-use-this onDisconnected = () => { emitter.emit(BUS_EVENTS.WEBSOCKET_DISCONNECT); }; @@ -90,7 +88,6 @@ class ActionCableConnector extends BaseActionCableConnector { this.app.$store.dispatch('updateConversation', data); }; - // eslint-disable-next-line class-methods-use-this onLogout = () => AuthAPI.logout(); onMessageCreated = data => { @@ -106,7 +103,6 @@ class ActionCableConnector extends BaseActionCableConnector { }); }; - // eslint-disable-next-line class-methods-use-this onReload = () => window.location.reload(); onStatusChange = data => { @@ -161,7 +157,6 @@ class ActionCableConnector extends BaseActionCableConnector { }, 30000); }; - // eslint-disable-next-line class-methods-use-this fetchConversationStats = () => { emitter.emit('fetch_conversation_stats'); }; diff --git a/app/javascript/dashboard/helper/automationHelper.js b/app/javascript/dashboard/helper/automationHelper.js index fa6120c16..eb4802b9e 100644 --- a/app/javascript/dashboard/helper/automationHelper.js +++ b/app/javascript/dashboard/helper/automationHelper.js @@ -212,9 +212,8 @@ export const isCustomAttribute = (attrs, key) => { }; export const generateCustomAttributes = ( - // eslint-disable-next-line default-param-last conversationAttributes = [], - // eslint-disable-next-line default-param-last + contactAttributes = [], conversationlabel, contactlabel diff --git a/app/javascript/dashboard/helper/emailQuoteExtractor.js b/app/javascript/dashboard/helper/emailQuoteExtractor.js index f29d48cca..58af28fcc 100644 --- a/app/javascript/dashboard/helper/emailQuoteExtractor.js +++ b/app/javascript/dashboard/helper/emailQuoteExtractor.js @@ -61,7 +61,7 @@ export class EmailQuoteExtractor { tempDiv.innerHTML = DOMPurify.sanitize(htmlContent); // Check for class-based quotes - // eslint-disable-next-line no-restricted-syntax + for (const selector of QUOTE_INDICATORS) { if (tempDiv.querySelector(selector)) { return true; diff --git a/app/javascript/dashboard/helper/pushHelper.js b/app/javascript/dashboard/helper/pushHelper.js index 44757ffcd..464fa1a86 100644 --- a/app/javascript/dashboard/helper/pushHelper.js +++ b/app/javascript/dashboard/helper/pushHelper.js @@ -18,7 +18,6 @@ export const verifyServiceWorkerExistence = (callback = () => {}) => { .register('/sw.js') .then(registration => callback(registration)) .catch(registrationError => { - // eslint-disable-next-line console.log('SW registration failed: ', registrationError); }); }; @@ -69,7 +68,6 @@ export const registerSubscription = (onSuccess = () => {}) => { onSuccess(); }) .catch(error => { - // eslint-disable-next-line no-console console.error('Push subscription registration failed:', error); useAlert('This browser does not support desktop notification'); }); @@ -77,7 +75,6 @@ export const registerSubscription = (onSuccess = () => {}) => { export const requestPushPermissions = ({ onSuccess }) => { if (!('Notification' in window)) { - // eslint-disable-next-line no-console console.warn('Notification is not supported'); useAlert('This browser does not support desktop notification'); } else if (Notification.permission === 'granted') { diff --git a/app/javascript/dashboard/helper/specs/templateHelper.spec.js b/app/javascript/dashboard/helper/specs/templateHelper.spec.js index 375e38a2d..c5804fd79 100644 --- a/app/javascript/dashboard/helper/specs/templateHelper.spec.js +++ b/app/javascript/dashboard/helper/specs/templateHelper.spec.js @@ -288,10 +288,9 @@ describe('templateHelper', () => { }); it('should handle special characters in template variables', () => { - /* eslint-disable no-template-curly-in-string */ const templateText = 'Welcome {{user_name}}, your order #{{order_id}} costs ${{amount}}'; - /* eslint-enable no-template-curly-in-string */ + const processedParams = { body: { user_name: 'John & Jane', diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue index 39e0df818..b47d73d08 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue @@ -1,5 +1,4 @@