Fixed all warnings.
This commit is contained in:
parent
e6ebc16009
commit
f6986a45cd
@ -1,6 +1,6 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"short_name": "Farm Control",
|
||||
"name": "Farm Control",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
|
||||
@ -76,7 +76,7 @@ const LoadFilamentStock = ({
|
||||
if (filamentStockEventUnsubscribe) filamentStockEventUnsubscribe()
|
||||
}
|
||||
}
|
||||
}, [printer?._id, connected])
|
||||
}, [printer?._id, connected, subscribeToObjectEvent])
|
||||
|
||||
useEffect(() => {
|
||||
// Validate form fields
|
||||
|
||||
@ -60,7 +60,7 @@ const UnloadFilamentStock = ({ onOk, reset, printer = null }) => {
|
||||
if (filamentStockEventUnsubscribe) filamentStockEventUnsubscribe()
|
||||
}
|
||||
}
|
||||
}, [printer?._id, connected])
|
||||
}, [printer?._id, connected, subscribeToObjectEvent])
|
||||
|
||||
useEffect(() => {
|
||||
if (reset) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { useContext, useEffect, useState, useRef } from 'react'
|
||||
import { useContext, useEffect, useState, useRef, useCallback } from 'react'
|
||||
import { Input, Result, Typography, Flex, Progress } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { ApiServerContext } from '../../context/ApiServerContext'
|
||||
@ -17,7 +17,7 @@ const HostOTP = ({ id }) => {
|
||||
const [initialized, setInitialized] = useState(false)
|
||||
const intervalRef = useRef(null)
|
||||
|
||||
const fetchNewOTP = () => {
|
||||
const fetchNewOTP = useCallback(() => {
|
||||
setLoading(true)
|
||||
setHostObject(null) // Reset to show loading
|
||||
fetchHostOTP(id, (hostOTPObject) => {
|
||||
@ -33,14 +33,14 @@ const HostOTP = ({ id }) => {
|
||||
setTotalTime(remaining)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [id, fetchHostOTP])
|
||||
|
||||
useEffect(() => {
|
||||
if (hostObject === null && initialized == false) {
|
||||
setInitialized(true)
|
||||
fetchNewOTP()
|
||||
}
|
||||
}, [id])
|
||||
}, [id, fetchNewOTP, initialized, hostObject])
|
||||
|
||||
useEffect(() => {
|
||||
if (hostObject && timeRemaining > 0) {
|
||||
@ -62,7 +62,7 @@ const HostOTP = ({ id }) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [hostObject, timeRemaining])
|
||||
}, [hostObject, timeRemaining, fetchNewOTP])
|
||||
|
||||
// Clean up interval on unmount
|
||||
useEffect(() => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useState, useContext, useEffect } from 'react'
|
||||
import { useState, useContext, useEffect, useCallback } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import WizardView from '../../common/WizardView'
|
||||
import { ApiServerContext } from '../../context/ApiServerContext'
|
||||
@ -15,7 +15,7 @@ const DeployJob = ({ onOk, objectData = undefined }) => {
|
||||
const [subJobsCount, setSubJobsCount] = useState(999)
|
||||
const { sendObjectAction, fetchObjects } = useContext(ApiServerContext)
|
||||
|
||||
const handleDeploy = async () => {
|
||||
const handleDeploy = useCallback(async () => {
|
||||
setDeployLoading(true)
|
||||
var hasMore = true
|
||||
var currentPage = 1
|
||||
@ -50,13 +50,13 @@ const DeployJob = ({ onOk, objectData = undefined }) => {
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}, [job._id, sendObjectAction, fetchObjects])
|
||||
|
||||
useEffect(() => {
|
||||
if (deployedSubJobsCount == subJobsCount && deployLoading == true) {
|
||||
onOk()
|
||||
}
|
||||
}, [deployedSubJobsCount, subJobsCount, deployLoading])
|
||||
}, [deployedSubJobsCount, subJobsCount, deployLoading, onOk])
|
||||
|
||||
const steps = [
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// DashboardNavigation.js
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { useContext, useEffect, useState, useMemo } from 'react'
|
||||
import {
|
||||
Menu,
|
||||
Flex,
|
||||
@ -59,28 +59,31 @@ const DashboardNavigation = () => {
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
const { platform, isElectron, isFullScreen } = useContext(ElectronContext)
|
||||
|
||||
const mainMenuItems = [
|
||||
{
|
||||
key: 'production',
|
||||
label: 'Production',
|
||||
icon: <ProductionIcon />
|
||||
},
|
||||
{
|
||||
key: 'inventory',
|
||||
label: 'Inventory',
|
||||
icon: <InventoryIcon />
|
||||
},
|
||||
{
|
||||
key: 'finance',
|
||||
label: 'Finance',
|
||||
icon: <FinanceIcon />
|
||||
},
|
||||
{
|
||||
key: 'management',
|
||||
label: 'Management',
|
||||
icon: <SettingsIcon />
|
||||
}
|
||||
]
|
||||
const mainMenuItems = useMemo(
|
||||
() => [
|
||||
{
|
||||
key: 'production',
|
||||
label: 'Production',
|
||||
icon: <ProductionIcon />
|
||||
},
|
||||
{
|
||||
key: 'inventory',
|
||||
label: 'Inventory',
|
||||
icon: <InventoryIcon />
|
||||
},
|
||||
{
|
||||
key: 'finance',
|
||||
label: 'Finance',
|
||||
icon: <FinanceIcon />
|
||||
},
|
||||
{
|
||||
key: 'management',
|
||||
label: 'Management',
|
||||
icon: <SettingsIcon />
|
||||
}
|
||||
],
|
||||
[]
|
||||
)
|
||||
|
||||
const userMenuItems = {
|
||||
items: [
|
||||
@ -119,7 +122,7 @@ const DashboardNavigation = () => {
|
||||
)
|
||||
setSelectedKey(pathParts[1]) // Return the section (production/management)
|
||||
}
|
||||
}, [location.pathname])
|
||||
}, [location.pathname, mainMenuItems])
|
||||
|
||||
useEffect(() => {
|
||||
if (connecting == true) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { Tree, Typography, Space, Tag } from 'antd'
|
||||
import { useState, useMemo } from 'react'
|
||||
import { useState, useMemo, useCallback } from 'react'
|
||||
import XMarkIcon from '../../Icons/XMarkIcon'
|
||||
import QuestionCircleIcon from '../../Icons/QuestionCircleIcon'
|
||||
import JsonStringIcon from '../../Icons/JsonStringIcon'
|
||||
@ -48,7 +48,7 @@ const DataTree = ({
|
||||
}
|
||||
|
||||
// Function to format value for display
|
||||
const formatValue = (value) => {
|
||||
const formatValue = useCallback((value) => {
|
||||
if (value === null) return 'null'
|
||||
if (value === undefined) return 'undefined'
|
||||
if (typeof value === 'boolean') return value.toString()
|
||||
@ -63,10 +63,10 @@ const DataTree = ({
|
||||
return `Object (${keys.length} properties)`
|
||||
}
|
||||
return String(value)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Function to get raw value for copying
|
||||
const getCopyValue = (value) => {
|
||||
const getCopyValue = useCallback((value) => {
|
||||
if (value === null) return 'null'
|
||||
if (value === undefined) return 'undefined'
|
||||
if (typeof value === 'boolean') return value.toString()
|
||||
@ -75,64 +75,67 @@ const DataTree = ({
|
||||
if (Array.isArray(value)) return JSON.stringify(value, null, 2)
|
||||
if (typeof value === 'object') return JSON.stringify(value, null, 2)
|
||||
return String(value)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Recursive function to convert JSON to tree data
|
||||
const convertToTreeData = (obj, key = 'root', path = '') => {
|
||||
const currentPath = path ? `${path}.${key}` : key
|
||||
const dataInfo = getDataTypeInfo(obj)
|
||||
const convertToTreeData = useCallback(
|
||||
(obj, key = 'root', path = '') => {
|
||||
const currentPath = path ? `${path}.${key}` : key
|
||||
const dataInfo = getDataTypeInfo(obj)
|
||||
|
||||
const node = {
|
||||
title: (
|
||||
<Space size='small'>
|
||||
<Tag color={dataInfo.color} size='small' style={{ margin: 0 }}>
|
||||
{dataInfo.icon}
|
||||
</Tag>
|
||||
<Text strong>{key}</Text>
|
||||
{showKeyCopy && (
|
||||
<CopyButton text={key} tooltip={`Copy key: ${key}`} />
|
||||
)}
|
||||
<Text type='secondary'>({dataInfo.type})</Text>
|
||||
{dataInfo.type !== 'object' && dataInfo.type !== 'array' && (
|
||||
<>
|
||||
<Text code>{formatValue(obj)}</Text>
|
||||
{showValueCopy && (
|
||||
const node = {
|
||||
title: (
|
||||
<Space size='small'>
|
||||
<Tag color={dataInfo.color} size='small' style={{ margin: 0 }}>
|
||||
{dataInfo.icon}
|
||||
</Tag>
|
||||
<Text strong>{key}</Text>
|
||||
{showKeyCopy && (
|
||||
<CopyButton text={key} tooltip={`Copy key: ${key}`} />
|
||||
)}
|
||||
<Text type='secondary'>({dataInfo.type})</Text>
|
||||
{dataInfo.type !== 'object' && dataInfo.type !== 'array' && (
|
||||
<>
|
||||
<Text code>{formatValue(obj)}</Text>
|
||||
{showValueCopy && (
|
||||
<CopyButton
|
||||
text={getCopyValue(obj)}
|
||||
tooltip={`Copy ${dataInfo.type} value`}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{(dataInfo.type === 'object' || dataInfo.type === 'array') &&
|
||||
showValueCopy && (
|
||||
<CopyButton
|
||||
text={getCopyValue(obj)}
|
||||
tooltip={`Copy ${dataInfo.type} value`}
|
||||
tooltip={`Copy ${dataInfo.type} as JSON`}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{(dataInfo.type === 'object' || dataInfo.type === 'array') &&
|
||||
showValueCopy && (
|
||||
<CopyButton
|
||||
text={getCopyValue(obj)}
|
||||
tooltip={`Copy ${dataInfo.type} as JSON`}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
),
|
||||
key: currentPath,
|
||||
value: obj,
|
||||
path: currentPath
|
||||
}
|
||||
|
||||
// Add children for objects and arrays
|
||||
if (typeof obj === 'object' && obj !== null) {
|
||||
if (Array.isArray(obj)) {
|
||||
node.children = obj.map((item, index) =>
|
||||
convertToTreeData(item, `[${index}]`, currentPath)
|
||||
)
|
||||
} else {
|
||||
node.children = Object.entries(obj).map(([childKey, childValue]) =>
|
||||
convertToTreeData(childValue, childKey, currentPath)
|
||||
)
|
||||
</Space>
|
||||
),
|
||||
key: currentPath,
|
||||
value: obj,
|
||||
path: currentPath
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
// Add children for objects and arrays
|
||||
if (typeof obj === 'object' && obj !== null) {
|
||||
if (Array.isArray(obj)) {
|
||||
node.children = obj.map((item, index) =>
|
||||
convertToTreeData(item, `[${index}]`, currentPath)
|
||||
)
|
||||
} else {
|
||||
node.children = Object.entries(obj).map(([childKey, childValue]) =>
|
||||
convertToTreeData(childValue, childKey, currentPath)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
},
|
||||
[showValueCopy, getCopyValue, formatValue, showKeyCopy]
|
||||
)
|
||||
|
||||
// Convert data to tree structure
|
||||
const treeData = useMemo(() => {
|
||||
@ -171,7 +174,7 @@ const DataTree = ({
|
||||
}
|
||||
]
|
||||
}
|
||||
}, [data])
|
||||
}, [data, showValueCopy, convertToTreeData, getCopyValue, formatValue])
|
||||
|
||||
// Handle node selection
|
||||
const handleSelect = (selectedKeys, { selected, selectedNodes }) => {
|
||||
|
||||
@ -18,7 +18,7 @@ const FilePreview = ({ file, style = {} }) => {
|
||||
const objectUrl = await fetchFileContent(file, false)
|
||||
setFileObjectUrl(objectUrl)
|
||||
setLoading(false)
|
||||
}, [file._id, fetchFileContent])
|
||||
}, [file, fetchFileContent])
|
||||
|
||||
useEffect(() => {
|
||||
if (file?.type && token != null) {
|
||||
|
||||
@ -42,7 +42,14 @@ function GCodePreviewUI(props) {
|
||||
return () => {
|
||||
window.removeEventListener('resize', resizePreview)
|
||||
}
|
||||
}, [endLayer, lastSegmentColor, lineWidth, startLayer, topLayerColor])
|
||||
}, [
|
||||
endLayer,
|
||||
lastSegmentColor,
|
||||
lineWidth,
|
||||
startLayer,
|
||||
topLayerColor,
|
||||
resizePreview
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
const loadFromSrc = async () => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, cloneElement } from 'react'
|
||||
import { useEffect, useRef, cloneElement, useCallback } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Popover, Typography } from 'antd'
|
||||
|
||||
@ -24,10 +24,9 @@ const { Text } = Typography
|
||||
const KeyboardShortcut = ({ shortcut, children, hint, onTrigger }) => {
|
||||
const childRef = useRef()
|
||||
const shortcutObj = parseShortcut(shortcut)
|
||||
let pressedKeys = new Set()
|
||||
|
||||
// Helper to get the set of keys required for the shortcut
|
||||
function getShortcutKeySet(shortcutObj) {
|
||||
const getShortcutKeySet = useCallback((shortcutObj) => {
|
||||
const keys = []
|
||||
if (shortcutObj.meta) keys.push('Meta')
|
||||
if (shortcutObj.ctrl) keys.push('Control')
|
||||
@ -38,12 +37,12 @@ const KeyboardShortcut = ({ shortcut, children, hint, onTrigger }) => {
|
||||
keys.push('Key' + shortcutObj.key.toUpperCase())
|
||||
}
|
||||
return new Set(keys)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const shortcutKeySet = getShortcutKeySet(shortcutObj)
|
||||
|
||||
useEffect(() => {
|
||||
pressedKeys = new Set()
|
||||
const pressedKeys = new Set()
|
||||
const handleKeyDown = (event) => {
|
||||
if (
|
||||
event.key === 'Meta' ||
|
||||
@ -83,7 +82,7 @@ const KeyboardShortcut = ({ shortcut, children, hint, onTrigger }) => {
|
||||
window.removeEventListener('keydown', handleKeyDown)
|
||||
window.removeEventListener('keyup', handleKeyUp)
|
||||
}
|
||||
}, [shortcut, shortcutObj, onTrigger])
|
||||
}, [shortcut, shortcutObj, onTrigger, shortcutKeySet])
|
||||
|
||||
// Clone the child to attach a ref
|
||||
const element = cloneElement(children, { ref: childRef })
|
||||
|
||||
@ -272,7 +272,7 @@ const ObjectChildTable = ({
|
||||
})
|
||||
|
||||
return [summaryRow]
|
||||
}, [properties, rollups, objectData])
|
||||
}, [properties, rollups, objectData, value])
|
||||
|
||||
const rollupColumns = useMemo(() => {
|
||||
const propertyColumns = properties.map((property, index) => {
|
||||
|
||||
@ -340,28 +340,31 @@ const ObjectSelect = ({
|
||||
})
|
||||
}
|
||||
|
||||
const onTreeSelectChange = (value) => {
|
||||
// Mark this as an internal change
|
||||
isInternalChangeRef.current = true
|
||||
const onTreeSelectChange = useCallback(
|
||||
(value) => {
|
||||
// Mark this as an internal change
|
||||
isInternalChangeRef.current = true
|
||||
|
||||
// value can be a string (single) or array (multiple)
|
||||
if (multiple) {
|
||||
// Multiple selection
|
||||
let selectedObjects = []
|
||||
if (Array.isArray(value)) {
|
||||
selectedObjects = value
|
||||
.map((id) => objectList.find((obj) => obj._id === id))
|
||||
.filter(Boolean)
|
||||
// value can be a string (single) or array (multiple)
|
||||
if (multiple) {
|
||||
// Multiple selection
|
||||
let selectedObjects = []
|
||||
if (Array.isArray(value)) {
|
||||
selectedObjects = value
|
||||
.map((id) => objectList.find((obj) => obj._id === id))
|
||||
.filter(Boolean)
|
||||
}
|
||||
setTreeSelectValue(value)
|
||||
if (rest.onChange) rest.onChange(selectedObjects)
|
||||
} else {
|
||||
// Single selection
|
||||
const selectedObject = objectList.find((obj) => obj._id === value)
|
||||
setTreeSelectValue(value)
|
||||
if (rest.onChange) rest.onChange(selectedObject)
|
||||
}
|
||||
setTreeSelectValue(value)
|
||||
if (rest.onChange) rest.onChange(selectedObjects)
|
||||
} else {
|
||||
// Single selection
|
||||
const selectedObject = objectList.find((obj) => obj._id === value)
|
||||
setTreeSelectValue(value)
|
||||
if (rest.onChange) rest.onChange(selectedObject)
|
||||
}
|
||||
}
|
||||
},
|
||||
[multiple, objectList, rest]
|
||||
)
|
||||
|
||||
// Update treeData when objectPropertiesTree changes
|
||||
useEffect(() => {
|
||||
@ -494,7 +497,7 @@ const ObjectSelect = ({
|
||||
setError(false)
|
||||
prevValuesRef.current = { type, masterFilter }
|
||||
}
|
||||
}, [type, masterFilter])
|
||||
}, [type, masterFilter, onTreeSelectChange])
|
||||
|
||||
useEffect(() => {
|
||||
// Check if value has actually changed
|
||||
@ -519,7 +522,7 @@ const ObjectSelect = ({
|
||||
prevValueRef.current = value
|
||||
prevValueIdentityRef.current = currentValueIdentity
|
||||
}
|
||||
}, [value, getValueIdentity])
|
||||
}, [value, getValueIdentity, type, masterFilter])
|
||||
|
||||
const placeholder = useMemo(
|
||||
() =>
|
||||
|
||||
@ -16,7 +16,6 @@ const PrinterMiscPanel = ({ id, showControls = true }) => {
|
||||
target: 0
|
||||
},
|
||||
lcdBacklight: {
|
||||
// eslint-disable-line camelcase
|
||||
brightness: 0
|
||||
},
|
||||
beeper: {
|
||||
|
||||
@ -38,14 +38,14 @@ const PrinterPositionPanel = ({
|
||||
const { subscribeToObjectEvent, connected, sendObjectAction } =
|
||||
useContext(ApiServerContext)
|
||||
const [positionData, setPositionData] = useState({
|
||||
speedFactor: 1.0, // eslint-disable-line
|
||||
speedFactor: 1.0,
|
||||
speed: 100,
|
||||
extrudeFactor: 1.0, // eslint-disable-line
|
||||
absoluteCoordinates: true, // eslint-disable-line
|
||||
absoluteExtrude: false, // eslint-disable-line
|
||||
homingOrigin: [0.0, 0.0, 0.0, 0.0], // eslint-disable-line
|
||||
extrudeFactor: 1.0,
|
||||
absoluteCoordinates: true,
|
||||
absoluteExtrude: false,
|
||||
homingOrigin: [0.0, 0.0, 0.0, 0.0],
|
||||
toolheadPosition: [0.0, 0.0, 0.0, 0.0],
|
||||
gcodePosition: [0.0, 0.0, 0.0, 0.0], // eslint-disable-line
|
||||
gcodePosition: [0.0, 0.0, 0.0, 0.0],
|
||||
livePosition: [0.0, 0.0, 0.0, 0.0],
|
||||
maxVelocity: 1000,
|
||||
maxAcceleration: 1000,
|
||||
@ -70,7 +70,7 @@ const PrinterPositionPanel = ({
|
||||
if (motionEventUnsubscribe) motionEventUnsubscribe()
|
||||
}
|
||||
}
|
||||
}, [id, connected])
|
||||
}, [id, connected, subscribeToObjectEvent])
|
||||
const [speedFactor, setSpeedFactor] = useState(positionData.speedFactor)
|
||||
const [extrudeFactor, setExtrudeFactor] = useState(positionData.extrudeFactor)
|
||||
const [maxVelocity, setMaxVelocity] = useState(positionData.maxVelocity)
|
||||
|
||||
@ -87,7 +87,7 @@ const PrinterTemperaturePanel = ({
|
||||
if (temperatureEventUnsubscribe) temperatureEventUnsubscribe()
|
||||
}
|
||||
}
|
||||
}, [id, connected])
|
||||
}, [id, connected, subscribeToObjectEvent])
|
||||
|
||||
const [extruderTarget, setExtruderTarget] = useState(0)
|
||||
const [bedTarget, setBedTarget] = useState(0)
|
||||
|
||||
@ -44,22 +44,25 @@ const TemplatePreview = ({
|
||||
}
|
||||
}
|
||||
|
||||
const reloadPreviewPDF = (content, testObject = {}) => {
|
||||
setReloadLoading(true)
|
||||
fetchTemplatePDF(documentTemplate._id, content, testObject, (result) => {
|
||||
setReloadLoading(false)
|
||||
if (result?.error) {
|
||||
// Handle error through parent component
|
||||
onPreviewMessage(result.error, true)
|
||||
} else {
|
||||
const pdfBlob = new Blob([result.pdf], { type: 'application/pdf' })
|
||||
const pdfUrl = URL.createObjectURL(pdfBlob)
|
||||
const reloadPreviewPDF = useCallback(
|
||||
(content, testObject = {}) => {
|
||||
setReloadLoading(true)
|
||||
fetchTemplatePDF(documentTemplate._id, content, testObject, (result) => {
|
||||
setReloadLoading(false)
|
||||
if (result?.error) {
|
||||
// Handle error through parent component
|
||||
onPreviewMessage(result.error, true)
|
||||
} else {
|
||||
const pdfBlob = new Blob([result.pdf], { type: 'application/pdf' })
|
||||
const pdfUrl = URL.createObjectURL(pdfBlob)
|
||||
|
||||
setPDFBlob(pdfUrl)
|
||||
onPreviewMessage('No issues found.', false)
|
||||
}
|
||||
})
|
||||
}
|
||||
setPDFBlob(pdfUrl)
|
||||
onPreviewMessage('No issues found.', false)
|
||||
}
|
||||
})
|
||||
},
|
||||
[documentTemplate?._id, fetchTemplatePDF, onPreviewMessage]
|
||||
)
|
||||
|
||||
const reloadPreview = useCallback(
|
||||
(content, testObject = {}, scale = 1) => {
|
||||
@ -81,7 +84,7 @@ const TemplatePreview = ({
|
||||
}
|
||||
)
|
||||
},
|
||||
[fetchTemplatePreview, objectData?._id, onPreviewMessage]
|
||||
[fetchTemplatePreview, onPreviewMessage, documentTemplate?._id]
|
||||
)
|
||||
|
||||
// Move useEffect to component level and use state to track objectData changes
|
||||
@ -93,7 +96,14 @@ const TemplatePreview = ({
|
||||
reloadPreviewPDF(documentTemplate.content, objectData)
|
||||
}
|
||||
}
|
||||
}, [objectData, documentTemplate, previewScale, previewType])
|
||||
}, [
|
||||
objectData,
|
||||
documentTemplate,
|
||||
previewScale,
|
||||
previewType,
|
||||
reloadPreview,
|
||||
reloadPreviewPDF
|
||||
])
|
||||
|
||||
return (
|
||||
<Flex vertical gap={'middle'} style={{ height: '100%' }}>
|
||||
|
||||
@ -10,10 +10,7 @@ function ThreeDPreview(props) {
|
||||
width = 500,
|
||||
height = 500,
|
||||
style = {},
|
||||
backgroundColor = '#ffffff',
|
||||
showGrid = true,
|
||||
showAxes = true,
|
||||
enableControls = true
|
||||
backgroundColor = '#ffffff'
|
||||
} = props
|
||||
const containerRef = useRef(null)
|
||||
const viewer = useRef(null)
|
||||
@ -34,6 +31,9 @@ function ThreeDPreview(props) {
|
||||
}, [viewer, width, height])
|
||||
|
||||
useEffect(() => {
|
||||
// Variable to track the viewer instance created in this effect
|
||||
let currentViewer = null
|
||||
|
||||
const initializeViewer = async () => {
|
||||
if (!containerRef.current) return
|
||||
|
||||
@ -42,7 +42,10 @@ function ThreeDPreview(props) {
|
||||
setError(null)
|
||||
|
||||
// Clear any existing viewer
|
||||
if (viewer) {
|
||||
if (viewer.current) {
|
||||
if (viewer.current.dispose) {
|
||||
viewer.current.dispose()
|
||||
}
|
||||
containerRef.current.innerHTML = ''
|
||||
}
|
||||
|
||||
@ -71,6 +74,10 @@ function ThreeDPreview(props) {
|
||||
environmentSettings: new OV.EnvironmentSettings([], false)
|
||||
})
|
||||
|
||||
// Store the viewer instance in the ref and local variable
|
||||
viewer.current = newViewer
|
||||
currentViewer = newViewer
|
||||
|
||||
try {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
@ -105,11 +112,11 @@ function ThreeDPreview(props) {
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', resizeViewer)
|
||||
if (viewer.current && viewer.current.dispose) {
|
||||
viewer.current.dispose()
|
||||
if (currentViewer && currentViewer.dispose) {
|
||||
currentViewer.dispose()
|
||||
}
|
||||
}
|
||||
}, [width, height, backgroundColor, showGrid, showAxes, enableControls, src])
|
||||
}, [width, height, src, extension, resizeViewer])
|
||||
|
||||
const containerStyle = {
|
||||
width: width + 'px',
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
useCallback
|
||||
} from 'react'
|
||||
import io from 'socket.io-client'
|
||||
import { message, notification, Modal, Space, Button } from 'antd'
|
||||
import { message, Modal, Space, Button } from 'antd'
|
||||
import PropTypes from 'prop-types'
|
||||
import { AuthContext } from './AuthContext'
|
||||
|
||||
@ -30,7 +30,6 @@ const ApiServerProvider = ({ children }) => {
|
||||
const [connecting, setConnecting] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
const [notificationApi] = notification.useNotification()
|
||||
const [fetchLoading, setFetchLoading] = useState(false)
|
||||
const [showErrorModal, setShowErrorModal] = useState(false)
|
||||
const [errorModalContent, setErrorModalContent] = useState('')
|
||||
@ -125,7 +124,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
|
||||
socketRef.current = newSocket
|
||||
}
|
||||
}, [token, authenticated, messageApi, notificationApi, handleLockUpdate])
|
||||
}, [token, authenticated, messageApi, handleLockUpdate, clearSubscriptions])
|
||||
|
||||
useEffect(() => {
|
||||
if (token && authenticated == true) {
|
||||
@ -539,7 +538,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
return () => offObjectEventEvent(id, objectType, eventType, callback)
|
||||
}
|
||||
},
|
||||
[offObjectUpdatesEvent]
|
||||
[offObjectEventEvent]
|
||||
)
|
||||
|
||||
const offModelStats = useCallback((objectType, callback) => {
|
||||
|
||||
@ -338,12 +338,12 @@ const AuthProvider = ({ children }) => {
|
||||
}
|
||||
},
|
||||
[
|
||||
isElectron,
|
||||
navigate,
|
||||
location.search,
|
||||
location.pathname,
|
||||
messageApi,
|
||||
persistSession
|
||||
persistSession,
|
||||
redirectType
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ const electron = window.require ? window.require('electron') : null
|
||||
const ipcRenderer = electron ? electron.ipcRenderer : null
|
||||
|
||||
// Utility to check if running in Electron
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export function isElectron() {
|
||||
// Renderer process
|
||||
|
||||
@ -88,6 +89,7 @@ const ElectronProvider = ({ children }) => {
|
||||
// Listen for navigate
|
||||
const navigateHandler = (event, url) => {
|
||||
console.log('Navigating to:', url)
|
||||
|
||||
navigate(url)
|
||||
}
|
||||
ipcRenderer.on('navigate', navigateHandler)
|
||||
@ -96,7 +98,7 @@ const ElectronProvider = ({ children }) => {
|
||||
ipcRenderer.removeListener('navigate', navigateHandler)
|
||||
ipcRenderer.removeListener('window-state', windowStateHandler)
|
||||
}
|
||||
}, [])
|
||||
}, [navigate])
|
||||
|
||||
// Window control handler
|
||||
const handleWindowControl = (action) => {
|
||||
|
||||
@ -47,6 +47,7 @@ MessageProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useMessageContext = () => {
|
||||
const context = useContext(MessageContext)
|
||||
if (!context) {
|
||||
|
||||
@ -17,7 +17,8 @@ import {
|
||||
useState,
|
||||
useRef,
|
||||
createElement,
|
||||
useContext
|
||||
useContext,
|
||||
useCallback
|
||||
} from 'react'
|
||||
import axios from 'axios'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
@ -608,7 +609,7 @@ const ElectronSpotlightContentPage = () => {
|
||||
const { resizeSpotlightWindow, isElectron } = useContext(ElectronContext)
|
||||
|
||||
// Function to measure and resize window
|
||||
const updateWindowHeight = () => {
|
||||
const updateWindowHeight = useCallback(() => {
|
||||
if (!cardRef.current || !isElectron || !resizeSpotlightWindow) return
|
||||
|
||||
// Clear any pending resize
|
||||
@ -639,7 +640,7 @@ const ElectronSpotlightContentPage = () => {
|
||||
console.warn('Failed to update spotlight window height:', error)
|
||||
}
|
||||
}, 100) // 100ms debounce
|
||||
}
|
||||
}, [isElectron, resizeSpotlightWindow])
|
||||
|
||||
// Use ResizeObserver to watch for content changes
|
||||
useEffect(() => {
|
||||
@ -666,7 +667,7 @@ const ElectronSpotlightContentPage = () => {
|
||||
}
|
||||
clearTimeout(initialTimeout)
|
||||
}
|
||||
}, [isElectron, resizeSpotlightWindow])
|
||||
}, [isElectron, resizeSpotlightWindow, updateWindowHeight])
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@ -135,6 +135,7 @@ ThemeProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useThemeContext = () => {
|
||||
const context = useContext(ThemeContext)
|
||||
if (!context) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user