Revert "feat: Adds support for draft in conversation reply box (#4205)" (#4425)

This reverts commit 5ea0436051.
This commit is contained in:
Pranav Raj S 2022-04-08 15:52:39 +05:30 committed by GitHub
parent 7e5ec7925c
commit bc7bcc20b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 24 additions and 202 deletions

View file

@ -12,11 +12,12 @@
</template> </template>
<script> <script>
import Banner from 'dashboard/components/ui/Banner.vue'; import Banner from 'dashboard/components/ui/Banner.vue';
import { LocalStorage, LOCAL_STORAGE_KEYS } from '../../helper/localStorage'; import LocalStorage from '../../helper/localStorage';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import adminMixin from 'dashboard/mixins/isAdmin'; import adminMixin from 'dashboard/mixins/isAdmin';
const semver = require('semver'); const semver = require('semver');
const dismissedUpdates = new LocalStorage('dismissedUpdates');
export default { export default {
components: { components: {
@ -56,22 +57,16 @@ export default {
}, },
methods: { methods: {
isVersionNotificationDismissed(version) { isVersionNotificationDismissed(version) {
const dismissedVersions = return dismissedUpdates.get().includes(version);
LocalStorage.get(LOCAL_STORAGE_KEYS.DISMISSED_UPDATES) || [];
return dismissedVersions.includes(version);
}, },
dismissUpdateBanner() { dismissUpdateBanner() {
let updatedDismissedItems = let updatedDismissedItems = dismissedUpdates.get();
LocalStorage.get(LOCAL_STORAGE_KEYS.DISMISSED_UPDATES) || [];
if (updatedDismissedItems instanceof Array) { if (updatedDismissedItems instanceof Array) {
updatedDismissedItems.push(this.latestChatwootVersion); updatedDismissedItems.push(this.latestChatwootVersion);
} else { } else {
updatedDismissedItems = [this.latestChatwootVersion]; updatedDismissedItems = [this.latestChatwootVersion];
} }
LocalStorage.set( dismissedUpdates.store(updatedDismissedItems);
LOCAL_STORAGE_KEYS.DISMISSED_UPDATES,
updatedDismissedItems
);
this.latestChatwootVersion = this.globalConfig.appVersion; this.latestChatwootVersion = this.globalConfig.appVersion;
}, },
}, },

View file

@ -148,8 +148,8 @@ export default {
showCannedMenu(updatedValue) { showCannedMenu(updatedValue) {
this.$emit('toggle-canned-menu', !this.isPrivate && updatedValue); this.$emit('toggle-canned-menu', !this.isPrivate && updatedValue);
}, },
value(newValue = '', oldValue = '') { value(newValue = '') {
if (newValue !== oldValue) { if (newValue !== this.lastValue) {
const { tr } = this.state; const { tr } = this.state;
if (this.isFormatMode) { if (this.isFormatMode) {
this.state = createState( this.state = createState(

View file

@ -137,7 +137,6 @@ import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
import { checkFileSizeLimit } from 'shared/helpers/FileHelper'; import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
import { MAXIMUM_FILE_UPLOAD_SIZE } from 'shared/constants/messages'; import { MAXIMUM_FILE_UPLOAD_SIZE } from 'shared/constants/messages';
import { BUS_EVENTS } from 'shared/constants/busEvents'; import { BUS_EVENTS } from 'shared/constants/busEvents';
import { debounce } from 'shared/helpers/TimeHelpers';
import { import {
isEscape, isEscape,
@ -150,8 +149,6 @@ import inboxMixin from 'shared/mixins/inboxMixin';
import uiSettingsMixin from 'dashboard/mixins/uiSettings'; import uiSettingsMixin from 'dashboard/mixins/uiSettings';
import { DirectUpload } from 'activestorage'; import { DirectUpload } from 'activestorage';
import { frontendURL } from '../../../helper/URLHelper'; import { frontendURL } from '../../../helper/URLHelper';
import { LocalStorage, LOCAL_STORAGE_KEYS } from '../../../helper/localStorage';
import { trimMessage } from '../../../store/modules/conversations/helpers';
export default { export default {
components: { components: {
@ -204,7 +201,6 @@ export default {
hasSlashCommand: false, hasSlashCommand: false,
bccEmails: '', bccEmails: '',
ccEmails: '', ccEmails: '',
doAutoSaveDraft: () => {},
}; };
}, },
computed: { computed: {
@ -410,19 +406,10 @@ export default {
profilePath() { profilePath() {
return frontendURL(`accounts/${this.accountId}/profile/settings`); return frontendURL(`accounts/${this.accountId}/profile/settings`);
}, },
conversationId() {
return this.currentChat.id;
},
}, },
watch: { watch: {
currentChat(conversation, oldConversation) { currentChat(conversation) {
const { can_reply: canReply } = conversation; const { can_reply: canReply } = conversation;
if (oldConversation.id !== conversation.id) {
this.setToDraft(oldConversation.id, this.replyType);
this.getFromDraft();
}
if (this.isOnPrivateNote) { if (this.isOnPrivateNote) {
return; return;
} }
@ -447,87 +434,22 @@ export default {
this.mentionSearchKey = ''; this.mentionSearchKey = '';
this.showMentions = false; this.showMentions = false;
} }
this.doAutoSaveDraft();
},
replyType(updatedReplyType, oldReplyType) {
this.setToDraft(this.conversationId, oldReplyType);
this.getFromDraft();
}, },
}, },
mounted() { mounted() {
this.getFromDraft();
// Donot use the keyboard listener mixin here as the events here are supposed to be // Donot use the keyboard listener mixin here as the events here are supposed to be
// working even if input/textarea is focussed. // working even if input/textarea is focussed.
document.addEventListener('keydown', this.handleKeyEvents); document.addEventListener('keydown', this.handleKeyEvents);
document.addEventListener('paste', this.onPaste); document.addEventListener('paste', this.onPaste);
this.setCCEmailFromLastChat(); this.setCCEmailFromLastChat();
this.doAutoSaveDraft = debounce(
() => {
this.saveDraft(this.conversationId, this.replyType);
},
5000,
false
);
}, },
destroyed() { destroyed() {
document.removeEventListener('keydown', this.handleKeyEvents); document.removeEventListener('keydown', this.handleKeyEvents);
document.removeEventListener('paste', this.onPaste); document.removeEventListener('paste', this.onPaste);
}, },
methods: { methods: {
getSavedDraftMessages() {
return LocalStorage.get(LOCAL_STORAGE_KEYS.DRAFT_MESSAGES) || {};
},
saveDraft(conversationId, replyType) {
if (this.message || this.message === '') {
const savedDraftMessages = this.getSavedDraftMessages();
const key = `draft-${conversationId}-${replyType}`;
const draftToSave = trimMessage(this.message || '');
const {
[key]: currentDraft,
...restOfDraftMessages
} = savedDraftMessages;
const updatedDraftMessages = draftToSave
? {
...restOfDraftMessages,
[key]: draftToSave,
}
: restOfDraftMessages;
LocalStorage.set(
LOCAL_STORAGE_KEYS.DRAFT_MESSAGES,
updatedDraftMessages
);
}
},
setToDraft(conversationId, replyType) {
this.saveDraft(conversationId, replyType);
this.message = '';
},
getFromDraft() {
if (this.conversationId) {
try {
const key = `draft-${this.conversationId}-${this.replyType}`;
const savedDraftMessages = this.getSavedDraftMessages();
this.message = `${savedDraftMessages[key] || ''}`;
} catch (error) {
this.message = '';
}
}
},
removeFromDraft() {
if (this.conversationId) {
const key = `draft-${this.conversationId}-${this.replyType}`;
const draftMessages = this.getSavedDraftMessages();
const { [key]: toBeRemoved, ...updatedDraftMessages } = draftMessages;
LocalStorage.set(
LOCAL_STORAGE_KEYS.DRAFT_MESSAGES,
updatedDraftMessages
);
}
},
onPaste(e) { onPaste(e) {
const data = e.clipboardData.files; const data = e.clipboardData.files;
if (!this.showRichContentEditor && data.length !== 0) { if (!this.showRichContentEditor && data.length !== 0) {
@ -615,7 +537,6 @@ export default {
messagePayload messagePayload
); );
bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE); bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE);
this.removeFromDraft();
} catch (error) { } catch (error) {
const errorMessage = const errorMessage =
error?.response?.data?.error || error?.response?.data?.error ||
@ -687,7 +608,6 @@ export default {
}, },
onBlur() { onBlur() {
this.isFocused = false; this.isFocused = false;
this.saveDraft(this.conversationId, this.replyType);
}, },
onFocus() { onFocus() {
this.isFocused = true; this.isFocused = true;

View file

@ -1,32 +1,17 @@
export const LOCAL_STORAGE_KEYS = { class LocalStorage {
DISMISSED_UPDATES: 'dismissedUpdates', constructor(key) {
DRAFT_MESSAGES: 'draftMessages', this.key = key;
};
export const LocalStorage = {
clearAll() {
window.localStorage.clear();
},
get(key) {
const value = window.localStorage.getItem(key);
try {
return typeof value === 'string' ? JSON.parse(value) : value;
} catch (error) {
return value;
} }
},
set(key, value) {
if (typeof value === 'object') {
window.localStorage.setItem(key, JSON.stringify(value));
} else {
window.localStorage.setItem(key, value);
}
window.localStorage.setItem(key + ':ts', Date.now());
},
remove(key) { store(allItems) {
window.localStorage.removeItem(key); localStorage.setItem(this.key, JSON.stringify(allItems));
window.localStorage.removeItem(key + ':ts'); localStorage.setItem(this.key + ':ts', Date.now());
}, }
};
get() {
let stored = localStorage.getItem(this.key);
return JSON.parse(stored) || [];
}
}
export default LocalStorage;

View file

@ -5,12 +5,7 @@ import * as types from '../mutation-types';
import authAPI from '../../api/auth'; import authAPI from '../../api/auth';
import createAxios from '../../helper/APIHelper'; import createAxios from '../../helper/APIHelper';
import actionCable from '../../helper/actionCable'; import actionCable from '../../helper/actionCable';
import { import { setUser, getHeaderExpiry, clearCookiesOnLogout } from '../utils/api';
setUser,
getHeaderExpiry,
clearCookiesOnLogout,
clearLocalStorageOnLogout,
} from '../utils/api';
import { getLoginRedirectURL } from '../../helper/URLHelper'; import { getLoginRedirectURL } from '../../helper/URLHelper';
const state = { const state = {
@ -99,9 +94,9 @@ export const actions = {
.login(credentials) .login(credentials)
.then(response => { .then(response => {
commit(types.default.SET_CURRENT_USER); commit(types.default.SET_CURRENT_USER);
clearLocalStorageOnLogout();
window.axios = createAxios(axios); window.axios = createAxios(axios);
actionCable.init(Vue); actionCable.init(Vue);
window.location = getLoginRedirectURL(ssoAccountId, response.data); window.location = getLoginRedirectURL(ssoAccountId, response.data);
resolve(); resolve();
}) })

View file

@ -35,10 +35,3 @@ export const applyPageFilters = (conversation, filters) => {
return shouldFilter; return shouldFilter;
}; };
export const trimMessage = (content = '', maxLength = 1024) => {
if (content.length > maxLength) {
return content.substring(0, maxLength);
}
return content;
};

View file

@ -1,7 +1,6 @@
import { import {
findPendingMessageIndex, findPendingMessageIndex,
applyPageFilters, applyPageFilters,
trimMessage,
} from '../../conversations/helpers'; } from '../../conversations/helpers';
const conversationList = [ const conversationList = [
@ -120,9 +119,3 @@ describe('#applyPageFilters', () => {
}); });
}); });
}); });
describe('#trimMessage', () => {
expect(trimMessage('Hello world', 5)).toEqual('Hello');
expect(trimMessage('Hello', 5)).toEqual('Hello');
expect(trimMessage(undefined, 5)).toEqual('');
});

View file

@ -9,7 +9,6 @@ import {
CHATWOOT_RESET, CHATWOOT_RESET,
CHATWOOT_SET_USER, CHATWOOT_SET_USER,
} from '../../helper/scriptHelpers'; } from '../../helper/scriptHelpers';
import { LocalStorage, LOCAL_STORAGE_KEYS } from '../../helper/localStorage';
Cookies.defaults = { sameSite: 'Lax' }; Cookies.defaults = { sameSite: 'Lax' };
@ -44,15 +43,10 @@ export const clearBrowserSessionCookies = () => {
Cookies.remove('user'); Cookies.remove('user');
}; };
export const clearLocalStorageOnLogout = () => {
LocalStorage.remove(LOCAL_STORAGE_KEYS.DRAFT_MESSAGES);
};
export const clearCookiesOnLogout = () => { export const clearCookiesOnLogout = () => {
window.bus.$emit(CHATWOOT_RESET); window.bus.$emit(CHATWOOT_RESET);
window.bus.$emit(ANALYTICS_RESET); window.bus.$emit(ANALYTICS_RESET);
clearBrowserSessionCookies(); clearBrowserSessionCookies();
clearLocalStorageOnLogout();
const globalConfig = window.globalConfig || {}; const globalConfig = window.globalConfig || {};
const logoutRedirectLink = const logoutRedirectLink =
globalConfig.LOGOUT_REDIRECT_LINK || frontendURL('login'); globalConfig.LOGOUT_REDIRECT_LINK || frontendURL('login');

View file

@ -1,21 +0,0 @@
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
export const debounce = (func, delay, immediate) => {
let timerId;
return (...args) => {
const boundFunc = func.bind(this, ...args);
clearTimeout(timerId);
if (immediate && !timerId) {
boundFunc();
}
const calleeFunc = immediate
? () => {
timerId = null;
}
: boundFunc;
timerId = setTimeout(calleeFunc, delay);
};
};

View file

@ -1,32 +0,0 @@
import { debounce } from '../TimeHelpers';
// Tell Jest to mock all timeout functions
jest.useFakeTimers('modern');
describe('debounce', () => {
test('execute just once with immediate false', () => {
let func = jest.fn();
let debouncedFunc = debounce(func, 1000);
for (let i = 0; i < 100; i += 1) {
debouncedFunc();
}
// Fast-forward time
jest.runAllTimers();
expect(func).toBeCalledTimes(1);
});
test('execute just once with immediate true', () => {
let func = jest.fn();
let debouncedFunc = debounce(func, 1000, true);
for (let i = 0; i < 100; i += 1) {
debouncedFunc();
}
jest.runAllTimers();
expect(func).toBeCalledTimes(1);
});
});