This commit is contained in:
min.jiang 2024-07-14 01:11:39 +08:00
parent a5bc5d4266
commit 2a9b0135c9
12 changed files with 131 additions and 15 deletions

View File

@ -9,6 +9,7 @@
@blur="updateAction" @blur="updateAction"
@mousedown.stop="selectionStart" @mousedown.stop="selectionStart"
@mouseup.stop="selectionEnd" @mouseup.stop="selectionEnd"
@keyup="keyupAction"
/> />
<div v-if="!disabled" class="editor-control" :style="editorCtrlStyle"> <div v-if="!disabled" class="editor-control" :style="editorCtrlStyle">
<transition-group appear name="fade-transform" mode="out-in"> <transition-group appear name="fade-transform" mode="out-in">
@ -223,7 +224,7 @@ export default {
// console.log('window.getSelection',this.selectedRange) // console.log('window.getSelection',this.selectedRange)
// console.log('is bold ? ', this.queryCommandState(sel.getRangeAt(0), 'bold')) // console.log('is bold ? ', this.queryCommandState(sel.getRangeAt(0), 'bold'))
// this.iconClick(null, 'bold') // this.iconClick(null, 'bold')
this.editorCtrlStyle = { display: 'flex', top: `${e.layerY}px`, left: `${e.layerX}px` } this.editorCtrlStyle = { display: 'flex', top: `${e.layerY - 30}px`, left: `${e.layerX}px` }
} else { } else {
this.selectedRange = null this.selectedRange = null
this.editorCtrlStyle = { display: 'none' } this.editorCtrlStyle = { display: 'none' }
@ -232,6 +233,12 @@ export default {
// this.commandStates = [] // this.commandStates = []
} }
}, },
keyupAction(e) {
console.log('keyupAction', e)
// if (e.code == 'ShiftLeft' || e.code == 'ShiftRight') {
// }
},
queryCommandState(range, command) { queryCommandState(range, command) {
const container = document.createElement('span') const container = document.createElement('span')
container.style.display = 'none' container.style.display = 'none'

View File

@ -12,18 +12,24 @@
<button <button
class="navigation-item" class="navigation-item"
@click="gotoWorkspace" @click="gotoWorkspace"
:class="activePath == 'Workspace' ? 'active' : ''" :class="{'active': activePath == 'Workspace', 'badge': unreadWorkspace}"
> >
<svg-icon icon="workspace" class-name="icon" /> <svg-icon icon="workspace" class-name="icon" />
{{ $t('Workspace') }} {{ $t('Workspace') }}
<div v-if="unreadWorkspace" class="navigation-item-tip">
{{ $t('Some update in your work') }}
</div>
</button> </button>
<button <button
class="navigation-item" class="navigation-item"
@click="gotoRequests" @click="gotoRequests"
:class="activePath == 'Requests' ? 'active' : ''" :class="{'active': activePath == 'Requests', 'badge': unreadRequest}"
> >
<svg-icon icon="requests" class-name="icon" /> <svg-icon icon="requests" class-name="icon" />
{{ $t('Requests') }} {{ $t('Requests') }}
<div v-if="unreadRequest" class="navigation-item-tip">
{{ $t('Some update in your request') }}
</div>
</button> </button>
<button <button
class="navigation-item" class="navigation-item"
@ -96,6 +102,12 @@ export default {
computed: { computed: {
unreadConversationCount() { unreadConversationCount() {
return this.$store.getters['basic/unreadConversationCount'] return this.$store.getters['basic/unreadConversationCount']
},
unreadWorkspace() {
return this.$store.getters['basic/unreadWorkspace']
},
unreadRequest() {
return this.$store.getters['basic/unreadRequest']
} }
}, },
created() { created() {
@ -236,9 +248,36 @@ export default {
color: #6e7387; color: #6e7387;
text-decoration: none; text-decoration: none;
margin: 0 30px; margin: 0 30px;
position: relative;
&.badge::after {
content: '';
position: absolute;
right: 0;
top: 0;
width: 8px;
height: 8px;
border-radius: 4px;
background-color: #f44837;
}
.navigation-item-tip {
position: absolute;
background-color: white;
left: 10px;
bottom: -16px;
font-size: 12px;
color: #3d455f;
white-space: nowrap;
padding: 2px 5px;
display: none;
}
&:hover { &:hover {
color: $primary; color: $primary;
.navigation-item-tip {
display: block;
}
} }
&.active { &.active {

View File

@ -203,5 +203,9 @@ export default {
Ready: 'Ready', Ready: 'Ready',
'Not available': 'Not available', 'Not available': 'Not available',
'Please input issue description': 'Please input issue description', 'Please input issue description': 'Please input issue description',
'day(s)': 'day(s)' 'day(s)': 'day(s)',
'Some update in your work': 'Some update in your work',
'Some update in your request': 'Some update in your request',
'min(s)': 'min(s)',
'line(s)': 'line(s)',
} }

View File

@ -185,5 +185,9 @@ export default {
'Providing service': '提供服务中', 'Providing service': '提供服务中',
'Please go to profile page to add money receiving method': '请于个人资料页添加收款方式', 'Please go to profile page to add money receiving method': '请于个人资料页添加收款方式',
'Log out': '登出', 'Log out': '登出',
'day(s)': '天' 'day(s)': '天',
'Some update in your work': 'Some update in your work',
'Some update in your request': 'Some update in your request',
'min(s)': '响应时间',
'line(s)': '每周产出代码',
} }

View File

@ -6,7 +6,7 @@
:key="index" :key="index"
@click="view_link(directory)" @click="view_link(directory)"
> >
<img class="directory_cover_image" :src="directory.cover_picture" /> <div class="directory_cover_image" :style="{'background-image': `url(${directory.cover_picture})`}" />
<p class="directory-title">{{ directory.title_text }}</p> <p class="directory-title">{{ directory.title_text }}</p>
<p class="directory-subtitle">{{ directory.summary_text }}</p> <p class="directory-subtitle">{{ directory.summary_text }}</p>
<button class="btn btn-link">{{ $t('Read More') }}</button> <button class="btn btn-link">{{ $t('Read More') }}</button>
@ -65,6 +65,10 @@ export default {
.directory_cover_image { .directory_cover_image {
width: 100%; width: 100%;
height: 311px;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
border-radius: 16px; border-radius: 16px;
margin-bottom: 16px; margin-bottom: 16px;
} }

View File

@ -7,7 +7,7 @@
@click="view_blog(blog)" @click="view_blog(blog)"
> >
<h2>{{ blog.blog_name }}</h2> <h2>{{ blog.blog_name }}</h2>
<img class="blog_cover_image" :src="blog.cover_picture" /> <div class="blog_cover_image" :style="{'background-image': `url(${blog.cover_picture})`}" />
<p v-text="retrieve_summary(blog)"></p> <p v-text="retrieve_summary(blog)"></p>
</div> </div>
</div> </div>
@ -63,6 +63,12 @@ export default {
} }
.blog_cover_image { .blog_cover_image {
width: 100%;
height: 311px; height: 311px;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
border-radius: 16px;
margin-bottom: 16px;
} }
</style> </style>

View File

@ -154,7 +154,8 @@ export default {
}) })
}, },
getDateFromFulltimeString(fulltime) { getDateFromFulltimeString(fulltime) {
return DateUtils.FromJsonToHMDateString(fulltime) // FromJsonToHMDateString
return DateUtils.FromJsonToDatetimeString(fulltime)
} }
} }
} }
@ -220,6 +221,7 @@ export default {
.conversation-last-update-date { .conversation-last-update-date {
white-space: nowrap; white-space: nowrap;
flex-shrink: 0; flex-shrink: 0;
font-size: 12px;
} }
.conversation-unreadcount { .conversation-unreadcount {
@ -318,7 +320,7 @@ export default {
color: #737478; color: #737478;
white-space: nowrap; white-space: nowrap;
flex-shrink: 0; flex-shrink: 0;
font-size: 16px; font-size: 12px;
} }
} }

