Mike Liao 2024-07-03 14:05:30 -07:00
commit 3ae84ce548
6 changed files with 123 additions and 64 deletions

View File

@ -4,7 +4,7 @@
<div <div
class="information-bar" class="information-bar"
@click="gotoMessages" @click="gotoMessages"
:class="{ active: activePath == 'message', unread: unreadCount > 0 }" :class="{ active: activePath == 'message', unread: unreadConversationCount > 0 }"
> >
<img alt="freeleaps logo" src="@/assets/message.png" /> <img alt="freeleaps logo" src="@/assets/message.png" />
</div> </div>
@ -94,9 +94,8 @@ export default {
name: 'HeaderGuest', name: 'HeaderGuest',
components: { LaguageSwitch }, components: { LaguageSwitch },
computed: { computed: {
unreadCount() { unreadConversationCount() {
console.log('unreadCount', this.$store.getters['basic/unreadCount']) return this.$store.getters['basic/unreadConversationCount']
return this.$store.getters['basic/unreadCount']
} }
}, },
created() { created() {

View File

@ -13,6 +13,7 @@
</div> </div>
</template> </template>
<script> <script>
import cover_picture from '@/assets/images/lab-translation.png'
export default { export default {
name: 'LabHome', name: 'LabHome',
components: {}, components: {},
@ -31,7 +32,7 @@ export default {
title_text: 'Machine Translation', title_text: 'Machine Translation',
summary_text: 'Translate lanuages leverage AI power', summary_text: 'Translate lanuages leverage AI power',
icon_picture: '', icon_picture: '',
cover_picture: 'src/assets/images/lab-translation.png' cover_picture: cover_picture
} }
] ]
} }

View File

