diff --git a/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue b/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue index 77dbdca22..9ab5fd9df 100644 --- a/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue +++ b/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue @@ -119,11 +119,13 @@ import aiMixin from 'dashboard/mixins/aiMixin'; import { getTypingUsersText } from '../../../helper/commons'; import { calculateScrollTop } from './helpers/scrollTopCalculationHelper'; import { isEscape } from 'shared/helpers/KeyboardHelpers'; +import { LocalStorage } from 'shared/helpers/localStorage'; // constants import { BUS_EVENTS } from 'shared/constants/busEvents'; import { REPLY_POLICY } from 'shared/constants/links'; import wootConstants from 'dashboard/constants/globals'; +import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage'; export default { components: { @@ -392,8 +394,11 @@ export default { }); }, isLabelSuggestionDismissed() { - const dismissed = this.getDismissedConversations(this.currentAccountId); - return dismissed[this.currentAccountId].includes(this.conversationId); + return LocalStorage.getFlag( + LOCAL_STORAGE_KEYS.DISMISSED_LABEL_SUGGESTIONS, + this.currentAccountId, + this.currentChat.id + ); }, fetchAllAttachmentsFromCurrentChat() { this.$store.dispatch('fetchAllAttachments', this.currentChat.id); diff --git a/app/javascript/dashboard/components/widgets/conversation/conversation/LabelSuggestion.vue b/app/javascript/dashboard/components/widgets/conversation/conversation/LabelSuggestion.vue index 5192be341..1dc859b90 100644 --- a/app/javascript/dashboard/components/widgets/conversation/conversation/LabelSuggestion.vue +++ b/app/javascript/dashboard/components/widgets/conversation/conversation/LabelSuggestion.vue @@ -190,12 +190,10 @@ export default { } }, dismissSuggestions() { - const dismissed = this.getDismissedConversations(this.currentAccountId); - dismissed[this.currentAccountId].push(this.conversationId); - - LocalStorage.set( + LocalStorage.setFlag( LOCAL_STORAGE_KEYS.DISMISSED_LABEL_SUGGESTIONS, - dismissed + this.currentAccountId, + this.conversationId ); // dismiss this once the values are set @@ -203,8 +201,11 @@ export default { this.trackLabelEvent(OPEN_AI_EVENTS.DISMISS_LABEL_SUGGESTION); }, isConversationDismissed() { - const dismissed = this.getDismissedConversations(this.currentAccountId); - return dismissed[this.currentAccountId].includes(this.conversationId); + return LocalStorage.getFlag( + LOCAL_STORAGE_KEYS.DISMISSED_LABEL_SUGGESTIONS, + this.currentAccountId, + this.conversationId + ); }, addAllLabels() { let labelsToAdd = this.selectedLabels; diff --git a/app/javascript/dashboard/constants/localStorage.js b/app/javascript/dashboard/constants/localStorage.js index 44d90735e..21360e178 100644 --- a/app/javascript/dashboard/constants/localStorage.js +++ b/app/javascript/dashboard/constants/localStorage.js @@ -3,5 +3,5 @@ export const LOCAL_STORAGE_KEYS = { WIDGET_BUILDER: 'widgetBubble_', DRAFT_MESSAGES: 'draftMessages', COLOR_SCHEME: 'color_scheme', - DISMISSED_LABEL_SUGGESTIONS: 'dismissedLabelSuggestions', + DISMISSED_LABEL_SUGGESTIONS: 'labelSuggestionsDismissed', }; diff --git a/app/javascript/dashboard/mixins/aiMixin.js b/app/javascript/dashboard/mixins/aiMixin.js index 48b187120..6e6911dac 100644 --- a/app/javascript/dashboard/mixins/aiMixin.js +++ b/app/javascript/dashboard/mixins/aiMixin.js @@ -1,7 +1,5 @@ import { mapGetters } from 'vuex'; import { OPEN_AI_EVENTS } from '../helper/AnalyticsHelper/events'; -import { LOCAL_STORAGE_KEYS } from '../constants/localStorage'; -import { LocalStorage } from '../../shared/helpers/localStorage'; import OpenAPI from '../api/integrations/openapi'; export default { @@ -66,29 +64,6 @@ export default { return []; } }, - getDismissedConversations(accountId) { - const suggestionKey = LOCAL_STORAGE_KEYS.DISMISSED_LABEL_SUGGESTIONS; - - // fetch the value from Storage - const valueFromStorage = LocalStorage.get(suggestionKey); - - // Case 1: the key is not initialized - if (!valueFromStorage) { - LocalStorage.set(suggestionKey, { - [accountId]: [], - }); - return LocalStorage.get(suggestionKey); - } - - // Case 2: the key is initialized, but account ID is not present - if (!valueFromStorage[accountId]) { - valueFromStorage[accountId] = []; - LocalStorage.set(suggestionKey, valueFromStorage); - return LocalStorage.get(suggestionKey); - } - - return valueFromStorage; - }, cleanLabels(labels) { return labels .toLowerCase() // Set it to lowercase diff --git a/app/javascript/dashboard/mixins/specs/aiMixin.spec.js b/app/javascript/dashboard/mixins/specs/aiMixin.spec.js index a3200b6f3..952127c0d 100644 --- a/app/javascript/dashboard/mixins/specs/aiMixin.spec.js +++ b/app/javascript/dashboard/mixins/specs/aiMixin.spec.js @@ -88,47 +88,6 @@ describe('aiMixin', () => { }); }); - it('gets dismissed conversations', () => { - const getSpy = jest.spyOn(LocalStorage, 'get'); - const setSpy = jest.spyOn(LocalStorage, 'set'); - - const accountId = 123; - const valueFromStorage = { [accountId]: ['conv1', 'conv2'] }; - - // in case key is not initialized - getSpy.mockReturnValueOnce(null); - wrapper.vm.getDismissedConversations(accountId); - - expect(getSpy).toHaveBeenCalledWith('dismissedLabelSuggestions'); - expect(setSpy).toHaveBeenCalledWith('dismissedLabelSuggestions', { - [accountId]: [], - }); - - // rest spy - getSpy.mockReset(); - setSpy.mockReset(); - - // in case we get the value from storage - getSpy.mockReturnValueOnce(valueFromStorage); - const result = wrapper.vm.getDismissedConversations(accountId); - expect(result).toEqual(valueFromStorage); - expect(getSpy).toHaveBeenCalledWith('dismissedLabelSuggestions'); - expect(setSpy).not.toHaveBeenCalled(); - - // rest spy - getSpy.mockReset(); - setSpy.mockReset(); - - // in case we get the value from storage but accountId is not present - getSpy.mockReturnValueOnce(valueFromStorage); - wrapper.vm.getDismissedConversations(234); - expect(getSpy).toHaveBeenCalledWith('dismissedLabelSuggestions'); - expect(setSpy).toHaveBeenCalledWith('dismissedLabelSuggestions', { - ...valueFromStorage, - 234: [], - }); - }); - it('cleans labels', () => { const labels = 'label1, label2, label1'; expect(wrapper.vm.cleanLabels(labels)).toEqual(['label1', 'label2']); diff --git a/app/javascript/shared/helpers/localStorage.js b/app/javascript/shared/helpers/localStorage.js index 2c002bd5c..0457d1c50 100644 --- a/app/javascript/shared/helpers/localStorage.js +++ b/app/javascript/shared/helpers/localStorage.js @@ -12,6 +12,7 @@ export const LocalStorage = { return value; } }, + set(key, value) { if (typeof value === 'object') { window.localStorage.setItem(key, JSON.stringify(value)); @@ -21,6 +22,26 @@ export const LocalStorage = { window.localStorage.setItem(key + ':ts', Date.now()); }, + setFlag(store, accountId, key, expiry = 24 * 60 * 60 * 1000) { + const storeName = accountId ? `${store}::${accountId}` : store; + + const rawValue = window.localStorage.getItem(storeName); + const parsedValue = rawValue ? JSON.parse(rawValue) : {}; + + parsedValue[key] = Date.now() + expiry; + + window.localStorage.setItem(storeName, JSON.stringify(parsedValue)); + }, + + getFlag(store, accountId, key) { + const storeName = store ? `${store}::${accountId}` : store; + + const rawValue = window.localStorage.getItem(storeName); + const parsedValue = rawValue ? JSON.parse(rawValue) : {}; + + return parsedValue[key] && parsedValue[key] > Date.now(); + }, + remove(key) { window.localStorage.removeItem(key); window.localStorage.removeItem(key + ':ts');