This commit is contained in:
min.jiang 2024-08-09 03:37:17 +08:00
parent 336c31a345
commit df196385e4
8 changed files with 99 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,6 +1,8 @@
<template>
<div class="empty-content-container" :class="{autoFit : 'auto-fit'}">
<div v-if="loading || empty" class="empty-content-container" :class="{autoFit : 'auto-fit'}">
<img v-if="loading" src="@/assets/images/loading.gif" class="loading-big" alt="">
<img v-if="empty && !loading" src="@/assets/images/no_content.jpg" class="empty-img" alt="">
<span v-if="empty && !loading" class="empty-text">No content yet</span>
</div>
</template>
@ -8,7 +10,9 @@
export default {
name: 'EmptyContent',
props: {
autoFit: { type: Boolean, default: false }
autoFit: { type: Boolean, default: false },
loading: { type: Boolean, default: true },
empty: { type: Boolean, default: false }
}
}
</script>
@ -19,10 +23,15 @@ export default {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
&.auto-fit {
width: 100%;
height: 100%;
}
.loading-big {width: 188px; height: 188px;}
.empty-img {width: 188px; height: 188px; margin-bottom: 15px;}
.empty-text {font-size: 26px; color: #6E7387;}
}
</style>

View File

@ -227,6 +227,9 @@ export default {
img {
width: 56px;
height: 56px;
overflow: hidden;
border-radius: 50%;
}
}
@ -286,6 +289,12 @@ export default {
position: relative;
cursor: pointer;
&:hover {
.header-switch-desc {
display: block;
}
}
.header-switch-desc {
position: absolute;
background-color: white;
@ -295,6 +304,7 @@ export default {
color: #3d455f;
white-space: nowrap;
padding: 2px 5px;
display: none;
}
}

View File

@ -204,15 +204,19 @@
<div class="collapse collapse-content-container" id="collapse-personal-user-photo"
aria-labelledby="personal-summary" data-bs-parent="#personal-panel">
<div class="collapse-item-container">
<div class="collapse-item-container column-flex">
<label class="btn btn-link" for="personal-photo-operation-image">
<img class="user-portrait-img" id="personal-photo-operation-image" alt="user portrait" :src="userProfile.account.basic.photo.base64
? userProfile.account.basic.photo.base64
: profileUrl
" v-tooltip title="Click to update" @click="selectUserPhoto()" />
<div v-if="photoLoading" class="spinner-container">
<div class="spinner-border text-primary" role="status" />
</div>
</label>
<input ref="uploadUserPhotoInput" type="file" :accept="identityOperation.photo.acceptableType" hidden
@change="onUserPhotoChange($event)" />
<p v-if="message">{{message}}</p>
</div>
</div>
<div class="collapse collapse-content-container" id="collapse-personal-user-intro"
@ -264,7 +268,7 @@
}}</span>
</div>
</div>
<div class="collapse-item-container">
<div class="collapse-item-container column-flex">
<label v-if="Is_Wechat_QR_Code_Payment()" class="collapse-item-uploader" for="qr-uploader">
<img v-if="paymentOperation.wechat_qr_code_img.data" class="uploader-img-show"
:src="paymentOperation.wechat_qr_code_img.data" />
@ -273,10 +277,14 @@
<span v-if="!paymentOperation.wechat_qr_code_img.data" class="upload-text-btn">{{
$t('Upload QR code to receive payment')
}}</span>
<div v-if="photoLoading" class="spinner-container">
<div class="spinner-border text-primary" role="status" />
</div>
</label>
<input v-if="Is_Wechat_QR_Code_Payment()" ref="uploadWechatQRCodePhotoInput" type="file" id="qr-uploader"
:accept="paymentOperation.wechat_qr_code_img.acceptableType" hidden
@change="onUploadWechatQRCodePhoto($event)" />
<p v-if="message">{{message}}</p>
</div>
<div v-if="Is_Stripe_Payment()" class="collapse-item-container">
<span>{{ $t('Have you linked your strip account?') }}</span><button class="btn btn-link"
@ -491,7 +499,7 @@ export default {
name: 'UserProfile',
props: {},
mounted() {
this.fetchProfile()
// this.fetchProfile()
this.fetchTemplates()
},
watch: {
@ -518,12 +526,21 @@ export default {
}
},
deep: true
},
userProfile() {
this.fetchProfile()
}
},
computed: {
userProfile() {
return this.$store.getters['userProfile/profile']
}
},
data() {
return {
profileUrl,
userProfile: null,
// userProfile: null,
photoLoading: false,
message: null,
accountNeedAttention: false,
availableTemplates: null,
@ -593,7 +610,7 @@ export default {
methods: {
fetchProfile() {
this.userProfile = this.$store.getters['userProfile/profile']
// this.userProfile = this.$store.getters['userProfile/profile']
this.updateLocalIdentityData()
this.updateLocalEmailData()
this.updateLocalMobileData()
@ -645,9 +662,11 @@ export default {
this.userProfile.account.basic.photo = response.data.photo
this.updateLocalIdentityData()
this.updateLocalProfileData()
this.photoLoading = false
})
.catch((error) => {
this.mnx_backendErrorHandler(error)
this.photoLoading = false
})
},
selectUserPhoto() {
@ -656,12 +675,15 @@ export default {
onUserPhotoChange(event) {
let file = event.target.files[0]
let reader = new FileReader()
this.message = null
this.photoLoading = true
reader.addEventListener(
'load',
function () {
this.identityOperation.photo.base64 = reader.result
this.identityOperation.photo.filename = file.name
if (file.size > this.identityOperation.photo.filesizeLimit) {
this.photoLoading = false
this.message =
'file need to be smaller than ' +
this.identityOperation.photo.filesizeLimit +
@ -988,8 +1010,10 @@ export default {
if (response.data.account_link != '') {
window.location = 'user-profile'
}
this.photoLoading = false
})
.catch((error) => {
this.photoLoading = false
this.mnx_backendErrorHandler(error)
})
},
@ -999,6 +1023,8 @@ export default {
onUploadWechatQRCodePhoto(event) {
let file = event.target.files[0]
let reader = new FileReader()
this.message = null
this.photoLoading = true
reader.addEventListener(
'load',
function () {
@ -1009,6 +1035,7 @@ export default {
'file need to be smaller than ' +
this.paymentOperation.wechat_qr_code_img.filesizeLimit +
' byptes'
this.photoLoading = false
} else {
this.updateWechatQRCode(reader.result, file.name)
}
@ -1133,9 +1160,31 @@ export default {
align-items: center;
justify-content: center;
&.column-flex {
flex-direction: column;
}
.btn-link {
position: relative;
}
.spinner-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
background-color: rgba(0,0,0,.3);
justify-content: center;
align-items: center;
}
.user-portrait-img {
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
}
.collapse-item-editor {
@ -1210,6 +1259,7 @@ export default {
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
&:hover {
opacity: 0.78;

View File

@ -1,4 +1,5 @@
<template>
<empty-content :loading="loading" :empty="recommendedProviders?.length === 0" />
<div class="provider-hub-container" id="provider-accordion-container">
<template v-if="recommendedProviders">
<div
@ -280,15 +281,19 @@
<script>
import { ProviderHubApi } from '@/utils/index'
import EmptyContent from '@/components/EmptyContent.vue'
export default {
components: { EmptyContent },
name: 'ProviderHub',
props: {},
mounted() {
this.loading = true
this.fetchProviders()
this.fetchRequests()
},
data() {
return {
loading: false,
recommendedProviders: null,
checkedRequests: [],
requests: null,
@ -300,9 +305,11 @@ export default {
fetchProviders() {
ProviderHubApi.fetchProvidersForHub()
.then((response) => {
this.loading = false
this.recommendedProviders = response.data.recommended
})
.catch((error) => {
this.loading = false
this.mnx_backendErrorHandler(error)
})
},

View File

@ -1,4 +1,5 @@
<template>
<empty-content :loading="loading" :empty="requestGroups?.length === 0" />
<div class="request-hub">
<div
v-for="(group, index) in requestGroups"
@ -223,16 +224,19 @@
<script>
import { RequestHubApi, WorksapceApi, DateUtils, requestHubUtils } from '@/utils/index'
import { proposingModelEnum } from '@/types/index'
import EmptyContent from '@/components/EmptyContent.vue'
import PDFReader from '@/components/PDFReader.vue'
export default {
components: { PDFReader },
components: { PDFReader, EmptyContent },
name: 'RequestHub',
props: {},
mounted() {
this.loading = true
this.fetchRequests()
},
data() {
return {
loading: false,
requestGroups: [],
message: null,
pdfDocument: {}
@ -245,8 +249,10 @@ export default {
.then((response) => {
this.requestGroups = response.data
this.$store.dispatch('basic/clearUnreadRequest')
this.loading = false
})
.catch((error) => {
this.loading = false
this.mnx_backendErrorHandler(error)
})
},

View File

@ -1,6 +1,6 @@
<template>
<div class="workspace-container">
<!-- <div class="workspace-header"></div> -->
<empty-content :loading="loading" :empty="projects?.length === 0" />
<div v-if="projects && projects.length > 0" class="workspace-container">
<div class="workspace-body">
<div class="accordion accordion-list" v-for="(project, project_index) in projects" :key="project_index"
:id="project.id">
@ -510,12 +510,14 @@ import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
import { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
import VChart from 'vue-echarts'
import EmptyContent from '@/components/EmptyContent.vue'
use([CanvasRenderer, LineChart, LegendComponent, GridComponent, TooltipComponent])
export default {
name: 'Workspace',
components: { VChart },
components: { VChart, EmptyContent },
props: {},
mounted() {
this.loading = true
this.fetchView()
// this.connectWebSocket()
},
@ -523,6 +525,7 @@ export default {
return {
projects: null,
message: null,
loading: false,
newIssueDescriptions: null,
newInviteCollaborator: null,
qrCode: {
@ -561,8 +564,10 @@ export default {
this.newIssueDescriptions = new Array(this.projects.length)
this.newInviteCollaborator = new Array(this.projects.length)
this.$store.dispatch('basic/clearUnreadWorkspace')
this.loading = false
})
.catch((error) => {
this.loading = false
this.mnx_backendErrorHandler(error)
})
},