feat: Rewrite configMixin to a composable (#9921)

# Pull Request Template

## Description

This PR will replace the usage of `configMixin` with the `useConfig`
composable.

**Files updated**
1. dashboard/components/layout/sidebarComponents/SecondaryNavItem.vue
2. dashboard/components/widgets/conversation/MessagesView.vue
3. dashboard/routes/dashboard/settings/inbox/Settings.vue **(Not used)**
4. dashboard/routes/dashboard/settings/inbox/FinishSetup.vue **(Not
used)**
5.
dashboard/routes/dashboard/settings/inbox/settingsPage/CollaboratorsPage.vue
6.
dashboard/routes/dashboard/settings/profile/NotificationPreferences.vue
**(Not used)**
7. dashboard/routes/dashboard/settings/profile/AudioNotifications.vue
**(Not used)**
8. dashboard/routes/dashboard/settings/sla/Index.vue **(Not used)**
9. dashboard/routes/dashboard/settings/account/Index.vue
10. survey/views/Response.vue **(Not used)**

Fixes
https://linear.app/chatwoot/issue/CW-3464/rewrite-configmixin-mixin-to-a-composable

## Type of change

- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

Test in the component related pages


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
This commit is contained in:
Sivin Varghese
2024-08-14 12:56:30 +05:30
committed by GitHub
parent 207933ed70
commit dd8abe975c
13 changed files with 116 additions and 47 deletions

View File

@@ -1,7 +1,7 @@
<script>
import { mapGetters } from 'vuex';
import { useAdmin } from 'dashboard/composables/useAdmin';
import configMixin from 'shared/mixins/configMixin';
import { useConfig } from 'dashboard/composables/useConfig';
import {
getInboxClassByType,
getInboxWarningIconClass,
@@ -16,7 +16,6 @@ import Policy from '../../policy.vue';
export default {
components: { SecondaryChildNavItem, Policy },
mixins: [configMixin],
props: {
menuItem: {
type: Object,
@@ -25,8 +24,10 @@ export default {
},
setup() {
const { isAdmin } = useAdmin();
const { isEnterprise } = useConfig();
return {
isAdmin,
isEnterprise,
};
},
computed: {

View File

@@ -1,6 +1,7 @@
<script>
import { ref } from 'vue';
// composable
import { useConfig } from 'dashboard/composables/useConfig';
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
// components
@@ -14,7 +15,6 @@ import { mapGetters } from 'vuex';
// mixins
import inboxMixin, { INBOX_FEATURES } from 'shared/mixins/inboxMixin';
import configMixin from 'shared/mixins/configMixin';
import aiMixin from 'dashboard/mixins/aiMixin';
// utils
@@ -40,7 +40,7 @@ export default {
Banner,
ConversationLabelSuggestion,
},
mixins: [inboxMixin, configMixin, aiMixin],
mixins: [inboxMixin, aiMixin],
props: {
isContactPanelOpen: {
type: Boolean,
@@ -54,6 +54,7 @@ export default {
setup() {
const conversationFooterRef = ref(null);
const isPopOutReplyBox = ref(false);
const { isEnterprise } = useConfig();
const closePopOutReplyBox = () => {
isPopOutReplyBox.value = false;
@@ -72,6 +73,7 @@ export default {
useKeyboardEvents(keyboardEvents, conversationFooterRef);
return {
isEnterprise,
conversationFooterRef,
isPopOutReplyBox,
closePopOutReplyBox,

View File

@@ -0,0 +1,51 @@
import { useConfig } from '../useConfig';
describe('useConfig', () => {
const originalChatwootConfig = window.chatwootConfig;
beforeEach(() => {
window.chatwootConfig = {
hostURL: 'https://example.com',
vapidPublicKey: 'vapid-key',
enabledLanguages: ['en', 'fr'],
isEnterprise: 'true',
enterprisePlanName: 'enterprise',
};
});
afterEach(() => {
window.chatwootConfig = originalChatwootConfig;
});
it('returns the correct configuration values', () => {
const config = useConfig();
expect(config.hostURL).toBe('https://example.com');
expect(config.vapidPublicKey).toBe('vapid-key');
expect(config.enabledLanguages).toEqual(['en', 'fr']);
expect(config.isEnterprise).toBe(true);
expect(config.enterprisePlanName).toBe('enterprise');
});
it('handles missing configuration values', () => {
window.chatwootConfig = {};
const config = useConfig();
expect(config.hostURL).toBeUndefined();
expect(config.vapidPublicKey).toBeUndefined();
expect(config.enabledLanguages).toBeUndefined();
expect(config.isEnterprise).toBe(false);
expect(config.enterprisePlanName).toBeUndefined();
});
it('handles undefined window.chatwootConfig', () => {
window.chatwootConfig = undefined;
const config = useConfig();
expect(config.hostURL).toBeUndefined();
expect(config.vapidPublicKey).toBeUndefined();
expect(config.enabledLanguages).toBeUndefined();
expect(config.isEnterprise).toBe(false);
expect(config.enterprisePlanName).toBeUndefined();
});
});

View File

@@ -0,0 +1,46 @@
/**
* A function that provides access to various configuration values.
* @returns {Object} An object containing configuration values.
*/
export function useConfig() {
const config = window.chatwootConfig || {};
/**
* The host URL of the Chatwoot instance.
* @type {string|undefined}
*/
const hostURL = config.hostURL;
/**
* The VAPID public key for web push notifications.
* @type {string|undefined}
*/
const vapidPublicKey = config.vapidPublicKey;
/**
* An array of enabled languages in the Chatwoot instance.
* @type {string[]|undefined}
*/
const enabledLanguages = config.enabledLanguages;
/**
* Indicates whether the current instance is an enterprise version.
* @type {boolean}
*/
const isEnterprise = config.isEnterprise === 'true';
/**
* The name of the enterprise plan, if applicable.
* Returns "community" or "enterprise"
* @type {string|undefined}
*/
const enterprisePlanName = config.enterprisePlanName;
return {
hostURL,
vapidPublicKey,
enabledLanguages,
isEnterprise,
enterprisePlanName,
};
}

View File

@@ -4,18 +4,18 @@ import { required, minValue, maxValue } from '@vuelidate/validators';
import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import { useUISettings } from 'dashboard/composables/useUISettings';
import configMixin from 'shared/mixins/configMixin';
import { useConfig } from 'dashboard/composables/useConfig';
import { FEATURE_FLAGS } from '../../../../featureFlags';
import semver from 'semver';
import { getLanguageDirection } from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
export default {
mixins: [configMixin],
setup() {
const { updateUISettings } = useUISettings();
const { enabledLanguages } = useConfig();
const v$ = useVuelidate();
return { updateUISettings, v$ };
return { updateUISettings, v$, enabledLanguages };
},
data() {
return {

View File

@@ -1,12 +1,10 @@
<script>
import configMixin from 'shared/mixins/configMixin';
import EmptyState from '../../../../components/widgets/EmptyState.vue';
export default {
components: {
EmptyState,
},
mixins: [configMixin],
computed: {
currentInbox() {
return this.$store.getters['inboxes/getInbox'](
@@ -94,11 +92,11 @@ export default {
/>
</div>
<div v-if="isWhatsAppCloudInbox" class="w-[50%] max-w-[50%] ml-[25%]">
<p class="text-slate-700 dark:text-slate-200 font-medium mt-8">
<p class="mt-8 font-medium text-slate-700 dark:text-slate-200">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.WEBHOOK_URL') }}
</p>
<woot-code lang="html" :script="currentInbox.callback_webhook_url" />
<p class="text-slate-700 dark:text-slate-200 font-medium mt-8">
<p class="mt-8 font-medium text-slate-700 dark:text-slate-200">
{{
$t(
'INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.WEBHOOK_VERIFICATION_TOKEN'
@@ -132,7 +130,7 @@ export default {
</div>
<div class="flex justify-center gap-2 mt-4">
<router-link
class="button hollow primary rounded"
class="rounded button hollow primary"
:to="{
name: 'settings_inbox_show',
params: { inboxId: $route.params.inbox_id },
@@ -141,7 +139,7 @@ export default {
{{ $t('INBOX_MGMT.FINISH.MORE_SETTINGS') }}
</router-link>
<router-link
class="button success rounded"
class="rounded button success"
:to="{
name: 'inbox_dashboard',
params: { inboxId: $route.params.inbox_id },

View File

@@ -1,7 +1,6 @@
<script>
import { mapGetters } from 'vuex';
import { shouldBeUrl } from 'shared/helpers/Validators';
import configMixin from 'shared/mixins/configMixin';
import { useAlert } from 'dashboard/composables';
import { useVuelidate } from '@vuelidate/core';
import SettingIntroBanner from 'dashboard/components/widgets/SettingIntroBanner.vue';
@@ -34,7 +33,7 @@ export default {
SenderNameExamplePreview,
MicrosoftReauthorize,
},
mixins: [configMixin, inboxMixin],
mixins: [inboxMixin],
setup() {
return { v$: useVuelidate() };
},

View File

@@ -3,14 +3,13 @@ import { mapGetters } from 'vuex';
import { useVuelidate } from '@vuelidate/core';
import { minValue } from '@vuelidate/validators';
import { useAlert } from 'dashboard/composables';
import configMixin from 'shared/mixins/configMixin';
import { useConfig } from 'dashboard/composables/useConfig';
import SettingsSection from '../../../../../components/SettingsSection.vue';
export default {
components: {
SettingsSection,
},
mixins: [configMixin],
props: {
inbox: {
type: Object,
@@ -18,7 +17,9 @@ export default {
},
},
setup() {
return { v$: useVuelidate() };
const { isEnterprise } = useConfig();
return { v$: useVuelidate(), isEnterprise };
},
data() {
return {

View File

@@ -1,6 +1,5 @@
<script>
import { useAlert } from 'dashboard/composables';
import configMixin from 'shared/mixins/configMixin';
import { useUISettings } from 'dashboard/composables/useUISettings';
import AudioAlertTone from './AudioAlertTone.vue';
import AudioAlertEvent from './AudioAlertEvent.vue';
@@ -12,7 +11,6 @@ export default {
AudioAlertTone,
AudioAlertCondition,
},
mixins: [configMixin],
setup() {
const { uiSettings, updateUISettings } = useUISettings();

View File

@@ -1,7 +1,6 @@
<script>
import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import configMixin from 'shared/mixins/configMixin';
import TableHeaderCell from 'dashboard/components/widgets/TableHeaderCell.vue';
import CheckBox from 'v3/components/Form/CheckBox.vue';
import {
@@ -19,7 +18,6 @@ export default {
FormSwitch,
CheckBox,
},
mixins: [configMixin],
data() {
return {
selectedEmailFlags: [],

View File

@@ -10,7 +10,6 @@ import SLAPaywallEnterprise from './components/SLAPaywallEnterprise.vue';
import { mapGetters } from 'vuex';
import { convertSecondsToTimeUnit } from '@chatwoot/utils';
import { useAlert } from 'dashboard/composables';
import configMixin from 'shared/mixins/configMixin';
export default {
components: {
@@ -22,7 +21,6 @@ export default {
SLAListItemLoading,
SLAPaywallEnterprise,
},
mixins: [configMixin],
data() {
return {
loading: {},

View File

@@ -1,20 +0,0 @@
export default {
computed: {
hostURL() {
return window.chatwootConfig.hostURL;
},
vapidPublicKey() {
return window.chatwootConfig.vapidPublicKey;
},
enabledLanguages() {
return window.chatwootConfig.enabledLanguages;
},
isEnterprise() {
return window.chatwootConfig.isEnterprise === 'true';
},
enterprisePlanName() {
// returns "community" or "enterprise"
return window.chatwootConfig?.enterprisePlanName;
},
},
};

View File

@@ -5,7 +5,6 @@ import Spinner from 'shared/components/Spinner.vue';
import Rating from 'survey/components/Rating.vue';
import Feedback from 'survey/components/Feedback.vue';
import Banner from 'survey/components/Banner.vue';
import configMixin from 'shared/mixins/configMixin';
import { getSurveyDetails, updateSurvey } from 'survey/api/survey';
export default {
@@ -17,8 +16,6 @@ export default {
Banner,
Feedback,
},
mixins: [configMixin],
data() {
return {
surveyDetails: null,