Add more changes
This commit is contained in:
@@ -9,6 +9,15 @@
|
||||
@click="openAIAssist"
|
||||
/>
|
||||
|
||||
<!-- <woot-button
|
||||
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.TITLE')"
|
||||
icon="text-grammar-wand"
|
||||
color-scheme="secondary"
|
||||
variant="smooth"
|
||||
size="small"
|
||||
@click="toggleDropdown"
|
||||
/> -->
|
||||
|
||||
<div v-if="!message">
|
||||
<!-- <woot-button
|
||||
v-if="isPrivateNote"
|
||||
@@ -32,51 +41,53 @@
|
||||
/> -->
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<!-- <woot-button
|
||||
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.TITLE')"
|
||||
icon="text-grammar-wand"
|
||||
color-scheme="secondary"
|
||||
variant="smooth"
|
||||
size="small"
|
||||
@click="toggleDropdown"
|
||||
/> -->
|
||||
|
||||
<div
|
||||
v-if="showDropdown"
|
||||
v-on-clickaway="closeDropdown"
|
||||
class="dropdown-pane dropdown-pane--open ai-modal"
|
||||
>
|
||||
<h4 class="sub-block-title margin-top-1">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TITLE') }}
|
||||
</h4>
|
||||
<p>
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.SUBTITLE') }}
|
||||
</p>
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TONE.TITLE') }}
|
||||
</label>
|
||||
<div class="tone__item">
|
||||
<select v-model="activeTone" class="status--filter small">
|
||||
<option v-for="tone in tones" :key="tone.key" :value="tone.key">
|
||||
{{ tone.value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="modal-footer flex-container align-right">
|
||||
<woot-button variant="clear" size="small" @click="closeDropdown">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.BUTTONS.CANCEL') }}
|
||||
</woot-button>
|
||||
<woot-button
|
||||
:is-loading="uiFlags.rephrase"
|
||||
size="small"
|
||||
@click="processEvent('rephrase')"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</woot-button>
|
||||
</div>
|
||||
<div
|
||||
v-if="showDropdown"
|
||||
v-on-clickaway="closeDropdown"
|
||||
class="dropdown-pane dropdown-pane--open ai-modal"
|
||||
>
|
||||
<h4 class="sub-block-title margin-top-1">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TITLE') }}
|
||||
</h4>
|
||||
<p>
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.SUBTITLE') }}
|
||||
</p>
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TONE.TITLE') }}
|
||||
</label>
|
||||
<div class="tone__item">
|
||||
<select v-model="activeTone" class="status--filter small">
|
||||
<option v-for="tone in tones" :key="tone.key" :value="tone.key">
|
||||
{{ tone.value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="modal-footer flex-container align-right">
|
||||
<woot-button variant="clear" size="small" @click="closeDropdown">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.BUTTONS.CANCEL') }}
|
||||
</woot-button>
|
||||
<woot-button
|
||||
:is-loading="uiFlags.rephrase"
|
||||
size="small"
|
||||
@click="processEvent('rephrase')"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</woot-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<woot-modal
|
||||
:show.sync="showAIAssistanceModal"
|
||||
:on-close="hideAIAssistanceModal"
|
||||
>
|
||||
<AIAssistanceModal @close="hideAIAssistanceModal" />
|
||||
</woot-modal>
|
||||
<woot-modal
|
||||
:show.sync="showAIAssistanceReply"
|
||||
:on-close="hideAIAssistanceReplyModal"
|
||||
>
|
||||
<AIAssistanceReply @close="hideAIAssistanceReplyModal" />
|
||||
</woot-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -86,8 +97,14 @@ import OpenAPI from 'dashboard/api/integrations/openapi';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
import { CMD_AI_ASSIST } from '../../routes/dashboard/commands/commandBarBusEvents';
|
||||
import AIAssistanceModal from './AIAssistanceModal.vue';
|
||||
import AIAssistanceReply from './AIAssistanceReply.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AIAssistanceModal,
|
||||
AIAssistanceReply,
|
||||
},
|
||||
mixins: [alertMixin, clickaway],
|
||||
props: {
|
||||
conversationId: {
|
||||
@@ -105,6 +122,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAIAssistanceModal: false,
|
||||
showAIAssistanceReply: false,
|
||||
uiFlags: {
|
||||
rephrase: false,
|
||||
reply_suggestion: false,
|
||||
@@ -154,14 +173,19 @@ export default {
|
||||
bus.$off(CMD_AI_ASSIST, this.onAIAssist);
|
||||
},
|
||||
methods: {
|
||||
hideAIAssistanceReplyModal() {
|
||||
this.showAIAssistanceReply = false;
|
||||
},
|
||||
hideAIAssistanceModal() {
|
||||
this.showAIAssistanceModal = false;
|
||||
},
|
||||
openAIAssist() {
|
||||
const ninja = document.querySelector('ninja-keys');
|
||||
ninja.open({ parent: 'ai_assist' });
|
||||
},
|
||||
onAIAssist() {
|
||||
// this.$track(OPEN_AI_EVENTS.AI_ASSIST);
|
||||
// this.openAIAssist();
|
||||
// console.log('onAIAssist', action);
|
||||
this.showAIAssistanceModal = true;
|
||||
// this.showAIAssistanceReply = true;
|
||||
},
|
||||
toggleDropdown() {
|
||||
this.showDropdown = !this.showDropdown;
|
||||
|
||||
@@ -1,22 +1,59 @@
|
||||
<template>
|
||||
<div class="column">
|
||||
<woot-modal-header :header-title="$t('CONVERSATION.CUSTOM_SNOOZE.TITLE')" />
|
||||
<woot-modal-header header-title="Rephrase the content" />
|
||||
<form class="row modal-content" @submit.prevent="chooseTime">
|
||||
<date-picker
|
||||
v-model="snoozeTime"
|
||||
type="datetime"
|
||||
inline
|
||||
:lang="lang"
|
||||
:disabled-date="disabledDate"
|
||||
:disabled-time="disabledTime"
|
||||
:popup-style="{ width: '100%' }"
|
||||
/>
|
||||
<div>
|
||||
<h4 class="sub-block-title margin-top-1">
|
||||
Draft content
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
{{ draftContent }}
|
||||
</p>
|
||||
<div class="container">
|
||||
<h4 class="sub-block-title margin-top-1">
|
||||
AI generated content
|
||||
</h4>
|
||||
</div>
|
||||
<!-- <TypingIndicator /> -->
|
||||
<div class="animation-container">
|
||||
<label>AI is typing</label> <span class="loader" />
|
||||
</div>
|
||||
<!-- <div class="loading loading04">
|
||||
<label>AI is typing</label>
|
||||
<span>.</span>
|
||||
<span>.</span>
|
||||
<span>.</span>
|
||||
</div> -->
|
||||
|
||||
<!-- <div v-else>
|
||||
<p>
|
||||
{{ aiContent }}
|
||||
</p>
|
||||
</div> -->
|
||||
|
||||
<div class="modal-footer justify-content-end w-full">
|
||||
<!-- <woot-button
|
||||
icon="delete-outline"
|
||||
variant="clear"
|
||||
@click.prevent="onClose"
|
||||
>
|
||||
Discard
|
||||
</woot-button> -->
|
||||
<woot-button variant="clear" @click.prevent="onClose">
|
||||
{{ this.$t('CONVERSATION.CUSTOM_SNOOZE.CANCEL') }}
|
||||
Discard
|
||||
</woot-button>
|
||||
<woot-button>
|
||||
{{ this.$t('CONVERSATION.CUSTOM_SNOOZE.APPLY') }}
|
||||
<!-- <woot-button
|
||||
v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')"
|
||||
color-scheme="alert"
|
||||
variant="clear"
|
||||
icon="arrow-clockwise"
|
||||
:disabled="!enableButtons"
|
||||
>Retry
|
||||
</woot-button> -->
|
||||
<woot-button :disabled="!enableButtons">
|
||||
Apply
|
||||
</woot-button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -24,52 +61,119 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import TypingIndicator from './TypingIndicator.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DatePicker,
|
||||
TypingIndicator,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
snoozeTime: null,
|
||||
lang: {
|
||||
days: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMMM',
|
||||
},
|
||||
draftContent:
|
||||
'I am closing this thread as there is no response. Please feel to create a new one if the issue/query is not resolved.',
|
||||
generatedContent: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
aiContent() {
|
||||
return this.generatedContent.length > 0
|
||||
? this.generatedContent
|
||||
: 'Generating content...';
|
||||
},
|
||||
enableButtons() {
|
||||
return this.generatedContent.length > 0;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this.generatedContent =
|
||||
'I am closing this thread as there has been no response. Please feel free to create a new thread if the issue or query remains unresolved.';
|
||||
}, 6000);
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('close');
|
||||
},
|
||||
chooseTime() {
|
||||
this.$emit('choose-time', this.snoozeTime);
|
||||
},
|
||||
disabledDate(date) {
|
||||
// Disable all the previous dates
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
return date < yesterday;
|
||||
},
|
||||
disabledTime(date) {
|
||||
// Allow only time after 1 hour
|
||||
const now = new Date();
|
||||
now.setHours(now.getHours() + 1);
|
||||
return date < now;
|
||||
},
|
||||
chooseTime() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-footer {
|
||||
padding: var(--space-two);
|
||||
}
|
||||
.modal-content {
|
||||
padding: var(--space-small) var(--space-two) var(--space-zero);
|
||||
padding-top: var(--space-small);
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.animation-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
label {
|
||||
width: 8rem;
|
||||
}
|
||||
}
|
||||
.loader {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
position: relative;
|
||||
color: #000;
|
||||
box-sizing: border-box;
|
||||
animation: animloader 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes animloader {
|
||||
0% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 -2px;
|
||||
}
|
||||
25% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 2px;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 2px, -38px 0 0 -2px;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 14px 0 0 2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 -2px;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 2px, -14px 0 0 -2px, -38px 0 0 -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
span {
|
||||
display: inline-block;
|
||||
margin: 0 -0.05em;
|
||||
}
|
||||
}
|
||||
|
||||
.loading04 {
|
||||
span {
|
||||
animation: loading04 0.7s infinite;
|
||||
@for $i from 1 through 6 {
|
||||
&:nth-child(#{$i + 1}) {
|
||||
animation-delay: #{$i * 0.1}s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes loading04 {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(15px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div class="column">
|
||||
<woot-modal-header header-title="Reply suggestion with AI" />
|
||||
<form class="row modal-content" @submit.prevent="chooseTime">
|
||||
<div v-if="!generatedContent" class="animation-container">
|
||||
<span class="loader" />
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<p>
|
||||
{{ aiContent }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer justify-content-end w-full">
|
||||
<!-- <woot-button
|
||||
icon="delete-outline"
|
||||
variant="clear"
|
||||
@click.prevent="onClose"
|
||||
>
|
||||
Discard
|
||||
</woot-button> -->
|
||||
<woot-button variant="clear" @click.prevent="onClose">
|
||||
Discard
|
||||
</woot-button>
|
||||
<!-- <woot-button
|
||||
v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')"
|
||||
color-scheme="alert"
|
||||
variant="clear"
|
||||
icon="arrow-clockwise"
|
||||
:disabled="!enableButtons"
|
||||
>Retry
|
||||
</woot-button> -->
|
||||
<woot-button :disabled="!enableButtons">
|
||||
Apply
|
||||
</woot-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
draftContent:
|
||||
'I am closing this thread as there is no response. Please feel to create a new one if the issue/query is not resolved.',
|
||||
generatedContent: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
aiContent() {
|
||||
return this.generatedContent.length > 0
|
||||
? this.generatedContent
|
||||
: 'Generating content...';
|
||||
},
|
||||
enableButtons() {
|
||||
return this.generatedContent.length > 0;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this.generatedContent =
|
||||
'Hi there! Its great to see you here. How can I be of assistance to you today? Whether you need help with a specific task or have a general question, I am here to lend a hand. Let me know what you need, and I will do my best to provide you with the information or guidance you are looking for.';
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('close');
|
||||
},
|
||||
chooseTime() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-content {
|
||||
padding-top: var(--space-small);
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.animation-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.loader {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
margin-top: 2rem;
|
||||
position: relative;
|
||||
color: #000;
|
||||
box-sizing: border-box;
|
||||
animation: animloader 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes animloader {
|
||||
0% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 -2px;
|
||||
}
|
||||
25% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 2px;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 2px, -38px 0 0 -2px;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 14px 0 0 2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 -2px;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 14px 0 0 -2px, 38px 0 0 2px, -14px 0 0 -2px, -38px 0 0 -2px;
|
||||
}
|
||||
}
|
||||
|
||||
// .typewriter p {
|
||||
// overflow: hidden; /* Ensures the content is not revealed until the animation */
|
||||
// border-right: 0.15em solid orange; /* The typwriter cursor */
|
||||
// margin: 0 auto; /* Gives that scrolling effect as the typing happens */
|
||||
// animation: typing 3.5s steps(30, end), blink-caret 0.5s step-end infinite;
|
||||
// }
|
||||
|
||||
// /* The typing effect */
|
||||
// @keyframes typing {
|
||||
// from {
|
||||
// width: 0;
|
||||
// }
|
||||
// to {
|
||||
// width: 100%;
|
||||
// }
|
||||
// }
|
||||
|
||||
// @keyframes blink-caret {
|
||||
// from,
|
||||
// to {
|
||||
// border-color: transparent;
|
||||
// }
|
||||
// 50% {
|
||||
// border-color: orange;
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="typing-indicator">
|
||||
<label>AI is typing</label>
|
||||
<div class="typing">
|
||||
<span class="circle scaling" />
|
||||
<span class="circle scaling" />
|
||||
<span class="circle scaling" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.typing-indicator {
|
||||
color: #282d3e;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
width: fit-content;
|
||||
|
||||
.typing {
|
||||
display: block;
|
||||
width: 36px;
|
||||
height: 16px;
|
||||
border-radius: 20px;
|
||||
margin: 0 4px 0 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.circle {
|
||||
display: block;
|
||||
height: 6px;
|
||||
width: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: #000;
|
||||
margin: 3px;
|
||||
|
||||
&.scaling {
|
||||
animation: typing 1000ms ease-in-out infinite;
|
||||
animation-delay: 3600ms;
|
||||
}
|
||||
|
||||
&.bouncing {
|
||||
animation: bounce 1000ms ease-in-out infinite;
|
||||
animation-delay: 3600ms;
|
||||
}
|
||||
.circle:nth-child(1) {
|
||||
animation-delay: 0ms;
|
||||
}
|
||||
|
||||
.circle:nth-child(2) {
|
||||
animation-delay: 333ms;
|
||||
}
|
||||
|
||||
.circle:nth-child(3) {
|
||||
animation-delay: 666ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes typing {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
33% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user