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*
|
*build*
|
||||||
package-lock.json
|
package-lock.json
|
||||||
.vite
|
.vite
|
||||||
|
.idea
|
||||||
|
|||||||
9
Dockerfile
Normal file → Executable file
@ -2,6 +2,10 @@
|
|||||||
FROM node:lts-alpine as build-stage
|
FROM node:lts-alpine as build-stage
|
||||||
ARG CONTAINER_APP_ROOT="/app"
|
ARG CONTAINER_APP_ROOT="/app"
|
||||||
ARG FRONTEND_PORT=8080
|
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 update npm -g
|
||||||
RUN npm config set "@fortawesome:registry" https://npm.fontawesome.com/
|
RUN npm config set "@fortawesome:registry" https://npm.fontawesome.com/
|
||||||
RUN npm config set "//npm.fontawesome.com/:_authToken" 58624E90-2685-43C6-BF0F-0BFECCE11CD2
|
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/src ./src
|
||||||
COPY frontend/public ./public
|
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
|
RUN npm run build
|
||||||
|
|
||||||
# production stage
|
# 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",
|
"echarts": "^5.5.1",
|
||||||
"graphql": "^16.9.0",
|
"graphql": "^16.9.0",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
|
"jwt-decode": "^4.0.0",
|
||||||
"pdfjs-dist": "^4.3.136",
|
"pdfjs-dist": "^4.3.136",
|
||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"vue": "^3.3.4",
|
"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
6
frontend/src/components/EmptyContent.vue
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="loading || empty" 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="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="">
|
<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>
|
<span v-if="empty && !loading" class="empty-text">{{ $t('No content yet') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -34,11 +34,13 @@ export default {
|
|||||||
width: 188px;
|
width: 188px;
|
||||||
height: 188px;
|
height: 188px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-img {
|
.empty-img {
|
||||||
width: 188px;
|
width: 188px;
|
||||||
height: 188px;
|
height: 188px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-text {
|
.empty-text {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
color: #6e7387;
|
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>
|
<template>
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<div class="header-content">
|
<div class="header-content">
|
||||||
<div class="information-bar" @click="gotoMessages"
|
<div
|
||||||
:class="{ active: activePath == 'message', unread: unreadConversationCount > 0 }">
|
class="information-bar"
|
||||||
|
@click="gotoMessages"
|
||||||
|
:class="{ active: activePath == 'message', unread: unreadConversationCount > 0 }"
|
||||||
|
>
|
||||||
<img alt="freeleaps message" src="@/assets/message.png" />
|
<img alt="freeleaps message" src="@/assets/message.png" />
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-container" role="navigation">
|
<div class="navigation-container" role="navigation">
|
||||||
<button class="navigation-item" @click="gotoWorkspace"
|
<button
|
||||||
:class="{ active: activePath == 'Workspace', badge: unreadWorkspace }">
|
class="navigation-item"
|
||||||
|
@click="gotoWorkspace"
|
||||||
|
:class="{ active: activePath == 'Workspace', badge: unreadWorkspace }"
|
||||||
|
>
|
||||||
<svg-icon icon="workspace" class-name="icon" />
|
<svg-icon icon="workspace" class-name="icon" />
|
||||||
{{ $t('My Work') }}
|
{{ $t('My Work') }}
|
||||||
<div v-if="unreadWorkspace" class="navigation-item-tip">
|
<div v-if="unreadWorkspace" class="navigation-item-tip">
|
||||||
{{ $t('Some update in your work') }}
|
{{ $t('Some update in your work') }}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button class="navigation-item" @click="gotoRequests"
|
<button
|
||||||
:class="{ active: activePath == 'Requests', badge: unreadRequest }">
|
class="navigation-item"
|
||||||
|
@click="gotoRequests"
|
||||||
|
:class="{ active: activePath == 'Requests', badge: unreadRequest }"
|
||||||
|
>
|
||||||
<svg-icon icon="requests" class-name="icon" />
|
<svg-icon icon="requests" class-name="icon" />
|
||||||
{{ $t('Jobs') }}
|
{{ $t('Jobs') }}
|
||||||
<div v-if="unreadRequest" class="navigation-item-tip">
|
<div v-if="unreadRequest" class="navigation-item-tip">
|
||||||
{{ $t('Some update in your request') }}
|
{{ $t('Some update in your request') }}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</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" />
|
<svg-icon icon="providers" class-name="icon" />
|
||||||
{{ $t('Workers') }}
|
{{ $t('Workers') }}
|
||||||
</button>
|
</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" />
|
<svg-icon icon="post" class-name="icon" />
|
||||||
{{ $t('Post a Job') }}
|
{{ $t('Post a Job') }}
|
||||||
</button>
|
</button>
|
||||||
<div class="form-check form-switch header-switch-container" @click="gotoProfile">
|
<div class="form-check form-switch header-switch-container" @click="gotoProfile">
|
||||||
<input class="form-check-input" type="checkbox" role="switch"
|
<input
|
||||||
:checked="userProfile?.account?.provider?.accepting_request" id="personal-earning-now-checkbox" disabled />
|
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">
|
<label class="form-check-label" for="personal-earning-now-checkbox">
|
||||||
<span>{{ $t('Providing service') }}</span>
|
<span>{{ $t('Providing service') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@ -44,10 +67,17 @@
|
|||||||
<laguage-switch class="laguage-switch" />
|
<laguage-switch class="laguage-switch" />
|
||||||
</div>
|
</div>
|
||||||
<div class="profile-container">
|
<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
|
? userProfile?.account?.basic?.photo?.base64
|
||||||
: profileUrl
|
: profileUrl
|
||||||
" />
|
"
|
||||||
|
/>
|
||||||
<ul class="dropdown-menu" aria-labelledby="accountButton">
|
<ul class="dropdown-menu" aria-labelledby="accountButton">
|
||||||
<li>
|
<li>
|
||||||
<button class="account-menu-button" @click="gotoProfile">{{ $t('Profile') }}</button>
|
<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',
|
Goal: 'Goal',
|
||||||
Message: 'Message',
|
Message: 'Message',
|
||||||
'Upload attachment': 'Upload attachment',
|
'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',
|
'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': '每周代码产量',
|
'Lines of code per week': '每周代码产量',
|
||||||
Message: '消息',
|
Message: '消息',
|
||||||
'Upload attachment': '上传附件',
|
'Upload attachment': '上传附件',
|
||||||
'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': '暂无内容',
|
||||||
|
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="form-group">
|
||||||
<div class="input-group-container">
|
<div class="input-group-container">
|
||||||
<div class="form-floating">
|
<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>
|
<label for="inputEmail">{{ $t('Enter email address to start') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn-start" ref="submitButton" @click="trySigninWithEmail()">
|
<button class="btn-start" ref="submitButton" @click="trySigninWithEmail()">
|
||||||
@ -51,6 +57,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
trySigninWithEmail() {
|
trySigninWithEmail() {
|
||||||
|
// Prevent the page from refreshing on form submission
|
||||||
|
event.preventDefault()
|
||||||
this.message = null
|
this.message = null
|
||||||
if (this.email === null || this.email.length < 1) {
|
if (this.email === null || this.email.length < 1) {
|
||||||
this.message = this.$t('Please type in your email')
|
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
22
frontend/src/pages/guest/SigninWithEmailAndCode.vue
Normal file → Executable file
@ -9,8 +9,14 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group-container">
|
<div class="input-group-container">
|
||||||
<div class="form-floating">
|
<div class="form-floating">
|
||||||
<input class="input-email" id="inputCode" type="text" :placeholder="'Code sent to your email'"
|
<input
|
||||||
v-model="code" @focus="inputFocus" />
|
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>
|
<label for="inputCode">{{ $t('Authenticaion Code Sent To Your Email') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn-start">{{ $t('SIGN IN') }}</button>
|
<button type="submit" class="btn-start">{{ $t('SIGN IN') }}</button>
|
||||||
@ -18,9 +24,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="error-msg" v-if="message != null">{{ message }}</p>
|
<p class="error-msg" v-if="message != null">{{ message }}</p>
|
||||||
<p class="error-msg msg-center" v-if="!message">
|
<p class="error-msg msg-center" v-if="!message">
|
||||||
<span>{{ $t('Didn\'t get the email? Check junk folder or') }}</span>
|
<span>{{ $t("Didn't get the email? Check junk folder or") }}</span>
|
||||||
<button class="btn btn-link resend-btn" :disabled="countdown !== 0" type="button"
|
<button
|
||||||
@click="trySigninWithEmail">{{ $t('send again') }}</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>
|
<span v-if="countdown !== 0" class="countdown">({{ countdown }})</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
8
frontend/src/pages/guest/SigninWithEmailAndPassword.vue
Normal file → Executable file
@ -78,6 +78,14 @@ export default {
|
|||||||
|
|
||||||
UserAuthApi.signinByEmail(this.email, this.password)
|
UserAuthApi.signinByEmail(this.email, this.password)
|
||||||
.then((response) => {
|
.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
|
let signinAction = response.data.signin_result
|
||||||
switch (signinAction) {
|
switch (signinAction) {
|
||||||
case signinActionEnum.EXISTING_USER_PASSWORD_REQUIRED:
|
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) {
|
view_link(directory) {
|
||||||
if (directory.content_id)
|
if (directory.content_id) this.mnx_navToPdfContentViewer(directory.content_id)
|
||||||
this.mnx_navToPdfContentViewer(directory.content_id)
|
else if (directory.content_link) this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
||||||
else if (directory.content_link)
|
|
||||||
this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -87,6 +85,7 @@ export default {
|
|||||||
color: #666666;
|
color: #666666;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory-btn {
|
.directory-btn {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|||||||
6
frontend/src/pages/public/Blogs.vue
Normal file → Executable file
@ -32,10 +32,8 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
view_blog(blog) {
|
view_blog(blog) {
|
||||||
if (blog.content_id)
|
if (blog.content_id) this.mnx_navToPdfContentViewer(blog.content_id)
|
||||||
this.mnx_navToPdfContentViewer(blog.content_id)
|
else if (blog.content_link) this.mnx_navToLinkContentViewer(btoa(blog.content_link))
|
||||||
else if (blog.content_link)
|
|
||||||
this.mnx_navToLinkContentViewer(btoa(blog.content_link))
|
|
||||||
},
|
},
|
||||||
retrieve_summary(blog) {
|
retrieve_summary(blog) {
|
||||||
return blog.summary_text
|
return blog.summary_text
|
||||||
|
|||||||
13
frontend/src/pages/public/Career.vue
Normal file → Executable file
@ -1,6 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="career_containter">
|
<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">
|
<p class="career-title">
|
||||||
{{ directory.title_text }}
|
{{ directory.title_text }}
|
||||||
</p>
|
</p>
|
||||||
@ -28,10 +33,8 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
view_link(directory) {
|
view_link(directory) {
|
||||||
if (directory.content_id)
|
if (directory.content_id) this.mnx_navToPdfContentViewer(directory.content_id)
|
||||||
this.mnx_navToPdfContentViewer(directory.content_id)
|
else if (directory.content_link) this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
||||||
else if (directory.content_link)
|
|
||||||
this.mnx_navToLinkContentViewer(btoa(directory.content_link))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|||||||