Skip to content

Commit 962401d

Browse files
committed
Vue 3 migration almost complete
1 parent b400bcb commit 962401d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+17455
-37026
lines changed

backend/src/app.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,14 @@ if (isSSO) {
7676
// Socket IO configuration
7777
io.on('connection', (socket) => {
7878
socket.on('join', (data) => {
79-
console.log(`user ${data.username.replace(/\n|\r/g, "")} joined room ${data.room.replace(/\n|\r/g, "")}`)
79+
console.log(`user ${data?.username?.replace(/\n|\r/g, "")} joined room ${data?.room?.replace(/\n|\r/g, "")}`)
8080
socket.username = data.username;
8181
do { socket.color = '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6); } while (socket.color === "#77c84e")
8282
socket.join(data.room);
8383
io.to(data.room).emit('updateUsers');
8484
});
8585
socket.on('leave', (data) => {
86-
console.log(`user ${data.username.replace(/\n|\r/g, "")} left room ${data.room.replace(/\n|\r/g, "")}`)
86+
console.log(`user ${data?.username?.replace(/\n|\r/g, "")} left room ${data?.room?.replace(/\n|\r/g, "")}`)
8787
socket.leave(data.room)
8888
io.to(data.room).emit('updateUsers');
8989
})

frontend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
### STAGE 1: Build ###
2-
FROM node:lts-alpine AS build
2+
FROM node:18-alpine AS build
33
WORKDIR /app
44
COPY package.json ./
55
RUN npm install

frontend/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:lts-alpine AS build
1+
FROM node:18-alpine AS build
22

33
RUN mkdir -p /app
44
WORKDIR /app

frontend/package-lock.json

Lines changed: 10366 additions & 30171 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,42 @@
77
"author": "Stanley Hammer",
88
"private": true,
99
"scripts": {
10-
"build": "export NODE_OPTIONS=--openssl-legacy-provider && quasar build",
11-
"dev": "export NODE_OPTIONS=--openssl-legacy-provider && quasar dev",
10+
"build": "quasar build",
11+
"dev": "quasar dev",
1212
"test": "echo \"No test specified\" && exit 0"
1313
},
1414
"dependencies": {
15-
"@quasar/extras": "^1.16.11",
15+
"@quasar/babel-preset-app": "^2.0.3",
16+
"@quasar/extras": "^1.16.13",
1617
"@tiptap/extension-highlight": "^2.4.0",
1718
"@tiptap/extension-image": "^2.4.0",
1819
"@tiptap/extension-underline": "^2.4.0",
1920
"@tiptap/pm": "^2.4.0",
2021
"@tiptap/starter-kit": "^2.4.0",
21-
"@tiptap/vue-2": "^2.4.0",
22+
"@tiptap/vue-3": "^2.10.2",
23+
"autoprefixer": "^10.4.20",
2224
"axios": "^0.18.1",
2325
"core-js": "^3.37.1",
2426
"diff": "^4.0.2",
2527
"js-yaml": "^4.1.0",
2628
"jwt-decode": "^2.2.0",
2729
"lodash": "^4.17.21",
28-
"quasar": "^1.15.4",
30+
"quasar": "^2.17.4",
2931
"socket.io-client": "^4.7.5",
32+
"stylus": "^0.64.0",
33+
"stylus-loader": "^8.1.1",
34+
"vue": "^3.5.13",
3035
"vue-affix": "^0.5.2",
3136
"vue-dragula": "^1.3.1",
32-
"vue-i18n": "^8.25.0",
37+
"vue-i18n": "^10.0.4",
3338
"vue-lodash": "^2.1.2",
39+
"vue-router": "^4.5.0",
3440
"vue2-dragula": "^2.5.5",
35-
"vuedraggable": "^2.24.3"
41+
"vue3-draggable": "^2.0.9"
3642
},
3743
"devDependencies": {
38-
"@quasar/app": "^2.0.0",
39-
"@quasar/cli": "^1.0.5",
44+
"@quasar/app-webpack": "^3.15.1",
45+
"@quasar/cli": "^2.4.1",
4046
"devtron": "^1.4.0",
4147
"electron": "^2.0.0",
4248
"electron-debug": "^1.5.0",

frontend/src/boot/affix.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Affix from 'vue-affix';
2-
3-
export default ({ Vue }) => {
4-
Vue.use(Affix);
5-
}
1+
import { createApp } from 'vue';
2+
import { Affix } from 'vue-affix';
3+
import App from '../App.vue';
4+
const app = createApp(App);
5+
app.use(Affix);

frontend/src/boot/auth.js

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,83 @@
1-
import User from '@/services/user';
2-
import {isSSO} from '../config/config.json'
1+
import {refreshToken, isAuth} from '@/services/user'
2+
import config from '../config/config.json'
3+
import { ref } from 'vue'
4+
import router from '../router/index'
35

4-
export default async ({ urlPath, router, redirect }) => {
5-
// Launch refresh token countdown 840000=14min if not on login page
6-
setInterval(() => {
7-
User.refreshToken()
8-
.then()
9-
.catch(err => {
10-
//SSO redirection
11-
if (isSSO) {
12-
if (!router.currentRoute.path.startsWith('/api/sso'))
13-
if (err === 'Expired refreshToken')
14-
redirect('/api/sso?tokenError=2')
15-
else
16-
redirect('/api/sso')
17-
}
18-
else {
19-
if (!router.currentRoute.path.startsWith('/login'))
20-
if (err === 'Expired refreshToken')
21-
redirect('/login?tokenError=2')
22-
else
23-
redirect('/login')
24-
}
25-
})
26-
}, 840000)
6+
const isSSO = config.isSSO
7+
export function setupNavigation() {
8+
9+
// Create a ref to track authentication status
10+
const tokenRefreshInterval = ref(null)
2711

28-
// Call refreshToken when loading app and redirect to login if error
29-
try {
30-
await User.refreshToken()
31-
}
32-
catch (err) {
33-
//SSO integration
12+
// Function to handle token refresh and redirection
13+
const handleTokenRefreshError = (err) => {
14+
//SSO redirection
3415
if (isSSO) {
35-
if (!urlPath.startsWith('/api/sso'))
16+
17+
if (!router.currentRoute.value.path.startsWith('/api/sso'))
3618
if (err === 'Expired refreshToken')
37-
redirect('/api/sso?tokenError=2')
19+
router.push('/api/sso?tokenError=2')
3820
else
39-
redirect('/api/sso')
21+
router.push('/api/sso')
4022
}
4123
else {
42-
if (!urlPath.startsWith('/login'))
24+
if (!router.currentRoute.value.path.startsWith('/login'))
4325
if (err === 'Expired refreshToken')
44-
redirect('/login?tokenError=2')
26+
router.push('/login?tokenError=2')
4527
else
46-
redirect('/login')
28+
router.push('/login')
4729
}
4830
}
4931

50-
router.beforeEach((to, from, next) => {
32+
// Initial token refresh and setup
33+
const initTokenRefresh = async () => {
34+
// Launch refresh token countdown 840000=14min if not on login page
35+
tokenRefreshInterval.value = setInterval(() => {
36+
refreshToken()
37+
.then()
38+
.catch(err => handleTokenRefreshError(err))
39+
}, 840000)
40+
41+
// Call refreshToken when loading app and redirect to login if error
42+
try {
43+
await refreshToken()
44+
}
45+
catch (err) {
46+
handleTokenRefreshError(err)
47+
}
48+
}
49+
50+
// Add navigation guard directly to the router
51+
router.beforeEach((to, from) => {
5152
//SSO Integration
5253
if (isSSO) {
5354
if (to.path === '/api/sso') {
54-
if (User.isAuth())
55-
next('/')
56-
else if (true) {
55+
if (isAuth())
56+
return '/'
57+
else {
5758
console.log("router crash")
58-
next('/api/sso')
59+
return '/api/sso'
5960
}
6061
}
61-
else
62-
next()
62+
return true
6363
}
6464
else {
6565
if (to.path === '/login') {
66-
if (User.isAuth())
67-
next('/')
68-
else
69-
next()
70-
}
71-
else {
72-
next()
66+
if (isAuth())
67+
return '/'
68+
return true
7369
}
70+
return true
71+
}
72+
})
73+
74+
// Initial token refresh
75+
initTokenRefresh()
76+
77+
// Return cleanup function
78+
return () => {
79+
if (tokenRefreshInterval.value) {
80+
clearInterval(tokenRefreshInterval.value)
7481
}
7582
}
76-
)
7783
}

frontend/src/boot/axios.js

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import axios from 'axios'
2-
import User from '@/services/user'
2+
import {clearUser } from '@/services/user'
33
import Router from '../router'
4-
import {isSSO} from '../config/config.json'
4+
import config from '../config/config.json';
5+
const isSSO = config.isSSO;
56

67
const axiosInstance = axios.create({
78
baseURL: `${window.location.origin}/api`
@@ -23,19 +24,20 @@ else {
2324
route2 = '/login'
2425
}
2526

27+
2628
// Redirect to login if response is 401 (Unauthenticated)
2729
axiosInstance.interceptors.response.use(
2830
response => {
2931
return response
30-
},
32+
},
3133
error => {
3234
const originalRequest = error.config
3335

3436
// **** 401 exceptions to avoid infinite loop
3537

3638
// 401 after User.refreshToken function call
3739
if (error.response.status === 401 && originalRequest.url.endsWith('/users/refreshtoken')) {
38-
User.clear()
40+
clearUser()
3941
return Promise.reject(error)
4042
}
4143

@@ -62,20 +64,22 @@ axiosInstance.interceptors.response.use(
6264
// **** End of exceptions
6365

6466
// All other 401 calls
67+
68+
6569
if (error.response.status === 401) {
6670
if (!refreshPending) {
6771
refreshPending = true
6872
axiosInstance.get(route1)
69-
.then(() => {
70-
requestsQueue.forEach(e => e())
71-
requestsQueue = []
72-
})
73-
.catch(err => {
74-
Router.push(route2)
75-
})
76-
.finally(() => {
77-
refreshPending = false
78-
})
73+
.then(() => {
74+
requestsQueue.forEach(e => e())
75+
requestsQueue = []
76+
})
77+
.catch(err => {
78+
Router.push(route2)
79+
})
80+
.finally(() => {
81+
refreshPending = false
82+
})
7983
}
8084
return new Promise((resolve) => {
8185
requestsQueue.push(() => resolve(axiosInstance.request(originalRequest)))
@@ -85,6 +89,10 @@ axiosInstance.interceptors.response.use(
8589
}
8690
)
8791

88-
export default ({ Vue }) => {
89-
Vue.prototype.$axios = axiosInstance
92+
export default {
93+
install(app) {
94+
app.config.globalProperties.$axios = axiosInstance
95+
},
96+
9097
}
98+
export { axiosInstance }

frontend/src/boot/darkmode.js

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
1-
import Vue from "vue";
2-
import { Dark } from "quasar";
1+
import { createApp } from 'vue';
2+
import App from './../App.vue';
3+
import { Dark } from 'quasar';
34

4-
const DarkModeSwitcher = {
5-
install: function(Vue) {
6-
Vue.prototype.toggleDarkMode = function() {
7-
updateDarkMode(!Dark.isActive);
8-
}
9-
}
10-
};
11-
Vue.use(DarkModeSwitcher);
5+
const app = createApp(App);
126

137
function updateDarkMode(dark = null) {
14-
// using !! to convert it to a boolean is ok in this case,
15-
// because we are checking, if the key exists
16-
let darkmode = !!localStorage.getItem("darkmodeEnabled") || false;
17-
if(dark != null) {
18-
// set mode
19-
darkmode = dark;
20-
}
21-
22-
Dark.set(darkmode);
23-
if(darkmode) {
24-
localStorage.setItem("darkmodeEnabled", "y");
25-
} else {
26-
localStorage.removeItem("darkmodeEnabled");
27-
}
8+
Dark.set(dark !== null ? dark : !!localStorage.getItem("darkmode"));
9+
if (dark !== null) {
10+
localStorage.setItem('darkmode', dark ? 'y' : 'n');
11+
} else {
12+
localStorage.removeItem('darkmode');
13+
}
14+
}
15+
16+
const toggleDarkMode = function() {
17+
updateDarkMode(!Dark.isActive);
18+
};
19+
20+
// Initialize dark mode based on local storage value
21+
function initializeDarkMode() {
22+
const darkMode = localStorage.getItem('darkmode');
23+
if (darkMode === 'y') {
24+
Dark.set(true);
25+
} else if (darkMode === 'n') {
26+
Dark.set(false);
27+
}
2828
}
2929

30-
updateDarkMode();
30+
// Call initializeDarkMode when the app is created
31+
initializeDarkMode();
32+
33+
export { toggleDarkMode, Dark };

0 commit comments

Comments
 (0)