chore: Cleanup update banner with localstorage updates (#5209)
Co-authored-by: Aswin Dev P.S <aswindevps@gmail.com>
This commit is contained in:
parent
fc9699d993
commit
124390a019
5 changed files with 104 additions and 63 deletions
|
@ -12,33 +12,26 @@
|
|||
</template>
|
||||
<script>
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import LocalStorage from '../../helper/localStorage';
|
||||
import { LocalStorage, LOCAL_STORAGE_KEYS } from '../../helper/localStorage';
|
||||
import { mapGetters } from 'vuex';
|
||||
import adminMixin from 'dashboard/mixins/isAdmin';
|
||||
|
||||
const semver = require('semver');
|
||||
const dismissedUpdates = new LocalStorage('dismissedUpdates');
|
||||
import { hasAnUpdateAvailable } from './versionCheckHelper';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Banner,
|
||||
},
|
||||
components: { Banner },
|
||||
mixins: [adminMixin],
|
||||
props: {
|
||||
latestChatwootVersion: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
latestChatwootVersion: { type: String, default: '' },
|
||||
},
|
||||
data() {
|
||||
return { userDismissedBanner: false };
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({ globalConfig: 'globalConfig/get' }),
|
||||
hasAnUpdateAvailable() {
|
||||
if (!semver.valid(this.latestChatwootVersion)) {
|
||||
return false;
|
||||
}
|
||||
return semver.lt(
|
||||
this.globalConfig.appVersion,
|
||||
this.latestChatwootVersion
|
||||
updateAvailable() {
|
||||
return hasAnUpdateAvailable(
|
||||
this.latestChatwootVersion,
|
||||
this.globalConfig.appVersion
|
||||
);
|
||||
},
|
||||
bannerMessage() {
|
||||
|
@ -48,8 +41,9 @@ export default {
|
|||
},
|
||||
shouldShowBanner() {
|
||||
return (
|
||||
!this.userDismissedBanner &&
|
||||
this.globalConfig.displayManifest &&
|
||||
this.hasAnUpdateAvailable &&
|
||||
this.updateAvailable &&
|
||||
!this.isVersionNotificationDismissed(this.latestChatwootVersion) &&
|
||||
this.isAdmin
|
||||
);
|
||||
|
@ -57,17 +51,23 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
isVersionNotificationDismissed(version) {
|
||||
return dismissedUpdates.get().includes(version);
|
||||
const dismissedVersions =
|
||||
LocalStorage.get(LOCAL_STORAGE_KEYS.DISMISSED_UPDATES) || [];
|
||||
return dismissedVersions.includes(version);
|
||||
},
|
||||
dismissUpdateBanner() {
|
||||
let updatedDismissedItems = dismissedUpdates.get();
|
||||
let updatedDismissedItems =
|
||||
LocalStorage.get(LOCAL_STORAGE_KEYS.DISMISSED_UPDATES) || [];
|
||||
if (updatedDismissedItems instanceof Array) {
|
||||
updatedDismissedItems.push(this.latestChatwootVersion);
|
||||
} else {
|
||||
updatedDismissedItems = [this.latestChatwootVersion];
|
||||
}
|
||||
dismissedUpdates.store(updatedDismissedItems);
|
||||
this.latestChatwootVersion = this.globalConfig.appVersion;
|
||||
LocalStorage.set(
|
||||
LOCAL_STORAGE_KEYS.DISMISSED_UPDATES,
|
||||
updatedDismissedItems
|
||||
);
|
||||
this.userDismissedBanner = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { hasAnUpdateAvailable } from '../versionCheckHelper';
|
||||
|
||||
describe('#hasAnUpdateAvailable', () => {
|
||||
it('return false if latest version is invalid', () => {
|
||||
expect(hasAnUpdateAvailable('invalid', '1.0.0')).toBe(false);
|
||||
expect(hasAnUpdateAvailable(null, '1.0.0')).toBe(false);
|
||||
expect(hasAnUpdateAvailable(undefined, '1.0.0')).toBe(false);
|
||||
expect(hasAnUpdateAvailable('', '1.0.0')).toBe(false);
|
||||
});
|
||||
|
||||
it('return correct value if latest version is valid', () => {
|
||||
expect(hasAnUpdateAvailable('1.1.0', '1.0.0')).toBe(true);
|
||||
expect(hasAnUpdateAvailable('0.1.0', '1.0.0')).toBe(false);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
const semver = require('semver');
|
||||
|
||||
export const hasAnUpdateAvailable = (latestVersion, currentVersion) => {
|
||||
if (!semver.valid(latestVersion)) {
|
||||
return false;
|
||||
}
|
||||
return semver.lt(currentVersion, latestVersion);
|
||||
};
|
|
@ -1,17 +1,32 @@
|
|||
class LocalStorage {
|
||||
constructor(key) {
|
||||
this.key = key;
|
||||
}
|
||||
export const LOCAL_STORAGE_KEYS = {
|
||||
DISMISSED_UPDATES: 'dismissedUpdates',
|
||||
WIDGET_BUILDER: 'widgetBubble_',
|
||||
};
|
||||
|
||||
store(allItems) {
|
||||
localStorage.setItem(this.key, JSON.stringify(allItems));
|
||||
localStorage.setItem(this.key + ':ts', Date.now());
|
||||
}
|
||||
export const LocalStorage = {
|
||||
clearAll() {
|
||||
window.localStorage.clear();
|
||||
},
|
||||
|
||||
get() {
|
||||
let stored = localStorage.getItem(this.key);
|
||||
return JSON.parse(stored) || [];
|
||||
}
|
||||
}
|
||||
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());
|
||||
},
|
||||
|
||||
export default LocalStorage;
|
||||
remove(key) {
|
||||
window.localStorage.removeItem(key);
|
||||
window.localStorage.removeItem(key + ':ts');
|
||||
},
|
||||
};
|
||||
|
|
|
@ -158,7 +158,10 @@ import Widget from 'dashboard/modules/widget-preview/components/Widget';
|
|||
import InputRadioGroup from './components/InputRadioGroup';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import LocalStorage from 'dashboard/helper/localStorage';
|
||||
import {
|
||||
LocalStorage,
|
||||
LOCAL_STORAGE_KEYS,
|
||||
} from 'dashboard/helper/localStorage';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -225,6 +228,9 @@ export default {
|
|||
...mapGetters({
|
||||
uiFlags: 'inboxes/getUIFlags',
|
||||
}),
|
||||
storageKey() {
|
||||
return `${LOCAL_STORAGE_KEYS.WIDGET_BUILDER}${this.inbox.id}`;
|
||||
},
|
||||
widgetScript() {
|
||||
let options = {
|
||||
position: this.widgetBubblePosition,
|
||||
|
@ -313,24 +319,25 @@ export default {
|
|||
this.replyTime = reply_time;
|
||||
this.avatarUrl = avatar_url;
|
||||
|
||||
// Widget Bubble Settings
|
||||
const { key, storage } = this.getLocalStorageWithKey(this.inbox.id);
|
||||
this.widgetBubblePositions = this.widgetBubblePositions.map(item => {
|
||||
if (item.id === storage.get(key).position) {
|
||||
item.checked = true;
|
||||
this.widgetBubblePosition = item.id;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.widgetBubbleTypes = this.widgetBubbleTypes.map(item => {
|
||||
if (item.id === storage.get(key).type) {
|
||||
item.checked = true;
|
||||
this.widgetBubbleType = item.id;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.widgetBubbleLauncherTitle =
|
||||
storage.get(key).launcherTitle || 'Chat with us';
|
||||
const savedInformation = this.getSavedInboxInformation();
|
||||
if (savedInformation) {
|
||||
this.widgetBubblePositions = this.widgetBubblePositions.map(item => {
|
||||
if (item.id === savedInformation.position) {
|
||||
item.checked = true;
|
||||
this.widgetBubblePosition = item.id;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.widgetBubbleTypes = this.widgetBubbleTypes.map(item => {
|
||||
if (item.id === savedInformation.type) {
|
||||
item.checked = true;
|
||||
this.widgetBubbleType = item.id;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.widgetBubbleLauncherTitle =
|
||||
savedInformation.launcherTitle || 'Chat with us';
|
||||
}
|
||||
},
|
||||
handleWidgetBubblePositionChange(item) {
|
||||
this.widgetBubblePosition = item.id;
|
||||
|
@ -372,7 +379,7 @@ export default {
|
|||
type: this.widgetBubbleType,
|
||||
};
|
||||
|
||||
this.getLocalStorageWithKey(this.inbox.id).storage.store(bubbleSettings);
|
||||
LocalStorage.set(this.storageKey, bubbleSettings);
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
|
@ -403,12 +410,8 @@ export default {
|
|||
);
|
||||
}
|
||||
},
|
||||
getLocalStorageWithKey(id) {
|
||||
const storageKey = `widgetBubble_${id}`;
|
||||
return {
|
||||
key: storageKey,
|
||||
storage: new LocalStorage(storageKey),
|
||||
};
|
||||
getSavedInboxInformation() {
|
||||
return LocalStorage.get(this.storageKey);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue