mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 12:08:01 +00:00
feat: Add more snooze options (#7344)
This commit is contained in:
@@ -86,6 +86,7 @@ import {
|
|||||||
hasPressedAltAndMKey,
|
hasPressedAltAndMKey,
|
||||||
} from 'shared/helpers/KeyboardHelpers';
|
} from 'shared/helpers/KeyboardHelpers';
|
||||||
|
|
||||||
|
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
|
||||||
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||||
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||||
|
|
||||||
@@ -181,7 +182,7 @@ export default {
|
|||||||
onCmdSnoozeConversation(snoozeType) {
|
onCmdSnoozeConversation(snoozeType) {
|
||||||
this.toggleStatus(
|
this.toggleStatus(
|
||||||
this.STATUS_TYPE.SNOOZED,
|
this.STATUS_TYPE.SNOOZED,
|
||||||
this.snoozeTimes[snoozeType] || null
|
findSnoozeTime(snoozeType) || null
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onCmdOpenConversation() {
|
onCmdOpenConversation() {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import { hasPressedAltAndOKey } from 'shared/helpers/KeyboardHelpers';
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import agentMixin from '../../../mixins/agentMixin.js';
|
import agentMixin from '../../../mixins/agentMixin.js';
|
||||||
import BackButton from '../BackButton';
|
import BackButton from '../BackButton';
|
||||||
import differenceInHours from 'date-fns/differenceInHours';
|
|
||||||
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
|
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
|
||||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||||
import InboxName from '../InboxName';
|
import InboxName from '../InboxName';
|
||||||
@@ -65,6 +64,8 @@ import MoreActions from './MoreActions';
|
|||||||
import Thumbnail from '../Thumbnail';
|
import Thumbnail from '../Thumbnail';
|
||||||
import wootConstants from 'dashboard/constants/globals';
|
import wootConstants from 'dashboard/constants/globals';
|
||||||
import { conversationListPageURL } from 'dashboard/helper/URLHelper';
|
import { conversationListPageURL } from 'dashboard/helper/URLHelper';
|
||||||
|
import { conversationReopenTime } from 'dashboard/helper/snoozeHelpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
BackButton,
|
BackButton,
|
||||||
@@ -125,17 +126,9 @@ export default {
|
|||||||
snoozedDisplayText() {
|
snoozedDisplayText() {
|
||||||
const { snoozed_until: snoozedUntil } = this.currentChat;
|
const { snoozed_until: snoozedUntil } = this.currentChat;
|
||||||
if (snoozedUntil) {
|
if (snoozedUntil) {
|
||||||
// When the snooze is applied, it schedules the unsnooze event to next day/week 9AM.
|
return `${this.$t(
|
||||||
// By that logic if the time difference is less than or equal to 24 + 9 hours we can consider it tomorrow.
|
'CONVERSATION.HEADER.SNOOZED_UNTIL'
|
||||||
const MAX_TIME_DIFFERENCE = 33;
|
)} ${conversationReopenTime(snoozedUntil)}`;
|
||||||
const isSnoozedUntilTomorrow =
|
|
||||||
differenceInHours(new Date(snoozedUntil), new Date()) <=
|
|
||||||
MAX_TIME_DIFFERENCE;
|
|
||||||
return this.$t(
|
|
||||||
isSnoozedUntilTomorrow
|
|
||||||
? 'CONVERSATION.HEADER.SNOOZED_UNTIL_TOMORROW'
|
|
||||||
: 'CONVERSATION.HEADER.SNOOZED_UNTIL_NEXT_WEEK'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return this.$t('CONVERSATION.HEADER.SNOOZED_UNTIL_NEXT_REPLY');
|
return this.$t('CONVERSATION.HEADER.SNOOZED_UNTIL_NEXT_REPLY');
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,5 +30,12 @@ export default {
|
|||||||
TESTIMONIAL_URL: 'https://testimonials.cdn.chatwoot.com/content.json',
|
TESTIMONIAL_URL: 'https://testimonials.cdn.chatwoot.com/content.json',
|
||||||
SMALL_SCREEN_BREAKPOINT: 1024,
|
SMALL_SCREEN_BREAKPOINT: 1024,
|
||||||
AVAILABILITY_STATUS_KEYS: ['online', 'busy', 'offline'],
|
AVAILABILITY_STATUS_KEYS: ['online', 'busy', 'offline'],
|
||||||
|
SNOOZE_OPTIONS: {
|
||||||
|
UNTIL_NEXT_REPLY: 'until_next_reply',
|
||||||
|
AN_HOUR_FROM_NOW: 'an_hour_from_now',
|
||||||
|
UNTIL_TOMORROW: 'until_tomorrow',
|
||||||
|
UNTIL_NEXT_WEEK: 'until_next_week',
|
||||||
|
UNTIL_NEXT_MONTH: 'until_next_month',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export const DEFAULT_REDIRECT_URL = '/app/';
|
export const DEFAULT_REDIRECT_URL = '/app/';
|
||||||
|
|||||||
66
app/javascript/dashboard/helper/snoozeHelpers.js
Normal file
66
app/javascript/dashboard/helper/snoozeHelpers.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import {
|
||||||
|
getUnixTime,
|
||||||
|
format,
|
||||||
|
add,
|
||||||
|
startOfWeek,
|
||||||
|
addWeeks,
|
||||||
|
startOfMonth,
|
||||||
|
isMonday,
|
||||||
|
isToday,
|
||||||
|
setHours,
|
||||||
|
} from 'date-fns';
|
||||||
|
import wootConstants from 'dashboard/constants/globals';
|
||||||
|
|
||||||
|
const SNOOZE_OPTIONS = wootConstants.SNOOZE_OPTIONS;
|
||||||
|
|
||||||
|
export const findStartOfNextWeek = currentDate => {
|
||||||
|
const startOfNextWeek = startOfWeek(addWeeks(currentDate, 1));
|
||||||
|
return isMonday(startOfNextWeek)
|
||||||
|
? startOfNextWeek
|
||||||
|
: add(startOfNextWeek, {
|
||||||
|
days: (8 - startOfNextWeek.getDay()) % 7,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findStartOfNextMonth = currentDate => {
|
||||||
|
const startOfNextMonth = startOfMonth(add(currentDate, { months: 1 }));
|
||||||
|
return isMonday(startOfNextMonth)
|
||||||
|
? startOfNextMonth
|
||||||
|
: add(startOfNextMonth, {
|
||||||
|
days: (8 - startOfNextMonth.getDay()) % 7,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findNextDay = currentDate => {
|
||||||
|
return add(currentDate, { days: 1 });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setHoursToNine = date => {
|
||||||
|
return setHours(date, 9, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findSnoozeTime = (snoozeType, currentDate = new Date()) => {
|
||||||
|
let parsedDate = null;
|
||||||
|
if (snoozeType === SNOOZE_OPTIONS.AN_HOUR_FROM_NOW) {
|
||||||
|
parsedDate = add(currentDate, { hours: 1 });
|
||||||
|
} else if (snoozeType === SNOOZE_OPTIONS.UNTIL_TOMORROW) {
|
||||||
|
parsedDate = setHoursToNine(findNextDay(currentDate));
|
||||||
|
} else if (snoozeType === SNOOZE_OPTIONS.UNTIL_NEXT_WEEK) {
|
||||||
|
parsedDate = setHoursToNine(findStartOfNextWeek(currentDate));
|
||||||
|
} else if (snoozeType === SNOOZE_OPTIONS.UNTIL_NEXT_MONTH) {
|
||||||
|
parsedDate = setHoursToNine(findStartOfNextMonth(currentDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedDate ? getUnixTime(parsedDate) : null;
|
||||||
|
};
|
||||||
|
export const conversationReopenTime = snoozedUntil => {
|
||||||
|
if (!snoozedUntil) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const date = new Date(snoozedUntil);
|
||||||
|
|
||||||
|
if (isToday(date)) {
|
||||||
|
return format(date, 'h.mmaaa');
|
||||||
|
}
|
||||||
|
return snoozedUntil ? format(date, 'd MMM, h.mmaaa') : null;
|
||||||
|
};
|
||||||
105
app/javascript/dashboard/helper/specs/snoozeHelpers.spec.js
Normal file
105
app/javascript/dashboard/helper/specs/snoozeHelpers.spec.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import {
|
||||||
|
findSnoozeTime,
|
||||||
|
conversationReopenTime,
|
||||||
|
findStartOfNextWeek,
|
||||||
|
findStartOfNextMonth,
|
||||||
|
findNextDay,
|
||||||
|
setHoursToNine,
|
||||||
|
} from '../snoozeHelpers';
|
||||||
|
|
||||||
|
describe('#Snooze Helpers', () => {
|
||||||
|
describe('findStartOfNextWeek', () => {
|
||||||
|
it('should return first working day of next week if a date is passed', () => {
|
||||||
|
const today = new Date('06/16/2023');
|
||||||
|
const startOfNextWeek = new Date('06/19/2023');
|
||||||
|
expect(findStartOfNextWeek(today)).toEqual(startOfNextWeek);
|
||||||
|
});
|
||||||
|
it('should return first working day of next week if a date is passed', () => {
|
||||||
|
const today = new Date('06/03/2023');
|
||||||
|
const startOfNextWeek = new Date('06/05/2023');
|
||||||
|
expect(findStartOfNextWeek(today)).toEqual(startOfNextWeek);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findStartOfNextMonth', () => {
|
||||||
|
it('should return first working day of next month if a valid date is passed', () => {
|
||||||
|
const today = new Date('06/21/2023');
|
||||||
|
const startOfNextMonth = new Date('07/03/2023');
|
||||||
|
expect(findStartOfNextMonth(today)).toEqual(startOfNextMonth);
|
||||||
|
});
|
||||||
|
it('should return first working day of next month if a valid date is passed', () => {
|
||||||
|
const today = new Date('02/28/2023');
|
||||||
|
const startOfNextMonth = new Date('03/06/2023');
|
||||||
|
expect(findStartOfNextMonth(today)).toEqual(startOfNextMonth);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setHoursToNine', () => {
|
||||||
|
it('should return date with 9.00AM time', () => {
|
||||||
|
const nextDay = new Date('06/17/2023');
|
||||||
|
nextDay.setHours(9, 0, 0, 0);
|
||||||
|
expect(setHoursToNine(nextDay)).toEqual(nextDay);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findSnoozeTime', () => {
|
||||||
|
it('should return nil if until_next_reply is passed', () => {
|
||||||
|
expect(findSnoozeTime('until_next_reply')).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return next hour time stamp if an_hour_from_now is passed', () => {
|
||||||
|
const nextHour = new Date();
|
||||||
|
nextHour.setHours(nextHour.getHours() + 1);
|
||||||
|
expect(findSnoozeTime('an_hour_from_now')).toBeCloseTo(
|
||||||
|
Math.floor(nextHour.getTime() / 1000)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return next day 9.00AM time stamp until_tomorrow is passed', () => {
|
||||||
|
const today = new Date('06/16/2023');
|
||||||
|
const nextDay = new Date('06/17/2023');
|
||||||
|
nextDay.setHours(9, 0, 0, 0);
|
||||||
|
expect(findSnoozeTime('until_tomorrow', today)).toBeCloseTo(
|
||||||
|
nextDay.getTime() / 1000
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return next week monday 9.00AM time stamp if until_next_week is passed', () => {
|
||||||
|
const today = new Date('06/16/2023');
|
||||||
|
const startOfNextWeek = new Date('06/19/2023');
|
||||||
|
startOfNextWeek.setHours(9, 0, 0, 0);
|
||||||
|
expect(findSnoozeTime('until_next_week', today)).toBeCloseTo(
|
||||||
|
startOfNextWeek.getTime() / 1000
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return next month 9.00AM time stamp if until_next_month is passed', () => {
|
||||||
|
const today = new Date('06/21/2023');
|
||||||
|
const startOfNextMonth = new Date('07/03/2023');
|
||||||
|
startOfNextMonth.setHours(9, 0, 0, 0);
|
||||||
|
expect(findSnoozeTime('until_next_month', today)).toBeCloseTo(
|
||||||
|
startOfNextMonth.getTime() / 1000
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('conversationReopenTime', () => {
|
||||||
|
it('should return nil if snoozedUntil is nil', () => {
|
||||||
|
expect(conversationReopenTime(null)).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return formatted date if snoozedUntil is not nil', () => {
|
||||||
|
expect(conversationReopenTime('2023-06-07T09:00:00.000Z')).toEqual(
|
||||||
|
'7 Jun, 9.00am'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findNextDay', () => {
|
||||||
|
it('should return next day', () => {
|
||||||
|
const today = new Date('06/16/2023');
|
||||||
|
const nextDay = new Date('06/17/2023');
|
||||||
|
expect(findNextDay(today)).toEqual(nextDay);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -106,6 +106,7 @@
|
|||||||
"CHANGE_ASSIGNEE": "Change Assignee",
|
"CHANGE_ASSIGNEE": "Change Assignee",
|
||||||
"CHANGE_PRIORITY": "Change Priority",
|
"CHANGE_PRIORITY": "Change Priority",
|
||||||
"CHANGE_TEAM": "Change Team",
|
"CHANGE_TEAM": "Change Team",
|
||||||
|
"SNOOZE_CONVERSATION": "Snooze Conversation",
|
||||||
"ADD_LABEL": "Add label to the conversation",
|
"ADD_LABEL": "Add label to the conversation",
|
||||||
"REMOVE_LABEL": "Remove label from the conversation",
|
"REMOVE_LABEL": "Remove label from the conversation",
|
||||||
"SETTINGS": "Settings"
|
"SETTINGS": "Settings"
|
||||||
@@ -141,7 +142,10 @@
|
|||||||
"SNOOZE_CONVERSATION": "Snooze Conversation",
|
"SNOOZE_CONVERSATION": "Snooze Conversation",
|
||||||
"UNTIL_NEXT_REPLY": "Until next reply",
|
"UNTIL_NEXT_REPLY": "Until next reply",
|
||||||
"UNTIL_NEXT_WEEK": "Until next week",
|
"UNTIL_NEXT_WEEK": "Until next week",
|
||||||
"UNTIL_TOMORROW": "Until tomorrow"
|
"UNTIL_TOMORROW": "Until tomorrow",
|
||||||
|
"UNTIL_NEXT_MONTH": "Until next month",
|
||||||
|
"AN_HOUR_FROM_NOW": "Until an hour from now",
|
||||||
|
"CUSTOM": "Custom..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DASHBOARD_APPS": {
|
"DASHBOARD_APPS": {
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ export const ICON_REMOVE_LABEL = `<svg role="img" class="ninja-icon ninja-icon--
|
|||||||
export const ICON_REOPEN_CONVERSATION = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19.25 2a.75.75 0 0 0-.743.648l-.007.102v5.69l-4.574-4.56a6.41 6.41 0 0 0-8.878-.179l-.186.18a6.41 6.41 0 0 0 0 9.063l8.845 8.84a.75.75 0 0 0 1.06-1.062l-8.845-8.838a4.91 4.91 0 0 1 6.766-7.112l.178.17L17.438 9.5H11.75a.75.75 0 0 0-.743.648L11 10.25c0 .38.282.694.648.743l.102.007h7.5a.75.75 0 0 0 .743-.648L20 10.25v-7.5a.75.75 0 0 0-.75-.75Z" fill="currentColor"/></svg>`;
|
export const ICON_REOPEN_CONVERSATION = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19.25 2a.75.75 0 0 0-.743.648l-.007.102v5.69l-4.574-4.56a6.41 6.41 0 0 0-8.878-.179l-.186.18a6.41 6.41 0 0 0 0 9.063l8.845 8.84a.75.75 0 0 0 1.06-1.062l-8.845-8.838a4.91 4.91 0 0 1 6.766-7.112l.178.17L17.438 9.5H11.75a.75.75 0 0 0-.743.648L11 10.25c0 .38.282.694.648.743l.102.007h7.5a.75.75 0 0 0 .743-.648L20 10.25v-7.5a.75.75 0 0 0-.75-.75Z" fill="currentColor"/></svg>`;
|
||||||
export const ICON_RESOLVE_CONVERSATION = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2Zm0 1.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Zm-1.25 9.94 4.47-4.47a.75.75 0 0 1 1.133.976l-.073.084-5 5a.75.75 0 0 1-.976.073l-.084-.073-2.5-2.5a.75.75 0 0 1 .976-1.133l.084.073 1.97 1.97 4.47-4.47-4.47 4.47Z" fill="currentColor"/></svg>`;
|
export const ICON_RESOLVE_CONVERSATION = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2Zm0 1.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Zm-1.25 9.94 4.47-4.47a.75.75 0 0 1 1.133.976l-.073.084-5 5a.75.75 0 0 1-.976.073l-.084-.073-2.5-2.5a.75.75 0 0 1 .976-1.133l.084.073 1.97 1.97 4.47-4.47-4.47 4.47Z" fill="currentColor"/></svg>`;
|
||||||
export const ICON_SEND_TRANSCRIPT = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19.75 11.5a.75.75 0 0 1 .743.648l.007.102v5a4.75 4.75 0 0 1-4.533 4.745L15.75 22h-7.5c-.98 0-1.813-.626-2.122-1.5h9.622l.184-.005a3.25 3.25 0 0 0 3.06-3.06L19 17.25v-5a.75.75 0 0 1 .75-.75Zm-2.5-2a.75.75 0 0 1 .743.648l.007.102v7a2.25 2.25 0 0 1-2.096 2.245l-.154.005h-10a2.25 2.25 0 0 1-2.245-2.096L3.5 17.25v-7a.75.75 0 0 1 1.493-.102L5 10.25v7c0 .38.282.694.648.743L5.75 18h10a.75.75 0 0 0 .743-.648l.007-.102v-7a.75.75 0 0 1 .75-.75ZM6.218 6.216l3.998-3.996a.75.75 0 0 1 .976-.073l.084.072 4.004 3.997a.75.75 0 0 1-.976 1.134l-.084-.073-2.72-2.714v9.692a.75.75 0 0 1-.648.743l-.102.007a.75.75 0 0 1-.743-.648L10 14.255V4.556L7.279 7.277a.75.75 0 0 1-.977.072l-.084-.072a.75.75 0 0 1-.072-.977l.072-.084 3.998-3.996-3.998 3.996Z" fill="currentColor"/></svg>`;
|
export const ICON_SEND_TRANSCRIPT = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19.75 11.5a.75.75 0 0 1 .743.648l.007.102v5a4.75 4.75 0 0 1-4.533 4.745L15.75 22h-7.5c-.98 0-1.813-.626-2.122-1.5h9.622l.184-.005a3.25 3.25 0 0 0 3.06-3.06L19 17.25v-5a.75.75 0 0 1 .75-.75Zm-2.5-2a.75.75 0 0 1 .743.648l.007.102v7a2.25 2.25 0 0 1-2.096 2.245l-.154.005h-10a2.25 2.25 0 0 1-2.245-2.096L3.5 17.25v-7a.75.75 0 0 1 1.493-.102L5 10.25v7c0 .38.282.694.648.743L5.75 18h10a.75.75 0 0 0 .743-.648l.007-.102v-7a.75.75 0 0 1 .75-.75ZM6.218 6.216l3.998-3.996a.75.75 0 0 1 .976-.073l.084.072 4.004 3.997a.75.75 0 0 1-.976 1.134l-.084-.073-2.72-2.714v9.692a.75.75 0 0 1-.648.743l-.102.007a.75.75 0 0 1-.743-.648L10 14.255V4.556L7.279 7.277a.75.75 0 0 1-.977.072l-.084-.072a.75.75 0 0 1-.072-.977l.072-.084 3.998-3.996-3.998 3.996Z" fill="currentColor"/></svg>`;
|
||||||
export const ICON_SNOOZE_CONVERSATION = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.245 13.003a.75.75 0 0 1 .661 1.104l-.057.09-4.622 6.302h4.018a.75.75 0 0 1 .743.648l.007.102a.75.75 0 0 1-.649.743L8.245 22H2.748a.75.75 0 0 1-.662-1.104l.057-.09 4.621-6.302H2.75a.75.75 0 0 1-.743-.648l-.007-.102a.75.75 0 0 1 .648-.743l.102-.007h5.496ZM21.252 2c.6 0 .943.66.639 1.145l-.06.083-8.492 10.269h7.913a.75.75 0 0 1 .743.648l.007.102a.75.75 0 0 1-.648.743l-.102.007h-9.504a.75.75 0 0 1-.639-1.144l.06-.084 8.49-10.27-7.911.001a.75.75 0 0 1-.743-.648l-.007-.102a.75.75 0 0 1 .648-.743L11.748 2h9.504Z" fill="currentColor"/></svg>`;
|
export const ICON_SNOOZE_CONVERSATION = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c5.523 0 10 4.478 10 10s-4.477 10-10 10S2 17.522 2 12S6.477 2 12 2Zm0 1.667c-4.595 0-8.333 3.738-8.333 8.333c0 4.595 3.738 8.333 8.333 8.333c4.595 0 8.333-3.738 8.333-8.333c0-4.595-3.738-8.333-8.333-8.333ZM11.25 6a.75.75 0 0 1 .743.648L12 6.75V12h3.25a.75.75 0 0 1 .102 1.493l-.102.007h-4a.75.75 0 0 1-.743-.648l-.007-.102v-6a.75.75 0 0 1 .75-.75Z" fill="currentColor"/></svg>`;
|
||||||
export const ICON_SNOOZE_UNTIL_NEXT_REPLY = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M9.277 16.221a.75.75 0 0 1-1.061 1.06l-4.997-5.003a.75.75 0 0 1 0-1.06L8.217 6.22a.75.75 0 0 1 1.061 1.06L5.557 11h7.842c1.595 0 2.81.242 3.889.764l.246.126a6.203 6.203 0 0 1 2.576 2.576c.61 1.14.89 2.418.89 4.135a.75.75 0 0 1-1.5 0c0-1.484-.228-2.52-.713-3.428a4.702 4.702 0 0 0-1.96-1.96c-.838-.448-1.786-.676-3.094-.709L13.4 12.5H5.562l3.715 3.721Z" fill="currentColor"/></svg>`;
|
|
||||||
export const ICON_SNOOZE_UNTIL_NEXT_WEEK = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.75 7a.75.75 0 0 0-.75.75v4c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75v-4a.75.75 0 0 0-.75-.75h-8.5Zm.75 4V8.5h7V11h-7Z" fill="currentColor"/><path d="M17.75 21A3.25 3.25 0 0 0 21 17.75V6.25A3.25 3.25 0 0 0 17.75 3H6.25A3.25 3.25 0 0 0 3 6.25v11.5A3.25 3.25 0 0 0 6.25 21h11.5ZM19.5 6.25v11.5a1.75 1.75 0 0 1-1.75 1.75H6.25a1.75 1.75 0 0 1-1.75-1.75V6.25c0-.966.784-1.75 1.75-1.75h11.5c.966 0 1.75.784 1.75 1.75Z" fill="currentColor"/></svg>`;
|
export const ICON_SNOOZE_UNTIL_NEXT_WEEK = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.75 7a.75.75 0 0 0-.75.75v4c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75v-4a.75.75 0 0 0-.75-.75h-8.5Zm.75 4V8.5h7V11h-7Z" fill="currentColor"/><path d="M17.75 21A3.25 3.25 0 0 0 21 17.75V6.25A3.25 3.25 0 0 0 17.75 3H6.25A3.25 3.25 0 0 0 3 6.25v11.5A3.25 3.25 0 0 0 6.25 21h11.5ZM19.5 6.25v11.5a1.75 1.75 0 0 1-1.75 1.75H6.25a1.75 1.75 0 0 1-1.75-1.75V6.25c0-.966.784-1.75 1.75-1.75h11.5c.966 0 1.75.784 1.75 1.75Z" fill="currentColor"/></svg>`;
|
||||||
export const ICON_SNOOZE_UNTIL_TOMORRROW = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 8.744C7.847 8.362 8.415 8 9.25 8c1.152 0 1.894.792 2.155 1.661.253.847.1 1.895-.62 2.618a8.092 8.092 0 0 1-.793.67l-.04.031c-.28.216-.53.412-.75.63-.255.256-.464.535-.585.89h2.133a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1-.75-.75c0-1.247.524-2.083 1.144-2.701.296-.296.618-.545.89-.756l.003-.002c.286-.221.508-.393.685-.57.272-.274.367-.725.246-1.13-.115-.381-.37-.591-.718-.591-.353 0-.535.137-.64.253a.843.843 0 0 0-.148.229v.003a.75.75 0 0 1-1.428-.462l.035-.096a2.343 2.343 0 0 1 .43-.683ZM13.25 8a.75.75 0 0 1 .75.75v2.75h1.5V8.75a.75.75 0 0 1 1.5 0v6.47a.75.75 0 0 1-1.5 0V13h-2.25a.75.75 0 0 1-.75-.75v-3.5a.75.75 0 0 1 .75-.75Z" fill="currentColor"/><path d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12s4.477 10 10 10 10-4.477 10-10ZM3.5 12a8.5 8.5 0 1 1 17 0 8.5 8.5 0 0 1-17 0Z" fill="currentColor"/></svg>`;
|
export const ICON_SNOOZE_UNTIL_TOMORRROW = `<svg role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 8.744C7.847 8.362 8.415 8 9.25 8c1.152 0 1.894.792 2.155 1.661.253.847.1 1.895-.62 2.618a8.092 8.092 0 0 1-.793.67l-.04.031c-.28.216-.53.412-.75.63-.255.256-.464.535-.585.89h2.133a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1-.75-.75c0-1.247.524-2.083 1.144-2.701.296-.296.618-.545.89-.756l.003-.002c.286-.221.508-.393.685-.57.272-.274.367-.725.246-1.13-.115-.381-.37-.591-.718-.591-.353 0-.535.137-.64.253a.843.843 0 0 0-.148.229v.003a.75.75 0 0 1-1.428-.462l.035-.096a2.343 2.343 0 0 1 .43-.683ZM13.25 8a.75.75 0 0 1 .75.75v2.75h1.5V8.75a.75.75 0 0 1 1.5 0v6.47a.75.75 0 0 1-1.5 0V13h-2.25a.75.75 0 0 1-.75-.75v-3.5a.75.75 0 0 1 .75-.75Z" fill="currentColor"/><path d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12s4.477 10 10 10 10-4.477 10-10ZM3.5 12a8.5 8.5 0 1 1 17 0 8.5 8.5 0 0 1-17 0Z" fill="currentColor"/></svg>`;
|
||||||
export const ICON_CONVERSATION_DASHBOARD = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none"><path d="M10.55 2.532a2.25 2.25 0 0 1 2.9 0l6.75 5.692c.507.428.8 1.057.8 1.72v9.803a1.75 1.75 0 0 1-1.75 1.75h-3.5a1.75 1.75 0 0 1-1.75-1.75v-5.5a.25.25 0 0 0-.25-.25h-3.5a.25.25 0 0 0-.25.25v5.5a1.75 1.75 0 0 1-1.75 1.75h-3.5A1.75 1.75 0 0 1 3 19.747V9.944c0-.663.293-1.292.8-1.72l6.75-5.692zm1.933 1.147a.75.75 0 0 0-.966 0L4.767 9.37a.75.75 0 0 0-.267.573v9.803c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-5.5c0-.967.784-1.75 1.75-1.75h3.5c.966 0 1.75.783 1.75 1.75v5.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25V9.944a.75.75 0 0 0-.267-.573l-6.75-5.692z" fill="currentColor"></path></g></svg>`;
|
export const ICON_CONVERSATION_DASHBOARD = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="ninja-icon ninja-icon--fluent" width="18" height="18" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none"><path d="M10.55 2.532a2.25 2.25 0 0 1 2.9 0l6.75 5.692c.507.428.8 1.057.8 1.72v9.803a1.75 1.75 0 0 1-1.75 1.75h-3.5a1.75 1.75 0 0 1-1.75-1.75v-5.5a.25.25 0 0 0-.25-.25h-3.5a.25.25 0 0 0-.25.25v5.5a1.75 1.75 0 0 1-1.75 1.75h-3.5A1.75 1.75 0 0 1 3 19.747V9.944c0-.663.293-1.292.8-1.72l6.75-5.692zm1.933 1.147a.75.75 0 0 0-.966 0L4.767 9.37a.75.75 0 0 0-.267.573v9.803c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-5.5c0-.967.784-1.75 1.75-1.75h3.5c.966 0 1.75.783 1.75 1.75v5.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25V9.944a.75.75 0 0 0-.267-.573l-6.75-5.692z" fill="currentColor"></path></g></svg>`;
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ import {
|
|||||||
ICON_RESOLVE_CONVERSATION,
|
ICON_RESOLVE_CONVERSATION,
|
||||||
ICON_SEND_TRANSCRIPT,
|
ICON_SEND_TRANSCRIPT,
|
||||||
ICON_SNOOZE_CONVERSATION,
|
ICON_SNOOZE_CONVERSATION,
|
||||||
ICON_SNOOZE_UNTIL_NEXT_REPLY,
|
|
||||||
ICON_SNOOZE_UNTIL_NEXT_WEEK,
|
|
||||||
ICON_SNOOZE_UNTIL_TOMORRROW,
|
|
||||||
ICON_UNMUTE_CONVERSATION,
|
ICON_UNMUTE_CONVERSATION,
|
||||||
ICON_PRIORITY_URGENT,
|
ICON_PRIORITY_URGENT,
|
||||||
ICON_PRIORITY_HIGH,
|
ICON_PRIORITY_HIGH,
|
||||||
@@ -31,6 +28,8 @@ import {
|
|||||||
ICON_PRIORITY_NONE,
|
ICON_PRIORITY_NONE,
|
||||||
} from './CommandBarIcons';
|
} from './CommandBarIcons';
|
||||||
|
|
||||||
|
const SNOOZE_OPTIONS = wootConstants.SNOOZE_OPTIONS;
|
||||||
|
|
||||||
const OPEN_CONVERSATION_ACTIONS = [
|
const OPEN_CONVERSATION_ACTIONS = [
|
||||||
{
|
{
|
||||||
id: 'resolve_conversation',
|
id: 'resolve_conversation',
|
||||||
@@ -39,32 +38,60 @@ const OPEN_CONVERSATION_ACTIONS = [
|
|||||||
icon: ICON_RESOLVE_CONVERSATION,
|
icon: ICON_RESOLVE_CONVERSATION,
|
||||||
handler: () => bus.$emit(CMD_RESOLVE_CONVERSATION),
|
handler: () => bus.$emit(CMD_RESOLVE_CONVERSATION),
|
||||||
},
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const SNOOZE_CONVERSATION_ACTIONS = [
|
||||||
{
|
{
|
||||||
id: 'snooze_conversation',
|
id: 'snooze_conversation',
|
||||||
title: 'COMMAND_BAR.COMMANDS.SNOOZE_CONVERSATION',
|
title: 'COMMAND_BAR.COMMANDS.SNOOZE_CONVERSATION',
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
children: ['until_next_reply', 'until_tomorrow', 'until_next_week'],
|
children: Object.values(SNOOZE_OPTIONS),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: 'until_next_reply',
|
id: SNOOZE_OPTIONS.UNTIL_NEXT_REPLY,
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_REPLY',
|
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_REPLY',
|
||||||
parent: 'snooze_conversation',
|
parent: 'snooze_conversation',
|
||||||
icon: ICON_SNOOZE_UNTIL_NEXT_REPLY,
|
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
||||||
handler: () => bus.$emit(CMD_SNOOZE_CONVERSATION, 'nextReply'),
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
|
handler: () =>
|
||||||
|
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_NEXT_REPLY),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'until_tomorrow',
|
id: SNOOZE_OPTIONS.AN_HOUR_FROM_NOW,
|
||||||
|
title: 'COMMAND_BAR.COMMANDS.AN_HOUR_FROM_NOW',
|
||||||
|
parent: 'snooze_conversation',
|
||||||
|
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
||||||
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
|
handler: () =>
|
||||||
|
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.AN_HOUR_FROM_NOW),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: SNOOZE_OPTIONS.UNTIL_TOMORROW,
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_TOMORROW',
|
title: 'COMMAND_BAR.COMMANDS.UNTIL_TOMORROW',
|
||||||
|
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
||||||
parent: 'snooze_conversation',
|
parent: 'snooze_conversation',
|
||||||
icon: ICON_SNOOZE_UNTIL_TOMORRROW,
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
handler: () => bus.$emit(CMD_SNOOZE_CONVERSATION, 'tomorrow'),
|
handler: () =>
|
||||||
|
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_TOMORROW),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'until_next_week',
|
id: SNOOZE_OPTIONS.UNTIL_NEXT_WEEK,
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_WEEK',
|
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_WEEK',
|
||||||
|
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
||||||
parent: 'snooze_conversation',
|
parent: 'snooze_conversation',
|
||||||
icon: ICON_SNOOZE_UNTIL_NEXT_WEEK,
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
handler: () => bus.$emit(CMD_SNOOZE_CONVERSATION, 'nextWeek'),
|
handler: () =>
|
||||||
|
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_NEXT_WEEK),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: SNOOZE_OPTIONS.UNTIL_NEXT_MONTH,
|
||||||
|
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_MONTH',
|
||||||
|
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
||||||
|
parent: 'snooze_conversation',
|
||||||
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
|
handler: () =>
|
||||||
|
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_NEXT_MONTH),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -135,6 +162,7 @@ export default {
|
|||||||
conversationId() {
|
conversationId() {
|
||||||
return this.currentChat?.id;
|
return this.currentChat?.id;
|
||||||
},
|
},
|
||||||
|
|
||||||
statusActions() {
|
statusActions() {
|
||||||
const isOpen =
|
const isOpen =
|
||||||
this.currentChat?.status === wootConstants.STATUS_TYPE.OPEN;
|
this.currentChat?.status === wootConstants.STATUS_TYPE.OPEN;
|
||||||
@@ -145,7 +173,10 @@ export default {
|
|||||||
|
|
||||||
let actions = [];
|
let actions = [];
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
actions = OPEN_CONVERSATION_ACTIONS;
|
actions = [
|
||||||
|
...OPEN_CONVERSATION_ACTIONS,
|
||||||
|
...SNOOZE_CONVERSATION_ACTIONS,
|
||||||
|
];
|
||||||
} else if (isResolved || isSnoozed) {
|
} else if (isResolved || isSnoozed) {
|
||||||
actions = RESOLVED_CONVERSATION_ACTIONS;
|
actions = RESOLVED_CONVERSATION_ACTIONS;
|
||||||
}
|
}
|
||||||
@@ -296,6 +327,7 @@ export default {
|
|||||||
SEND_TRANSCRIPT_ACTION,
|
SEND_TRANSCRIPT_ACTION,
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
conversationHotKeys() {
|
conversationHotKeys() {
|
||||||
if (isAConversationRoute(this.$route.name)) {
|
if (isAConversationRoute(this.$route.name)) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
Reference in New Issue
Block a user