mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-30 18:47:51 +00:00
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:
@@ -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: {
|
||||
|
||||
@@ -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,
|
||||
|
||||
51
app/javascript/dashboard/composables/spec/useConfig.spec.js
Normal file
51
app/javascript/dashboard/composables/spec/useConfig.spec.js
Normal 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();
|
||||
});
|
||||
});
|
||||
46
app/javascript/dashboard/composables/useConfig.js
Normal file
46
app/javascript/dashboard/composables/useConfig.js
Normal 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,
|
||||
};
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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() };
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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: {},
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user