Compare commits
No commits in common. "cb49baaf934e3791d5ac1a2fef74e9c00dd46508" and "1466fe0f62961f0d36b5808f4dc8145f0912a4ba" have entirely different histories.
cb49baaf93
...
1466fe0f62
@ -475,67 +475,6 @@ body {
|
|||||||
.ant-spin-blur {
|
.ant-spin-blur {
|
||||||
filter: blur(3px);
|
filter: blur(3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.spin {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: var(--color-primary);
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spin-nested {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 0;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spin-content {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 0;
|
|
||||||
flex: 1;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spin-content.is-spinning {
|
|
||||||
filter: blur(3px);
|
|
||||||
opacity: 0.5;
|
|
||||||
user-select: none;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spin-overlay {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
z-index: 4;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: var(--color-primary);
|
|
||||||
font-size: 20px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spin.spin-sm,
|
|
||||||
.spin-nested.spin-sm .spin-overlay {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spin.spin-lg,
|
|
||||||
.spin-nested.spin-lg .spin-overlay {
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
/* --- End of src/index.css --- */
|
/* --- End of src/index.css --- */
|
||||||
|
|
||||||
/* --- Start of src/components/Dashboard/Layout.css --- */
|
/* --- Start of src/components/Dashboard/Layout.css --- */
|
||||||
@ -1438,6 +1377,26 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.objectTableCardsContainer > .ant-spin-nested-loading,
|
||||||
|
.objectTableCardsContainer > .ant-spin-nested-loading > .ant-spin-container,
|
||||||
|
.objectTableCardsContainer .ant-spin-nested-loading {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectTableCardsContainer .ant-spin-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.objectKanbanContainerWrapper {
|
.objectKanbanContainerWrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1448,6 +1407,15 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.objectKanbanContainerWrapper > .ant-spin-nested-loading,
|
||||||
|
.objectKanbanContainerWrapper > .ant-spin-nested-loading > .ant-spin-container {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.objectKanbanContainerSkeletons {
|
.objectKanbanContainerSkeletons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -1481,8 +1449,12 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
}
|
||||||
flex-direction: column;
|
|
||||||
|
.objectKanbanWrap > .ant-spin-nested-loading,
|
||||||
|
.objectKanbanWrap > .ant-spin-nested-loading > .ant-spin-container {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.objectKanbanScroll {
|
.objectKanbanScroll {
|
||||||
|
|||||||
@ -4,29 +4,13 @@ import PropTypes from 'prop-types'
|
|||||||
|
|
||||||
const { Text } = Typography
|
const { Text } = Typography
|
||||||
|
|
||||||
const LoadingPlaceholder = ({
|
const LoadingPlaceholder = ({ message, hasBackground = true }) => {
|
||||||
message,
|
|
||||||
hasBackground = true,
|
|
||||||
hasBorder = true,
|
|
||||||
height = undefined
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
size='small'
|
size='small'
|
||||||
style={{
|
style={{
|
||||||
background: hasBackground == false ? 'transparent' : undefined,
|
background: hasBackground == false ? 'transparent' : undefined,
|
||||||
|
border: hasBackground == false ? '1px solid rgb(0 0 0 / 7%)' : undefined
|
||||||
border:
|
|
||||||
hasBackground == false && hasBorder == false
|
|
||||||
? '1px solid rgb(0 0 0 / 7%)'
|
|
||||||
: hasBackground == true && hasBorder == false
|
|
||||||
? 'none'
|
|
||||||
: undefined
|
|
||||||
}}
|
|
||||||
styles={{
|
|
||||||
body: {
|
|
||||||
height: height == undefined ? undefined : height
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
@ -48,9 +32,7 @@ const LoadingPlaceholder = ({
|
|||||||
|
|
||||||
LoadingPlaceholder.propTypes = {
|
LoadingPlaceholder.propTypes = {
|
||||||
message: PropTypes.string.isRequired,
|
message: PropTypes.string.isRequired,
|
||||||
hasBackground: PropTypes.bool,
|
hasBackground: PropTypes.bool
|
||||||
hasBorder: PropTypes.bool,
|
|
||||||
height: PropTypes.string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LoadingPlaceholder
|
export default LoadingPlaceholder
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
|
|||||||
import ObjectProperty from './ObjectProperty'
|
import ObjectProperty from './ObjectProperty'
|
||||||
import { createElement } from 'react'
|
import { createElement } from 'react'
|
||||||
import Thumbnail from './Thumbnail'
|
import Thumbnail from './Thumbnail'
|
||||||
import { LoadingOutlined } from '@ant-design/icons'
|
|
||||||
|
|
||||||
const ObjectCard = ({
|
const ObjectCard = ({
|
||||||
isSkeleton = false,
|
isSkeleton = false,
|
||||||
@ -14,7 +13,6 @@ const ObjectCard = ({
|
|||||||
isEditing = false,
|
isEditing = false,
|
||||||
rowActions = [],
|
rowActions = [],
|
||||||
renderActions,
|
renderActions,
|
||||||
lazyLoading = false,
|
|
||||||
cardStyle = 'borderless'
|
cardStyle = 'borderless'
|
||||||
}) => {
|
}) => {
|
||||||
const descriptionItems = []
|
const descriptionItems = []
|
||||||
@ -61,7 +59,7 @@ const ObjectCard = ({
|
|||||||
var actions = undefined
|
var actions = undefined
|
||||||
|
|
||||||
if (rowActions.length > 0) {
|
if (rowActions.length > 0) {
|
||||||
actions = renderActions(record, lazyLoading)
|
actions = renderActions(record)
|
||||||
}
|
}
|
||||||
|
|
||||||
const primaryDescriptionItems = thumbnailPresent
|
const primaryDescriptionItems = thumbnailPresent
|
||||||
@ -148,21 +146,9 @@ const ObjectCard = ({
|
|||||||
{actions && (
|
{actions && (
|
||||||
<>
|
<>
|
||||||
<Divider style={{ margin: '4px 0 0 0' }} />
|
<Divider style={{ margin: '4px 0 0 0' }} />
|
||||||
|
<Flex align='flex-end' gap={10}>
|
||||||
<Flex
|
|
||||||
align='center'
|
|
||||||
gap={10}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
justify='space-between'
|
|
||||||
>
|
|
||||||
<Flex align='center' gap={10}>
|
|
||||||
{actions}
|
{actions}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{lazyLoading && (
|
|
||||||
<LoadingOutlined spin style={{ marginRight: 4 }} />
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -180,8 +166,7 @@ ObjectCard.propTypes = {
|
|||||||
rowActions: PropTypes.array,
|
rowActions: PropTypes.array,
|
||||||
renderActions: PropTypes.func.isRequired,
|
renderActions: PropTypes.func.isRequired,
|
||||||
cardStyle: PropTypes.string,
|
cardStyle: PropTypes.string,
|
||||||
isSkeleton: PropTypes.bool,
|
isSkeleton: PropTypes.bool
|
||||||
lazyLoading: PropTypes.bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ObjectCard
|
export default ObjectCard
|
||||||
|
|||||||
@ -8,14 +8,14 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
useState
|
useState
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { Empty, Flex } from 'antd'
|
import { Empty, Flex, Spin } from 'antd'
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { ApiServerContext } from '../context/ApiServerContext'
|
import { ApiServerContext } from '../context/ApiServerContext'
|
||||||
import ObjectCard from './ObjectCard'
|
import ObjectCard from './ObjectCard'
|
||||||
import ObjectKanbanColumn from './ObjectKanbanColumn'
|
import ObjectKanbanColumn from './ObjectKanbanColumn'
|
||||||
import ObjectKanbanHeader from './ObjectKanbanHeader'
|
import ObjectKanbanHeader from './ObjectKanbanHeader'
|
||||||
import ScrollBox from './ScrollBox'
|
import ScrollBox from './ScrollBox'
|
||||||
import Spin from './Spin'
|
|
||||||
import { getCategoryValueKey } from './viewModeUtils'
|
import { getCategoryValueKey } from './viewModeUtils'
|
||||||
|
|
||||||
const KANBAN_COLUMN_WIDTH = 360
|
const KANBAN_COLUMN_WIDTH = 360
|
||||||
@ -101,7 +101,6 @@ const ObjectKanban = forwardRef(
|
|||||||
baseFilter = {},
|
baseFilter = {},
|
||||||
masterFilter = {},
|
masterFilter = {},
|
||||||
sorter = {},
|
sorter = {},
|
||||||
lazyLoading = false,
|
|
||||||
pageSize = 25,
|
pageSize = 25,
|
||||||
model,
|
model,
|
||||||
modelProperties,
|
modelProperties,
|
||||||
@ -312,7 +311,11 @@ const ObjectKanban = forwardRef(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='objectKanbanContainerWrapper'>
|
<div className='objectKanbanContainerWrapper'>
|
||||||
<Spin spinning={showSkeleton}>
|
<Spin
|
||||||
|
indicator={<LoadingOutlined />}
|
||||||
|
spinning={showSkeleton}
|
||||||
|
style={{ height: '100%', flex: 1, minHeight: 0 }}
|
||||||
|
>
|
||||||
<div className='objectKanbanContainerSkeletons'>
|
<div className='objectKanbanContainerSkeletons'>
|
||||||
<ObjectKanbanHeader
|
<ObjectKanbanHeader
|
||||||
categoryValues={categoryValues}
|
categoryValues={categoryValues}
|
||||||
@ -322,7 +325,6 @@ const ObjectKanban = forwardRef(
|
|||||||
skeletonColumnCount={
|
skeletonColumnCount={
|
||||||
showSkeleton ? skeletonLayout.columnCount : 0
|
showSkeleton ? skeletonLayout.columnCount : 0
|
||||||
}
|
}
|
||||||
lazyLoading={showSkeleton || lazyLoading}
|
|
||||||
/>
|
/>
|
||||||
<div className='objectKanbanKanbanBody' ref={kanbanBodyRef}>
|
<div className='objectKanbanKanbanBody' ref={kanbanBodyRef}>
|
||||||
{!showSkeleton && (
|
{!showSkeleton && (
|
||||||
@ -412,7 +414,6 @@ ObjectKanban.propTypes = {
|
|||||||
baseFilter: PropTypes.object,
|
baseFilter: PropTypes.object,
|
||||||
masterFilter: PropTypes.object,
|
masterFilter: PropTypes.object,
|
||||||
sorter: PropTypes.object,
|
sorter: PropTypes.object,
|
||||||
lazyLoading: PropTypes.bool,
|
|
||||||
pageSize: PropTypes.number,
|
pageSize: PropTypes.number,
|
||||||
model: PropTypes.object.isRequired,
|
model: PropTypes.object.isRequired,
|
||||||
modelProperties: PropTypes.array.isRequired,
|
modelProperties: PropTypes.array.isRequired,
|
||||||
|
|||||||
@ -9,11 +9,11 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
useState
|
useState
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { Flex } from 'antd'
|
import { Flex, Spin } from 'antd'
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { ApiServerContext } from '../context/ApiServerContext'
|
import { ApiServerContext } from '../context/ApiServerContext'
|
||||||
import ObjectCard from './ObjectCard'
|
import ObjectCard from './ObjectCard'
|
||||||
import Spin from './Spin'
|
|
||||||
import { toCategoryFilterValue } from './viewModeUtils'
|
import { toCategoryFilterValue } from './viewModeUtils'
|
||||||
|
|
||||||
const SCROLL_THRESHOLD = 50
|
const SCROLL_THRESHOLD = 50
|
||||||
@ -33,7 +33,6 @@ const ObjectKanbanColumn = forwardRef(
|
|||||||
visibleColumns = {},
|
visibleColumns = {},
|
||||||
isEditing = false,
|
isEditing = false,
|
||||||
rowActions = [],
|
rowActions = [],
|
||||||
lazyLoading = false,
|
|
||||||
renderActions,
|
renderActions,
|
||||||
scrollElement = null
|
scrollElement = null
|
||||||
},
|
},
|
||||||
@ -359,8 +358,7 @@ const ObjectKanbanColumn = forwardRef(
|
|||||||
[loadBoundaryPage]
|
[loadBoundaryPage]
|
||||||
)
|
)
|
||||||
|
|
||||||
const loadInitialPage = useCallback(
|
const loadInitialPage = useCallback(async ({ silent = false } = {}) => {
|
||||||
async ({ silent = false } = {}) => {
|
|
||||||
dataLoadGenerationRef.current += 1
|
dataLoadGenerationRef.current += 1
|
||||||
loadingPagesRef.current.clear()
|
loadingPagesRef.current.clear()
|
||||||
pendingScrollAnchorRef.current = null
|
pendingScrollAnchorRef.current = null
|
||||||
@ -405,8 +403,7 @@ const ObjectKanbanColumn = forwardRef(
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}, [
|
||||||
[
|
|
||||||
categoryProperty,
|
categoryProperty,
|
||||||
categoryValue,
|
categoryValue,
|
||||||
createPageWindow,
|
createPageWindow,
|
||||||
@ -414,8 +411,7 @@ const ObjectKanbanColumn = forwardRef(
|
|||||||
fetchPage,
|
fetchPage,
|
||||||
isStaleDataLoad,
|
isStaleDataLoad,
|
||||||
setTablePages
|
setTablePages
|
||||||
]
|
])
|
||||||
)
|
|
||||||
|
|
||||||
const reloadLoadedPages = useCallback(async () => {
|
const reloadLoadedPages = useCallback(async () => {
|
||||||
const loadedPages = pagesRef.current.filter(
|
const loadedPages = pagesRef.current.filter(
|
||||||
@ -505,7 +501,7 @@ const ObjectKanbanColumn = forwardRef(
|
|||||||
return (
|
return (
|
||||||
<Flex vertical className='objectKanbanColumn'>
|
<Flex vertical className='objectKanbanColumn'>
|
||||||
<div className='objectKanbanColumnCards' ref={containerRef}>
|
<div className='objectKanbanColumnCards' ref={containerRef}>
|
||||||
<Spin spinning={loading}>
|
<Spin indicator={<LoadingOutlined />} spinning={loading}>
|
||||||
<Flex
|
<Flex
|
||||||
vertical
|
vertical
|
||||||
gap='middle'
|
gap='middle'
|
||||||
@ -537,7 +533,6 @@ const ObjectKanbanColumn = forwardRef(
|
|||||||
rowActions={rowActions}
|
rowActions={rowActions}
|
||||||
renderActions={renderActions}
|
renderActions={renderActions}
|
||||||
cardStyle='bordered'
|
cardStyle='bordered'
|
||||||
lazyLoading={lazyLoading}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -565,7 +560,6 @@ ObjectKanbanColumn.propTypes = {
|
|||||||
visibleColumns: PropTypes.object,
|
visibleColumns: PropTypes.object,
|
||||||
isEditing: PropTypes.bool,
|
isEditing: PropTypes.bool,
|
||||||
rowActions: PropTypes.array,
|
rowActions: PropTypes.array,
|
||||||
lazyLoading: PropTypes.bool,
|
|
||||||
renderActions: PropTypes.func,
|
renderActions: PropTypes.func,
|
||||||
scrollElement: PropTypes.object
|
scrollElement: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,22 +2,20 @@ import { Flex, Skeleton } from 'antd'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import ObjectProperty from './ObjectProperty'
|
import ObjectProperty from './ObjectProperty'
|
||||||
import { getCategoryValueKey } from './viewModeUtils'
|
import { getCategoryValueKey } from './viewModeUtils'
|
||||||
import { LoadingOutlined } from '@ant-design/icons'
|
|
||||||
|
|
||||||
const ObjectKanbanHeader = ({
|
const ObjectKanbanHeader = ({
|
||||||
categoryValues,
|
categoryValues,
|
||||||
categoryProperty,
|
categoryProperty,
|
||||||
categoryPropertyDef,
|
categoryPropertyDef,
|
||||||
trackRef,
|
trackRef,
|
||||||
skeletonColumnCount = 0,
|
skeletonColumnCount = 0
|
||||||
lazyLoading = false
|
|
||||||
}) => {
|
}) => {
|
||||||
const showSkeleton = skeletonColumnCount > 0
|
const showSkeleton = skeletonColumnCount > 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='objectKanbanHeader'>
|
<div className='objectKanbanHeader'>
|
||||||
<div className='objectKanbanHeaderTrack' ref={trackRef}>
|
<div className='objectKanbanHeaderTrack' ref={trackRef}>
|
||||||
<Flex gap='middle' className='objectKanbanHeaderRow' align='center'>
|
<Flex gap='middle' className='objectKanbanHeaderRow'>
|
||||||
{showSkeleton
|
{showSkeleton
|
||||||
? Array.from({ length: skeletonColumnCount }).map((_, index) => (
|
? Array.from({ length: skeletonColumnCount }).map((_, index) => (
|
||||||
<div
|
<div
|
||||||
@ -34,13 +32,7 @@ const ObjectKanbanHeader = ({
|
|||||||
: categoryValues.map((categoryValue) => {
|
: categoryValues.map((categoryValue) => {
|
||||||
const columnKey = getCategoryValueKey(categoryValue)
|
const columnKey = getCategoryValueKey(categoryValue)
|
||||||
return (
|
return (
|
||||||
<Flex
|
<div key={columnKey} className='objectKanbanHeaderCell'>
|
||||||
key={columnKey}
|
|
||||||
className='objectKanbanHeaderCell'
|
|
||||||
align='center'
|
|
||||||
justify='space-between'
|
|
||||||
gap={8}
|
|
||||||
>
|
|
||||||
{categoryPropertyDef ? (
|
{categoryPropertyDef ? (
|
||||||
<ObjectProperty
|
<ObjectProperty
|
||||||
{...categoryPropertyDef}
|
{...categoryPropertyDef}
|
||||||
@ -49,13 +41,7 @@ const ObjectKanbanHeader = ({
|
|||||||
name={categoryProperty}
|
name={categoryProperty}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{lazyLoading && (
|
</div>
|
||||||
<LoadingOutlined
|
|
||||||
spin
|
|
||||||
style={{ flexShrink: 0, marginRight: 6 }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -71,8 +57,7 @@ ObjectKanbanHeader.propTypes = {
|
|||||||
categoryProperty: PropTypes.string.isRequired,
|
categoryProperty: PropTypes.string.isRequired,
|
||||||
categoryPropertyDef: PropTypes.object,
|
categoryPropertyDef: PropTypes.object,
|
||||||
trackRef: PropTypes.object,
|
trackRef: PropTypes.object,
|
||||||
skeletonColumnCount: PropTypes.number,
|
skeletonColumnCount: PropTypes.number
|
||||||
lazyLoading: PropTypes.bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ObjectKanbanHeader
|
export default ObjectKanbanHeader
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import {
|
|||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
Flex,
|
Flex,
|
||||||
|
Spin,
|
||||||
Button,
|
Button,
|
||||||
Space,
|
Space,
|
||||||
Form,
|
Form,
|
||||||
@ -46,7 +47,6 @@ import { useActions } from '../context/ActionsContext'
|
|||||||
import ActionsIcon from '../../Icons/ActionsIcon'
|
import ActionsIcon from '../../Icons/ActionsIcon'
|
||||||
import FilterIcon from '../../Icons/FilterIcon'
|
import FilterIcon from '../../Icons/FilterIcon'
|
||||||
import ScrollBox from './ScrollBox'
|
import ScrollBox from './ScrollBox'
|
||||||
import Spin from './Spin'
|
|
||||||
import SimplePropertyFilter from './SimplePropertyFilter'
|
import SimplePropertyFilter from './SimplePropertyFilter'
|
||||||
import QuickPropertyFilters from './QuickPropertyFilters'
|
import QuickPropertyFilters from './QuickPropertyFilters'
|
||||||
import FilterInput from './FilterInput'
|
import FilterInput from './FilterInput'
|
||||||
@ -60,7 +60,6 @@ import Tooltip from './Tooltip'
|
|||||||
import { ObjectTableFilterContext } from './ObjectTableFilterContext'
|
import { ObjectTableFilterContext } from './ObjectTableFilterContext'
|
||||||
import ObjectListViewContext from '../context/ObjectListViewContext'
|
import ObjectListViewContext from '../context/ObjectListViewContext'
|
||||||
import { isCardsView, isKanbanView, normalizeViewMode } from './viewModeUtils'
|
import { isCardsView, isKanbanView, normalizeViewMode } from './viewModeUtils'
|
||||||
import LoadingPlaceholder from './LoadingPlaceholder'
|
|
||||||
|
|
||||||
const logger = loglevel.getLogger('DasboardTable')
|
const logger = loglevel.getLogger('DasboardTable')
|
||||||
logger.setLevel(config.logLevel)
|
logger.setLevel(config.logLevel)
|
||||||
@ -564,7 +563,7 @@ const ObjectTable = forwardRef(
|
|||||||
)
|
)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const renderActions = (objectData, actionsDisabled = false) => {
|
const renderActions = (objectData) => {
|
||||||
return (
|
return (
|
||||||
<Flex gap='small' align='center' justify='center'>
|
<Flex gap='small' align='center' justify='center'>
|
||||||
{rowActions.map((action, index) => {
|
{rowActions.map((action, index) => {
|
||||||
@ -577,10 +576,9 @@ const ObjectTable = forwardRef(
|
|||||||
action.disabled({
|
action.disabled({
|
||||||
...objectData,
|
...objectData,
|
||||||
_user: userProfile
|
_user: userProfile
|
||||||
}) ||
|
})
|
||||||
actionsDisabled
|
|
||||||
} else {
|
} else {
|
||||||
disabled = denied || action.disabled || actionsDisabled
|
disabled = denied || action.disabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@ -1177,10 +1175,8 @@ const ObjectTable = forwardRef(
|
|||||||
|
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setLazyLoading(false)
|
|
||||||
} else {
|
} else {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
setLazyLoading(true)
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let loadKanban = kanbanRef.current?.load
|
let loadKanban = kanbanRef.current?.load
|
||||||
@ -1195,12 +1191,8 @@ const ObjectTable = forwardRef(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Error loading kanban view:', error)
|
logger.error('Error loading kanban view:', error)
|
||||||
} finally {
|
} finally {
|
||||||
if (generation === dataLoadGenerationRef.current) {
|
if (!silent && generation === dataLoadGenerationRef.current) {
|
||||||
if (!silent) {
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
} else {
|
|
||||||
setLazyLoading(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -1212,7 +1204,6 @@ const ObjectTable = forwardRef(
|
|||||||
loadingPagesRef.current.clear()
|
loadingPagesRef.current.clear()
|
||||||
pendingScrollAnchorRef.current = null
|
pendingScrollAnchorRef.current = null
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
setLazyLoading(true)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const firstResult = await fetchPage(pageNum, filter, sorter)
|
const firstResult = await fetchPage(pageNum, filter, sorter)
|
||||||
@ -1233,10 +1224,6 @@ const ObjectTable = forwardRef(
|
|||||||
if (!isStaleDataLoad(generation)) {
|
if (!isStaleDataLoad(generation)) {
|
||||||
logger.error(`Error loading page ${pageNum}:`, error)
|
logger.error(`Error loading page ${pageNum}:`, error)
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
if (!isStaleDataLoad(generation)) {
|
|
||||||
setLazyLoading(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1248,7 +1235,6 @@ const ObjectTable = forwardRef(
|
|||||||
const skeletonPage = createSkeletonPage(pageNum)
|
const skeletonPage = createSkeletonPage(pageNum)
|
||||||
setTablePages([skeletonPage])
|
setTablePages([skeletonPage])
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setLazyLoading(false)
|
|
||||||
if (isStaleDataLoad(generation)) return
|
if (isStaleDataLoad(generation)) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1984,7 +1970,6 @@ const ObjectTable = forwardRef(
|
|||||||
modelProperties={modelProperties}
|
modelProperties={modelProperties}
|
||||||
visibleColumns={visibleColumns}
|
visibleColumns={visibleColumns}
|
||||||
record={record}
|
record={record}
|
||||||
lazyLoading={lazyLoading}
|
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
rowActions={rowActions}
|
rowActions={rowActions}
|
||||||
renderActions={renderActions}
|
renderActions={renderActions}
|
||||||
@ -1996,14 +1981,6 @@ const ObjectTable = forwardRef(
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Row>
|
</Row>
|
||||||
{lazyLoading && tableData.length <= 0 && (
|
|
||||||
<LoadingPlaceholder
|
|
||||||
message='Loading, please wait...'
|
|
||||||
hasBackground={true}
|
|
||||||
hasBorder={false}
|
|
||||||
height='260px'
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollBox>
|
</ScrollBox>
|
||||||
)
|
)
|
||||||
@ -2045,7 +2022,11 @@ const ObjectTable = forwardRef(
|
|||||||
<Splitter.Panel>
|
<Splitter.Panel>
|
||||||
{isKanban ? (
|
{isKanban ? (
|
||||||
<div className='objectKanbanWrap'>
|
<div className='objectKanbanWrap'>
|
||||||
<Spin spinning={loading}>
|
<Spin
|
||||||
|
indicator={<LoadingOutlined />}
|
||||||
|
spinning={loading}
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
>
|
||||||
<ObjectKanban
|
<ObjectKanban
|
||||||
ref={kanbanRef}
|
ref={kanbanRef}
|
||||||
type={type}
|
type={type}
|
||||||
@ -2053,7 +2034,6 @@ const ObjectTable = forwardRef(
|
|||||||
baseFilter={effectiveFilter}
|
baseFilter={effectiveFilter}
|
||||||
masterFilter={resolvedMasterFilter}
|
masterFilter={resolvedMasterFilter}
|
||||||
sorter={effectiveSorter}
|
sorter={effectiveSorter}
|
||||||
lazyLoading={lazyLoading}
|
|
||||||
pageSize={pageSize}
|
pageSize={pageSize}
|
||||||
model={model}
|
model={model}
|
||||||
modelProperties={modelProperties}
|
modelProperties={modelProperties}
|
||||||
@ -2069,10 +2049,20 @@ const ObjectTable = forwardRef(
|
|||||||
className='objectTableCardsContainer'
|
className='objectTableCardsContainer'
|
||||||
ref={objectTableCardsContainerRef}
|
ref={objectTableCardsContainerRef}
|
||||||
>
|
>
|
||||||
<Spin spinning={loading}>{renderCards()}</Spin>
|
<Spin
|
||||||
|
indicator={<LoadingOutlined />}
|
||||||
|
spinning={loading}
|
||||||
|
style={{
|
||||||
|
height: '300px',
|
||||||
|
flex: 1,
|
||||||
|
minHeight: 0,
|
||||||
|
width: '100%'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{renderCards()}
|
||||||
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Spin spinning={loading}>
|
|
||||||
<Table
|
<Table
|
||||||
key={tableListKey}
|
key={tableListKey}
|
||||||
ref={tableRef}
|
ref={tableRef}
|
||||||
@ -2082,6 +2072,10 @@ const ObjectTable = forwardRef(
|
|||||||
pagination={false}
|
pagination={false}
|
||||||
scroll={{ y: adjustedScrollHeight }}
|
scroll={{ y: adjustedScrollHeight }}
|
||||||
rowKey='_id'
|
rowKey='_id'
|
||||||
|
loading={{
|
||||||
|
spinning: loading,
|
||||||
|
indicator: <LoadingOutlined spin />
|
||||||
|
}}
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
showSorterTooltip={false}
|
showSorterTooltip={false}
|
||||||
@ -2090,7 +2084,6 @@ const ObjectTable = forwardRef(
|
|||||||
components={components}
|
components={components}
|
||||||
onRow={onRow}
|
onRow={onRow}
|
||||||
/>
|
/>
|
||||||
</Spin>
|
|
||||||
)}
|
)}
|
||||||
</Splitter.Panel>
|
</Splitter.Panel>
|
||||||
{(showSortSidebar || showFilterSidebar) && (
|
{(showSortSidebar || showFilterSidebar) && (
|
||||||
|
|||||||
@ -1,77 +0,0 @@
|
|||||||
import PropTypes from 'prop-types'
|
|
||||||
import { LoadingOutlined } from '@ant-design/icons'
|
|
||||||
|
|
||||||
const SIZE_CLASS = {
|
|
||||||
small: 'spin-sm',
|
|
||||||
default: '',
|
|
||||||
large: 'spin-lg'
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_INDICATOR = (
|
|
||||||
<LoadingOutlined spin style={{ color: 'var(--color-primary)' }} />
|
|
||||||
)
|
|
||||||
|
|
||||||
const Spin = ({
|
|
||||||
spinning = true,
|
|
||||||
children,
|
|
||||||
indicator = DEFAULT_INDICATOR,
|
|
||||||
size = 'default',
|
|
||||||
style,
|
|
||||||
className
|
|
||||||
}) => {
|
|
||||||
const sizeClass = SIZE_CLASS[size] ?? ''
|
|
||||||
|
|
||||||
if (children == null) {
|
|
||||||
if (!spinning) return null
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={['spin', sizeClass, className].filter(Boolean).join(' ')}
|
|
||||||
style={style}
|
|
||||||
role='status'
|
|
||||||
aria-live='polite'
|
|
||||||
>
|
|
||||||
{indicator}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={[
|
|
||||||
'spin-nested',
|
|
||||||
spinning ? 'is-spinning' : null,
|
|
||||||
sizeClass,
|
|
||||||
className
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' ')}
|
|
||||||
style={style}
|
|
||||||
>
|
|
||||||
{spinning && (
|
|
||||||
<div className='spin-overlay' role='status' aria-live='polite'>
|
|
||||||
{indicator}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className={['spin-content', spinning ? 'is-spinning' : null]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' ')}
|
|
||||||
aria-busy={spinning}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spin.propTypes = {
|
|
||||||
spinning: PropTypes.bool,
|
|
||||||
children: PropTypes.node,
|
|
||||||
indicator: PropTypes.node,
|
|
||||||
size: PropTypes.oneOf(['small', 'default', 'large']),
|
|
||||||
style: PropTypes.object,
|
|
||||||
className: PropTypes.string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Spin
|
|
||||||
Loading…
x
Reference in New Issue
Block a user