Compare commits
17 Commits
bd704a4691
...
1078f9759a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1078f9759a | ||
| 7f8ca4503d | |||
|
|
4d0d5d3884 | ||
|
|
0cfde7cad2 | ||
| 8523041810 | |||
|
|
878da11d40 | ||
|
|
a17d9d07a2 | ||
|
|
f9345c3e35 | ||
|
|
21fccd4969 | ||
| ee71097034 | |||
| 1abbb121c0 | |||
| 0628ad507f | |||
| 8632070391 | |||
| c1fb9cfa50 | |||
| 2f73d454bb | |||
| 0ea55d7e44 | |||
|
|
e56f544b4a |
1
.gitignore
vendored
Normal file → Executable file
@ -14,3 +14,4 @@ ythe.sh
|
||||
*build*
|
||||
package-lock.json
|
||||
.vite
|
||||
.idea
|
||||
|
||||
9
Dockerfile
Normal file → Executable file
@ -2,6 +2,10 @@
|
||||
FROM node:lts-alpine as build-stage
|
||||
ARG CONTAINER_APP_ROOT="/app"
|
||||
ARG FRONTEND_PORT=8080
|
||||
# TODO: further testing before turning on
|
||||
# ARG ZOOM_CLIENT_ID
|
||||
# ARG ZOOM_REDIRECT_URI
|
||||
# ARG ZOOM_SCOPE
|
||||
RUN npm update npm -g
|
||||
RUN npm config set "@fortawesome:registry" https://npm.fontawesome.com/
|
||||
RUN npm config set "//npm.fontawesome.com/:_authToken" 58624E90-2685-43C6-BF0F-0BFECCE11CD2
|
||||
@ -17,6 +21,11 @@ COPY frontend/*.html ./
|
||||
COPY frontend/src ./src
|
||||
COPY frontend/public ./public
|
||||
|
||||
# TODO: further testing before turning on
|
||||
# RUN echo "VUE_APP_ZOOM_CLIENT_ID=${ZOOM_CLIENT_ID}" >> .env
|
||||
# RUN echo "VUE_APP_ZOOM_REDIRECT_URI=${ZOOM_REDIRECT_URI}" >> .env
|
||||
# RUN echo "VUE_APP_ZOOM_SCOPE=${ZOOM_SCOPE}" >> .env
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# production stage
|
||||
|
||||
0
frontend/.eslintrc.cjs
Normal file → Executable file
0
frontend/.gitignore
vendored
Normal file → Executable file
0
frontend/.prettierrc.json
Normal file → Executable file
0
frontend/README.md
Normal file → Executable file
1
frontend/frontend
Symbolic link
@ -0,0 +1 @@
|
||||
../freeleaps2-frontend/frontend
|
||||
0
frontend/index.html
Normal file → Executable file
0
frontend/nginx_docker.conf
Normal file → Executable file
1
frontend/package.json
Normal file → Executable file
@ -19,6 +19,7 @@
|
||||
"echarts": "^5.5.1",
|
||||
"graphql": "^16.9.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"pdfjs-dist": "^4.3.136",
|
||||
"pinia": "^2.1.6",
|
||||
"vue": "^3.3.4",
|
||||
|
||||
0
frontend/public/favicon.ico
Normal file → Executable file
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
0
frontend/src/App.vue
Normal file → Executable file
0
frontend/src/assets/account.png
Normal file → Executable file
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
0
frontend/src/assets/base.css
Normal file → Executable file
0
frontend/src/assets/freeleaps.png
Normal file → Executable file
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
0
frontend/src/assets/images/default-user-portrait.png
Normal file → Executable file
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
0
frontend/src/assets/images/home-bg-left.png
Normal file → Executable file
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
0
frontend/src/assets/images/home-bg-right.png
Normal file → Executable file
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
0
frontend/src/assets/images/lab-translation.png
Normal file → Executable file
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
0
frontend/src/assets/images/loading.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
0
frontend/src/assets/images/no_content.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
0
frontend/src/assets/images/qr-code.png
Normal file → Executable file
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
0
frontend/src/assets/images/submited.png
Normal file → Executable file
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
0
frontend/src/assets/images/wechat_qr_code_upload.png
Normal file → Executable file
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
0
frontend/src/assets/lang/us.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
0
frontend/src/assets/lang/zh.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
frontend/src/assets/logo.png
Normal file → Executable file
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
0
frontend/src/assets/logo.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 757 B After Width: | Height: | Size: 757 B |
0
frontend/src/assets/main.css
Normal file → Executable file
0
frontend/src/assets/message.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
frontend/src/assets/profile.png
Normal file → Executable file
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
0
frontend/src/assets/styles/_sizing.scss
Normal file → Executable file
0
frontend/src/assets/styles/_utilities.scss
Normal file → Executable file
0
frontend/src/assets/styles/_variables.scss
Normal file → Executable file
0
frontend/src/assets/styles/buttons.scss
Normal file → Executable file
0
frontend/src/assets/styles/components.scss
Normal file → Executable file
0
frontend/src/assets/styles/containers.scss
Normal file → Executable file
0
frontend/src/assets/styles/focused_input.scss
Normal file → Executable file
0
frontend/src/assets/styles/inputs.scss
Normal file → Executable file
0
frontend/src/assets/styles/main.scss
Normal file → Executable file
0
frontend/src/assets/styles/story_board.scss
Normal file → Executable file
0
frontend/src/assets/styles/texts.scss
Normal file → Executable file
72
frontend/src/components/CustomChart.vue
Executable file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<v-chart ref="customChart" :option="option" autoresize />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { use } from 'echarts/core'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { LineChart, BarChart } from 'echarts/charts'
|
||||
import { GridComponent, LegendComponent, TooltipComponent, DataZoomComponent } from 'echarts/components'
|
||||
import VChart from 'vue-echarts'
|
||||
use([CanvasRenderer, LineChart, LegendComponent, GridComponent, TooltipComponent, BarChart, DataZoomComponent])
|
||||
|
||||
export default {
|
||||
name: 'CustomChart',
|
||||
props: {
|
||||
customOption: { type: Object, default: () => {} }
|
||||
},
|
||||
components: {
|
||||
VChart,
|
||||
},
|
||||
computed: {
|
||||
option() {
|
||||
if (this.customOption) {
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
textStyle: {
|
||||
align: 'left'
|
||||
},
|
||||
...this.customOption?.tooltip
|
||||
},
|
||||
legend: {
|
||||
data: this.customOption.series.map(ser => ser.name) || [],
|
||||
...this.customOption?.legend
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLabel: {
|
||||
showMaxLabel: true,
|
||||
showMinLabel: true
|
||||
},
|
||||
boundaryGap: false,
|
||||
...this.customOption?.xAxis
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
...this.customOption?.yAxis
|
||||
},
|
||||
dataZoom: [{
|
||||
type: 'slider',
|
||||
startValue: 0,
|
||||
endValue: 3,
|
||||
show: this.customOption?.xAxis?.data?.length > 4
|
||||
}],
|
||||
series: this.customOption.series || [],
|
||||
}
|
||||
return option
|
||||
}
|
||||
return {}
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
// 手动销毁实例
|
||||
if (this.$refs.customChart && this.$refs.customChart.dispose) {
|
||||
this.$refs.customChart.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
0
frontend/src/components/CustomPagination.vue
Normal file → Executable file
8
frontend/src/components/EmptyContent.vue
Normal file → Executable file
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<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="">
|
||||
<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">{{ $t('No content yet') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
@ -34,11 +34,13 @@ export default {
|
||||
width: 188px;
|
||||
height: 188px;
|
||||
}
|
||||
|
||||
.empty-img {
|
||||
width: 188px;
|
||||
height: 188px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 26px;
|
||||
color: #6e7387;
|
||||
|
||||
0
frontend/src/components/FreeleapsEditor.vue
Normal file → Executable file
0
frontend/src/components/InputSelector.vue
Normal file → Executable file
0
frontend/src/components/LaguageSwitch.vue
Normal file → Executable file
58
frontend/src/components/LineChart.vue
Executable file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<v-chart ref="lineChart" :option="option" autoresize />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { use } from 'echarts/core'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { LineChart } from 'echarts/charts'
|
||||
import { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
|
||||
import VChart from 'vue-echarts'
|
||||
use([CanvasRenderer, LineChart, LegendComponent, GridComponent, TooltipComponent])
|
||||
|
||||
export default {
|
||||
name: 'LineChart',
|
||||
props: {
|
||||
data: { type: Object, default: () => {} }
|
||||
},
|
||||
components: {
|
||||
VChart,
|
||||
},
|
||||
computed: {
|
||||
option() {
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: this.data.series.map(ser => ser.name) || []
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: this.data.xData || [],
|
||||
axisLabel: {
|
||||
showMaxLabel: true,
|
||||
showMinLabel: true
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
minInterval: 1
|
||||
},
|
||||
series: this.data.series || []
|
||||
}
|
||||
return option
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
// 手动销毁实例
|
||||
if (this.$refs.lineChart && this.$refs.lineChart.dispose) {
|
||||
this.$refs.lineChart.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
0
frontend/src/components/PDFReader.vue
Normal file → Executable file
0
frontend/src/components/SvgIcon.vue
Normal file → Executable file
0
frontend/src/footers/FooterGuest.vue
Normal file → Executable file
0
frontend/src/footers/FooterUser.vue
Normal file → Executable file
0
frontend/src/headers/HeaderGuest.vue
Normal file → Executable file
54
frontend/src/headers/HeaderUser.vue
Normal file → Executable file
@ -2,38 +2,61 @@
|
||||
<template>
|
||||
<div class="header-container">
|
||||
<div class="header-content">
|
||||
<div class="information-bar" @click="gotoMessages"
|
||||
:class="{ active: activePath == 'message', unread: unreadConversationCount > 0 }">
|
||||
<div
|
||||
class="information-bar"
|
||||
@click="gotoMessages"
|
||||
:class="{ active: activePath == 'message', unread: unreadConversationCount > 0 }"
|
||||
>
|
||||
<img alt="freeleaps message" src="@/assets/message.png" />
|
||||
</div>
|
||||
<div class="navigation-container" role="navigation">
|
||||
<button class="navigation-item" @click="gotoWorkspace"
|
||||
:class="{ active: activePath == 'Workspace', badge: unreadWorkspace }">
|
||||
<button
|
||||
class="navigation-item"
|
||||
@click="gotoWorkspace"
|
||||
:class="{ active: activePath == 'Workspace', badge: unreadWorkspace }"
|
||||
>
|
||||
<svg-icon icon="workspace" class-name="icon" />
|
||||
{{ $t('My Work') }}
|
||||
<div v-if="unreadWorkspace" class="navigation-item-tip">
|
||||
{{ $t('Some update in your work') }}
|
||||
</div>
|
||||
</button>
|
||||
<button class="navigation-item" @click="gotoRequests"
|
||||
:class="{ active: activePath == 'Requests', badge: unreadRequest }">
|
||||
<button
|
||||
class="navigation-item"
|
||||
@click="gotoRequests"
|
||||
:class="{ active: activePath == 'Requests', badge: unreadRequest }"
|
||||
>
|
||||
<svg-icon icon="requests" class-name="icon" />
|
||||
{{ $t('Jobs') }}
|
||||
<div v-if="unreadRequest" class="navigation-item-tip">
|
||||
{{ $t('Some update in your request') }}
|
||||
</div>
|
||||
</button>
|
||||
<button class="navigation-item" @click="gotoProviders" :class="activePath == 'Providers' ? 'active' : ''">
|
||||
<button
|
||||
class="navigation-item"
|
||||
@click="gotoProviders"
|
||||
:class="activePath == 'Providers' ? 'active' : ''"
|
||||
>
|
||||
<svg-icon icon="providers" class-name="icon" />
|
||||
{{ $t('Workers') }}
|
||||
</button>
|
||||
<button class="navigation-item" @click="gotoIssueRequest" :class="activePath == 'Post' ? 'active' : ''">
|
||||
<button
|
||||
class="navigation-item"
|
||||
@click="gotoIssueRequest"
|
||||
:class="activePath == 'Post' ? 'active' : ''"
|
||||
>
|
||||
<svg-icon icon="post" class-name="icon" />
|
||||
{{ $t('Post a Job') }}
|
||||
</button>
|
||||
<div class="form-check form-switch header-switch-container" @click="gotoProfile">
|
||||
<input class="form-check-input" type="checkbox" role="switch"
|
||||
:checked="userProfile?.account?.provider?.accepting_request" id="personal-earning-now-checkbox" disabled />
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
:checked="userProfile?.account?.provider?.accepting_request"
|
||||
id="personal-earning-now-checkbox"
|
||||
disabled
|
||||
/>
|
||||
<label class="form-check-label" for="personal-earning-now-checkbox">
|
||||
<span>{{ $t('Providing service') }}</span>
|
||||
</label>
|
||||
@ -44,10 +67,17 @@
|
||||
<laguage-switch class="laguage-switch" />
|
||||
</div>
|
||||
<div class="profile-container">
|
||||
<img alt="freeleaps logo" data-bs-toggle="dropdown" aria-expanded="false" id="accountButton" :src="userProfile?.account?.basic?.photo?.base64
|
||||
<img
|
||||
alt="freeleaps logo"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
id="accountButton"
|
||||
:src="
|
||||
userProfile?.account?.basic?.photo?.base64
|
||||
? userProfile?.account?.basic?.photo?.base64
|
||||
: profileUrl
|
||||
" />
|
||||
"
|
||||
/>
|
||||
<ul class="dropdown-menu" aria-labelledby="accountButton">
|
||||
<li>
|
||||
<button class="account-menu-button" @click="gotoProfile">{{ $t('Profile') }}</button>
|
||||
|
||||
0
frontend/src/icons/back.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 214 B |
0
frontend/src/icons/btn-history.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 821 B After Width: | Height: | Size: 821 B |
0
frontend/src/icons/btn-templates.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
0
frontend/src/icons/delete.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
0
frontend/src/icons/dropdown.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 307 B |
0
frontend/src/icons/fe-alignjustify.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 583 B |
0
frontend/src/icons/fe-back.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 325 B |
0
frontend/src/icons/fe-bold.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 537 B |
0
frontend/src/icons/fe-char.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 307 B |
0
frontend/src/icons/fe-clear.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 968 B After Width: | Height: | Size: 968 B |
0
frontend/src/icons/fe-italic.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 347 B |
0
frontend/src/icons/fe-link.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
0
frontend/src/icons/fe-orderedlist.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 926 B |
0
frontend/src/icons/fe-paragraph.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 468 B |
0
frontend/src/icons/fe-strike.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
0
frontend/src/icons/fe-underline.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 515 B After Width: | Height: | Size: 515 B |
0
frontend/src/icons/fe-unorderedlist.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 455 B |
0
frontend/src/icons/msg-enter.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 843 B After Width: | Height: | Size: 843 B |
0
frontend/src/icons/post.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
0
frontend/src/icons/providers.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 649 B |
0
frontend/src/icons/requests.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
0
frontend/src/icons/workspace.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
8
frontend/src/lang/en.js
Normal file → Executable file
@ -215,8 +215,10 @@ export default {
|
||||
Goal: 'Goal',
|
||||
Message: 'Message',
|
||||
'Upload attachment': 'Upload attachment',
|
||||
'Didn\'t get the email? Check junk folder or': 'Didn\'t get the email? Check junk folder or ',
|
||||
"Didn't get the email? Check junk folder or": "Didn't get the email? Check junk folder or ",
|
||||
'send again': 'send again',
|
||||
'No content yet': 'No content yet'
|
||||
|
||||
'No content yet': 'No content yet',
|
||||
'open': 'open',
|
||||
'resolved': 'resolved',
|
||||
'unresolved': 'unresolved'
|
||||
}
|
||||
|
||||
0
frontend/src/lang/index.js
Normal file → Executable file
17
frontend/src/lang/zh.js
Normal file → Executable file
@ -213,7 +213,20 @@ export default {
|
||||
'Lines of code per week': '每周代码产量',
|
||||
Message: '消息',
|
||||
'Upload attachment': '上传附件',
|
||||
'Didn\'t get the email? Check junk folder or': '没收到邮件?检查垃圾文件夹或',
|
||||
"Didn't get the email? Check junk folder or": '没收到邮件?检查垃圾文件夹或',
|
||||
'send again': '重新发送',
|
||||
'No content yet': '暂无内容'
|
||||
'No content yet': '暂无内容',
|
||||
OUTSTANDING: '进行中',
|
||||
PAID: '已付款',
|
||||
DONE: '已完成',
|
||||
RECRUITING: '招人中',
|
||||
ONGOING: '进行中',
|
||||
PENDING: '待确认',
|
||||
CLOSED: '已关闭',
|
||||
REJECTED: '已拒绝',
|
||||
APPLYING: '申请中',
|
||||
ACCEPTING: '接受中',
|
||||
'open': '未解决',
|
||||
'resolved': '已解决',
|
||||
'unresolved': '未解决总计'
|
||||
}
|
||||
|
||||
0
frontend/src/main.js
Normal file → Executable file
0
frontend/src/mixins/errorHandler.js
Normal file → Executable file
0
frontend/src/mixins/index.js
Normal file → Executable file
0
frontend/src/mixins/navigator.js
Normal file → Executable file
0
frontend/src/mixins/userAuth.js
Normal file → Executable file
0
frontend/src/mixins/userIdentity.js
Normal file → Executable file
10
frontend/src/pages/guest/FrontDoor.vue
Normal file → Executable file
@ -8,7 +8,13 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group-container">
|
||||
<div class="form-floating">
|
||||
<input class="input-email" id="inputEmail" type="text" placeholder="name@example.com" v-model="email" />
|
||||
<input
|
||||
class="input-email"
|
||||
id="inputEmail"
|
||||
type="text"
|
||||
placeholder="name@example.com"
|
||||
v-model="email"
|
||||
/>
|
||||
<label for="inputEmail">{{ $t('Enter email address to start') }}</label>
|
||||
</div>
|
||||
<button class="btn-start" ref="submitButton" @click="trySigninWithEmail()">
|
||||
@ -51,6 +57,8 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
trySigninWithEmail() {
|
||||
// Prevent the page from refreshing on form submission
|
||||
event.preventDefault()
|
||||
this.message = null
|
||||
if (this.email === null || this.email.length < 1) {
|
||||
this.message = this.$t('Please type in your email')
|
||||
|
||||
0
frontend/src/pages/guest/NewUserSetFlid.vue
Normal file → Executable file
0
frontend/src/pages/guest/NewUserSetPassword.vue
Normal file → Executable file
24
frontend/src/pages/guest/SigninWithEmailAndCode.vue
Normal file → Executable file
@ -9,8 +9,14 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group-container">
|
||||
<div class="form-floating">
|
||||
<input class="input-email" id="inputCode" type="text" :placeholder="'Code sent to your email'"
|
||||
v-model="code" @focus="inputFocus" />
|
||||
<input
|
||||
class="input-email"
|
||||
id="inputCode"
|
||||
type="text"
|
||||
:placeholder="'Code sent to your email'"
|
||||
v-model="code"
|
||||
@focus="inputFocus"
|
||||
/>
|
||||
<label for="inputCode">{{ $t('Authenticaion Code Sent To Your Email') }}</label>
|
||||
</div>
|
||||
<button type="submit" class="btn-start">{{ $t('SIGN IN') }}</button>
|
||||
@ -18,9 +24,15 @@
|
||||
</div>
|
||||
<p class="error-msg" v-if="message != null">{{ message }}</p>
|
||||
<p class="error-msg msg-center" v-if="!message">
|
||||
<span>{{ $t('Didn\'t get the email? Check junk folder or') }}</span>
|
||||
<button class="btn btn-link resend-btn" :disabled="countdown !== 0" type="button"
|
||||
@click="trySigninWithEmail">{{ $t('send again') }}</button>
|
||||
<span>{{ $t("Didn't get the email? Check junk folder or") }}</span>
|
||||
<button
|
||||
class="btn btn-link resend-btn"
|
||||
:disabled="countdown !== 0"
|
||||
type="button"
|
||||
@click="trySigninWithEmail"
|
||||
>
|
||||
{{ $t('send again') }}
|
||||
</button>
|
||||
<span v-if="countdown !== 0" class="countdown">({{ countdown }})</span>
|
||||
</p>
|
||||
</div>
|
||||
@ -52,7 +64,7 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
created() { },
|
||||
created() {},
|
||||
mounted() {
|
||||
if (this.mnx_IsKeepUserSignedIn() && this.mnx_isUserAuthenticated()) {
|
||||
this.mnx_navAfterSignedin()
|
||||
|
||||
8
frontend/src/pages/guest/SigninWithEmailAndPassword.vue
Normal file → Executable file
@ -78,6 +78,14 @@ export default {
|
||||
|
||||
UserAuthApi.signinByEmail(this.email, this.password)
|
||||
.then((response) => {
|
||||
// Extract the necessary data from the response
|
||||
const { access_token, refresh_token, expires_in } = response.data
|
||||
|
||||
// Save tokens and expiration time in localStorage
|
||||
localStorage.setItem('access_token', access_token)
|
||||
localStorage.setItem('refresh_token', refresh_token)
|
||||
localStorage.setItem('expires_in', expires_in)
|
||||
|
||||
let signinAction = response.data.signin_result
|
||||
switch (signinAction) {
|
||||
case signinActionEnum.EXISTING_USER_PASSWORD_REQUIRED:
|
||||
|
||||
0
frontend/src/pages/lab/Home.vue
Normal file → Executable file
0
frontend/src/pages/lab/openai/ImageGeneration.vue
Normal file → Executable file
0
frontend/src/pages/lab/openai/MultiturnChat.vue
Normal file → Executable file
0
frontend/src/pages/lab/openai/TaskCompletion.vue
Normal file → Executable file
0
frontend/src/pages/lab/translation/Home.vue
Normal file → Executable file
7
frontend/src/pages/public/About.vue
Normal file → Executable file
@ -33,10 +33,8 @@ export default {
|
||||
})
|
||||
},
|
||||
view_link(directory) {
|
||||
if (directory.content_id)
|
||||
this.mnx_navToPdfContentViewer(directory.content_id)
|
||||
else if (directory.content_link)
|
||||
this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
||||
if (directory.content_id) this.mnx_navToPdfContentViewer(directory.content_id)
|
||||
else if (directory.content_link) this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -87,6 +85,7 @@ export default {
|
||||
color: #666666;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.directory-btn {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
6
frontend/src/pages/public/Blogs.vue
Normal file → Executable file
@ -32,10 +32,8 @@ export default {
|
||||
})
|
||||
},
|
||||
view_blog(blog) {
|
||||
if (blog.content_id)
|
||||
this.mnx_navToPdfContentViewer(blog.content_id)
|
||||
else if (blog.content_link)
|
||||
this.mnx_navToLinkContentViewer(btoa(blog.content_link))
|
||||
if (blog.content_id) this.mnx_navToPdfContentViewer(blog.content_id)
|
||||
else if (blog.content_link) this.mnx_navToLinkContentViewer(btoa(blog.content_link))
|
||||
},
|
||||
retrieve_summary(blog) {
|
||||
return blog.summary_text
|
||||
|
||||
13
frontend/src/pages/public/Career.vue
Normal file → Executable file
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div class="career_containter">
|
||||
<div class="career-item" v-for="(directory, index) in directories" :key="index" @click="view_link(directory)">
|
||||
<div
|
||||
class="career-item"
|
||||
v-for="(directory, index) in directories"
|
||||
:key="index"
|
||||
@click="view_link(directory)"
|
||||
>
|
||||
<p class="career-title">
|
||||
{{ directory.title_text }}
|
||||
</p>
|
||||
@ -28,10 +33,8 @@ export default {
|
||||
})
|
||||
},
|
||||
view_link(directory) {
|
||||
if (directory.content_id)
|
||||
this.mnx_navToPdfContentViewer(directory.content_id)
|
||||
else if (directory.content_link)
|
||||
this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
||||
if (directory.content_id) this.mnx_navToPdfContentViewer(directory.content_id)
|
||||
else if (directory.content_link) this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
||||