Compare commits
No commits in common. "749ddf0c315514d3f80b932499cd748590a58dc4" and "56479ea358e0413a1338c72910dd2892a08dc335" have entirely different histories.
749ddf0c31
...
56479ea358
@ -5,7 +5,6 @@ import { useMessageContext } from '../context/MessageContext'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import set from 'lodash/set'
|
import set from 'lodash/set'
|
||||||
import { getModelByName } from '../../../database/ObjectModels'
|
import { getModelByName } from '../../../database/ObjectModels'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
mergeFormData,
|
mergeFormData,
|
||||||
stripNestedObjectProperties,
|
stripNestedObjectProperties,
|
||||||
@ -15,34 +14,26 @@ import {
|
|||||||
const buildObjectFromEntries = (entries = []) => {
|
const buildObjectFromEntries = (entries = []) => {
|
||||||
return entries.reduce((acc, entry) => {
|
return entries.reduce((acc, entry) => {
|
||||||
const { namePath, value } = entry || {}
|
const { namePath, value } = entry || {}
|
||||||
|
|
||||||
if (!Array.isArray(namePath) || value === undefined) {
|
if (!Array.isArray(namePath) || value === undefined) {
|
||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
|
|
||||||
set(acc, namePath, value)
|
set(acc, namePath, value)
|
||||||
|
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch computed fields onto the complete object.
|
|
||||||
// This mirrors the handling used by ObjectForm.
|
|
||||||
const applyComputedEntries = (base, entries = []) => {
|
const applyComputedEntries = (base, entries = []) => {
|
||||||
const result = mergeFormData(base || {})
|
const result = mergeFormData(base || {})
|
||||||
|
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
const { namePath, value } = entry || {}
|
const { namePath, value } = entry || {}
|
||||||
if (!Array.isArray(namePath) || value === undefined) return
|
if (!Array.isArray(namePath) || value === undefined) return
|
||||||
set(result, namePath, value)
|
set(result, namePath, value)
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NewObjectForm is a reusable form component for creating new objects.
|
* NewObjectForm is a reusable form component for creating new objects.
|
||||||
*
|
|
||||||
* It handles form validation, submission, and error handling logic.
|
* It handles form validation, submission, and error handling logic.
|
||||||
*
|
*
|
||||||
* Props:
|
* Props:
|
||||||
@ -54,33 +45,21 @@ const applyComputedEntries = (base, entries = []) => {
|
|||||||
* }) => ReactNode
|
* }) => ReactNode
|
||||||
*/
|
*/
|
||||||
const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
||||||
// Do not initialise this from defaultValues.
|
|
||||||
// The form initialisation effect below is the single source of truth,
|
|
||||||
// matching ObjectForm's fetched-object handling.
|
|
||||||
const [objectData, setObjectData] = useState({
|
const [objectData, setObjectData] = useState({
|
||||||
|
...defaultValues,
|
||||||
_isEditing: true
|
_isEditing: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const [submitLoading, setSubmitLoading] = useState(false)
|
const [submitLoading, setSubmitLoading] = useState(false)
|
||||||
const [formValid, setFormValid] = useState(false)
|
const [formValid, setFormValid] = useState(false)
|
||||||
|
|
||||||
const [form] = Form.useForm()
|
const [form] = Form.useForm()
|
||||||
|
|
||||||
const validationRunRef = useRef(0)
|
const validationRunRef = useRef(0)
|
||||||
|
|
||||||
const formUpdateValues = Form.useWatch([], form)
|
const formUpdateValues = Form.useWatch([], form)
|
||||||
|
|
||||||
const { showSuccess, showError: showMessageError } = useMessageContext()
|
const { showSuccess, showError: showMessageError } = useMessageContext()
|
||||||
|
|
||||||
const { createObject, showError } = useContext(ApiServerContext)
|
const { createObject, showError } = useContext(ApiServerContext)
|
||||||
|
|
||||||
const model = getModelByName(type)
|
|
||||||
|
|
||||||
const validateForm = useCallback(() => {
|
const validateForm = useCallback(() => {
|
||||||
const validationRun = ++validationRunRef.current
|
const validationRun = ++validationRunRef.current
|
||||||
|
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
|
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
form
|
form
|
||||||
.validateFields({ validateOnly: true })
|
.validateFields({ validateOnly: true })
|
||||||
@ -102,59 +81,27 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
|||||||
}
|
}
|
||||||
}, [form])
|
}, [form])
|
||||||
|
|
||||||
|
const model = getModelByName(type)
|
||||||
|
|
||||||
const calculateComputedValues = useCallback(
|
const calculateComputedValues = useCallback(
|
||||||
(currentData, modelDefinition, options = {}) => {
|
(currentData, modelDefinition, options = {}) => {
|
||||||
return calculateModelComputedEntries(
|
return calculateModelComputedEntries(currentData, modelDefinition, options)
|
||||||
currentData,
|
|
||||||
modelDefinition,
|
|
||||||
options
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
// Set initial form values when defaultValues change
|
||||||
* Initialise the form from defaultValues.
|
|
||||||
*
|
|
||||||
* This deliberately follows ObjectForm's initial fetch handling:
|
|
||||||
*
|
|
||||||
* defaultValues
|
|
||||||
* ↓
|
|
||||||
* calculate computed values
|
|
||||||
* ↓
|
|
||||||
* apply computed values to the complete object
|
|
||||||
* ↓
|
|
||||||
* setObjectData(...)
|
|
||||||
* ↓
|
|
||||||
* form.setFieldsValue(...)
|
|
||||||
*
|
|
||||||
* Keeping the exact same object structure in objectData and the Form
|
|
||||||
* is important for object-select fields.
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initialData = mergeFormData(defaultValues || {})
|
if (Object.keys(defaultValues).length > 0) {
|
||||||
|
const computedEntries = calculateComputedValues(defaultValues, model)
|
||||||
const computedEntries = calculateComputedValues(initialData, model)
|
const initialFormData = applyComputedEntries(
|
||||||
|
defaultValues,
|
||||||
const initialFormData = applyComputedEntries(initialData, computedEntries)
|
computedEntries
|
||||||
|
)
|
||||||
const nextObjectData = {
|
form.setFieldsValue(initialFormData)
|
||||||
...initialFormData,
|
setObjectData((prev) => mergeFormData(prev, initialFormData))
|
||||||
_isEditing: true
|
return validateForm()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear any previous values before applying the new defaults.
|
|
||||||
// This is particularly important when defaultValues changes while
|
|
||||||
// the component remains mounted.
|
|
||||||
form.resetFields()
|
|
||||||
|
|
||||||
// Use the complete object as the form value, just like ObjectForm.
|
|
||||||
form.setFieldsValue(initialFormData)
|
|
||||||
|
|
||||||
// Keep objectData in sync with exactly the same initial data.
|
|
||||||
setObjectData(nextObjectData)
|
|
||||||
|
|
||||||
return validateForm()
|
|
||||||
}, [form, defaultValues, calculateComputedValues, model, validateForm])
|
}, [form, defaultValues, calculateComputedValues, model, validateForm])
|
||||||
|
|
||||||
// Validate form on change
|
// Validate form on change
|
||||||
@ -165,34 +112,23 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
|||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
setSubmitLoading(true)
|
setSubmitLoading(true)
|
||||||
|
|
||||||
const currentFormValues = form.getFieldsValue()
|
const currentFormValues = form.getFieldsValue()
|
||||||
|
|
||||||
const currentFormData = mergeFormData(objectData || {}, currentFormValues)
|
const currentFormData = mergeFormData(objectData || {}, currentFormValues)
|
||||||
|
|
||||||
const computedEntries = calculateComputedValues(currentFormData, model)
|
const computedEntries = calculateComputedValues(currentFormData, model)
|
||||||
|
|
||||||
const computedObjectData = applyComputedEntries(
|
const computedObjectData = applyComputedEntries(
|
||||||
currentFormData,
|
currentFormData,
|
||||||
computedEntries
|
computedEntries
|
||||||
)
|
)
|
||||||
|
|
||||||
const payload = stripNestedObjectProperties(computedObjectData, model)
|
const payload = stripNestedObjectProperties(computedObjectData, model)
|
||||||
|
|
||||||
const newObject = await createObject(type, payload)
|
const newObject = await createObject(type, payload)
|
||||||
|
|
||||||
showSuccess('Object created successfully')
|
showSuccess('Object created successfully')
|
||||||
|
|
||||||
return newObject
|
return newObject
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
||||||
if (err.errorFields) {
|
if (err.errorFields) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
showMessageError('Failed to create object')
|
showMessageError('Failed to create object')
|
||||||
|
|
||||||
showError(
|
showError(
|
||||||
`Failed to create object. Message: ${err.message}. Code: ${err.code}`,
|
`Failed to create object. Message: ${err.message}. Code: ${err.code}`,
|
||||||
() => handleSubmit()
|
() => handleSubmit()
|
||||||
@ -210,17 +146,12 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
|||||||
disabled={submitLoading}
|
disabled={submitLoading}
|
||||||
onValuesChange={(_changedValues, allFormValues) => {
|
onValuesChange={(_changedValues, allFormValues) => {
|
||||||
const currentFormData = mergeFormData(objectData || {}, allFormValues)
|
const currentFormData = mergeFormData(objectData || {}, allFormValues)
|
||||||
|
|
||||||
const computedEntries = calculateComputedValues(currentFormData, model)
|
const computedEntries = calculateComputedValues(currentFormData, model)
|
||||||
|
|
||||||
if (Array.isArray(computedEntries) && computedEntries.length > 0) {
|
if (Array.isArray(computedEntries) && computedEntries.length > 0) {
|
||||||
computedEntries.forEach(({ namePath, value }) => {
|
computedEntries.forEach(({ namePath, value }) => {
|
||||||
if (!Array.isArray(namePath) || value === undefined) {
|
if (!Array.isArray(namePath) || value === undefined) return
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentValue = form.getFieldValue(namePath)
|
const currentValue = form.getFieldValue(namePath)
|
||||||
|
|
||||||
if (currentValue !== value) {
|
if (currentValue !== value) {
|
||||||
if (typeof form.setFieldValue === 'function') {
|
if (typeof form.setFieldValue === 'function') {
|
||||||
form.setFieldValue(namePath, value)
|
form.setFieldValue(namePath, value)
|
||||||
@ -228,7 +159,6 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
|||||||
const fallbackPayload = buildObjectFromEntries([
|
const fallbackPayload = buildObjectFromEntries([
|
||||||
{ namePath, value }
|
{ namePath, value }
|
||||||
])
|
])
|
||||||
|
|
||||||
form.setFieldsValue(fallbackPayload)
|
form.setFieldsValue(fallbackPayload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,9 +166,6 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const allValues = applyComputedEntries(allFormValues, computedEntries)
|
const allValues = applyComputedEntries(allFormValues, computedEntries)
|
||||||
|
|
||||||
allValues._isEditing = true
|
|
||||||
|
|
||||||
setObjectData((prev) => mergeFormData(prev, allValues))
|
setObjectData((prev) => mergeFormData(prev, allValues))
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -258,11 +185,8 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
|
|||||||
|
|
||||||
NewObjectForm.propTypes = {
|
NewObjectForm.propTypes = {
|
||||||
type: PropTypes.string.isRequired,
|
type: PropTypes.string.isRequired,
|
||||||
|
|
||||||
children: PropTypes.func.isRequired,
|
children: PropTypes.func.isRequired,
|
||||||
|
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
|
|
||||||
defaultValues: PropTypes.object
|
defaultValues: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,14 +25,6 @@ const areValuesEqual = (v1, v2) => {
|
|||||||
return String(id1) === String(id2)
|
return String(id1) === String(id2)
|
||||||
}
|
}
|
||||||
|
|
||||||
const toSelectValue = (id) => {
|
|
||||||
if (id == null || id === '') return null
|
|
||||||
return String(id).toLowerCase()
|
|
||||||
}
|
|
||||||
|
|
||||||
const getValueId = (item) =>
|
|
||||||
item && typeof item === 'object' ? item._id : item
|
|
||||||
|
|
||||||
const getFirstSelectableLeaf = (nodes) => {
|
const getFirstSelectableLeaf = (nodes) => {
|
||||||
if (!Array.isArray(nodes)) return null
|
if (!Array.isArray(nodes)) return null
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
@ -77,23 +69,6 @@ const isValueInTree = (nodes, id) => {
|
|||||||
return findTreeNodeByValue(nodes, id) != null
|
return findTreeNodeByValue(nodes, id) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSelectValueFromExternal = (externalValue, multiple, nodes) => {
|
|
||||||
if (externalValue == null || !Array.isArray(nodes) || nodes.length === 0) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (multiple) {
|
|
||||||
const values = Array.isArray(externalValue) ? externalValue : []
|
|
||||||
const ids = values
|
|
||||||
.map((item) => toSelectValue(getValueId(item)))
|
|
||||||
.filter((id) => id != null && isValueInTree(nodes, id))
|
|
||||||
return ids
|
|
||||||
}
|
|
||||||
|
|
||||||
const node = findTreeNodeByValue(nodes, getValueId(externalValue))
|
|
||||||
return node?.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const isExternalValueMissing = (
|
const isExternalValueMissing = (
|
||||||
externalValue,
|
externalValue,
|
||||||
multiple,
|
multiple,
|
||||||
@ -553,27 +528,9 @@ const ObjectSelect = ({
|
|||||||
setObjectList(objects)
|
setObjectList(objects)
|
||||||
setTreeData(treeNodes)
|
setTreeData(treeNodes)
|
||||||
treeDataRef.current = treeNodes
|
treeDataRef.current = treeNodes
|
||||||
|
|
||||||
const syncedValue = getSelectValueFromExternal(
|
|
||||||
valueRef.current,
|
|
||||||
multiple,
|
|
||||||
treeNodes
|
|
||||||
)
|
|
||||||
if (multiple) {
|
|
||||||
if (Array.isArray(syncedValue) && syncedValue.length > 0) {
|
|
||||||
setTreeSelectValue(syncedValue)
|
|
||||||
setValueNotFound(false)
|
|
||||||
clearedMissingValueRef.current = false
|
|
||||||
}
|
|
||||||
} else if (syncedValue != null) {
|
|
||||||
setTreeSelectValue(syncedValue)
|
|
||||||
setValueNotFound(false)
|
|
||||||
clearedMissingValueRef.current = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return { treeNodes, objects }
|
return { treeNodes, objects }
|
||||||
},
|
},
|
||||||
[buildTreeData, multiple]
|
[buildTreeData]
|
||||||
)
|
)
|
||||||
|
|
||||||
const buildFilterFromNode = useCallback(
|
const buildFilterFromNode = useCallback(
|
||||||
@ -676,17 +633,6 @@ const ObjectSelect = ({
|
|||||||
|
|
||||||
const onTreeSelectChange = useCallback(
|
const onTreeSelectChange = useCallback(
|
||||||
(value) => {
|
(value) => {
|
||||||
const isEmptySelection = multiple
|
|
||||||
? !Array.isArray(value) || value.length === 0
|
|
||||||
: value == null || value === ''
|
|
||||||
if (
|
|
||||||
isEmptySelection &&
|
|
||||||
treeDataRef.current.length === 0 &&
|
|
||||||
valueRef.current != null
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setValueNotFound(false)
|
setValueNotFound(false)
|
||||||
clearedMissingValueRef.current = false
|
clearedMissingValueRef.current = false
|
||||||
// Mark this as an internal change
|
// Mark this as an internal change
|
||||||
@ -881,7 +827,7 @@ const ObjectSelect = ({
|
|||||||
setExpandedKeys([...new Set(pathKeys)])
|
setExpandedKeys([...new Set(pathKeys)])
|
||||||
setTreeSelectValue(
|
setTreeSelectValue(
|
||||||
value
|
value
|
||||||
.map((item) => toSelectValue(getValueId(item)))
|
.map((item) => (item && typeof item === 'object' ? item._id : item))
|
||||||
.filter((id) => id != null)
|
.filter((id) => id != null)
|
||||||
)
|
)
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
@ -934,7 +880,7 @@ const ObjectSelect = ({
|
|||||||
setExpandedKeys(pathKeys)
|
setExpandedKeys(pathKeys)
|
||||||
// Fetch with the new filter
|
// Fetch with the new filter
|
||||||
handleFetchObjectsProperties(valueFilter)
|
handleFetchObjectsProperties(valueFilter)
|
||||||
setTreeSelectValue(toSelectValue(valueRef.current._id))
|
setTreeSelectValue(valueRef.current._id)
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -959,13 +905,7 @@ const ObjectSelect = ({
|
|||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const timeoutId = setTimeout(() => {
|
handleValue()
|
||||||
handleValue()
|
|
||||||
}, 10)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearTimeout(timeoutId)
|
|
||||||
}
|
|
||||||
}, [
|
}, [
|
||||||
value,
|
value,
|
||||||
filter,
|
filter,
|
||||||
@ -1000,7 +940,6 @@ const ObjectSelect = ({
|
|||||||
setTreeVersion((v) => v + 1)
|
setTreeVersion((v) => v + 1)
|
||||||
setExpandedKeys([])
|
setExpandedKeys([])
|
||||||
setInitialized(false)
|
setInitialized(false)
|
||||||
valueRef.current = null
|
|
||||||
onTreeSelectChange(null)
|
onTreeSelectChange(null)
|
||||||
setTreeSelectValue(null)
|
setTreeSelectValue(null)
|
||||||
setInitialLoading(true)
|
setInitialLoading(true)
|
||||||
@ -1024,12 +963,7 @@ const ObjectSelect = ({
|
|||||||
if (changeSource == 'external') {
|
if (changeSource == 'external') {
|
||||||
setObjectPropertiesTree({})
|
setObjectPropertiesTree({})
|
||||||
setTreeData([])
|
setTreeData([])
|
||||||
treeDataRef.current = []
|
|
||||||
setInitialized(false)
|
setInitialized(false)
|
||||||
setInitialLoading(true)
|
|
||||||
valueRef.current = null
|
|
||||||
clearedMissingValueRef.current = false
|
|
||||||
setValueNotFound(false)
|
|
||||||
prevValuesRef.current = { type, masterFilter }
|
prevValuesRef.current = { type, masterFilter }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,14 +12,13 @@ import { message, Modal, Space, Button, Typography, Flex } from 'antd'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { AuthContext } from './AuthContext'
|
import { AuthContext } from './AuthContext'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
import { LoadingOutlined } from '@ant-design/icons'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon'
|
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon'
|
||||||
import ReloadIcon from '../../Icons/ReloadIcon'
|
import ReloadIcon from '../../Icons/ReloadIcon'
|
||||||
import LockIcon from '../../Icons/LockIcon'
|
import LockIcon from '../../Icons/LockIcon'
|
||||||
import config from '../../../config'
|
import config from '../../../config'
|
||||||
import loglevel from 'loglevel'
|
import loglevel from 'loglevel'
|
||||||
|
|
||||||
import { getModelByName } from '../../../database/ObjectModels'
|
import { getModelByName } from '../../../database/ObjectModels'
|
||||||
import ProgressDisplay from '../common/ProgressDisplay'
|
import ProgressDisplay from '../common/ProgressDisplay'
|
||||||
const logger = loglevel.getLogger('ApiServerContext')
|
const logger = loglevel.getLogger('ApiServerContext')
|
||||||
@ -2921,59 +2920,42 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
{children}
|
{children}
|
||||||
<Modal
|
<Modal
|
||||||
title={
|
title={
|
||||||
!isReconnecting ? (
|
<Space size={'middle'}>
|
||||||
<Space size={'middle'}>
|
<ExclamationOctagonIcon />
|
||||||
<ExclamationOctagonIcon />
|
Connection Lost
|
||||||
Connection Lost
|
</Space>
|
||||||
</Space>
|
|
||||||
) : (
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
open={Boolean(token) && authenticated == true && connectionIssue}
|
open={Boolean(token) && authenticated == true && connectionIssue}
|
||||||
style={{ maxWidth: !isReconnecting ? 480 : 260 }}
|
style={{ maxWidth: 480 }}
|
||||||
zIndex={3000}
|
zIndex={3000}
|
||||||
closable={false}
|
closable={false}
|
||||||
height={isReconnecting ? 20 : undefined}
|
|
||||||
centered
|
centered
|
||||||
className={isReconnecting ? 'loading-modal' : undefined}
|
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
getContainer={() => document.body}
|
getContainer={() => document.body}
|
||||||
footer={
|
footer={[
|
||||||
!isReconnecting
|
<Button
|
||||||
? [
|
key='reconnect'
|
||||||
<Button
|
loading={isReconnecting}
|
||||||
key='reconnect'
|
onClick={() => attemptReconnect()}
|
||||||
loading={isReconnecting}
|
>
|
||||||
onClick={() => attemptReconnect()}
|
Reconnect
|
||||||
>
|
</Button>
|
||||||
Reconnect
|
]}
|
||||||
</Button>
|
|
||||||
]
|
|
||||||
: false
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{!isReconnecting ? (
|
<Flex vertical gap='middle'>
|
||||||
<Flex vertical gap='middle'>
|
<Text>
|
||||||
<Text>
|
{isReconnecting
|
||||||
{isReconnecting
|
? 'Reconnecting to the API server...'
|
||||||
? 'Reconnecting to the API server...'
|
: `Lost connection to the API server. Reconnecting in ${reconnectSecondsRemaining} second${
|
||||||
: `Lost connection to the API server. Reconnecting in ${reconnectSecondsRemaining} second${
|
reconnectSecondsRemaining === 1 ? '' : 's'
|
||||||
reconnectSecondsRemaining === 1 ? '' : 's'
|
}...`}
|
||||||
}...`}
|
</Text>
|
||||||
</Text>
|
<ProgressDisplay
|
||||||
<ProgressDisplay
|
percent={isReconnecting ? 0 : 100 - reconnectProgress}
|
||||||
percent={isReconnecting ? 0 : 100 - reconnectProgress}
|
showInfo={false}
|
||||||
showInfo={false}
|
status={'exception'}
|
||||||
status={'exception'}
|
/>
|
||||||
/>
|
</Flex>
|
||||||
</Flex>
|
|
||||||
) : (
|
|
||||||
<Space size={'middle'}>
|
|
||||||
<LoadingOutlined />
|
|
||||||
<Text style={{ margin: 0 }}>Reconnecting, please wait...</Text>
|
|
||||||
</Space>
|
|
||||||
)}
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal
|
<Modal
|
||||||
title={
|
title={
|
||||||
|
|||||||
@ -128,7 +128,7 @@ export const SalesOrder = {
|
|||||||
return objectData?.state?.type != 'draft'
|
return objectData?.state?.type != 'draft'
|
||||||
},
|
},
|
||||||
objectData: (objectData) => ({
|
objectData: (objectData) => ({
|
||||||
order: objectData,
|
order: { _id: objectData._id },
|
||||||
orderType: 'salesOrder',
|
orderType: 'salesOrder',
|
||||||
syncAmount: 'itemPrice'
|
syncAmount: 'itemPrice'
|
||||||
})
|
})
|
||||||
@ -142,12 +142,10 @@ export const SalesOrder = {
|
|||||||
disabled: (objectData) => {
|
disabled: (objectData) => {
|
||||||
return objectData?.state?.type != 'draft'
|
return objectData?.state?.type != 'draft'
|
||||||
},
|
},
|
||||||
objectData: (objectData) => {
|
objectData: (objectData) => ({
|
||||||
return {
|
orderType: 'salesOrder',
|
||||||
orderType: 'salesOrder',
|
order: { _id: objectData._id }
|
||||||
order: objectData
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'newInvoice',
|
name: 'newInvoice',
|
||||||
|
|||||||
@ -74,7 +74,7 @@ export const User = {
|
|||||||
disabled: (objectData) => {
|
disabled: (objectData) => {
|
||||||
return objectData?._user?._id != objectData?._id
|
return objectData?._user?._id != objectData?._id
|
||||||
},
|
},
|
||||||
objectData: (objectData) => ({ user: objectData?._user || objectData })
|
objectData: (objectData) => ({ user: objectData })
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
pages: [
|
pages: [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user