Skip to content

Commit

Permalink
Vue 3 migration almost complete
Browse files Browse the repository at this point in the history
  • Loading branch information
Chapizze committed Dec 6, 2024
1 parent b400bcb commit 962401d
Show file tree
Hide file tree
Showing 69 changed files with 17,455 additions and 37,026 deletions.
4 changes: 2 additions & 2 deletions backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ if (isSSO) {
// Socket IO configuration
io.on('connection', (socket) => {
socket.on('join', (data) => {
console.log(`user ${data.username.replace(/\n|\r/g, "")} joined room ${data.room.replace(/\n|\r/g, "")}`)
console.log(`user ${data?.username?.replace(/\n|\r/g, "")} joined room ${data?.room?.replace(/\n|\r/g, "")}`)
socket.username = data.username;
do { socket.color = '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6); } while (socket.color === "#77c84e")
socket.join(data.room);
io.to(data.room).emit('updateUsers');
});
socket.on('leave', (data) => {
console.log(`user ${data.username.replace(/\n|\r/g, "")} left room ${data.room.replace(/\n|\r/g, "")}`)
console.log(`user ${data?.username?.replace(/\n|\r/g, "")} left room ${data?.room?.replace(/\n|\r/g, "")}`)
socket.leave(data.room)
io.to(data.room).emit('updateUsers');
})
Expand Down
2 changes: 1 addition & 1 deletion frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
### STAGE 1: Build ###
FROM node:lts-alpine AS build
FROM node:18-alpine AS build
WORKDIR /app
COPY package.json ./
RUN npm install
Expand Down
2 changes: 1 addition & 1 deletion frontend/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:lts-alpine AS build
FROM node:18-alpine AS build

RUN mkdir -p /app
WORKDIR /app
Expand Down
40,537 changes: 10,366 additions & 30,171 deletions frontend/package-lock.json

Large diffs are not rendered by default.

24 changes: 15 additions & 9 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,42 @@
"author": "Stanley Hammer",
"private": true,
"scripts": {
"build": "export NODE_OPTIONS=--openssl-legacy-provider && quasar build",
"dev": "export NODE_OPTIONS=--openssl-legacy-provider && quasar dev",
"build": "quasar build",
"dev": "quasar dev",
"test": "echo \"No test specified\" && exit 0"
},
"dependencies": {
"@quasar/extras": "^1.16.11",
"@quasar/babel-preset-app": "^2.0.3",
"@quasar/extras": "^1.16.13",
"@tiptap/extension-highlight": "^2.4.0",
"@tiptap/extension-image": "^2.4.0",
"@tiptap/extension-underline": "^2.4.0",
"@tiptap/pm": "^2.4.0",
"@tiptap/starter-kit": "^2.4.0",
"@tiptap/vue-2": "^2.4.0",
"@tiptap/vue-3": "^2.10.2",
"autoprefixer": "^10.4.20",
"axios": "^0.18.1",
"core-js": "^3.37.1",
"diff": "^4.0.2",
"js-yaml": "^4.1.0",
"jwt-decode": "^2.2.0",
"lodash": "^4.17.21",
"quasar": "^1.15.4",
"quasar": "^2.17.4",
"socket.io-client": "^4.7.5",
"stylus": "^0.64.0",
"stylus-loader": "^8.1.1",
"vue": "^3.5.13",
"vue-affix": "^0.5.2",
"vue-dragula": "^1.3.1",
"vue-i18n": "^8.25.0",
"vue-i18n": "^10.0.4",
"vue-lodash": "^2.1.2",
"vue-router": "^4.5.0",
"vue2-dragula": "^2.5.5",
"vuedraggable": "^2.24.3"
"vue3-draggable": "^2.0.9"
},
"devDependencies": {
"@quasar/app": "^2.0.0",
"@quasar/cli": "^1.0.5",
"@quasar/app-webpack": "^3.15.1",
"@quasar/cli": "^2.4.1",
"devtron": "^1.4.0",
"electron": "^2.0.0",
"electron-debug": "^1.5.0",
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/boot/affix.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Affix from 'vue-affix';

export default ({ Vue }) => {
Vue.use(Affix);
}
import { createApp } from 'vue';
import { Affix } from 'vue-affix';
import App from '../App.vue';
const app = createApp(App);
app.use(Affix);
110 changes: 58 additions & 52 deletions frontend/src/boot/auth.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,83 @@
import User from '@/services/user';
import {isSSO} from '../config/config.json'
import {refreshToken, isAuth} from '@/services/user'
import config from '../config/config.json'
import { ref } from 'vue'
import router from '../router/index'

export default async ({ urlPath, router, redirect }) => {
// Launch refresh token countdown 840000=14min if not on login page
setInterval(() => {
User.refreshToken()
.then()
.catch(err => {
//SSO redirection
if (isSSO) {
if (!router.currentRoute.path.startsWith('/api/sso'))
if (err === 'Expired refreshToken')
redirect('/api/sso?tokenError=2')
else
redirect('/api/sso')
}
else {
if (!router.currentRoute.path.startsWith('/login'))
if (err === 'Expired refreshToken')
redirect('/login?tokenError=2')
else
redirect('/login')
}
})
}, 840000)
const isSSO = config.isSSO
export function setupNavigation() {

// Create a ref to track authentication status
const tokenRefreshInterval = ref(null)

// Call refreshToken when loading app and redirect to login if error
try {
await User.refreshToken()
}
catch (err) {
//SSO integration
// Function to handle token refresh and redirection
const handleTokenRefreshError = (err) => {
//SSO redirection
if (isSSO) {
if (!urlPath.startsWith('/api/sso'))

if (!router.currentRoute.value.path.startsWith('/api/sso'))
if (err === 'Expired refreshToken')
redirect('/api/sso?tokenError=2')
router.push('/api/sso?tokenError=2')
else
redirect('/api/sso')
router.push('/api/sso')
}
else {
if (!urlPath.startsWith('/login'))
if (!router.currentRoute.value.path.startsWith('/login'))
if (err === 'Expired refreshToken')
redirect('/login?tokenError=2')
router.push('/login?tokenError=2')
else
redirect('/login')
router.push('/login')
}
}

router.beforeEach((to, from, next) => {
// Initial token refresh and setup
const initTokenRefresh = async () => {
// Launch refresh token countdown 840000=14min if not on login page
tokenRefreshInterval.value = setInterval(() => {
refreshToken()
.then()
.catch(err => handleTokenRefreshError(err))
}, 840000)

// Call refreshToken when loading app and redirect to login if error
try {
await refreshToken()
}
catch (err) {
handleTokenRefreshError(err)
}
}

// Add navigation guard directly to the router
router.beforeEach((to, from) => {
//SSO Integration
if (isSSO) {
if (to.path === '/api/sso') {
if (User.isAuth())
next('/')
else if (true) {
if (isAuth())
return '/'
else {
console.log("router crash")
next('/api/sso')
return '/api/sso'
}
}
else
next()
return true
}
else {
if (to.path === '/login') {
if (User.isAuth())
next('/')
else
next()
}
else {
next()
if (isAuth())
return '/'
return true
}
return true
}
})

// Initial token refresh
initTokenRefresh()

// Return cleanup function
return () => {
if (tokenRefreshInterval.value) {
clearInterval(tokenRefreshInterval.value)
}
}
)
}
40 changes: 24 additions & 16 deletions frontend/src/boot/axios.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import axios from 'axios'
import User from '@/services/user'
import {clearUser } from '@/services/user'
import Router from '../router'
import {isSSO} from '../config/config.json'
import config from '../config/config.json';
const isSSO = config.isSSO;

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


// Redirect to login if response is 401 (Unauthenticated)
axiosInstance.interceptors.response.use(
response => {
return response
},
},
error => {
const originalRequest = error.config

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

// 401 after User.refreshToken function call
if (error.response.status === 401 && originalRequest.url.endsWith('/users/refreshtoken')) {
User.clear()
clearUser()
return Promise.reject(error)
}

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

// All other 401 calls


if (error.response.status === 401) {
if (!refreshPending) {
refreshPending = true
axiosInstance.get(route1)
.then(() => {
requestsQueue.forEach(e => e())
requestsQueue = []
})
.catch(err => {
Router.push(route2)
})
.finally(() => {
refreshPending = false
})
.then(() => {
requestsQueue.forEach(e => e())
requestsQueue = []
})
.catch(err => {
Router.push(route2)
})
.finally(() => {
refreshPending = false
})
}
return new Promise((resolve) => {
requestsQueue.push(() => resolve(axiosInstance.request(originalRequest)))
Expand All @@ -85,6 +89,10 @@ axiosInstance.interceptors.response.use(
}
)

export default ({ Vue }) => {
Vue.prototype.$axios = axiosInstance
export default {
install(app) {
app.config.globalProperties.$axios = axiosInstance
},

}
export { axiosInstance }
53 changes: 28 additions & 25 deletions frontend/src/boot/darkmode.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import Vue from "vue";
import { Dark } from "quasar";
import { createApp } from 'vue';
import App from './../App.vue';
import { Dark } from 'quasar';

const DarkModeSwitcher = {
install: function(Vue) {
Vue.prototype.toggleDarkMode = function() {
updateDarkMode(!Dark.isActive);
}
}
};
Vue.use(DarkModeSwitcher);
const app = createApp(App);

function updateDarkMode(dark = null) {
// using !! to convert it to a boolean is ok in this case,
// because we are checking, if the key exists
let darkmode = !!localStorage.getItem("darkmodeEnabled") || false;
if(dark != null) {
// set mode
darkmode = dark;
}

Dark.set(darkmode);
if(darkmode) {
localStorage.setItem("darkmodeEnabled", "y");
} else {
localStorage.removeItem("darkmodeEnabled");
}
Dark.set(dark !== null ? dark : !!localStorage.getItem("darkmode"));
if (dark !== null) {
localStorage.setItem('darkmode', dark ? 'y' : 'n');
} else {
localStorage.removeItem('darkmode');
}
}

const toggleDarkMode = function() {
updateDarkMode(!Dark.isActive);
};

// Initialize dark mode based on local storage value
function initializeDarkMode() {
const darkMode = localStorage.getItem('darkmode');
if (darkMode === 'y') {
Dark.set(true);
} else if (darkMode === 'n') {
Dark.set(false);
}
}

updateDarkMode();
// Call initializeDarkMode when the app is created
initializeDarkMode();

export { toggleDarkMode, Dark };
Loading

0 comments on commit 962401d

Please sign in to comment.