diff --git a/package.json b/package.json
index ceda37c..661f60e 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,7 @@
"eject": "react-scripts eject",
"minify-svgs": "node scripts/minify-svgs.js",
- "dev:electron": "concurrently \"react-scripts start\" \"ELECTRON_START_URL=http://192.168.68.53:3000 electron src/electron/main.js\"",
+ "dev:electron": "concurrently \"react-scripts start\" \"ELECTRON_START_URL=http://192.168.68.53:3000 electron public/electron.js\"",
"build:electron": "npm run build && electron-builder"
},
"eslintConfig": {
diff --git a/src/App.css b/src/App.css
index fa9a003..02a567e 100644
--- a/src/App.css
+++ b/src/App.css
@@ -68,6 +68,10 @@
line-height: 32.5px;
}
+.loading-modal .ant-modal-footer {
+display: none;
+}
+
:root {
--unit-100vh: 100vh;
diff --git a/src/components/Dashboard/Production/ProductionOverview.jsx b/src/components/Dashboard/Production/ProductionOverview.jsx
index 807d243..e6183de 100644
--- a/src/components/Dashboard/Production/ProductionOverview.jsx
+++ b/src/components/Dashboard/Production/ProductionOverview.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState, useCallback } from 'react'
+import React, { useEffect, useState, useCallback, useContext } from 'react'
import {
Descriptions,
Space,
@@ -21,10 +21,12 @@ import ReloadIcon from '../../Icons/ReloadIcon'
import useCollapseState from '../hooks/useCollapseState'
import config from '../../../config'
+import { AuthContext } from '../context/AuthContext'
const { Title, Text } = Typography
const ProductionOverview = () => {
+ const { token } = useContext(AuthContext)
const [messageApi, contextHolder] = message.useMessage()
const [error, setError] = useState(null)
const [fetchPrinterStatsLoading, setFetchPrinterStatsLoading] = useState(true)
@@ -68,9 +70,9 @@ const ProductionOverview = () => {
setFetchPrinterStatsLoading(true)
const response = await axios.get(`${config.backendUrl}/printers/stats`, {
headers: {
- Accept: 'application/json'
- },
- withCredentials: true
+ Accept: 'application/json',
+ Authorization: `Bearer ${token}`
+ }
})
const printStats = response.data
setStats((prev) => ({ ...prev, printers: printStats }))
@@ -88,9 +90,9 @@ const ProductionOverview = () => {
setFetchPrinterStatsLoading(true)
const response = await axios.get(`${config.backendUrl}/jobs/stats`, {
headers: {
- Accept: 'application/json'
- },
- withCredentials: true
+ Accept: 'application/json',
+ Authorization: `Bearer ${token}`
+ }
})
const jobstats = response.data
setStats((prev) => ({ ...prev, jobs: jobstats }))
@@ -107,9 +109,9 @@ const ProductionOverview = () => {
try {
const response = await axios.get(`${config.backendUrl}/stats/history`, {
headers: {
- Accept: 'application/json'
- },
- withCredentials: true
+ Accept: 'application/json',
+ Authorization: `Bearer ${token}`
+ }
})
setChartData(response.data)
} catch (err) {
@@ -118,8 +120,10 @@ const ProductionOverview = () => {
}
useEffect(() => {
- fetchAllStats()
- }, [fetchAllStats])
+ if (token != null) {
+ fetchAllStats()
+ }
+ }, [fetchAllStats, token])
if (fetchPrinterStatsLoading || fetchPrinterStatsLoading) {
return (
diff --git a/src/components/Dashboard/context/ApiServerContext.js b/src/components/Dashboard/context/ApiServerContext.js
index 9133911..a472b09 100644
--- a/src/components/Dashboard/context/ApiServerContext.js
+++ b/src/components/Dashboard/context/ApiServerContext.js
@@ -402,9 +402,6 @@ const ApiServerProvider = ({ children }) => {
sorter = {},
onDataChange
} = params
- if (token == null) {
- return []
- }
logger.debug('Fetching table data from:', type, {
page,
limit,
@@ -456,9 +453,6 @@ const ApiServerProvider = ({ children }) => {
// Fetch table data with pagination, filtering, and sorting
const fetchObjectsByProperty = async (type, params = {}) => {
- if (token == null) {
- return []
- }
const { filter = {}, properties = [] } = params
logger.debug('Fetching property object data from:', type, {
@@ -571,9 +565,6 @@ const ApiServerProvider = ({ children }) => {
// Download GCode file content
const fetchObjectContent = async (id, type, fileName) => {
- if (!token) {
- return
- }
try {
const response = await axios.get(
`${config.backendUrl}/${type.toLowerCase()}s/${id}/content`,
diff --git a/src/components/Dashboard/context/AuthContext.js b/src/components/Dashboard/context/AuthContext.js
index d12fd19..e968710 100644
--- a/src/components/Dashboard/context/AuthContext.js
+++ b/src/components/Dashboard/context/AuthContext.js
@@ -7,7 +7,16 @@ import React, {
useContext
} from 'react'
import axios from 'axios'
-import { message, Modal, notification, Progress, Button, Space } from 'antd'
+import {
+ message,
+ Modal,
+ notification,
+ Progress,
+ Button,
+ Space,
+ Typography
+} from 'antd'
+import { LoadingOutlined } from '@ant-design/icons'
import PropTypes from 'prop-types'
import ExclamationOctogonIcon from '../../Icons/ExclamationOctagonIcon'
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
@@ -21,12 +30,16 @@ logger.setLevel(config.logLevel)
const AuthContext = createContext()
+const Title = Typography
+
const AuthProvider = ({ children }) => {
const [messageApi, contextHolder] = message.useMessage()
const [notificationApi, notificationContextHolder] =
notification.useNotification()
const [authenticated, setAuthenticated] = useState(false)
const [initialized, setInitialized] = useState(false)
+ const [retreivedTokenFromSession, setRetreivedTokenFromSession] =
+ useState(false)
const [loading, setLoading] = useState(false)
const [token, setToken] = useState(null)
const [expiresAt, setExpiresAt] = useState(null)
@@ -46,7 +59,11 @@ const AuthProvider = ({ children }) => {
setToken(storedToken)
setExpiresAt(storedExpiresAt)
setAuthenticated(true)
+ } else {
+ setAuthenticated(false)
+ setShowUnauthorizedModal(true)
}
+ setRetreivedTokenFromSession(true)
}, [])
const logout = useCallback((redirectUri = '/login') => {
@@ -61,18 +78,19 @@ const AuthProvider = ({ children }) => {
// Login using query parameters
const loginWithSSO = useCallback(
- (redirectUri = window.location.pathname + window.location.search) => {
+ (redirectUri = location.pathname + location.search) => {
messageApi.info('Logging in with tombutcher.work')
const loginUrl = `${config.backendUrl}/auth/${isElectron ? 'app/' : ''}login?redirect_uri=${encodeURIComponent(redirectUri)}`
if (isElectron) {
console.log('Opening external url...')
openExternalUrl(loginUrl)
+ setLoading(true)
} else {
console.log('Redirecting...')
window.location.href = loginUrl
}
},
- [messageApi, openExternalUrl, isElectron]
+ [messageApi, openExternalUrl, isElectron, location.search]
)
const getLoginToken = useCallback(
@@ -94,6 +112,11 @@ const AuthProvider = ({ children }) => {
setUserProfile(response.data)
sessionStorage.setItem('authToken', response.data.access_token)
sessionStorage.setItem('authExpiresAt', response.data.expires_at)
+ const searchParams = new URLSearchParams(location.search)
+ searchParams.delete('authCode')
+ const newSearch = searchParams.toString()
+ const newPath = location.pathname + (newSearch ? `?${newSearch}` : '')
+ navigate(newPath, { replace: true })
} else {
setAuthenticated(false)
setAuthError('Failed to authenticate user.')
@@ -261,23 +284,20 @@ const AuthProvider = ({ children }) => {
}, [expiresAt, authenticated, notificationApi, refreshToken])
useEffect(() => {
- if (initialized == false) {
- const authCode =
- new URLSearchParams(location.search).get('authCode') || null
- if (authCode != null) {
- getLoginToken(authCode)
- const searchParams = new URLSearchParams(location.search)
- if (searchParams.has('authCode')) {
- searchParams.delete('authCode')
- const newSearch = searchParams.toString()
- const newPath = location.pathname + (newSearch ? `?${newSearch}` : '')
- navigate(newPath, { replace: true })
- }
- } else if (token == null) {
- setShowUnauthorizedModal(true)
- setAuthenticated(false)
- }
+ const authCode =
+ new URLSearchParams(location.search).get('authCode') || null
+ if (authCode != null) {
+ getLoginToken(authCode)
+ } else if (
+ token == null &&
+ retreivedTokenFromSession == true &&
+ initialized == false &&
+ authCode == null
+ ) {
setInitialized(true)
+ console.log('Showing unauth')
+ setShowUnauthorizedModal(true)
+ setAuthenticated(false)
}
}, [
checkAuthStatus,
@@ -286,7 +306,8 @@ const AuthProvider = ({ children }) => {
initialized,
location.pathname,
navigate,
- token
+ token,
+ retreivedTokenFromSession
])
if (authError) {
@@ -370,18 +391,22 @@ const AuthProvider = ({ children }) => {
tombutcher.work to continue.