update
This commit is contained in:
parent
327b8c5b35
commit
95c845c628
@ -1,3 +1,4 @@
|
|||||||
|
<!-- eslint-disable vue/valid-v-model -->
|
||||||
<template>
|
<template>
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<div class="header-content">
|
<div class="header-content">
|
||||||
@ -47,18 +48,19 @@
|
|||||||
<svg-icon icon="post" class-name="icon" />
|
<svg-icon icon="post" class-name="icon" />
|
||||||
{{ $t('Post') }}
|
{{ $t('Post') }}
|
||||||
</button>
|
</button>
|
||||||
<div class="form-check form-switch header-switch-container">
|
<div class="form-check form-switch header-switch-container" @click="gotoProfile">
|
||||||
<input
|
<input
|
||||||
class="form-check-input"
|
class="form-check-input"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
role="switch"
|
role="switch"
|
||||||
|
:checked="userProfile?.account?.provider?.accepting_request"
|
||||||
id="personal-earning-now-checkbox"
|
id="personal-earning-now-checkbox"
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" for="personal-earning-now-checkbox">
|
<label class="form-check-label" for="personal-earning-now-checkbox">
|
||||||
<span>{{ $t('Providing service') }}</span>
|
<span>{{ $t('Providing service') }}</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="header-switch-desc">
|
<div v-if="!userProfile?.account?.provider?.accepting_request" class="header-switch-desc">
|
||||||
{{ $t('Please go to profile page to add money receiving method') }}
|
{{ $t('Please go to profile page to add money receiving method') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -70,7 +72,10 @@
|
|||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
id="accountButton"
|
id="accountButton"
|
||||||
src="@/assets/profile.png"
|
:src="userProfile?.account?.basic?.photo?.base64
|
||||||
|
? userProfile?.account?.basic?.photo?.base64
|
||||||
|
: profileUrl
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<ul class="dropdown-menu" aria-labelledby="accountButton">
|
<ul class="dropdown-menu" aria-labelledby="accountButton">
|
||||||
<li>
|
<li>
|
||||||
@ -95,6 +100,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import { UserAuthApi } from '@/utils/backend/index'
|
import { UserAuthApi } from '@/utils/backend/index'
|
||||||
import LaguageSwitch from '@/components/LaguageSwitch.vue'
|
import LaguageSwitch from '@/components/LaguageSwitch.vue'
|
||||||
|
import { UserProfileApi } from '@/utils/index'
|
||||||
|
import profileUrl from '@/assets/profile.png'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HeaderGuest',
|
name: 'HeaderGuest',
|
||||||
@ -108,6 +115,9 @@ export default {
|
|||||||
},
|
},
|
||||||
unreadRequest() {
|
unreadRequest() {
|
||||||
return this.$store.getters['basic/unreadRequest']
|
return this.$store.getters['basic/unreadRequest']
|
||||||
|
},
|
||||||
|
userProfile() {
|
||||||
|
return this.$store.getters['userProfile/profile']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -115,9 +125,11 @@ export default {
|
|||||||
this.userIdentityNote = this.userIdentityNote.slice(0, 5) + '...'
|
this.userIdentityNote = this.userIdentityNote.slice(0, 5) + '...'
|
||||||
}
|
}
|
||||||
this.$store.dispatch('basic/initWebsocket', this.mnx_getUserAuthToken())
|
this.$store.dispatch('basic/initWebsocket', this.mnx_getUserAuthToken())
|
||||||
|
this.fetchProfile()
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
profileUrl,
|
||||||
userIdentityNote: this.mnx_getUserIdentity(),
|
userIdentityNote: this.mnx_getUserIdentity(),
|
||||||
activePath: this.$route.meta.activePath
|
activePath: this.$route.meta.activePath
|
||||||
}
|
}
|
||||||
@ -157,7 +169,16 @@ export default {
|
|||||||
this.mnx_logoutRole()
|
this.mnx_logoutRole()
|
||||||
this.mnx_navToFrontDoor()
|
this.mnx_navToFrontDoor()
|
||||||
},
|
},
|
||||||
|
fetchProfile() {
|
||||||
|
UserProfileApi.fetchUserProfile()
|
||||||
|
.then((response) => {
|
||||||
|
this.$store.dispatch('userProfile/updateProfile', response.data || {})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log('error', error)
|
||||||
|
this.mnx_backendErrorHandler(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
signout() {
|
signout() {
|
||||||
UserAuthApi.signout(this.mnx_getUserIdentity(), this.mnx_getUserAuthToken())
|
UserAuthApi.signout(this.mnx_getUserIdentity(), this.mnx_getUserAuthToken())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@ -289,6 +310,7 @@ export default {
|
|||||||
|
|
||||||
.header-switch-container {
|
.header-switch-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.header-switch-desc {
|
.header-switch-desc {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -208,4 +208,5 @@ export default {
|
|||||||
'Some update in your request': 'Some update in your request',
|
'Some update in your request': 'Some update in your request',
|
||||||
'min(s)': 'min(s)',
|
'min(s)': 'min(s)',
|
||||||
'line(s)': 'line(s)',
|
'line(s)': 'line(s)',
|
||||||
|
'Issues management': 'Issues management'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -190,4 +190,5 @@ export default {
|
|||||||
'Some update in your request': 'Some update in your request',
|
'Some update in your request': 'Some update in your request',
|
||||||
'min(s)': '响应时间',
|
'min(s)': '响应时间',
|
||||||
'line(s)': '每周产出代码',
|
'line(s)': '每周产出代码',
|
||||||
|
'Issues management': '问题管理'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,9 @@ export default {
|
|||||||
mnx_navToNewUserSetFlid(suggested_flid) {
|
mnx_navToNewUserSetFlid(suggested_flid) {
|
||||||
this.$router.push('/new-user-set-flid/' + suggested_flid)
|
this.$router.push('/new-user-set-flid/' + suggested_flid)
|
||||||
},
|
},
|
||||||
|
mnx_navToProjectIssue(project_id) {
|
||||||
|
this.$router.push(`/project-issue/${project_id}`)
|
||||||
|
},
|
||||||
mnx_navToRequestIssue(loadFrom) {
|
mnx_navToRequestIssue(loadFrom) {
|
||||||
this.$router.push('/request-issue/' + loadFrom)
|
this.$router.push('/request-issue/' + loadFrom)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -592,18 +592,12 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
fetchProfile() {
|
fetchProfile() {
|
||||||
UserProfileApi.fetchUserProfile()
|
this.userProfile = this.$store.getters['userProfile/profile']
|
||||||
.then((response) => {
|
|
||||||
this.userProfile = response.data
|
|
||||||
this.updateLocalIdentityData()
|
this.updateLocalIdentityData()
|
||||||
this.updateLocalEmailData()
|
this.updateLocalEmailData()
|
||||||
this.updateLocalMobileData()
|
this.updateLocalMobileData()
|
||||||
this.updateLocalPersonalData()
|
this.updateLocalPersonalData()
|
||||||
this.updateLocalPaymentData()
|
this.updateLocalPaymentData()
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.mnx_backendErrorHandler(error)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
updateLocalIdentityData() {
|
updateLocalIdentityData() {
|
||||||
this.identityOperation.first_name = this.userProfile.account.basic.first_name
|
this.identityOperation.first_name = this.userProfile.account.basic.first_name
|
||||||
@ -611,6 +605,9 @@ export default {
|
|||||||
this.identityOperation.photo.base64 = this.userProfile.account.basic.photo.base64
|
this.identityOperation.photo.base64 = this.userProfile.account.basic.photo.base64
|
||||||
this.identityOperation.photo.filename = this.userProfile.account.basic.photo.filename
|
this.identityOperation.photo.filename = this.userProfile.account.basic.photo.filename
|
||||||
},
|
},
|
||||||
|
updateLocalProfileData() {
|
||||||
|
this.$store.dispatch('userProfile/updateProfile', this.userProfile || {})
|
||||||
|
},
|
||||||
//User identity operation
|
//User identity operation
|
||||||
edittingFirstname($event) {
|
edittingFirstname($event) {
|
||||||
elementHandler.edittingInput($event.target)
|
elementHandler.edittingInput($event.target)
|
||||||
@ -646,6 +643,7 @@ export default {
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.userProfile.account.basic.photo = response.data.photo
|
this.userProfile.account.basic.photo = response.data.photo
|
||||||
this.updateLocalIdentityData()
|
this.updateLocalIdentityData()
|
||||||
|
this.updateLocalProfileData()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.mnx_backendErrorHandler(error)
|
this.mnx_backendErrorHandler(error)
|
||||||
@ -885,8 +883,8 @@ export default {
|
|||||||
textAreaAujuster.adjustHight(element)
|
textAreaAujuster.adjustHight(element)
|
||||||
},
|
},
|
||||||
updateSelfIntro() {
|
updateSelfIntro() {
|
||||||
this.personalOperation.self_intro.content_html =
|
// this.personalOperation.self_intro.content_html =
|
||||||
this.$refs.personal_self_intro_editor_div.innerHTML
|
// this.$refs.personal_self_intro_editor_div.innerHTML
|
||||||
if (!this.personalOperation.self_intro.content_html) {
|
if (!this.personalOperation.self_intro.content_html) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -948,6 +946,8 @@ export default {
|
|||||||
if (response.data.accepting_request && response.data.account_link != '') {
|
if (response.data.accepting_request && response.data.account_link != '') {
|
||||||
window.location = response.data.account_link
|
window.location = response.data.account_link
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateLocalProfileData()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.mnx_backendErrorHandler(error)
|
this.mnx_backendErrorHandler(error)
|
||||||
@ -1144,7 +1144,7 @@ export default {
|
|||||||
.btn-group-container {
|
.btn-group-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 32px;
|
right: 32px;
|
||||||
top: 10px;
|
top: -30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,14 @@ export default {
|
|||||||
components: { SvgIcon },
|
components: { SvgIcon },
|
||||||
name: 'MessageHub',
|
name: 'MessageHub',
|
||||||
props: {},
|
props: {},
|
||||||
mounted() {},
|
mounted() {
|
||||||
|
this.$store.dispatch('basic/updateConversationsPage', {
|
||||||
|
token: this.mnx_getUserAuthToken(),
|
||||||
|
cb: error => {
|
||||||
|
this.mnx_backendErrorHandler(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
userIdentityNote: this.mnx_getUserIdentity(),
|
userIdentityNote: this.mnx_getUserIdentity(),
|
||||||
@ -103,7 +110,7 @@ export default {
|
|||||||
this.messages = n_val[0].messages || []
|
this.messages = n_val[0].messages || []
|
||||||
this.clearUnreadMessageBy(n_val[0])
|
this.clearUnreadMessageBy(n_val[0])
|
||||||
} else {
|
} else {
|
||||||
if (this.selConversation.id === n_val?.[0]?.id) {
|
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])
|
this.clearUnreadMessageBy(n_val[0])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -474,7 +474,18 @@
|
|||||||
class="accordion-collapse collapse"
|
class="accordion-collapse collapse"
|
||||||
data-bs-parent="#collapse-project-issue"
|
data-bs-parent="#collapse-project-issue"
|
||||||
>
|
>
|
||||||
<div class="project-invite-collaborator-containter">
|
<div class="project-code-git-url-container">
|
||||||
|
<button
|
||||||
|
class="project-code-copy-git-url"
|
||||||
|
@click="gotoIssueManage(project)"
|
||||||
|
>
|
||||||
|
{{$t('Issues management')}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="chart-container">
|
||||||
|
<v-chart :option="currentChartData" autoresize />
|
||||||
|
</div>
|
||||||
|
<!-- <div class="project-invite-collaborator-containter">
|
||||||
<button
|
<button
|
||||||
class="accordion-button collapsed"
|
class="accordion-button collapsed"
|
||||||
type="button"
|
type="button"
|
||||||
@ -509,13 +520,10 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<textarea type="text" v-model="newIssueDescriptions[project_index]" />
|
<textarea type="text" v-model="newIssueDescriptions[project_index]" />
|
||||||
<!-- <div class="project-new-issue-action-container">
|
</div>
|
||||||
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
<!-- <div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
class="project-issue-container"
|
class="project-issue-container"
|
||||||
v-for="(issue, issue_index) in project.project.issue.open_issues"
|
v-for="(issue, issue_index) in project.project.issue.open_issues"
|
||||||
@ -593,7 +601,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -700,6 +708,10 @@ export default {
|
|||||||
console.error('unexpected value:' + project.status)
|
console.error('unexpected value:' + project.status)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
gotoIssueManage(project) {
|
||||||
|
// requestIssueUtils.fillProjectIssue(project)
|
||||||
|
this.mnx_navToProjectIssue(project.id)
|
||||||
|
},
|
||||||
fromIntToProjectStatus(statusInt) {
|
fromIntToProjectStatus(statusInt) {
|
||||||
return convertIntoToProjectStatus(statusInt)
|
return convertIntoToProjectStatus(statusInt)
|
||||||
},
|
},
|
||||||
@ -1242,6 +1254,7 @@ export default {
|
|||||||
@extend .w-20;
|
@extend .w-20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
.project-issue-bar-container {
|
.project-issue-bar-container {
|
||||||
@extend .flex-row-container;
|
@extend .flex-row-container;
|
||||||
@extend .justify-content-between;
|
@extend .justify-content-between;
|
||||||
@ -1272,6 +1285,7 @@ export default {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
@extend .initiate-button;
|
@extend .initiate-button;
|
||||||
}
|
}
|
||||||
|
// ...
|
||||||
|
|
||||||
.project-milestones-table {
|
.project-milestones-table {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|||||||
472
frontend/src/pages/user/workspace/projectIssue/Issue.vue
Normal file
472
frontend/src/pages/user/workspace/projectIssue/Issue.vue
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
<template>
|
||||||
|
<div class="workspace-container">
|
||||||
|
<div class="workspace-body">
|
||||||
|
<div class="accordion" id="workspace-project-accordion">
|
||||||
|
<div v-if="project.id" class="accordion-item">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button
|
||||||
|
class="accordion-button collapsed"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#collapse-project-issue"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="collapse-project-issue"
|
||||||
|
>
|
||||||
|
<div class="project-issue-bar-container dashed-container">
|
||||||
|
<div class="project-issue-open-issues">
|
||||||
|
<label class="project-item-label">{{ $t('Summary') }}</label>
|
||||||
|
<p class="project-item-text">{{ project.title }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="project-issue-open-issues">
|
||||||
|
<label class="project-item-label">{{ $t('Open issues') }}</label>
|
||||||
|
<p class="project-item-text">
|
||||||
|
{{ project.project.issue.number_of_open_issues }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="project-issue-resolved-issues">
|
||||||
|
<label class="project-item-label">{{ $t('Resolved issues') }}</label>
|
||||||
|
<p class="project-item-text">
|
||||||
|
{{ project.project.issue.number_of_resolved_issues }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="project-issue-closed-issues">
|
||||||
|
<label class="project-item-label">{{ $t('Closed issues') }}</label>
|
||||||
|
<p class="project-item-text">
|
||||||
|
{{ project.project.issue.number_of_closed_issues }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
id="collapse-project-issue"
|
||||||
|
class="accordion-collapse collapse"
|
||||||
|
data-bs-parent="#collapse-project-issue"
|
||||||
|
>
|
||||||
|
<div class="project-invite-collaborator-containter">
|
||||||
|
<button
|
||||||
|
class="accordion-button collapsed"
|
||||||
|
type="button"
|
||||||
|
ref="issueAddBtn"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#collapse-project-new-issue"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="collapse-project-issue"
|
||||||
|
>
|
||||||
|
<div class="project-invite-collaborator">+ {{ $t('Add Issue') }}</div>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
id="collapse-project-new-issue"
|
||||||
|
class="accordion-collapse collapse"
|
||||||
|
data-bs-parent="#collapse-project-new-issue"
|
||||||
|
>
|
||||||
|
<div class="project-issue-description-container">
|
||||||
|
<div class="project-issue-description">
|
||||||
|
<label class="project-item-label">{{
|
||||||
|
$t('New issue description')
|
||||||
|
}}</label>
|
||||||
|
<button
|
||||||
|
class="project-issue-description-btn"
|
||||||
|
@click="
|
||||||
|
postNewIssue(
|
||||||
|
project.request.product_id,
|
||||||
|
project.project_id,
|
||||||
|
newIssueDescriptions
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ $t('Submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea ref="issueBtn" type="text" v-model="newIssueDescriptions" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="project-issue-container"
|
||||||
|
v-for="(issue, issue_index) in project.project.issue.open_issues"
|
||||||
|
:key="issue_index"
|
||||||
|
:id="'project-issue-' + issue_index"
|
||||||
|
>
|
||||||
|
<div class="accordion-item">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button
|
||||||
|
class="accordion-button collapsed"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
:data-bs-target="'#collapse-project-issue-details' + issue_index"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="collapse-project-issue-details"
|
||||||
|
>
|
||||||
|
<div class="project-issue-header dashed-container">
|
||||||
|
<div class="project-issue-title">
|
||||||
|
<label class="project-item-label">{{ $t('Issue title') }}</label>
|
||||||
|
<p class="project-item-text">{{ issue.title }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="project-issue-status">
|
||||||
|
<label class="project-item-label">{{ $t('Status') }}</label>
|
||||||
|
<p class="project-item-text">
|
||||||
|
{{ fromIntToProjectIssueStatus(issue.status) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="project-issue-update">
|
||||||
|
<label class="project-item-label">{{ $t('Last updated') }}</label>
|
||||||
|
<p class="project-item-text">
|
||||||
|
{{ getDateFromFulltimeString(issue.update_time) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
:id="'collapse-project-issue-details' + issue_index"
|
||||||
|
class="accordion-collapse collapse"
|
||||||
|
:data-bs-parent="'#collapse-project-issue-details' + issue_index"
|
||||||
|
>
|
||||||
|
<div class="project-issue-description-container">
|
||||||
|
<div class="project-issue-description">
|
||||||
|
<label class="project-item-label">{{
|
||||||
|
$t('Issue description')
|
||||||
|
}}</label>
|
||||||
|
<button
|
||||||
|
:hidden="
|
||||||
|
!showIssueActionButton(project.project, issue, 'Resolve')
|
||||||
|
"
|
||||||
|
class="project-issue-description-btn"
|
||||||
|
@click="setProjectIssueStatus(issue.id, 1)"
|
||||||
|
>
|
||||||
|
{{ $t('Resolve') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
:hidden="
|
||||||
|
!showIssueActionButton(project.project, issue, 'Confirm')
|
||||||
|
"
|
||||||
|
class="project-issue-description-btn"
|
||||||
|
@click="setProjectIssueStatus(issue.id, 2)"
|
||||||
|
>
|
||||||
|
{{ $t('Confirm') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
:hidden="!showIssueActionButton(project.project, issue, 'Reopen')"
|
||||||
|
class="project-issue-description-btn"
|
||||||
|
@click="setProjectIssueStatus(issue.id, 0)"
|
||||||
|
>
|
||||||
|
{{ $t('Reopen') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p class="project-item-text">{{ issue.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { DateUtils, WorksapceApi } from '@/utils/index'
|
||||||
|
import { projectStatusEnum, convertIntoToProjectIssueStatus, projectIssueStatusEnum } from '@/types/index'
|
||||||
|
export default {
|
||||||
|
name: 'projectIssue',
|
||||||
|
props: {
|
||||||
|
project_id: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
project: {},
|
||||||
|
newIssueDescriptions: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchView()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchView() {
|
||||||
|
WorksapceApi.fetchWorkspaceView()
|
||||||
|
.then((response) => {
|
||||||
|
const projects = response.data || []
|
||||||
|
for (let i = 0; i < projects.length; i ++) {
|
||||||
|
if (projects[i].id == this.project_id) {
|
||||||
|
this.project = projects[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.mnx_backendErrorHandler(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
isOngoingProject(project) {
|
||||||
|
return project.status == projectStatusEnum.ONGOING
|
||||||
|
},
|
||||||
|
fromIntToProjectIssueStatus(issueStatus) {
|
||||||
|
return convertIntoToProjectIssueStatus(issueStatus)
|
||||||
|
},
|
||||||
|
getDateFromFulltimeString(fulltime) {
|
||||||
|
return DateUtils.FromJsonToDateString(fulltime)
|
||||||
|
},
|
||||||
|
postNewIssue(product_id, project_id, issue_description) {
|
||||||
|
if (issue_description == null || issue_description == '') {
|
||||||
|
alert(this.$t('Please input issue description'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
WorksapceApi.postIssueForProduct(product_id, project_id, issue_description)
|
||||||
|
.then((response) => {
|
||||||
|
this.$refs.issueBtn.blur()
|
||||||
|
this.$refs.issueAddBtn.click()
|
||||||
|
this.fetchView()
|
||||||
|
this.newIssueDescriptions = ''
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.mnx_backendErrorHandler(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setProjectIssueStatus(issue_id, status) {
|
||||||
|
WorksapceApi.setProductIssueStatus(issue_id, status)
|
||||||
|
.then((response) => {
|
||||||
|
this.fetchView()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.mnx_backendErrorHandler(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showIssueActionButton(project, issue, button_text) {
|
||||||
|
switch (issue.status) {
|
||||||
|
case projectIssueStatusEnum.OPEN:
|
||||||
|
if (button_text === this.$t('Resolve')) {
|
||||||
|
return project.providers.includes(project.current_user_id)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
if (button_text === this.$t('Reopen') || button_text === this.$t('Confirm')) {
|
||||||
|
return project.issuers.includes(project.current_user_id)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case projectIssueStatusEnum.CLOSED:
|
||||||
|
if (button_text === this.$t('Reopen')) {
|
||||||
|
return project.issuers.includes(project.current_user_id)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.workspace-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-header {
|
||||||
|
@extend .flex-row-container;
|
||||||
|
@extend .justify-content-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-body {
|
||||||
|
width: 100%;
|
||||||
|
max-width: $body-width;
|
||||||
|
padding: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-bar-container {
|
||||||
|
@extend .flex-row-container;
|
||||||
|
@extend .justify-content-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-resolved-issues {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .w-20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-open-issues {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .w-20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-closed-issues {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .w-20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-last-update {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .w-20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-add-new-issue {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
@extend .initiate-button;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item-label {
|
||||||
|
@extend .label-text-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item-text {
|
||||||
|
@extend .text-start;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.project-invite-collaborator-containter {
|
||||||
|
border-bottom: 1px solid #e1e1e1;
|
||||||
|
|
||||||
|
.accordion-button {
|
||||||
|
// border: 1px solid $primary;
|
||||||
|
// color: $primary;
|
||||||
|
// background-color: #F3F6FF;
|
||||||
|
padding: 12px !important;
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-invite-collaborator {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
@extend .initiate-button;
|
||||||
|
color: $primary;
|
||||||
|
background-color: #f3f6ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-invite-collaborator-form-container {
|
||||||
|
margin: 12px;
|
||||||
|
height: 37px;
|
||||||
|
display: flex;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-radius: 3px;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid #e7e8eb;
|
||||||
|
&:focus-within {
|
||||||
|
border: 1px solid #1748f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 12px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.project-invite-enter {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
padding: 3px;
|
||||||
|
background: #f3f3f5;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-invite-collaborator-form {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .flex-grow-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-invite-collaborator-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-invite-collaborator-action-button {
|
||||||
|
@extend .initiate-button;
|
||||||
|
@extend .float-end;
|
||||||
|
}
|
||||||
|
.project-new-issue-textarea {
|
||||||
|
height: 100px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-new-issue-action-button {
|
||||||
|
@extend .initiate-button;
|
||||||
|
@extend .float-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-new-issue-action-container {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-description-container {
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid #e1e1e1;
|
||||||
|
box-shadow: none;
|
||||||
|
outline: none;
|
||||||
|
height: 100px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.project-issue-description {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
label {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-description-btn {
|
||||||
|
@extend .btn;
|
||||||
|
@extend .btn-link;
|
||||||
|
padding: 0;
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-action-container {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-action-button {
|
||||||
|
@extend .btn;
|
||||||
|
@extend .btn-link;
|
||||||
|
@extend .float-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-statistics-container {
|
||||||
|
@extend .border;
|
||||||
|
height: 100px;
|
||||||
|
@extend .p-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-container {
|
||||||
|
@extend .justify-content-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-title {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .flex-grow-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-status {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .w-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-update {
|
||||||
|
@extend .text-start;
|
||||||
|
@extend .w-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-issue-manage-button {
|
||||||
|
@extend .initiate-button;
|
||||||
|
@extend .float-end;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -23,6 +23,8 @@ import MyWorkspaceRequests from '@/pages/user/workspace/requestManage/Home.vue'
|
|||||||
import IssueRequest from '@/pages/user/workspace/requestIssue/Issue.vue'
|
import IssueRequest from '@/pages/user/workspace/requestIssue/Issue.vue'
|
||||||
import RequestSubmitted from '@/pages/user/workspace/requestIssue/Submitted.vue'
|
import RequestSubmitted from '@/pages/user/workspace/requestIssue/Submitted.vue'
|
||||||
|
|
||||||
|
import ProjectIssue from '@/pages/user/workspace/projectIssue/Issue.vue'
|
||||||
|
|
||||||
//Workspace Proposals
|
//Workspace Proposals
|
||||||
import MyWorkspaceProposals from '@/pages/user/workspace/proposalManage/Home.vue'
|
import MyWorkspaceProposals from '@/pages/user/workspace/proposalManage/Home.vue'
|
||||||
|
|
||||||
@ -170,6 +172,13 @@ const router = createRouter({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'project-issue',
|
||||||
|
path: '/project-issue/:project_id',
|
||||||
|
meta: { requiredRoles: [userRoleEnum.PERSONAL] },
|
||||||
|
components: { default: ProjectIssue, footer: FooterUser, header: HeaderUser },
|
||||||
|
props: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'request-issue2',
|
name: 'request-issue2',
|
||||||
path: '/request-issue/:loadFrom/:requestId',
|
path: '/request-issue/:loadFrom/:requestId',
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { WsConnectionFactory } from '@/utils/backend/websocket'
|
|||||||
import { MessageHubApi } from '@/utils/backend/messageHub'
|
import { MessageHubApi } from '@/utils/backend/messageHub'
|
||||||
|
|
||||||
const ignoreEventType = ['test']
|
const ignoreEventType = ['test']
|
||||||
|
let timer = null
|
||||||
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 = [
|
const unreadWorkspaceRules = [
|
||||||
{subject:'request', event:'quoted'},
|
{subject:'request', event:'quoted'},
|
||||||
@ -23,6 +24,45 @@ const checkUnreadRulesBy = (message, rules = []) => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateConversations =(state, {token ,cb}, data) => {
|
||||||
|
MessageHubApi.fetchConversations(GWT, token).then((response) => {
|
||||||
|
const conversations = response.data.conversations || []
|
||||||
|
let updateLength = 0
|
||||||
|
if (conversations.length === 0) {
|
||||||
|
state.unreadConversationCount = 0
|
||||||
|
localStorage.setItem('unreadConversationCount', 0)
|
||||||
|
}
|
||||||
|
if (data && 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.conversations = conversations
|
||||||
|
localStorage.setItem('conversations', JSON.stringify(conversations))
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
if (cb && cb instanceof Function) {
|
||||||
|
cb(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const basicStore = {
|
const basicStore = {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state() {
|
state() {
|
||||||
@ -46,7 +86,7 @@ const basicStore = {
|
|||||||
token,
|
token,
|
||||||
() => {
|
() => {
|
||||||
// keep
|
// keep
|
||||||
setInterval(() => {
|
timer = setInterval(() => {
|
||||||
state.downstream_web_socket.send('keep alive')
|
state.downstream_web_socket.send('keep alive')
|
||||||
}, 1000 * 60)
|
}, 1000 * 60)
|
||||||
console.log('downstream_web_socket open')
|
console.log('downstream_web_socket open')
|
||||||
@ -80,39 +120,16 @@ const basicStore = {
|
|||||||
state.unreadWorkspace = true
|
state.unreadWorkspace = true
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageHubApi.fetchConversations(GWT, token).then((response) => {
|
updateConversations(state,{token},data)
|
||||||
const conversations = response.data.conversations || []
|
|
||||||
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')
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
console.log('downstream_web_socket closed')
|
if (timer) {
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -128,6 +145,9 @@ const basicStore = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateConversationsPage(state, token) {
|
||||||
|
updateConversations(state, token)
|
||||||
|
},
|
||||||
clearUnreadWorkspace(state) {
|
clearUnreadWorkspace(state) {
|
||||||
state.unreadWorkspace = false
|
state.unreadWorkspace = false
|
||||||
},
|
},
|
||||||
@ -145,6 +165,9 @@ const basicStore = {
|
|||||||
readMessageBy(context, sender) {
|
readMessageBy(context, sender) {
|
||||||
context.commit('readMessageBy', sender)
|
context.commit('readMessageBy', sender)
|
||||||
},
|
},
|
||||||
|
updateConversationsPage(context, {token, cb}) {
|
||||||
|
context.commit('updateConversationsPage', {token, cb})
|
||||||
|
},
|
||||||
clearUnreadWorkspace(context) {
|
clearUnreadWorkspace(context) {
|
||||||
context.commit('clearUnreadWorkspace')
|
context.commit('clearUnreadWorkspace')
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,7 +4,8 @@ const userProfileStore = {
|
|||||||
namespaced: true,
|
namespaced: true,
|
||||||
state() {
|
state() {
|
||||||
return {
|
return {
|
||||||
role: userRoleEnum.NONE
|
role: userRoleEnum.NONE,
|
||||||
|
profile: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@ -16,6 +17,18 @@ const userProfileStore = {
|
|||||||
if (localStorage.role) {
|
if (localStorage.role) {
|
||||||
state.role = Number(localStorage.role)
|
state.role = Number(localStorage.role)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setProfile(state, profile) {
|
||||||
|
state.profile = profile
|
||||||
|
localStorage.setItem('profile', JSON.stringify(profile || {}))
|
||||||
|
},
|
||||||
|
loadProfile(state) {
|
||||||
|
try {
|
||||||
|
const pj = localStorage.getItem('profile')
|
||||||
|
state.profile = JSON.parse(pj)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('err', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@ -24,14 +37,22 @@ const userProfileStore = {
|
|||||||
},
|
},
|
||||||
logoutRoles(context) {
|
logoutRoles(context) {
|
||||||
context.commit('setRole', { role: userRoleEnum.NONE })
|
context.commit('setRole', { role: userRoleEnum.NONE })
|
||||||
|
context.commit('setProfile', {})
|
||||||
},
|
},
|
||||||
loadRoleLocal(context) {
|
loadRoleLocal(context) {
|
||||||
context.commit('loadRole')
|
context.commit('loadRole')
|
||||||
|
context.commit('loadProfile')
|
||||||
|
},
|
||||||
|
updateProfile(context, profile) {
|
||||||
|
context.commit('setProfile', profile)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
userRole(state) {
|
userRole(state) {
|
||||||
return state.role
|
return state.role
|
||||||
|
},
|
||||||
|
profile(state) {
|
||||||
|
return state.profile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,14 @@ class RequestIssueUtils {
|
|||||||
return this.drafted_request
|
return this.drafted_request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fillProjectIssue(issue) {
|
||||||
|
this.projectIssue = issue
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchProjectIssue() {
|
||||||
|
return this.projectIssue
|
||||||
|
}
|
||||||
|
|
||||||
fillTemplatedRequest(request) {
|
fillTemplatedRequest(request) {
|
||||||
this.templated_request = request
|
this.templated_request = request
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user