Compare commits

..
Author SHA1 Message Date
Shivam Mishra 523b28bccb fix: blur and input events for woot input 2024-10-03 20:39:12 +05:30
Shivam Mishra f6353353ae fix: model update in add attribute 2024-10-03 20:32:28 +05:30
Shivam Mishra 268b0da488 fix: portal name slug generator 2024-10-03 20:31:12 +05:30
b3262597c1 fix: vue 3 followup fixes (#10213)
Fixes: CW-3602,  CW-3606, CW-3605, CW-3601, CW-3603, CW-3600, CW-3598

-
[CW-3602](https://linear.app/chatwoot/issue/CW-3602/chat-list-infinite-loader-fetching-only-odd-numbered-pages)
Chat list pagination broken
-
[CW-3606](https://linear.app/chatwoot/issue/CW-3606/saving-greeting-message-is-not-working-in-inbox-settings)
Greetings message not getting saved
-
[CW-3605](https://linear.app/chatwoot/issue/CW-3605/copy-and-paste-image-attachment-not-working-in-widget)
Paste not working on widget
-
[CW-3601](https://linear.app/chatwoot/issue/CW-3601/edit-category-is-not-working-properly)
Edit category not updating
-
[CW-3603](https://linear.app/chatwoot/issue/CW-3603/delete-filter-is-not-working)
Delete filter modal not toggling
-
[CW-3600](https://linear.app/chatwoot/issue/CW-3600/portal-editor-is-not-working-properly)
Portal editor events were flaky
-
[CW-3598](https://linear.app/chatwoot/issue/CW-3598/rearrange-of-pre-chat-form-fields-throws-an-error)
Prechat form re-order bug

---------

Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
2024-10-03 19:59:07 +05:30
Shivam MishraandGitHub 701135df92 fix: vitest resolution in vite.config [CW-3587] (#10204)
The ruby plugin conflicted with vitest resolution, this PR fixes it. We
will need to separate out the vite config for this
2024-10-03 19:54:57 +05:30
Vishnu NarayananandGitHub fdc3e370ef fix: gh actions for vite build (#10212)
Fixes https://linear.app/chatwoot/issue/CW-3604/fix-gh-actions-for-vite-build

- [x] response bot spec
- [x] chatwoot ce spec
- [x] size limit check
2024-10-03 16:25:48 +05:30
Shivam MishraandGitHub f14edd5242 fix: initOnEvents not removed [CW-3594] (#10200)
The `initOnEvents` was used to get the notification sound file and
trigger the 30 second loop, but since the function was replaced to using
class syntax, the removeEvent listener was not working. This PR fixes it
by reverting to the old syntax but moving it inside the constructor
instead and also adding a `once: true` to ensure it is always removed
automatically
2024-10-03 15:03:44 +05:30
Shivam MishraandGitHub 578dce81a1 fix: suggestions not triggering directly (#10211) 2024-10-03 15:02:56 +05:30
Shivam MishraandGitHub c51a458c25 style: apply fixes for eslint issues [cw-3590] (#10210)
These fixes are all auto generated and can be merged directly

Fixes the following issues

1. Event used on components should be hypenated
2. Attribute orders in components
3. Use `unmounted` instead of `destroyed`
4. Add explicit `emits` declarations for components, autofixed [using
this
script](https://gist.github.com/scmmishra/6f549109b96400006bb69bbde392eddf)


We ignore the top level v-if for now, we will fix it later
2024-10-03 15:02:12 +05:30
Shivam MishraandGitHub b8d0252511 feat: remove usage of .sync and define explicitly emits (#10209)
References

- https://v3-migration.vuejs.org/breaking-changes/v-model
-
https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html
2024-10-03 12:44:18 +05:30
308 changed files with 1396 additions and 582 deletions
+7 -3
View File
@@ -49,13 +49,17 @@ jobs:
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: pnpm/action-setup@v2
with:
version: 9.3.0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
cache: pnpm
- name: yarn
run: yarn install
- name: pnpm
run: pnpm install
- name: Create database
run: bundle exec rake db:create
+15 -5
View File
@@ -19,23 +19,33 @@ jobs:
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: pnpm/action-setup@v2
with:
version: 9.3.0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'yarn'
cache: 'pnpm'
- name: yarn
run: yarn install
- name: pnpm
run: pnpm install
- name: Strip enterprise code
run: |
rm -rf enterprise
rm -rf spec/enterprise
- name: setup env
run: |
cp .env.example .env
- name: Run asset compile
run: bundle exec rake assets:precompile
env:
NODE_OPTIONS: --openssl-legacy-provider
RAILS_ENV: production
- name: Size Check
run: yarn run size
run: pnpm run size
@@ -537,12 +537,6 @@ function loadMoreConversations() {
return;
}
// Increment the current page
store.dispatch('conversationPage/setCurrentPage', {
filter: currentPageFilterKey.value,
page: currentFiltersPage.value + 1,
});
if (!hasAppliedFiltersOrActiveFolders.value) {
fetchConversations();
} else if (hasActiveFolders.value) {
@@ -769,11 +763,11 @@ watch(conversationFilters, (newVal, oldVal) => {
:has-applied-filters="hasAppliedFilters"
:has-active-folders="hasActiveFolders"
:active-status="activeStatus"
@addFolders="onClickOpenAddFoldersModal"
@deleteFolders="onClickOpenDeleteFoldersModal"
@filtersModal="onToggleAdvanceFiltersModal"
@resetFilters="resetAndFetchData"
@basicFilterChange="onBasicFilterChange"
@add-folders="onClickOpenAddFoldersModal"
@delete-folders="onClickOpenDeleteFoldersModal"
@filters-modal="onToggleAdvanceFiltersModal"
@reset-filters="resetAndFetchData"
@basic-filter-change="onBasicFilterChange"
/>
<AddCustomViews
@@ -785,7 +779,7 @@ watch(conversationFilters, (newVal, oldVal) => {
<DeleteCustomViews
v-if="showDeleteFoldersModal"
:show-delete-popup.sync="showDeleteFoldersModal"
v-model:show="showDeleteFoldersModal"
:active-custom-view="activeFolder"
:custom-views-id="foldersId"
:open-last-item-after-delete="openLastItemAfterDeleteInFolder"
@@ -796,7 +790,7 @@ watch(conversationFilters, (newVal, oldVal) => {
v-if="!hasAppliedFiltersOrActiveFolders"
:items="assigneeTabItems"
:active-tab="activeAssigneeTab"
@chatTabChange="updateAssigneeTab"
@chat-tab-change="updateAssigneeTab"
/>
<p
@@ -813,11 +807,11 @@ watch(conversationFilters, (newVal, oldVal) => {
:show-open-action="allSelectedConversationsStatus('open')"
:show-resolved-action="allSelectedConversationsStatus('resolved')"
:show-snoozed-action="allSelectedConversationsStatus('snoozed')"
@selectAllConversations="toggleSelectAll"
@assignAgent="onAssignAgent"
@updateConversations="onUpdateConversations"
@assignLabels="onAssignLabels"
@assignTeam="onAssignTeamsForBulk"
@select-all-conversations="toggleSelectAll"
@assign-agent="onAssignAgent"
@update-conversations="onUpdateConversations"
@assign-labels="onAssignLabels"
@assign-team="onAssignTeamsForBulk"
/>
<div
ref="conversationListRef"
@@ -854,8 +848,8 @@ watch(conversationFilters, (newVal, oldVal) => {
:folders-id="foldersId"
:conversation-type="conversationType"
:show-assignee="showAssigneeInConversationCard"
@selectConversation="selectConversation"
@deSelectConversation="deSelectConversation"
@select-conversation="selectConversation"
@de-select-conversation="deSelectConversation"
/>
</DynamicScrollerItem>
</template>
@@ -878,7 +872,7 @@ watch(conversationFilters, (newVal, oldVal) => {
</DynamicScroller>
</div>
<woot-modal
:show.sync="showAdvancedFilters"
v-model:show="showAdvancedFilters"
:on-close="closeAdvanceFiltersModal"
size="medium"
>
@@ -889,8 +883,8 @@ watch(conversationFilters, (newVal, oldVal) => {
:active-folder-name="activeFolderName"
:on-close="closeAdvanceFiltersModal"
:is-folder-view="hasActiveFolders"
@applyFilter="onApplyFilter"
@updateFolder="onUpdateSavedFilter"
@apply-filter="onApplyFilter"
@update-folder="onUpdateSavedFilter"
/>
</woot-modal>
</div>
@@ -108,7 +108,7 @@ const hasAppliedFiltersOrActiveFolders = computed(() => {
/>
<ConversationBasicFilter
v-if="!hasAppliedFiltersOrActiveFolders"
@changeFilter="onBasicFilterChange"
@change-filter="onBasicFilterChange"
/>
</div>
</div>
@@ -56,14 +56,14 @@ export default {
:selected="isConversationSelected(source.id)"
:show-assignee="showAssignee"
enable-context-menu
@selectConversation="selectConversation"
@deSelectConversation="deSelectConversation"
@assignAgent="assignAgent"
@assignTeam="assignTeam"
@assignLabel="assignLabels"
@updateConversationStatus="updateConversationStatus"
@contextMenuToggle="toggleContextMenu"
@markAsUnread="markAsUnread"
@assignPriority="assignPriority"
@select-conversation="selectConversation"
@de-select-conversation="deSelectConversation"
@assign-agent="assignAgent"
@assign-team="assignTeam"
@assign-label="assignLabels"
@update-conversation-status="updateConversationStatus"
@context-menu-toggle="toggleContextMenu"
@mark-as-unread="markAsUnread"
@assign-priority="assignPriority"
/>
</template>
@@ -31,6 +31,7 @@ export default {
attributeKey: { type: String, required: true },
contactId: { type: Number, default: null },
},
emits: ['update', 'delete', 'copy'],
setup() {
return { v$: useVuelidate() };
},
@@ -138,7 +139,7 @@ export default {
this.editedValue = this.formattedValue;
emitter.on(BUS_EVENTS.FOCUS_CUSTOM_ATTRIBUTE, this.onFocusAttribute);
},
destroyed() {
unmounted() {
emitter.off(BUS_EVENTS.FOCUS_CUSTOM_ATTRIBUTE, this.onFocusAttribute);
},
methods: {
@@ -18,6 +18,7 @@ const shouldShowContent = computed(
);
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<div v-if="shouldShowContent">
<slot />
@@ -5,6 +5,7 @@ export default {
components: {
DatePicker,
},
emits: ['close', 'chooseTime'],
data() {
return {
@@ -3,9 +3,8 @@
import { ref, computed, defineEmits, onMounted } from 'vue';
import { useEventListener } from '@vueuse/core';
const { show, modalType, closeOnBackdropClick, onClose } = defineProps({
const { modalType, closeOnBackdropClick, onClose } = defineProps({
closeOnBackdropClick: { type: Boolean, default: true },
show: Boolean,
showCloseButton: { type: Boolean, default: true },
onClose: { type: Function, required: true },
fullWidth: { type: Boolean, default: false },
@@ -14,6 +13,7 @@ const { show, modalType, closeOnBackdropClick, onClose } = defineProps({
});
const emit = defineEmits(['close']);
const show = defineModel('show', { type: Boolean, default: false });
const modalClassName = computed(() => {
const modalClassNameMap = {
@@ -32,6 +32,7 @@ const handleMouseDown = () => {
};
const close = () => {
show.value = false;
emit('close');
onClose();
};
@@ -40,14 +41,14 @@ const onMouseUp = () => {
if (mousedDownOnBackdrop.value) {
mousedDownOnBackdrop.value = false;
if (closeOnBackdropClick) {
onClose();
close();
}
}
};
const onKeydown = e => {
if (show && e.code === 'Escape') {
onClose();
if (show.value && e.code === 'Escape') {
close();
e.stopPropagation();
}
};
@@ -79,6 +79,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<Banner
v-if="shouldShowBanner"
@@ -86,6 +87,6 @@ export default {
:banner-message="bannerMessage"
:action-button-label="actionButtonMessage"
has-action-button
@primaryAction="routeToBilling"
@primary-action="routeToBilling"
/>
</template>
@@ -28,6 +28,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<Banner
v-if="shouldShowBanner"
@@ -36,6 +37,6 @@ export default {
:action-button-label="actionButtonMessage"
action-button-icon="mail"
has-action-button
@primaryAction="resendVerificationEmail"
@primary-action="resendVerificationEmail"
/>
</template>
@@ -67,6 +67,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<Banner
v-if="shouldShowBanner"
@@ -81,6 +81,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<Banner
v-if="shouldShowBanner"
@@ -88,6 +89,6 @@ export default {
:banner-message="bannerMessage"
:action-button-label="actionButtonMessage"
has-action-button
@primaryAction="routeToBilling"
@primary-action="routeToBilling"
/>
</template>
@@ -22,11 +22,14 @@ export default {
type: Boolean,
default: true,
},
hasBanner: {
type: Boolean,
default: false,
},
},
emits: [
'toggleAccountModal',
'showAddLabelPopup',
'openNotificationPanel',
'closeKeyShortcutModal',
'openKeyShortcutModal',
],
setup(props, { emit }) {
const route = useRoute();
const router = useRouter();
@@ -217,9 +220,9 @@ export default {
:account-id="accountId"
:menu-items="primaryMenuItems"
:active-menu-item="activePrimaryMenu.key"
@toggleAccounts="toggleAccountModal"
@openKeyShortcutModal="toggleKeyShortcutModal"
@openNotificationPanel="openNotificationPanel"
@toggle-accounts="toggleAccountModal"
@open-key-shortcut-modal="toggleKeyShortcutModal"
@open-notification-panel="openNotificationPanel"
/>
<SecondarySidebar
v-if="hasSecondarySidebar"
@@ -231,8 +234,8 @@ export default {
:menu-config="activeSecondaryMenu"
:current-user="currentUser"
:is-on-chatwoot-cloud="isOnChatwootCloud"
@addLabel="showAddLabelPopup"
@toggleAccounts="toggleAccountModal"
@add-label="showAddLabelPopup"
@toggle-accounts="toggleAccountModal"
/>
</aside>
</template>
@@ -2,6 +2,7 @@
import { mapGetters } from 'vuex';
export default {
emits: ['toggleAccounts'],
data() {
return { showSwitchButton: false };
},
@@ -25,6 +26,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<div
v-if="showShowCurrentAccountContext"
@@ -7,7 +7,7 @@ export default {
default: true,
},
},
emits: ['closeAccountModal', 'showCreateAccountModal'],
computed: {
...mapGetters({
accountId: 'getCurrentAccountId',
@@ -15,6 +15,7 @@ export default {
default: true,
},
},
emits: ['closeAccountCreateModal'],
setup() {
return { v$: useVuelidate() };
},
@@ -6,6 +6,7 @@ export default {
components: {
Thumbnail,
},
emits: ['toggleMenu'],
computed: {
...mapGetters({
currentUser: 'getCurrentUser',
@@ -2,6 +2,8 @@
import { mapGetters } from 'vuex';
export default {
emits: ['openNotificationPanel'],
computed: {
...mapGetters({
notificationMetadata: 'notifications/getMeta',
@@ -17,6 +17,12 @@ export default {
default: false,
},
},
emits: [
'close',
'openKeyShortcutModal',
'toggleAccounts',
'showSupportChatWindow',
],
computed: {
...mapGetters({
currentUser: 'getCurrentUser',
@@ -43,6 +43,7 @@ export default {
default: '',
},
},
emits: ['toggleAccounts', 'openNotificationPanel', 'openKeyShortcutModal'],
data() {
return {
helpDocsURL: wootConstants.DOCS_URL,
@@ -96,13 +97,13 @@ export default {
open-in-new-page
:to="helpDocsURL"
/>
<NotificationBell @openNotificationPanel="openNotificationPanel" />
<AgentDetails @toggleMenu="toggleOptions" />
<NotificationBell @open-notification-panel="openNotificationPanel" />
<AgentDetails @toggle-menu="toggleOptions" />
<OptionsMenu
:show="showOptionsMenu"
@toggleAccounts="toggleAccountModal"
@showSupportChatWindow="toggleSupportChatWindow"
@openKeyShortcutModal="$emit('openKeyShortcutModal')"
@toggle-accounts="toggleAccountModal"
@show-support-chat-window="toggleSupportChatWindow"
@open-key-shortcut-modal="$emit('openKeyShortcutModal')"
@close="toggleOptions"
/>
</div>
@@ -49,6 +49,7 @@ export default {
default: false,
},
},
emits: ['addLabel', 'toggleAccounts'],
computed: {
...mapGetters({
isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
@@ -242,7 +243,7 @@ export default {
<div
class="flex flex-col w-48 h-full px-2 pb-8 overflow-auto text-sm bg-white border-r dark:bg-slate-900 dark:border-slate-800/50 rtl:border-r-0 rtl:border-l border-slate-50"
>
<AccountContext @toggleAccounts="toggleAccountModal" />
<AccountContext @toggle-accounts="toggleAccountModal" />
<transition-group
name="menu-list"
tag="ul"
@@ -257,7 +258,7 @@ export default {
v-for="menuItem in additionalSecondaryMenuItems[menuConfig.parentNav]"
:key="menuItem.key"
:menu-item="menuItem"
@addLabel="showAddLabelPopup"
@add-label="showAddLabelPopup"
/>
</transition-group>
</div>
@@ -106,10 +106,11 @@ export default {
<span
v-if="showChildCount"
class="bg-slate-50 dark:bg-slate-700 rounded-full min-w-[18px] justify-center items-center flex text-xxs mx-1 py-0 px-1"
:class="isCountZero
:class="
isCountZero
? `text-slate-300 dark:text-slate-500`
: `text-slate-700 dark:text-slate-50`
"
"
>
{{ childItemCount }}
</span>
@@ -22,6 +22,7 @@ export default {
default: () => ({}),
},
},
emits: ['addLabel', 'open'],
setup() {
const { isAdmin } = useAdmin();
const { isEnterprise } = useConfig();
@@ -18,6 +18,7 @@ export default {
default: '',
},
},
emits: ['open', 'close'],
methods: {
onClickOpenPath() {
this.$emit('open');
@@ -38,6 +38,7 @@ export default {
default: false,
},
},
emits: ['primaryAction', 'close'],
computed: {
bannerClasses() {
const classList = [this.colorScheme];
@@ -222,7 +222,7 @@ const emitDateRange = () => {
>
<CalendarDateRange
:selected-range="selectedRange"
@setRange="setDateRange"
@set-range="setDateRange"
/>
<div
class="flex flex-col w-[680px] ltr:border-l rtl:border-r border-slate-50 dark:border-slate-700/50"
@@ -264,15 +264,15 @@ const emitDateRange = () => {
:calendar-type="calendar"
:start-current-date="startCurrentDate"
:end-current-date="endCurrentDate"
@selectYear="openCalendar($event, calendar, YEAR)"
@select-year="openCalendar($event, calendar, YEAR)"
/>
<CalendarMonth
v-else-if="calendarViews[calendar] === MONTH"
:calendar-type="calendar"
:start-current-date="startCurrentDate"
:end-current-date="endCurrentDate"
@selectMonth="openCalendar($event, calendar)"
@setView="setViewMode"
@select-month="openCalendar($event, calendar)"
@set-view="setViewMode"
@prev="moveCalendar(calendar, 'prev', YEAR)"
@next="moveCalendar(calendar, 'next', YEAR)"
/>
@@ -286,9 +286,9 @@ const emitDateRange = () => {
:selected-end-date="selectedEndDate"
:selecting-end-date="selectingEndDate"
:hovered-end-date="hoveredEndDate"
@updateHoveredEndDate="hoveredEndDate = $event"
@selectDate="selectDate"
@setView="setViewMode"
@update-hovered-end-date="hoveredEndDate = $event"
@select-date="selectDate"
@set-view="setViewMode"
@prev="moveCalendar(calendar, 'prev')"
@next="moveCalendar(calendar, 'next')"
/>
@@ -1,5 +1,5 @@
<script setup>
const emit = defineEmits(['clear', 'clear']);
const emit = defineEmits(['clear', 'change']);
const onClickClear = () => {
emit('clear');
@@ -62,7 +62,7 @@ const selectMonth = index => {
MONTH
)
"
@setView="setViewMode"
@set-view="setViewMode"
@prev="onClickPrev"
@next="onClickNext"
/>
@@ -139,7 +139,7 @@ const dayClasses = day => ({
"
@prev="onClickPrev"
@next="onClickNext"
@setView="setViewMode"
@set-view="setViewMode"
/>
<CalendarWeekLabel />
<div
@@ -16,6 +16,7 @@ export default {
default: () => [],
},
},
emits: ['change'],
methods: {
handleChange(value) {
this.$emit('change', value);
@@ -17,6 +17,7 @@ export default {
default: [],
},
},
emits: ['change'],
methods: {
handleChange(value) {
@@ -38,7 +38,7 @@ const props = defineProps({
},
});
const emit = defineEmits(['onSearch', 'select']);
const emit = defineEmits(['onSearch', 'select', 'removeFilter']);
const searchTerm = ref('');
@@ -44,6 +44,7 @@ export default {
default: '',
},
},
emits: ['remove'],
computed: {
textColor() {
if (this.variant === 'smooth') return '';
@@ -4,6 +4,7 @@ export default {
modelValue: { type: Boolean, default: false },
size: { type: String, default: '' },
},
emits: ['update:modelValue', 'input'],
methods: {
onClick() {
this.$emit('update:modelValue', !this.modelValue);
@@ -17,6 +17,7 @@ export default {
AICTAModal,
AIAssistanceCTAButton,
},
emits: ['replaceText'],
setup(props, { emit }) {
const { uiSettings, updateUISettings } = useUISettings();
@@ -137,19 +138,19 @@ export default {
@click="openAIAssist"
/>
<woot-modal
:show.sync="showAIAssistanceModal"
v-model:show="showAIAssistanceModal"
:on-close="hideAIAssistanceModal"
>
<AIAssistanceModal
:ai-option="aiOption"
@applyText="insertText"
@apply-text="insertText"
@close="hideAIAssistanceModal"
/>
</woot-modal>
</div>
<div v-else-if="shouldShowAIAssistCTAButtonForAdmin" class="relative">
<AIAssistanceCTAButton @click="openAICta" />
<woot-modal :show.sync="showAICtaModal" :on-close="hideAICtaModal">
<woot-modal v-model:show="showAICtaModal" :on-close="hideAICtaModal">
<AICTAModal @close="hideAICtaModal" />
</woot-modal>
</div>
@@ -1,5 +1,7 @@
<script>
export default {
emits: ['open'],
methods: {
onClick() {
this.$emit('open');
@@ -13,6 +13,7 @@ export default {
required: true,
},
},
emits: ['close', 'applyText'],
setup() {
const { formatMessage } = useMessageFormatter();
const { draftMessage, processEvent, recordAnalytics } = useAI();
@@ -7,6 +7,8 @@ import { useAI } from 'dashboard/composables/useAI';
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
export default {
emits: ['close'],
setup() {
const { updateUISettings } = useUISettings();
const { recordAnalytics } = useAI();
@@ -38,6 +38,7 @@ export default {
default: false,
},
},
emits: ['update:modelValue', 'input', 'removeAction', 'resetAction'],
computed: {
action_name: {
get() {
@@ -3,6 +3,7 @@ export default {
// The value types are dynamic, hence prop validation removed to work with our action schema
// eslint-disable-next-line vue/require-prop-types
props: ['teams', 'value'],
emits: ['input'],
data() {
return {
selectedTeams: [],
@@ -11,6 +11,7 @@ export default {
default: '',
},
},
emits: ['update:modelValue'],
data() {
return {
uploadState: 'idle',
@@ -12,6 +12,7 @@ export default {
required: true,
},
},
emits: ['channelItemClick'],
computed: {
hasFbConfigured() {
return window.chatwootConfig?.fbAppId;
@@ -11,6 +11,7 @@ export default {
default: '',
},
},
emits: ['update:modelValue'],
data() {
return {
isPickerOpen: false,
@@ -45,7 +46,7 @@ export default {
disable-alpha
:model-value="modelValue"
class="colorpicker--chrome"
@update:modelValue="updateColor"
@update:model-value="updateColor"
/>
</div>
</template>
@@ -80,6 +80,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<div v-if="hasOpenedAtleastOnce" class="dashboard-app--container">
<div
@@ -19,6 +19,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<div v-if="isFeatureEnabled">
<slot />
@@ -47,6 +47,7 @@ export default {
default: '',
},
},
emits: ['update:modelValue', 'removeFilter', 'resetFilter'],
computed: {
attributeKey: {
get() {
@@ -5,7 +5,7 @@ export default {
props: {
inbox: {
type: Object,
default: () => { },
default: () => {},
},
},
computed: {
@@ -16,6 +16,8 @@ const props = defineProps({
default: 0,
},
});
const emit = defineEmits(['pageChange']);
const totalPages = computed(() => Math.ceil(props.totalCount / props.pageSize));
const firstIndex = computed(() => props.pageSize * (props.currentPage - 1) + 1);
const lastIndex = computed(() =>
@@ -26,6 +28,7 @@ const isFooterVisible = computed(
);
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<footer
v-if="isFooterVisible"
@@ -42,7 +45,7 @@ const isFooterVisible = computed(
:total-pages="totalPages"
:total-count="totalCount"
:page-size="pageSize"
@pageChange="$emit('pageChange', $event)"
@page-change="emit('pageChange', $event)"
/>
</footer>
</template>
@@ -41,6 +41,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<woot-button
v-if="isVideoIntegrationEnabled"
@@ -176,7 +176,7 @@ const editorMenuOptions = computed(() => {
function createSuggestionPlugin({
trigger,
minChars = 1,
minChars = 0,
showMenu,
searchTerm,
isAllowed = () => true,
@@ -47,6 +47,7 @@ export default {
placeholder: { type: String, default: '' },
enabledMenuOptions: { type: Array, default: () => [] },
},
emits: ['blur', 'input', 'update:modelValue', 'keyup', 'focus', 'keydown'],
setup() {
const { uiSettings, updateUISettings } = useUISettings();
@@ -60,17 +61,9 @@ export default {
plugins: [imagePastePlugin(this.handleImageUpload)],
};
},
computed: {
contentFromEditor() {
if (editorView) {
return ArticleMarkdownSerializer.serialize(editorView.state.doc);
}
return '';
},
},
watch: {
modelValue(newValue = '') {
if (newValue !== this.contentFromEditor) {
if (newValue !== this.contentFromEditor()) {
this.reloadState();
}
},
@@ -95,6 +88,12 @@ export default {
this.focusEditorInputField();
},
methods: {
contentFromEditor() {
if (editorView) {
return ArticleMarkdownSerializer.serialize(editorView.state.doc);
}
return '';
},
openFileBrowser() {
this.$refs.imageUploadInput.click();
},
@@ -212,8 +211,8 @@ export default {
editorView.focus();
},
emitOnChange() {
this.$emit('update:modelValue', this.contentFromEditor);
this.$emit('input', this.contentFromEditor);
this.$emit('update:modelValue', this.contentFromEditor());
this.$emit('input', this.contentFromEditor());
},
onKeyup() {
this.$emit('keyup');
@@ -26,7 +26,7 @@ export default {
},
onSend: {
type: Function,
default: () => { },
default: () => {},
},
sendButtonText: {
type: String,
@@ -53,19 +53,19 @@ export default {
},
onFileUpload: {
type: Function,
default: () => { },
default: () => {},
},
toggleEmojiPicker: {
type: Function,
default: () => { },
default: () => {},
},
toggleAudioRecorder: {
type: Function,
default: () => { },
default: () => {},
},
toggleAudioRecorderPlayPause: {
type: Function,
default: () => { },
default: () => {},
},
isRecordingAudio: {
type: Boolean,
@@ -112,6 +112,12 @@ export default {
required: true,
},
},
emits: [
'replaceText',
'toggleInsertArticle',
'toggleEditor',
'selectWhatsappTemplate',
],
setup() {
const { setSignatureFlagForInbox, fetchSignatureFlagFromUISettings } =
useUISettings();
@@ -166,9 +172,9 @@ export default {
return false;
}
// Disable audio recorder for safari browser as recording is not supported
const isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(
navigator.userAgent
);
// const isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(
// navigator.userAgent
// );
return (
this.isFeatureEnabledonAccount(
@@ -340,7 +346,7 @@ export default {
:conversation-id="conversationId"
:is-private-note="isOnPrivateNote"
:message="message"
@replaceText="replaceText"
@replace-text="replaceText"
/>
<transition name="modal-fade">
<div
@@ -22,6 +22,7 @@ export default {
default: false,
},
},
emits: ['setReplyMode', 'togglePopout'],
setup(props, { emit }) {
const setReplyMode = mode => {
emit('setReplyMode', mode);
@@ -48,7 +48,7 @@ onMounted(() => {
v-if="items.length"
type="emoji"
:items="items"
@mentionSelect="handleMentionClick"
@mention-select="handleMentionClick"
>
<template #default="{ item, selected }">
<span
@@ -10,6 +10,7 @@ export default {
default: '',
},
},
emits: ['replace'],
computed: {
...mapGetters({
cannedMessages: 'getCannedResponses',
@@ -46,6 +47,6 @@ export default {
<MentionBox
v-if="items.length"
:items="items"
@mentionSelect="handleMentionClick"
@mention-select="handleMentionClick"
/>
</template>
@@ -37,6 +37,7 @@ export default {
default: false,
},
},
emits: ['applyFilter', 'updateFolder'],
setup() {
const { setFilterAttributes } = useFilter({
filteri18nKey: 'FILTER',
@@ -363,8 +364,8 @@ export default {
? $t(`CONTACTS_FILTER.ERRORS.VALUE_REQUIRED`)
: ''
"
@resetFilter="resetFilter(i, appliedFilters[i])"
@removeFilter="removeFilter(i)"
@reset-filter="resetFilter(i, appliedFilters[i])"
@remove-filter="removeFilter(i)"
/>
<div class="mt-4">
<woot-button
@@ -27,6 +27,7 @@ export default {
components: {
FilterItem,
},
emits: ['changeFilter'],
setup() {
const { updateUISettings } = useUISettings();
@@ -107,7 +108,7 @@ export default {
:selected-value="chatStatus"
:items="chatStatusItems"
path-prefix="CHAT_LIST.CHAT_STATUS_FILTER_ITEMS"
@onChangeFilter="onChangeFilter"
@on-change-filter="onChangeFilter"
/>
</div>
<div class="flex items-center justify-between last:mt-4">
@@ -119,7 +120,7 @@ export default {
:selected-value="sortFilter"
:items="chatSortItems"
path-prefix="CHAT_LIST.SORT_ORDER_ITEMS"
@onChangeFilter="onChangeFilter"
@on-change-filter="onChangeFilter"
/>
</div>
</div>
@@ -34,6 +34,7 @@ export default {
default: true,
},
},
emits: ['contactPanelToggle'],
data() {
return { activeIndex: 0 };
},
@@ -103,7 +104,7 @@ export default {
:is-inbox-view="isInboxView"
:is-contact-panel-open="isContactPanelOpen"
:show-back-button="isOnExpandedLayout && !isInboxView"
@contactPanelToggle="onToggleContactPanel"
@contact-panel-toggle="onToggleContactPanel"
/>
<woot-tabs
v-if="dashboardApps.length && currentChat.id"
@@ -128,7 +129,7 @@ export default {
:inbox-id="inboxId"
:is-inbox-view="isInboxView"
:is-contact-panel-open="isContactPanelOpen"
@contactPanelToggle="onToggleContactPanel"
@contact-panel-toggle="onToggleContactPanel"
/>
<EmptyState
v-if="!currentChat.id && !isInboxView"
@@ -69,6 +69,15 @@ export default {
default: false,
},
},
emits: [
'contextMenuToggle',
'assignAgent',
'assignLabel',
'assignTeam',
'markAsUnread',
'assignPriority',
'updateConversationStatus',
],
data() {
return {
hovered: false,
@@ -336,12 +345,12 @@ export default {
:priority="chat.priority"
:chat-id="chat.id"
:has-unread-messages="hasUnread"
@updateConversation="onUpdateConversation"
@assignAgent="onAssignAgent"
@assignLabel="onAssignLabel"
@assignTeam="onAssignTeam"
@markAsUnread="markAsUnread"
@assignPriority="assignPriority"
@update-conversation="onUpdateConversation"
@assign-agent="onAssignAgent"
@assign-label="onAssignLabel"
@assign-team="onAssignTeam"
@mark-as-unread="markAsUnread"
@assign-priority="assignPriority"
/>
</ContextMenu>
</div>
@@ -41,6 +41,7 @@ export default {
default: false,
},
},
emits: ['contactPanelToggle'],
setup(props, { emit }) {
const keyboardEvents = {
'Alt+KeyO': {
@@ -2,6 +2,7 @@
import { useVuelidate } from '@vuelidate/core';
import { required, minLength, email } from '@vuelidate/validators';
import { useAlert } from 'dashboard/composables';
export default {
props: {
show: {
@@ -13,6 +14,7 @@ export default {
default: () => ({}),
},
},
emits: ['cancel', 'update:show'],
setup() {
return { v$: useVuelidate() };
},
@@ -31,6 +33,14 @@ export default {
},
},
computed: {
localShow: {
get() {
return this.show;
},
set(value) {
this.$emit('update:show', value);
},
},
sentToOtherEmailAddress() {
return this.selectedType === 'other_email_address';
},
@@ -80,9 +90,8 @@ export default {
};
</script>
<!-- eslint-disable vue/no-mutating-props -->
<template>
<woot-modal :show.sync="show" :on-close="onCancel">
<woot-modal v-model:show="localShow" :on-close="onCancel">
<div class="flex flex-col h-auto overflow-auto">
<woot-modal-header
:header-title="$t('EMAIL_TRANSCRIPT.TITLE')"
@@ -18,6 +18,7 @@ export default {
required: true,
},
},
emits: ['onChangeFilter'],
data() {
return {
activeValue: this.selectedValue,
@@ -439,6 +439,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<li
v-if="shouldRenderMessage"
@@ -579,7 +580,7 @@ export default {
:message="data"
@open="openContextMenu"
@close="closeContextMenu"
@replyTo="handleReplyTo"
@reply-to="handleReplyTo"
/>
</div>
</li>
@@ -52,6 +52,7 @@ export default {
default: false,
},
},
emits: ['contactPanelToggle'],
setup() {
const isPopOutReplyBox = ref(false);
const { isEnterprise } = useConfig();
@@ -547,9 +548,9 @@ export default {
</div>
</div>
<ReplyBox
v-model:popout-reply-box="isPopOutReplyBox"
:conversation-id="currentChat.id"
:popout-reply-box.sync="isPopOutReplyBox"
@togglePopout="showPopOutReplyBox"
@toggle-popout="showPopOutReplyBox"
/>
</div>
</div>
@@ -28,7 +28,7 @@ export default {
emitter.on(CMD_UNMUTE_CONVERSATION, this.unmute);
emitter.on(CMD_SEND_TRANSCRIPT, this.toggleEmailActionsModal);
},
destroyed() {
unmounted() {
emitter.off(CMD_MUTE_CONVERSATION, this.mute);
emitter.off(CMD_UNMUTE_CONVERSATION, this.unmute);
emitter.off(CMD_SEND_TRANSCRIPT, this.toggleEmailActionsModal);
@@ -29,6 +29,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<span
v-if="priority"
@@ -1,5 +1,6 @@
<script>
import { defineAsyncComponent } from 'vue';
// [TODO] The popout events are needlessly complex and should be simplified
import { defineAsyncComponent, defineModel } from 'vue';
import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import { useUISettings } from 'dashboard/composables/useUISettings';
@@ -65,12 +66,7 @@ export default {
ArticleSearchPopover,
},
mixins: [inboxMixin, fileUploadMixin, keyboardEventListenerMixins],
props: {
popoutReplyBox: {
type: Boolean,
default: false,
},
},
emits: ['update:popoutReplyBox', 'togglePopout'],
setup() {
const {
uiSettings,
@@ -79,8 +75,14 @@ export default {
fetchSignatureFlagFromUISettings,
} = useUISettings();
const popoutReplyBox = defineModel('popoutReplyBox', {
type: Boolean,
default: false,
});
return {
uiSettings,
popoutReplyBox,
updateUISettings,
isEditorHotKeyEnabled,
fetchSignatureFlagFromUISettings,
@@ -463,12 +465,10 @@ export default {
this.onNewConversationModalActive
);
},
destroyed() {
unmounted() {
document.removeEventListener('paste', this.onPaste);
document.removeEventListener('keydown', this.handleKeyEvents);
emitter.off(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo);
},
unmounted() {
emitter.off(
BUS_EVENTS.NEW_CONVERSATION_MODAL,
this.onNewConversationModalActive
@@ -1081,15 +1081,15 @@ export default {
:banner-message="$t('CONVERSATION.NOT_ASSIGNED_TO_YOU')"
has-action-button
:action-button-label="$t('CONVERSATION.ASSIGN_TO_ME')"
@primaryAction="onClickSelfAssign"
@primary-action="onClickSelfAssign"
/>
<ReplyTopPanel
:mode="replyType"
:is-message-length-reaching-threshold="isMessageLengthReachingThreshold"
:characters-remaining="charactersRemaining"
:popout-reply-box="popoutReplyBox"
@setReplyMode="setReplyMode"
@togglePopout="$emit('togglePopout')"
@set-reply-mode="setReplyMode"
@toggle-popout="$emit('togglePopout')"
/>
<ArticleSearchPopover
v-if="showArticleSearchPopover && connectedPortalSlug"
@@ -1126,9 +1126,9 @@ export default {
v-if="showAudioRecorderEditor"
ref="audioRecorderInput"
:audio-record-format="audioRecordFormat"
@recorderProgressChanged="onRecordProgressChanged"
@stateRecorderChanged="onStateRecorderChanged"
@finishRecord="onFinishRecorder"
@recorder-progress-changed="onRecordProgressChanged"
@state-recorder-changed="onStateRecorderChanged"
@finish-record="onFinishRecorder"
/>
<ResizableTextArea
v-else-if="!showRichContentEditor"
@@ -1140,8 +1140,8 @@ export default {
:signature="signatureToApply"
allow-signature
:send-with-signature="sendWithSignature"
@typingOff="onTypingOff"
@typingOn="onTypingOn"
@typing-off="onTypingOff"
@typing-on="onTypingOn"
@focus="onFocus"
@blur="onBlur"
/>
@@ -1159,21 +1159,21 @@ export default {
:signature="signatureToApply"
allow-signature
:channel-type="channelType"
@typingOff="onTypingOff"
@typingOn="onTypingOn"
@typing-off="onTypingOff"
@typing-on="onTypingOn"
@focus="onFocus"
@blur="onBlur"
@toggleUserMention="toggleUserMention"
@toggleCannedMenu="toggleCannedMenu"
@toggleVariablesMenu="toggleVariablesMenu"
@clearSelection="clearEditorSelection"
@toggle-user-mention="toggleUserMention"
@toggle-canned-menu="toggleCannedMenu"
@toggle-variables-menu="toggleVariablesMenu"
@clear-selection="clearEditorSelection"
/>
</div>
<div v-if="hasAttachments" class="attachment-preview-box" @paste="onPaste">
<AttachmentPreview
class="flex-col mt-4"
:attachments="attachedFiles"
@removeAttachment="removeAttachment"
@remove-attachment="removeAttachment"
/>
</div>
<MessageSignatureMissingAlert
@@ -1203,16 +1203,16 @@ export default {
:message="message"
:portal-slug="connectedPortalSlug"
:new-conversation-modal-active="newConversationModalActive"
@selectWhatsappTemplate="openWhatsappTemplateModal"
@toggleEditor="toggleRichContentEditor"
@replaceText="replaceText"
@toggleInsertArticle="toggleInsertArticle"
@select-whatsapp-template="openWhatsappTemplateModal"
@toggle-editor="toggleRichContentEditor"
@replace-text="replaceText"
@toggle-insert-article="toggleInsertArticle"
/>
<WhatsappTemplates
:inbox-id="inbox.id"
:show="showWhatsAppTemplatesModal"
@close="hideWhatsappTemplatesModal"
@onSend="onSendWhatsAppReply"
@on-send="onSendWhatsAppReply"
@cancel="hideWhatsappTemplatesModal"
/>
@@ -17,6 +17,7 @@ export default {
default: '',
},
},
emits: ['update:bccEmails', 'update:ccEmails', 'update:toEmails'],
setup() {
return { v$: useVuelidate() };
},
@@ -9,6 +9,7 @@ export default {
required: true,
},
},
emits: ['dismiss'],
};
</script>
@@ -11,6 +11,7 @@ export default {
default: '',
},
},
emits: ['selectVariable'],
computed: {
...mapGetters({
customAttributes: 'attributes/getAttributes',
@@ -62,7 +63,7 @@ export default {
v-if="items.length"
type="variable"
:items="items"
@mentionSelect="handleVariableClick"
@mention-select="handleVariableClick"
/>
</template>
@@ -7,21 +7,30 @@ export default {
TemplateParser,
},
props: {
show: {
type: Boolean,
default: false,
},
inboxId: {
type: Number,
default: undefined,
},
show: {
type: Boolean,
default: true,
},
},
emits: ['onSend', 'cancel', 'update:show'],
data() {
return {
selectedWaTemplate: null,
};
},
computed: {
localShow: {
get() {
return this.show;
},
set(value) {
this.$emit('update:show', value);
},
},
modalHeaderContent() {
return this.selectedWaTemplate
? this.$t('WHATSAPP_TEMPLATES.MODAL.TEMPLATE_SELECTED_SUBTITLE', {
@@ -47,9 +56,8 @@ export default {
};
</script>
<!-- eslint-disable vue/no-mutating-props -->
<template>
<woot-modal :show.sync="show" :on-close="onClose" size="modal-big">
<woot-modal v-model:show="localShow" :on-close="onClose" size="modal-big">
<woot-modal-header
:header-title="$t('WHATSAPP_TEMPLATES.MODAL.TITLE')"
:header-content="modalHeaderContent"
@@ -58,13 +66,13 @@ export default {
<TemplatesPicker
v-if="!selectedWaTemplate"
:inbox-id="inboxId"
@onSelect="pickTemplate"
@on-select="pickTemplate"
/>
<TemplateParser
v-else
:template="selectedWaTemplate"
@resetTemplate="onResetTemplate"
@sendMessage="onSendMessage"
@reset-template="onResetTemplate"
@send-message="onSendMessage"
/>
</div>
</woot-modal>
@@ -19,6 +19,7 @@ export default {
default: () => ({}),
},
},
emits: ['sendMessage', 'resetTemplate'],
setup(props, { emit }) {
const processVariable = str => {
return str.replace(/{{|}}/g, '');
@@ -9,6 +9,7 @@ export default {
default: undefined,
},
},
emits: ['onSelect'],
data() {
return {
query: '',
@@ -7,6 +7,7 @@ export default {
required: true,
},
},
emits: ['error'],
data() {
return {
show: false,
@@ -26,7 +27,7 @@ export default {
<template>
<div class="image message-text__wrap">
<img :src="url" @click="onClick" @error="$emit('error')" />
<woot-modal full-width :show.sync="show" :on-close="onClose">
<woot-modal v-model:show="show" full-width :on-close="onClose">
<img :src="url" class="modal-image skip-context-menu" />
</woot-modal>
</div>
@@ -21,6 +21,7 @@ export default {
required: true,
},
},
emits: ['error'],
data() {
return {
show: false,
@@ -116,7 +117,7 @@ export default {
</audio>
<GalleryView
v-if="show"
:show.sync="show"
v-model:show="show"
:attachment="attachment"
:all-attachments="filteredCurrentChatAttachments"
@error="onImgError"
@@ -15,6 +15,7 @@ export default {
default: '',
},
},
emits: ['error'],
data() {
return {
hasImgStoryError: false,
@@ -31,6 +31,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<DyteVideoCall
v-if="showDyteIntegration"
@@ -45,6 +45,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<div
v-if="showHead"
@@ -106,7 +106,7 @@ export default {
</button>
<GalleryView
v-if="showGalleryViewer"
:show.sync="showGalleryViewer"
v-model:show="showGalleryViewer"
:attachment="attachment"
:all-attachments="availableAttachments"
@error="onClose"
@@ -10,6 +10,7 @@ export default {
default: '',
},
},
emits: ['close'],
computed: {
translationsAvailable() {
return !!Object.keys(this.translations).length;
@@ -6,6 +6,7 @@ export default {
required: true,
},
},
emits: ['error'],
data() {
return {
show: false,
@@ -30,7 +31,7 @@ export default {
<template>
<div class="video message-text__wrap">
<video ref="videoElement" :src="url" muted playsInline @click="onClick" />
<woot-modal :show.sync="show" :on-close="onClose">
<woot-modal v-model:show="show" :on-close="onClose">
<video
:src="url"
controls
@@ -7,10 +7,6 @@ import { messageTimestamp } from 'shared/helpers/timeHelper';
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
const props = defineProps({
show: {
type: Boolean,
required: true,
},
attachment: {
type: Object,
required: true,
@@ -22,6 +18,7 @@ const props = defineProps({
});
const emit = defineEmits(['close']);
const show = defineModel('show', { type: Boolean, default: false });
const getters = useStoreGetters();
@@ -208,11 +205,10 @@ onMounted(() => {
});
</script>
<!-- eslint-disable vue/no-mutating-props -->
<template>
<woot-modal
v-model:show="show"
full-width
:show.sync="show"
:show-close-button="false"
:on-close="onClose"
>
@@ -103,6 +103,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<div
v-if="hasSlaThreshold"
@@ -37,6 +37,14 @@ export default {
default: null,
},
},
emits: [
'updateConversation',
'assignPriority',
'markAsUnread',
'assignAgent',
'assignTeam',
'assignLabel',
],
data() {
return {
STATUS_TYPE: wootConstants.STATUS_TYPE,
@@ -150,6 +150,7 @@ export default {
};
</script>
<!-- eslint-disable-next-line vue/no-root-v-if -->
<template>
<li
v-if="shouldShowSuggestions"
@@ -18,6 +18,7 @@ export default {
default: 0,
},
},
emits: ['select', 'close'],
data() {
return {
query: '',
@@ -48,6 +48,14 @@ export default {
default: false,
},
},
emits: [
'selectAllConversations',
'assignAgent',
'updateConversations',
'assignLabels',
'assignTeam',
'resolveConversations',
],
data() {
return {
showAgentsList: false,
@@ -72,7 +80,7 @@ export default {
this.onCmdResolveConversation
);
},
destroyed() {
unmounted() {
emitter.off(
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
this.onCmdSnoozeConversation
@@ -231,7 +239,7 @@ export default {
<TeamActions
v-if="showTeamsList"
class="team-actions-box"
@assignTeam="assignTeam"
@assign-team="assignTeam"
@close="showTeamsList = false"
/>
</transition>
@@ -240,12 +248,12 @@ export default {
{{ $t('BULK_ACTION.ALL_CONVERSATIONS_SELECTED_ALERT') }}
</div>
<woot-modal
:show.sync="showCustomTimeSnoozeModal"
v-model:show="showCustomTimeSnoozeModal"
:on-close="hideCustomSnoozeModal"
>
<CustomSnoozeModal
@close="hideCustomSnoozeModal"
@chooseTime="customSnoozeTime"
@choose-time="customSnoozeTime"
/>
</woot-modal>
</div>
@@ -2,6 +2,7 @@
import { mapGetters } from 'vuex';
export default {
emits: ['update', 'close', 'assign'],
data() {
return {
query: '',
@@ -1,6 +1,8 @@
<script>
import { mapGetters } from 'vuex';
export default {
emits: ['assignTeam', 'close'],
data() {
return {
query: '',
@@ -63,7 +63,7 @@ const unlinkIssue = () => {
:identifier="issue.identifier"
:link-id="linkId"
:issue-url="issue.url"
@unlinkIssue="unlinkIssue"
@unlink-issue="unlinkIssue"
/>
<span class="mt-2 text-sm font-medium text-ash-900">
@@ -120,7 +120,7 @@ const linkIssue = async () => {
:loading-placeholder="$t('INTEGRATION_SETTINGS.LINEAR.LINK.LOADING')"
enable-search
class="left-0 flex flex-col w-full overflow-y-auto h-fit !max-h-[160px] md:left-auto md:right-0 top-10"
@onSearch="onSearch"
@on-search="onSearch"
@select="onSelectIssue"
/>
</template>
@@ -119,10 +119,10 @@ onMounted(() => {
:issue="linkedIssue.issue"
:link-id="linkedIssue.id"
class="absolute right-0 top-[40px] invisible group-hover:visible"
@unlinkIssue="unlinkIssue"
@unlink-issue="unlinkIssue"
/>
<woot-modal
:show.sync="shouldShowPopup"
v-model:show="shouldShowPopup"
:on-close="closePopup"
:close-on-backdrop-click="false"
class="!items-start [&>div]:!top-12 [&>div]:sticky"
@@ -18,6 +18,7 @@ export default {
default: false,
},
},
emits: ['onAvatarSelect', 'onAvatarDelete'],
watch: {},
methods: {
handleImageUpload(event) {
@@ -38,7 +38,8 @@ export default {
default: () => {},
},
},
created() {
emits: ['update:modelValue', 'input', 'blur'],
mounted() {
// eslint-disable-next-line
console.warn(
'[DEPRECATED] <WootInput> has be deprecated and will be removed soon. Please use v3/components/Form/Input.vue instead'
@@ -29,6 +29,7 @@ export default {
default: false,
},
},
emits: ['blur', 'input', 'setCode'],
data() {
return {
selectedIndex: -1,
@@ -8,35 +8,15 @@ export default {
Modal,
},
props: {
show: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
message: {
type: String,
default: '',
},
confirmText: {
type: String,
default: '',
},
rejectText: {
type: String,
default: '',
},
confirmValue: {
type: String,
default: '',
},
confirmPlaceHolderText: {
type: String,
default: '',
},
show: { type: Boolean, default: false },
title: { type: String, default: '' },
message: { type: String, default: '' },
confirmText: { type: String, default: '' },
rejectText: { type: String, default: '' },
confirmValue: { type: String, default: '' },
confirmPlaceHolderText: { type: String, default: '' },
},
emits: ['onClose', 'onConfirm', 'update:show'],
setup() {
return { v$: useVuelidate() };
},
@@ -53,6 +33,16 @@ export default {
},
},
},
computed: {
localShow: {
get() {
return this.show;
},
set(value) {
this.$emit('update:show', value);
},
},
},
methods: {
closeModal() {
this.value = '';
@@ -65,9 +55,8 @@ export default {
};
</script>
<!-- eslint-disable vue/no-mutating-props -->
<template>
<Modal :show.sync="show" :on-close="closeModal">
<Modal v-model:show="localShow" :on-close="closeModal">
<woot-modal-header :header-title="title" :header-content="message" />
<form @submit.prevent="onConfirm">
<woot-input
@@ -51,7 +51,7 @@ export default {
</script>
<template>
<Modal :show.sync="show" :on-close="cancel">
<Modal v-model:show="show" :on-close="cancel">
<div class="h-auto overflow-auto flex flex-col">
<woot-modal-header :header-title="title" :header-content="description" />
<div class="flex flex-row justify-end gap-2 py-4 px-6 w-full">
@@ -1,26 +1,21 @@
<script>
<script setup>
import Modal from '../../Modal.vue';
export default {
components: {
Modal,
},
props: {
show: Boolean,
onClose: { type: Function, default: () => {} },
onConfirm: { type: Function, default: () => {} },
title: { type: String, default: '' },
message: { type: String, default: '' },
messageValue: { type: String, default: '' },
confirmText: { type: String, default: '' },
rejectText: { type: String, default: '' },
},
};
defineProps({
onClose: { type: Function, default: () => {} },
onConfirm: { type: Function, default: () => {} },
title: { type: String, default: '' },
message: { type: String, default: '' },
messageValue: { type: String, default: '' },
confirmText: { type: String, default: '' },
rejectText: { type: String, default: '' },
});
const show = defineModel('show', { type: Boolean, default: false });
</script>
<!-- eslint-disable vue/no-mutating-props -->
<template>
<Modal :show.sync="show" :on-close="onClose">
<Modal v-model:show="show" :on-close="onClose">
<woot-modal-header
:header-title="title"
:header-content="message"
@@ -16,6 +16,8 @@ defineProps({
},
});
defineEmits(['close']);
const { t } = useI18n();
const shortcutKeys = SHORTCUT_KEYS;

Some files were not shown because too many files have changed in this diff Show More