View File

@ -53,7 +53,7 @@
$t('Responding time') $t('Responding time')
}}</label> }}</label>
<span class="provider-responding-time-span" id="provider-responding-time"> <span class="provider-responding-time-span" id="provider-responding-time">
{{ provider.provider_achievement.responding_time_in_minutes }} min(s) {{ provider.provider_achievement.responding_time_in_minutes }} {{$t('min(s)')}}
</span> </span>
</div> </div>
<div class="provider-credit-score-container"> <div class="provider-credit-score-container">
@ -129,7 +129,7 @@
$t('Weekly produced code') $t('Weekly produced code')
}}</label> }}</label>
<span class="dd-project-span" id="delivery-weekly-produced-code"> <span class="dd-project-span" id="delivery-weekly-produced-code">
{{ provider.provider_deliveries.lines_of_code_per_week }} line(s) {{ provider.provider_deliveries.lines_of_code_per_week }} {{$t('line(s)')}}
</span> </span>
</div> </div>
</div> </div>
@ -198,7 +198,7 @@
$t('Issue fixing time') $t('Issue fixing time')
}}</label> }}</label>
<span class="dd-project-span" id="quality-issue-fixing-time"> <span class="dd-project-span" id="quality-issue-fixing-time">
{{ provider.provider_work_quality.issue_fixing_time_minutes }} min(s) {{ provider.provider_work_quality.issue_fixing_time_minutes }} {{$t('min(s)')}}
</span> </span>
</div> </div>
</div> </div>

View File