@ -7,7 +7,7 @@
:key="index" :key="index"
class="conversation-container" class="conversation-container"
:class="{ :class="{
selected: selConversation.id === conversation.id selected: selConversation?.id === conversation?.id
}" }"
@click="selectConversation(conversation)" @click="selectConversation(conversation)"
> >
@ -22,9 +22,9 @@
}}</span> }}</span>
<!-- <span v-if="unreadCountMapper" class="conversation-unreadcount">{{unreadCountMapper}}</span> --> <!-- <span v-if="unreadCountMapper" class="conversation-unreadcount">{{unreadCountMapper}}</span> -->
</div> </div>
<!-- <div class="conversation-summary-highlight-container"> <div class="conversation-summary-highlight-container">
{{ conversation.summary.last_message?.message_body }} {{ conversation.last_message?.message_body }}
</div> --> </div>
</div> </div>
</div> </div>
</div> </div>
@ -78,12 +78,13 @@
<script> <script>
import SvgIcon from '@/components/SvgIcon.vue' import SvgIcon from '@/components/SvgIcon.vue'
import { MessageHubApi, DateUtils } from '@/utils/index' import { MessageHubApi, DateUtils } from '@/utils/index'
import { userUtils } from '@/utils/store/index'
export default { export default {
components: { SvgIcon }, components: { SvgIcon },
name: 'MessageHub', name: 'MessageHub',
props: {}, props: {},
mounted() { mounted() {
this.fetchConversations() // this.fetchConversations()
}, },
// watch: { // watch: {
// conversations: { // conversations: {
@ -99,39 +100,51 @@ export default {
data() { data() {
return { return {
userIdentityNote: this.mnx_getUserIdentity(), userIdentityNote: this.mnx_getUserIdentity(),
conversations: [], // conversations: [],
selConversation: null, selConversation: null,
messages: [], messages: [],
writtenMessage: null writtenMessage: null
} }
}, },
computed: { computed: {
unreadCountMapper() { conversations() {
if (this.selConversation) { return this.$store.getters['basic/conversations']
return this.$store.getters['basic/unreadCountMapper'] },
},
watch: {
conversations(n_val) {
if (!this.selConversation && n_val[0]) {
this.selConversation = n_val[0]
this.messages = n_val[0].messages || []
this.clearUnreadMessageBy(n_val[0])
} else { } else {
return 0 if (this.selConversation.id === n_val?.[0]?.id) {
this.messages = n_val[0].messages || []
this.clearUnreadMessageBy(n_val[0])
}
} }
} }
}, },
methods: { methods: {
fetchConversations() { // fetchConversations() {
MessageHubApi.fetchConversations(new Date('01 Jan 1970 00:00:00 GMT').toISOString()) // MessageHubApi.fetchConversations(new Date('01 Jan 1970 00:00:00 GMT').toISOString())
.then((response) => { // .then((response) => {
const conversations = response.data.conversations || [] // const conversations = response.data.conversations || []
this.conversations = conversations // this.conversations = conversations
if (conversations.length > 0) { // if (conversations.length > 0) {
this.selectConversation(conversations[0]) // this.selectConversation(conversations[0])
} // }
}) // })
.catch((error) => { // .catch((error) => {
this.mnx_backendErrorHandler(error) // this.mnx_backendErrorHandler(error)
}) // })
}, // },
fetchMessageForConversation(conversation_id) { fetchMessageForConversation(conversation_id) {
const jwt = userUtils.getJwtToken()
MessageHubApi.fetchMessages( MessageHubApi.fetchMessages(
conversation_id, conversation_id,
new Date('01 Jan 1975 00:00:00 GMT').toISOString() new Date('01 Jan 1975 00:00:00 GMT').toISOString(),
jwt
) )
.then((response) => { .then((response) => {
this.messages = response?.data || [] this.messages = response?.data || []
@ -147,14 +160,13 @@ export default {
this.clearUnreadMessageBy(conversation) this.clearUnreadMessageBy(conversation)
}, },
clearUnreadMessageBy(current) { clearUnreadMessageBy(current) {
const sender = current.initiator_id if (current.unread) {
if (sender) { this.$store.dispatch('basic/readMessageBy', current.id)
console.log('clear unread message by:', current)
this.$store.dispatch('basic/readMessageBy', sender)
} }
}, },
sendMessage(conversation_id) { sendMessage(conversation_id) {
MessageHubApi.sendMessageToConversation(conversation_id, this.writtenMessage) const jwt = userUtils.getJwtToken()
MessageHubApi.sendMessageToConversation(conversation_id, this.writtenMessage, jwt)
.then((response) => { .then((response) => {
let new_message = response.data let new_message = response.data
this.messages.push({ this.messages.push({
@ -230,6 +242,7 @@ export default {
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
text-align: left;
} }
.conversation-last-update-date { .conversation-last-update-date {

View File

@ -720,7 +720,7 @@ export default {
return this.$t('Proposals') return this.$t('Proposals')
case projectStatusEnum.PENDING: case projectStatusEnum.PENDING:
case projectStatusEnum.REJECTED: case projectStatusEnum.REJECTED:
return this.$('Issuer') return this.$t('Issuer')
case projectStatusEnum.ONGOING: case projectStatusEnum.ONGOING:
return this.$t('Milestone(s)') return this.$t('Milestone(s)')
default: default:

View File

@ -1,13 +1,19 @@
/* eslint-disable no-prototype-builtins */ /* eslint-disable no-prototype-builtins */
import { i18n } from '@/lang' import { i18n } from '@/lang'
import { WsConnectionFactory } from '@/utils/backend/websocket' import { WsConnectionFactory } from '@/utils/backend/websocket'
import { MessageHubApi } from '@/utils/backend/messageHub'
const ignoreEventType = ['test']
const GWT = new Date('01 Jan 1970 00:00:00 GMT').toISOString()
const basicStore = { const basicStore = {
namespaced: true, namespaced: true,
state() { state() {
return { return {
language: 'zh', language: 'zh',
unreadCountMapper: [], conversations: [],
unreadConversationCount: 0,
// conversation_update_time: null,
downstream_web_socket: null downstream_web_socket: null
} }
}, },
@ -29,16 +35,53 @@ const basicStore = {
}, },
(e) => { (e) => {
const data = JSON.parse(e.data) const data = JSON.parse(e.data)
let unread = state.unreadCountMapper[data.sender_id] // console.log('downstream_web_socket onmessage: ', data)
if (unread) { if (ignoreEventType.indexOf(data.event) !== -1) {
unread++ return
} else {
unread = 1
} }
const ucm = Object.assign({}, state.unreadCountMapper)
ucm[data.sender_id] = unread if (data.event === 'connected') {
state.unreadCountMapper = ucm // 读取缓存
console.log('downstream_web_socket onmessage: ', data, state.unreadCountMapper) let local_conversations, local_unreadConversationCount
try {
local_conversations = JSON.parse(localStorage.getItem('conversations'))
local_unreadConversationCount = localStorage.getItem('unreadConversationCount')
} catch (error) {
console.log('local error', error)
}
if (local_conversations) {
state.conversations = local_conversations
state.unreadConversationCount = local_unreadConversationCount || 0
return
}
}
// event = connected 初始化conversation list
// 似乎并不需要在获取conversation list的时候进行时间戳处理
MessageHubApi.fetchConversations(GWT, token).then((response) => {
const conversations = response.data.conversations || []
// 既然每次都是新消息在第一位那么只需要对比conversation list的长度就可以知道是否有新的会话产生。
// 消息初始化不做比对
let updateLength = 0
if (data.event !== 'connected') {
updateLength = conversations.length - state.conversations.length
if (updateLength === 0) updateLength = 1
for (let i = 0; i<updateLength; i++) {
conversations[i].unread = true
}
}
const conversation = conversations[0]
if (conversation?.id) {
MessageHubApi.fetchMessages(conversation.id, conversation.message_update_time ? conversation.message_update_time : GWT, token).then((response) => {
conversations[0].messages = response?.data || []
conversations[0].message_update_time = new Date().toISOString()
state.conversations = conversations
state.unreadConversationCount = updateLength
localStorage.setItem('conversations', JSON.stringify(conversations))
localStorage.setItem('unreadConversationCount', updateLength)
})
}
})
}, },
() => { () => {
console.log('downstream_web_socket error') console.log('downstream_web_socket error')
@ -48,8 +91,17 @@ const basicStore = {
} }
) )
}, },
readMessageBy(state, sender) { readMessageBy(state, conversation_id) {
delete state.unreadCountMapper?.[sender] for (let i = 0; i < state.conversations.length; i ++) {
if (conversation_id === state.conversations[i].id) {
const nsc = Object.assign([], state.conversations)
nsc[i].unread = false
state.conversations = nsc
if (state.unreadConversationCount > 0) {
state.unreadConversationCount = state.unreadConversationCount - 1
}
}
}
} }
}, },
actions: { actions: {
@ -67,17 +119,11 @@ const basicStore = {
language(state) { language(state) {
return state.language return state.language
}, },
unreadCount(state) { unreadConversationCount(state) {
let count = 0 return state.unreadConversationCount
for (let key in state.unreadCountMapper) {
if (state.unreadCountMapper.hasOwnProperty(key)) {
count += state.unreadCountMapper[key]
}
}
return count
}, },
unreadCountMapper(state) { conversations(state) {
return state.unreadCountMapper return state.conversations
} }
} }
} }

View File

@ -1,9 +1,9 @@
import { backendAxios } from './axios' import { backendAxios } from './axios'
import { userUtils } from '../store/index' // import { userUtils } from '../store/index'
class MessageHubApi { class MessageHubApi {
static fetchConversations(last_update_time) { static fetchConversations(last_update_time, jwt) {
let jwt = userUtils.getJwtToken() // let jwt = userUtils.getJwtToken()
const request = backendAxios.post( const request = backendAxios.post(
'/api/messages/fetch-conversations-for-user', '/api/messages/fetch-conversations-for-user',
{ {
@ -15,8 +15,8 @@ class MessageHubApi {
) )
return request return request
} }
static fetchMessages(conversation_id, last_update_time) { static fetchMessages(conversation_id, last_update_time, jwt) {
let jwt = userUtils.getJwtToken() // let jwt = userUtils.getJwtToken()
const request = backendAxios.post( const request = backendAxios.post(
'/api/messages/fetch-message-thread-for-conversation', '/api/messages/fetch-message-thread-for-conversation',
{ {
@ -30,8 +30,8 @@ class MessageHubApi {
return request return request
} }
static sendMessageToConversation(conversation_id, message) { static sendMessageToConversation(conversation_id, message, jwt) {
let jwt = userUtils.getJwtToken() // let jwt = userUtils.getJwtToken()
const request = backendAxios.post( const request = backendAxios.post(
'/api/messages/send-message-to-conversation', '/api/messages/send-message-to-conversation',
{ {