diff --git a/assets/stylesheets/App.css b/assets/stylesheets/App.css index f95d3f28..416e29e5 100644 --- a/assets/stylesheets/App.css +++ b/assets/stylesheets/App.css @@ -475,6 +475,67 @@ body { .ant-spin-blur { 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 --- */ /* --- Start of src/components/Dashboard/Layout.css --- */ @@ -1377,26 +1438,6 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton { 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 { position: relative; width: 100%; @@ -1407,15 +1448,6 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton { 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 { display: flex; flex-direction: column; @@ -1449,12 +1481,8 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton { height: 100%; min-width: 0; min-height: 0; -} - -.objectKanbanWrap > .ant-spin-nested-loading, -.objectKanbanWrap > .ant-spin-nested-loading > .ant-spin-container { - height: 100%; - min-height: 0; + display: flex; + flex-direction: column; } .objectKanbanScroll { diff --git a/src/components/Dashboard/common/ObjectKanban.jsx b/src/components/Dashboard/common/ObjectKanban.jsx index a93bc726..e4dc9e11 100644 --- a/src/components/Dashboard/common/ObjectKanban.jsx +++ b/src/components/Dashboard/common/ObjectKanban.jsx @@ -8,14 +8,14 @@ import { useRef, useState } from 'react' -import { Empty, Flex, Spin } from 'antd' -import { LoadingOutlined } from '@ant-design/icons' +import { Empty, Flex } from 'antd' import PropTypes from 'prop-types' import { ApiServerContext } from '../context/ApiServerContext' import ObjectCard from './ObjectCard' import ObjectKanbanColumn from './ObjectKanbanColumn' import ObjectKanbanHeader from './ObjectKanbanHeader' import ScrollBox from './ScrollBox' +import Spin from './Spin' import { getCategoryValueKey } from './viewModeUtils' const KANBAN_COLUMN_WIDTH = 360 @@ -311,11 +311,7 @@ const ObjectKanban = forwardRef( return (
- } - spinning={showSkeleton} - style={{ height: '100%', flex: 1, minHeight: 0 }} - > +
- } spinning={loading}> + {isKanban ? (
- } - spinning={loading} - style={{ height: '100%' }} - > + - } - spinning={loading} - style={{ - height: '300px', - flex: 1, - minHeight: 0, - width: '100%' - }} - > - {renderCards()} - + {renderCards()}
) : ( - - }} - onScroll={handleScroll} - onChange={handleTableChange} - showSorterTooltip={false} - style={{ height: '100%' }} - size={size} - components={components} - onRow={onRow} - /> + +
+ )} {(showSortSidebar || showFilterSidebar) && ( diff --git a/src/components/Dashboard/common/Spin.jsx b/src/components/Dashboard/common/Spin.jsx new file mode 100644 index 00000000..d0fafd4d --- /dev/null +++ b/src/components/Dashboard/common/Spin.jsx @@ -0,0 +1,77 @@ +import PropTypes from 'prop-types' +import { LoadingOutlined } from '@ant-design/icons' + +const SIZE_CLASS = { + small: 'spin-sm', + default: '', + large: 'spin-lg' +} + +const DEFAULT_INDICATOR = ( + +) + +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 ( +
+ {indicator} +
+ ) + } + + return ( +
+ {spinning && ( +
+ {indicator} +
+ )} +
+ {children} +
+
+ ) +} + +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