diff --git a/assets/stylesheets/App.css b/assets/stylesheets/App.css
index d7832b06..f358d943 100644
--- a/assets/stylesheets/App.css
+++ b/assets/stylesheets/App.css
@@ -1451,11 +1451,20 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
.objectKanbanContainerSkeletons {
display: flex;
flex-direction: column;
+ position: relative;
flex: 1;
min-width: 0;
min-height: 0;
}
+.objectKanbanOverlayColumns {
+ position: absolute;
+ inset: 0;
+ z-index: 4;
+ overflow: hidden;
+ pointer-events: none;
+}
+
.objectKanbanKanbanBody {
position: relative;
flex: 1;
@@ -1568,14 +1577,16 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
pointer-events: none;
}
-.objectKanbanSkeletonTrack {
+.objectKanbanSkeletonTrack,
+.objectKanbanOverlayTrack {
width: max-content;
min-width: 100%;
height: 100%;
will-change: transform;
}
-.objectKanbanSkeletonRow {
+.objectKanbanSkeletonRow,
+.objectKanbanOverlayRow {
width: max-content;
min-width: 100%;
height: 100%;
@@ -1592,16 +1603,21 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
border-radius: 0 0 12px 12px;
}
+.objectKanbanColumnResizeOverlay {
+ position: relative;
+}
+
.objectKanbanColumnResizeHandle {
position: absolute;
top: 0;
- right: -10px;
+ right: -11px;
bottom: 0;
width: 11px;
z-index: 3;
cursor: col-resize;
touch-action: none;
user-select: none;
+ pointer-events: auto;
}
.objectKanbanColumnResizeHandle::before {
@@ -1609,7 +1625,7 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
position: absolute;
top: 11px;
bottom: 11px;
- right: 0;
+ right: 1px;
width: 2px;
transform: translateX(-50%);
opacity: 0.6;
@@ -1620,7 +1636,7 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
content: '';
position: absolute;
top: 50%;
- right: 0;
+ right: 1px;
width: 2px;
height: 20px;
transform: translate(-50%, -50%);
@@ -1648,7 +1664,7 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
opacity: 1;
}
-.objectKanbanColumn:hover .objectKanbanColumnResizeHandle::before {
+.objectKanbanColumnResizeHandle:hover::before {
background: #0e3a5b;
}
@@ -1660,7 +1676,7 @@ body.objectKanbanColumnResizing * {
.objectKanbanColumnSkeleton {
border-radius: 0 0 12px 12px;
- overflow: hidden;
+ overflow: visible;
}
.objectKanbanColumnCards {
diff --git a/src/components/Dashboard/common/ObjectKanban.jsx b/src/components/Dashboard/common/ObjectKanban.jsx
index 7de270e8..23d28d90 100644
--- a/src/components/Dashboard/common/ObjectKanban.jsx
+++ b/src/components/Dashboard/common/ObjectKanban.jsx
@@ -11,6 +11,7 @@ import {
} from 'react'
import { Empty, Flex } from 'antd'
import PropTypes from 'prop-types'
+import classNames from 'classnames'
import { ApiServerContext } from '../context/ApiServerContext'
import ObjectCard from './ObjectCard'
import ObjectKanbanColumn from './ObjectKanbanColumn'
@@ -97,6 +98,99 @@ const getKanbanSkeletonLayout = (width, height) => {
return { columnCount, cardCount }
}
+const ObjectKanbanColumnResizeHandle = ({ active = false, onMouseDown }) => (
+
+)
+
+ObjectKanbanColumnResizeHandle.propTypes = {
+ active: PropTypes.bool,
+ onMouseDown: PropTypes.func
+}
+
+const ObjectKanbanColumnResizeOverlay = ({
+ columnKey,
+ width,
+ columnIndex,
+ isResizing,
+ onResizeStart
+}) => {
+ return (
+
+ {onResizeStart && columnKey && (
+ onResizeStart(event, columnKey)}
+ />
+ )}
+
+ )
+}
+
+const ObjectKanbanColumnSkeleton = ({
+ columnKey,
+ width,
+ cardCount = 0,
+ model,
+ modelProperties,
+ visibleColumns,
+ keyPrefix = 'skeleton',
+ columnIndex = 0
+}) => (
+
+
+ {cardCount > 0 && (
+
+ {Array.from({ length: cardCount }).map((_, cardIndex) => (
+
+ ))}
+
+ )}
+
+
+)
+
+ObjectKanbanColumnSkeleton.propTypes = {
+ columnKey: PropTypes.string,
+ width: PropTypes.number.isRequired,
+ cardCount: PropTypes.number,
+ model: PropTypes.object.isRequired,
+ modelProperties: PropTypes.array.isRequired,
+ visibleColumns: PropTypes.object,
+ keyPrefix: PropTypes.string,
+ columnIndex: PropTypes.number,
+ isResizing: PropTypes.bool,
+ onResizeStart: PropTypes.func
+}
+
const ObjectKanbanSkeletonColumns = ({
columnCount,
cardCount = 0,
@@ -105,7 +199,9 @@ const ObjectKanbanSkeletonColumns = ({
modelProperties,
visibleColumns,
keyPrefix = 'skeleton',
- columns = null
+ columns = null,
+ resizingKey = null,
+ onColumnResizeStart
}) => {
const skeletonColumns =
columns?.length > 0
@@ -120,38 +216,19 @@ const ObjectKanbanSkeletonColumns = ({
{skeletonColumns.map((column, columnIndex) => (
-
-
- {cardCount > 0 && (
-
- {Array.from({ length: cardCount }).map((_, cardIndex) => (
-
- ))}
-
- )}
-
-
+ columnKey={column.key}
+ width={column.width}
+ cardCount={cardCount}
+ model={model}
+ modelProperties={modelProperties}
+ visibleColumns={visibleColumns}
+ keyPrefix={keyPrefix}
+ columnIndex={columnIndex}
+ isResizing={resizingKey === column.key}
+ onResizeStart={onColumnResizeStart}
+ />
))}
@@ -159,6 +236,14 @@ const ObjectKanbanSkeletonColumns = ({
)
}
+ObjectKanbanColumnResizeOverlay.propTypes = {
+ columnKey: PropTypes.string,
+ width: PropTypes.number.isRequired,
+ columnIndex: PropTypes.number,
+ isResizing: PropTypes.bool,
+ onResizeStart: PropTypes.func
+}
+
ObjectKanbanSkeletonColumns.propTypes = {
columnCount: PropTypes.number.isRequired,
cardCount: PropTypes.number,
@@ -167,7 +252,9 @@ ObjectKanbanSkeletonColumns.propTypes = {
modelProperties: PropTypes.array.isRequired,
visibleColumns: PropTypes.object,
keyPrefix: PropTypes.string,
- columns: PropTypes.array
+ columns: PropTypes.array,
+ resizingKey: PropTypes.string,
+ onColumnResizeStart: PropTypes.func
}
const ObjectKanban = forwardRef(
@@ -200,6 +287,7 @@ const ObjectKanban = forwardRef(
const columnRefs = useRef({})
const headerTrackRef = useRef(null)
const skeletonTrackRef = useRef(null)
+ const overlayTrackRef = useRef(null)
const kanbanBodyRef = useRef(null)
const [scrollElement, setScrollElement] = useState(null)
const [categoryValues, setCategoryValues] = useState([])
@@ -272,6 +360,7 @@ const ObjectKanban = forwardRef(
const mainScroll = scrollElement
const headerTrack = headerTrackRef.current
const skeletonTrack = skeletonTrackRef.current
+ const overlayTrack = overlayTrackRef.current
if (!mainScroll || !headerTrack) return undefined
const handleMainScroll = () => {
@@ -280,6 +369,9 @@ const ObjectKanban = forwardRef(
if (skeletonTrack) {
skeletonTrack.style.transform = offset
}
+ if (overlayTrack) {
+ overlayTrack.style.transform = offset
+ }
}
handleMainScroll()
@@ -429,12 +521,14 @@ const ObjectKanban = forwardRef(
setReloadingColumnKeys(previousKeys)
try {
lastCategoryQueryKeyRef.current = null
- const nextValues = await load(baseFilterRef.current, sorterRef.current, {
- silent: true
- })
- const nextKeySet = new Set(
- (nextValues || []).map(getCategoryValueKey)
+ const nextValues = await load(
+ baseFilterRef.current,
+ sorterRef.current,
+ {
+ silent: true
+ }
)
+ const nextKeySet = new Set((nextValues || []).map(getCategoryValueKey))
// Only reload columns that existed before; newly created columns
// mount and load themselves.
const keysToReload = previousKeys.filter((key) => nextKeySet.has(key))
@@ -480,9 +574,9 @@ const ObjectKanban = forwardRef(
updatedData,
categoryPropertyName
)
- ? getCategoryColumnKeys(
- updatedData[categoryPropertyName]
- ).filter((key) => previousKeys.has(key))
+ ? getCategoryColumnKeys(updatedData[categoryPropertyName]).filter(
+ (key) => previousKeys.has(key)
+ )
: []
const tentativeKeys = [...new Set([...oldKeys, ...updatedKeys])]
@@ -755,11 +849,7 @@ const ObjectKanban = forwardRef(
setDropTargetKey(null)
return
}
- const nextColumns = reorderColumnsByKey(
- resolvedColumns,
- fromKey,
- toKey
- )
+ const nextColumns = reorderColumnsByKey(resolvedColumns, fromKey, toKey)
persistColumns(nextColumns)
setDraggedKey(null)
setDropTargetKey(null)
@@ -845,6 +935,23 @@ const ObjectKanban = forwardRef(
return (
+
+
+
+ {displayColumns.map(({ key: columnKey, width }, columnIndex) => (
+
+ ))}
+
+
+
+
- handleColumnResizeStart(event, columnKey)
- }
/>
)
)}
@@ -926,16 +1029,16 @@ const ObjectKanban = forwardRef(
>
{displayColumns.map(({ key: columnKey, width }) => (
-
+ columnKey={columnKey}
+ width={width}
+ model={model}
+ modelProperties={modelProperties}
+ visibleColumns={visibleColumns}
+ isResizing={resizingKey === columnKey}
+ onResizeStart={handleColumnResizeStart}
+ />
))}
diff --git a/src/components/Dashboard/common/ObjectKanbanColumn.jsx b/src/components/Dashboard/common/ObjectKanbanColumn.jsx
index d5d845c1..494a53c5 100644
--- a/src/components/Dashboard/common/ObjectKanbanColumn.jsx
+++ b/src/components/Dashboard/common/ObjectKanbanColumn.jsx
@@ -11,7 +11,6 @@ import {
} from 'react'
import { Flex } from 'antd'
import PropTypes from 'prop-types'
-import classNames from 'classnames'
import { ApiServerContext } from '../context/ApiServerContext'
import ObjectCard from './ObjectCard'
import Spin from './Spin'
@@ -42,9 +41,7 @@ const ObjectKanbanColumn = forwardRef(
lazyLoading = false,
renderActions,
scrollElement = null,
- width,
- isResizing = false,
- onResizeStart
+ width
},
ref
) => {
@@ -597,17 +594,6 @@ const ObjectKanbanColumn = forwardRef(
- {onResizeStart && (
- onResizeStart(event)}
- />
- )}
)
}
@@ -631,9 +617,7 @@ ObjectKanbanColumn.propTypes = {
lazyLoading: PropTypes.bool,
renderActions: PropTypes.func,
scrollElement: PropTypes.object,
- width: PropTypes.number,
- isResizing: PropTypes.bool,
- onResizeStart: PropTypes.func
+ width: PropTypes.number
}
export default ObjectKanbanColumn