added toast with copy to clipboard

This commit is contained in:
andzejsp 2023-05-07 15:40:57 +03:00
parent fdf334237c
commit 38b8fbdecc
3 changed files with 110 additions and 29 deletions

View File

@ -21,7 +21,7 @@
<i data-feather="edit"></i>
</div>
<div class="text-lg hover:text-secondary duration-75 active:scale-90 p-2"
title="Copy message to clipboard">
title="Copy message to clipboard" @click.stop="copyContentToClipboard()">
<i data-feather="copy"></i>
</div>
<div class="text-lg hover:text-secondary duration-75 active:scale-90 p-2"
@ -55,6 +55,7 @@ import feather from 'feather-icons'
import MarkdownRenderer from './MarkdownRenderer.vue';
export default {
name: 'Message',
emits: ['copy'],
components: {
MarkdownRenderer
},
@ -71,6 +72,11 @@ export default {
feather.replace()
})
},
},methods:{
copyContentToClipboard(){
this.$emit('copy', this.message.content)
navigator.clipboard.writeText(this.message.content);
}
}
}
</script>

View File

@ -0,0 +1,57 @@
<template>
<div v-if="show" class="absolute bottom-16 right-2 z-20">
<div id="toast-success"
class="flex items-center w-full max-w-xs p-4 mb-4 text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800"
role="alert">
<div class="flex flex-row">
<slot>
</slot>
</div>
<button type="button" @click="close"
class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"
data-dismiss-target="#toast-success" aria-label="Close">
<span class="sr-only">Close</span>
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</button>
</div>
</div>
</template>
<script>
export default {
name: 'Toast',
emits: ['close'],
props: {
showProp: false
},
data() {
return {
show: false,
};
},
methods: {
close() {
this.$emit('close')
this.show = false
}
},
watch: {
showProp(val) {
this.show = val
if (val) {
setTimeout(() => {
this.$emit('close')
this.show = false
}, 3000);
}
}
}
}
</script>

View File

@ -110,7 +110,7 @@
<!-- CHAT AREA -->
<div class="flex flex-col flex-grow">
<Message v-for="(msg, index) in discussionArr" :key="index" :message="msg"
@click="scrollToElement($event.target)" :id="'msg-' + msg.id" ref="messages" />
@click="scrollToElement($event.target)" :id="'msg-' + msg.id" ref="messages" @copy="copyToClipBoard" />
<WelcomeComponent v-if="!currentDiscussion.id" />
@ -122,6 +122,14 @@
</div>
</div>
<Toast :showProp="isCopiedToClipboard" @close="isCopiedToClipboard = false">
<div
class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
<i data-feather="check"></i>
<span class="sr-only">Check icon</span>
</div>
<div class="ml-3 text-sm font-normal">Message content copied to clipboard!</div>
</Toast>
</template>
<style scoped>
.height-64 {
@ -146,8 +154,8 @@ export default {
isCheckbox: false,
isSelectAll: false,
showConfirmation: false,
chime: new Audio("chime_aud.wav")
chime: new Audio("chime_aud.wav"),
isCopiedToClipboard: false
}
},
methods: {
@ -296,7 +304,7 @@ export default {
}
},
scrollToElement(el) {
if (el) {
el.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
} else {
@ -304,7 +312,7 @@ export default {
}
},
scrollBottom(el) {
if (el) {
el.scrollTo(
{
@ -315,7 +323,7 @@ export default {
} else {
console.log("Error: scrollBottom")
}
},
createUserMsg(msgObj) {
let usrMessage = {
@ -374,28 +382,28 @@ export default {
this.isGenerating = true;
this.setDiscussionLoading(this.currentDiscussion.id, this.isGenerating);
axios.get('/get_generation_status', {}).then((res) => {
if (res) {
console.log(res.data.status);
if(!res.data.status){
socket.emit('generate_msg', { prompt: msg });
if (res) {
console.log(res.data.status);
if (!res.data.status) {
socket.emit('generate_msg', { prompt: msg });
// Create new User message
// Temp data
let usrMessage = {
message: msg,
id: this.discussionArr[this.discussionArr.length - 1].id + 1,
rank: 0,
user: "user"
};
this.createUserMsg(usrMessage);
// Create new User message
// Temp data
let usrMessage = {
message: msg,
id: this.discussionArr[this.discussionArr.length - 1].id + 1,
rank: 0,
user: "user"
};
this.createUserMsg(usrMessage);
}
else {
console.log("Already generating");
}
}
else{
console.log("Already generating");
}
}
}).catch((error) => {
console.log("Error: Could not get generation status", error);
console.log("Error: Could not get generation status", error);
});
},
steamMessageContent(content) {
@ -559,8 +567,16 @@ export default {
this.setDiscussionLoading(this.currentDiscussion.id, this.isGenerating)
this.chime.play()
},
copyToClipBoard(){
copyToClipBoard(content) {
this.isCopiedToClipboard = true
nextTick(() => {
feather.replace()
})
},
closeToast() {
this.isCopiedToClipboard = false
}
},
async created() {
@ -597,7 +613,8 @@ export default {
Discussion,
Message,
ChatBox,
WelcomeComponent
WelcomeComponent,
Toast
},
watch: {
filterTitle(newVal) {
@ -646,6 +663,7 @@ import Discussion from '../components/Discussion.vue'
import Message from '../components/Message.vue'
import ChatBox from '../components/ChatBox.vue'
import WelcomeComponent from '../components/WelcomeComponent.vue'
import Toast from '../components/Toast.vue'
import feather from 'feather-icons'