This commit is contained in:
min.jiang 2024-07-24 03:03:53 +08:00
parent 1ba337ac4f
commit 9b1f18282b
9 changed files with 117 additions and 47 deletions

View File

@ -113,6 +113,7 @@ export default {
Apply: 'Apply',
'Empty conversation': 'Empty conversation',
'Please choose conversation': 'Please choose conversation',
'Please input message': 'Please input message',
Name: 'Name',
'Stay on Freeleaps': 'Stay on Freeleaps',
'Delivered projects': 'Delivered projects',
@ -211,4 +212,5 @@ export default {
'Issues management': 'Issues management',
'Payment progress': 'Payment progress',
'Goal': 'Goal',
'Message': 'Message'
}

View File

@ -112,6 +112,7 @@ export default {
Apply: '应用',
'Empty conversation': '空对话',
'Please choose conversation': '请选择对话',
'Please input message': '请输入消息',
Name: '名字',
'Stay on Freeleaps': 'Freeleaps注册时长',
'Delivered projects': '已交付项目',
@ -194,4 +195,5 @@ export default {
'Issues management': '问题管理',
'Payment progress': '付款进度',
'Goal': '项目目标',
'Message': '消息'
}

View File

@ -1,38 +1,40 @@
<template>
<div class="message-container">
<div class="message-hub-conainter">
<div v-if="conversations && conversations.length > 0" class="conversation-list-container">
<div
v-for="(conversation, index) in conversations"
:key="index"
class="conversation-container"
:class="{
selected: selConversation?.id === conversation?.id
}"
@click="selectConversation(conversation)"
>
<img class="participant-portrait" alt="user portrait" src="@/assets/profile.png" />
<div class="conversation-summary-container">
<div class="conversation-summary-header-container">
<span class="participant-fullname">
{{ conversation.subject }}
</span>
<span class="conversation-last-update-date">{{
getDateFromFulltimeString(conversation.create_time)
}}</span>
</div>
<div class="conversation-summary-highlight-container">
{{ conversation.last_message?.message_body }}
<template v-if="!receiver_id">
<div v-if="conversations && conversations.length > 0" class="conversation-list-container">
<div
v-for="(conversation, index) in conversations"
:key="index"
class="conversation-container"
:class="{
selected: selConversation?.id === conversation?.id
}"
@click="selectConversation(conversation)"
>
<img class="participant-portrait" alt="user portrait" src="@/assets/profile.png" />
<div class="conversation-summary-container">
<div class="conversation-summary-header-container">
<span class="participant-fullname">
{{ conversation.subject }}
</span>
<span class="conversation-last-update-date">{{
getDateFromFulltimeString(conversation.create_time)
}}</span>
</div>
<div class="conversation-summary-highlight-container">
{{ conversation.last_message?.message_body }}
</div>
</div>
</div>
</div>
</div>
<div
v-if="!conversations || conversations.length == 0"
class="conversation-list-empty-container"
>
{{ $t('Empty conversation') }}
</div>
<div
v-if="!conversations || conversations.length == 0"
class="conversation-list-empty-container"
>
{{ $t('Empty conversation') }}
</div>
</template>
<div class="message-panel-container">
<div v-if="messages && messages.length > 0" class="message-thread-container">
<div
@ -59,7 +61,7 @@
</div>
</div>
<div v-if="!messages || messages.length == 0" class="message-thread-empty-container">
{{ $t('Please choose conversation') }}
{{ receiver_id ? $t('Please input message') : $t('Please choose conversation') }}
</div>
<div class="message-writing-panel-container">
<svg-icon icon="msg-enter" class-name="writing-message-enter" />
@ -67,7 +69,7 @@
class="writing-message-input"
type="text"
v-model="writtenMessage"
@keypress.enter="sendMessage(selConversation.id)"
@keypress.enter="sendMessage(selConversation?.id)"
/>
</div>
</div>
@ -76,26 +78,27 @@
</template>
<script>
import SvgIcon from '@/components/SvgIcon.vue'
import { MessageHubApi, DateUtils } from '@/utils/index'
import { MessageHubApi, DateUtils, requestHubUtils } from '@/utils/index'
import { userUtils } from '@/utils/store/index'
export default {
components: { SvgIcon },
name: 'MessageHub',
props: {},
mounted() {
this.$store.dispatch('basic/updateConversationsPage', {
token: this.mnx_getUserAuthToken(),
cb: error => {
this.mnx_backendErrorHandler(error)
}
})
const request = requestHubUtils.fetchRequestToMessage()
if (request && request.user_id) {
this.receiver_id = request.user_id
} else {
this.fetchConversations()
}
},
data() {
return {
userIdentityNote: this.mnx_getUserIdentity(),
selConversation: null,
messages: [],
writtenMessage: null
writtenMessage: null,
receiver_id: null
}
},
computed: {
@ -105,19 +108,28 @@ export default {
},
watch: {
conversations(n_val) {
console.log('nval', n_val, this.selConversation, n_val[0].messages)
if (!this.selConversation && n_val[0]) {
this.selConversation = n_val[0]
this.messages = n_val[0].messages || []
this.clearUnreadMessageBy(n_val[0])
} else {
if (n_val?.[0] && this.selConversation?.id === n_val?.[0]?.id) {
this.messages = n_val[0].messages || []
// this.messages = n_val[0].messages || []
this.clearUnreadMessageBy(n_val[0])
}
}
}
},
methods: {
fetchConversations() {
this.$store.dispatch('basic/updateConversationsPage', {
token: this.mnx_getUserAuthToken(),
cb: error => {
this.mnx_backendErrorHandler(error)
}
})
},
fetchMessageForConversation(conversation_id) {
const jwt = userUtils.getJwtToken()
MessageHubApi.fetchMessages(
@ -145,7 +157,18 @@ export default {
},
sendMessage(conversation_id) {
const jwt = userUtils.getJwtToken()
MessageHubApi.sendMessageToConversation(conversation_id, this.writtenMessage, jwt)
if (this.receiver_id) {
MessageHubApi.sendMessageToUser(this.receiver_id, this.writtenMessage, jwt)
.then(() => {
requestHubUtils.fillRequestToMessage(null)
this.receiver_id = null
this.writtenMessage = null
})
.catch((error) => {
this.mnx_backendErrorHandler(error)
})
} else {
MessageHubApi.sendMessageToConversation(conversation_id, this.writtenMessage, jwt)
.then((response) => {
let new_message = response.data
this.messages.push({
@ -159,6 +182,7 @@ export default {
.catch((error) => {
this.mnx_backendErrorHandler(error)
})
}
},
getDateFromFulltimeString(fulltime) {
// FromJsonToHMDateString

View File

@ -76,6 +76,9 @@
<button class="make-proposal-button" type="button" @click="Propose(request)">
{{ $t('Propose') }}
</button>
<button class="make-proposal-button" type="button" @click="messageTo(request)">
{{ $t('Message') }}
</button>
<div class="request-description-content" v-html="request.content"></div>
<div
class="pdf-actions"
@ -251,6 +254,10 @@ export default {
requestHubUtils.fillRequestToPropose(request)
this.mnx_navToMakeProposal(request.id, proposingModelEnum.NO_LOADING)
},
messageTo(request) {
requestHubUtils.fillRequestToMessage(request)
this.mnx_navToMessageHub()
},
getDateFromFulltimeString(fulltime) {
return DateUtils.FromJsonToDateString(fulltime)
},

View File

@ -279,7 +279,7 @@
<td>
<div class="project-milestones-table-content">
<span class="project-milestones-table-label">{{ $t('Action') }}</span>
<button class="btn btn-link" :disabled="isMilestoneActionButtonDisabled(project.project, milestone)
<button class="project-milestones-table-btn" :disabled="isMilestoneActionButtonDisabled(project.project, milestone)
" :hidden="isMilestoneActionButtonHidden(project.project, milestone)"
@click="handleMilestoneAction(project.project, milestone)">
{{ fetchMilestoneActionButtonText(project.project, milestone) }}
@ -1482,4 +1482,19 @@ export default {
width: 100%;
height: 357px;
}
.project-milestones-table-btn {
@extend .btn;
@extend .btn-primary;
width: fit-content;
padding: 0 8px;
border-radius: 0;
&:disabled {
color: #000000;
border-color: #D9D9D9;
background-color: #D9D9D9;
opacity: 1;
}
}
</style>

View File

@ -239,17 +239,17 @@ export default {
showIssueActionButton(project, issue, button_text) {
switch (issue.status) {
case projectIssueStatusEnum.OPEN:
if (button_text === this.$t('Resolve')) {
if (button_text === 'Resolve') {
return project.providers.includes(project.current_user_id)
}
break
case 1:
if (button_text === this.$t('Reopen') || button_text === this.$t('Confirm')) {
if (button_text === 'Reopen' || button_text === 'Confirm') {
return project.issuers.includes(project.current_user_id)
}
break
case projectIssueStatusEnum.CLOSED:
if (button_text === this.$t('Reopen')) {
if (button_text === 'Reopen') {
return project.issuers.includes(project.current_user_id)
}
break

View File

@ -50,9 +50,9 @@ const updateConversations =(state, {token ,cb}, data) => {
).then((response) => {
conversations[0].messages = response?.data || []
conversations[0].message_update_time = new Date().toISOString()
// state.conversations = conversations
state.conversations = conversations
state.unreadConversationCount = updateLength
// localStorage.setItem('conversations', JSON.stringify(conversations))
localStorage.setItem('conversations', JSON.stringify(conversations))
localStorage.setItem('unreadConversationCount', updateLength)
})
}

View File

@ -44,6 +44,18 @@ class MessageHubApi {
)
return request
}
static sendMessageToUser(receiver_id, message, jwt) {
// let jwt = userUtils.getJwtToken()
const request = backendAxios.post(
'/api/messages/send-message-to-user',
{ receiver_id, message },
{
headers: { Authorization: `Bearer ${jwt}` }
}
)
return request
}
}
export { MessageHubApi }

View File

@ -13,6 +13,14 @@ class RequestHubUtils {
return this.request_to_propose
}
fillRequestToMessage(request) {
this.request_to_message = request
}
fetchRequestToMessage() {
return this.request_to_message
}
fillExistingProposal(proposal) {
this.existing_proposal = proposal
}