@ -241,6 +241,7 @@ export default {
RequestHubApi.fetchRequestForHub() RequestHubApi.fetchRequestForHub()
.then((response) => { .then((response) => {
this.requestGroups = response.data this.requestGroups = response.data
this.$store.dispatch('basic/clearUnreadRequest')
}) })
.catch((error) => { .catch((error) => {
this.mnx_backendErrorHandler(error) this.mnx_backendErrorHandler(error)

View File

@ -418,7 +418,8 @@ export default {
fetchExisting() { fetchExisting() {
RequestHubApi.fetchMyProposals() RequestHubApi.fetchMyProposals()
.then((response) => { .then((response) => {
this.existingProposals = response.data this.existingProposals = response.data || []
}) })
.catch((error) => { .catch((error) => {
this.mnx_backendErrorHandler(error) this.mnx_backendErrorHandler(error)
@ -509,6 +510,7 @@ export default {
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
color: #0d1637; color: #0d1637;
white-space: nowrap
} }
.load-templates-button { .load-templates-button {

View File

@ -679,6 +679,7 @@ export default {
this.projects = response.data this.projects = response.data
this.newIssueDescriptions = new Array(this.projects.length) this.newIssueDescriptions = new Array(this.projects.length)
this.newInviteCollaborator = new Array(this.projects.length) this.newInviteCollaborator = new Array(this.projects.length)
this.$store.dispatch('basic/clearUnreadWorkspace')
}) })
.catch((error) => { .catch((error) => {
this.mnx_backendErrorHandler(error) this.mnx_backendErrorHandler(error)
@ -897,7 +898,9 @@ export default {
WorksapceApi.withdrawProposal(project.proposal.id) WorksapceApi.withdrawProposal(project.proposal.id)
.then((response) => { .then((response) => {
//We treat the proposal as drafted not existing one because it has been withdrawn //We treat the proposal as drafted not existing one because it has been withdrawn
requestHubUtils.fillDraftedProposal(project.proposal) const proposal = Object.assign({}, project.proposal)
proposal.stages = proposal?.payment_plan?.stages || []
requestHubUtils.fillDraftedProposal(proposal)
this.mnx_navToMakeProposal(project.request.id, proposingModelEnum.FROM_DRAFT) this.mnx_navToMakeProposal(project.request.id, proposingModelEnum.FROM_DRAFT)
}) })
.catch((error) => { .catch((error) => {

View File

@ -5,6 +5,23 @@ import { MessageHubApi } from '@/utils/backend/messageHub'
const ignoreEventType = ['test'] const ignoreEventType = ['test']
const GWT = new Date('01 Jan 1970 00:00:00 GMT').toISOString() const GWT = new Date('01 Jan 1970 00:00:00 GMT').toISOString()
const unreadWorkspaceRules = [
{subject:'request', event:'quoted'},
{subject:'quote', event:'accepted'},
{subject:'quote',event:'rejected'},
{subject:'request',event:'invited'}
]
const unreadRequestRules = [
{subject:'request',event:'invited'}
]
const checkUnreadRulesBy = (message, rules = []) => {
for (let i = 0; i < rules.length; i ++) {
if (message?.subject == rules[i].subject && message?.event == rules[i].event) {
return true
}
}
return false
}
const basicStore = { const basicStore = {
namespaced: true, namespaced: true,
@ -13,6 +30,8 @@ const basicStore = {
language: 'zh', language: 'zh',
conversations: [], conversations: [],
unreadConversationCount: 0, unreadConversationCount: 0,
unreadWorkspace: false,
unreadRequest: false,
downstream_web_socket: null downstream_web_socket: null
} }
}, },
@ -55,6 +74,12 @@ const basicStore = {
} }
} }
if (checkUnreadRulesBy(data, unreadRequestRules)) {
state.unreadRequest = true
} else if (checkUnreadRulesBy(data, unreadWorkspaceRules)) {
state.unreadWorkspace = true
}
MessageHubApi.fetchConversations(GWT, token).then((response) => { MessageHubApi.fetchConversations(GWT, token).then((response) => {
const conversations = response.data.conversations || [] const conversations = response.data.conversations || []
let updateLength = 0 let updateLength = 0
@ -62,7 +87,7 @@ const basicStore = {
updateLength = conversations.length - state.conversations.length updateLength = conversations.length - state.conversations.length
if (updateLength === 0) updateLength = 1 if (updateLength === 0) updateLength = 1
for (let i = 0; i < updateLength; i++) { for (let i = 0; i < updateLength; i++) {
conversations[i].unread = true conversations[i]['unread'] = true
} }
} }
const conversation = conversations[0] const conversation = conversations[0]
@ -81,6 +106,7 @@ const basicStore = {
}) })
} }
}) })
}, },
() => { () => {
console.log('downstream_web_socket error') console.log('downstream_web_socket error')
@ -101,6 +127,12 @@ const basicStore = {
} }
} }
} }
},
clearUnreadWorkspace(state) {
state.unreadWorkspace = false
},
clearUnreadRequest(state) {
state.unreadRequest = false
} }
}, },
actions: { actions: {
@ -112,6 +144,12 @@ const basicStore = {
}, },
readMessageBy(context, sender) { readMessageBy(context, sender) {
context.commit('readMessageBy', sender) context.commit('readMessageBy', sender)
},
clearUnreadWorkspace(context) {
context.commit('clearUnreadWorkspace')
},
clearUnreadRequest(context) {
context.commit('clearUnreadRequest')
} }
}, },
getters: { getters: {
@ -123,6 +161,12 @@ const basicStore = {
}, },
conversations(state) { conversations(state) {
return state.conversations return state.conversations
},
unreadWorkspace(state) {
return state.unreadWorkspace
},
unreadRequest(state) {
return state.unreadRequest
} }
} }
} }