Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/dashboard/Data/CustomDashboard/CanvasElement.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,26 @@ const CanvasElement = ({
onSelect,
onPositionChange,
onSizeChange,
onDrag,
onResize,
children,
}) => {
const handleDrag = (e, d) => {
if (onDrag) {
onDrag(element.id, d.x, d.y, element.width, element.height);
}
};

const handleDragStop = (e, d) => {
onPositionChange(element.id, d.x, d.y);
};

const handleResize = (e, direction, ref, delta, position) => {
if (onResize) {
onResize(element.id, ref.offsetWidth, ref.offsetHeight, position.x, position.y);
}
};

const handleResizeStop = (e, direction, ref, delta, position) => {
onSizeChange(
element.id,
Expand All @@ -44,9 +58,10 @@ const CanvasElement = ({
resizeGrid={[16, 16]}
minWidth={100}
minHeight={50}
bounds="parent"
dragHandleClassName={styles.dragHandle}
onDrag={handleDrag}
onDragStop={handleDragStop}
onResize={handleResize}
onResizeStop={handleResizeStop}
className={`${styles.canvasElement} ${isSelected ? styles.selected : ''}`}
enableResizing={{
Expand Down
110 changes: 106 additions & 4 deletions src/dashboard/Data/CustomDashboard/CustomDashboard.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,16 @@ class CustomDashboard extends DashboardView {
currentCanvasFavorite: false,
hasUnsavedChanges: false,
isFullscreen: false,
// Track dragging element position for canvas auto-extend
dragPosition: null,
};
this.autoReloadTimer = null;
this.autoReloadProgressTimer = null;
this.autoReloadStartTime = null;
this.canvasPreferencesManager = null;
this._isMounted = false;
this._elementSeq = {};
this.canvasRef = React.createRef();
}

componentDidMount() {
Expand Down Expand Up @@ -623,21 +626,95 @@ class CustomDashboard extends DashboardView {
};

handlePositionChange = (id, x, y) => {
// Ensure position is not negative
const safeX = Math.max(0, x);
const safeY = Math.max(0, y);
this.setState(state => ({
elements: state.elements.map(el =>
el.id === id ? { ...el, x, y } : el
el.id === id ? { ...el, x: safeX, y: safeY } : el
),
}), this.markUnsavedChanges);
};

handleSizeChange = (id, width, height, x, y) => {
// Ensure position is not negative when resizing from left/top edges
const safeX = Math.max(0, x);
const safeY = Math.max(0, y);
this.setState(state => ({
elements: state.elements.map(el =>
el.id === id ? { ...el, width, height, x, y } : el
el.id === id ? { ...el, width, height, x: safeX, y: safeY } : el
),
}), this.markUnsavedChanges);
};

handleDrag = (id, x, y, width, height) => {
// Update drag position to trigger canvas auto-extend during drag
this.setState({
dragPosition: { id, x, y, width, height },
});
};

handleDragEnd = () => {
// Clear drag position when drag ends
this.setState({ dragPosition: null });
};

handleResize = (id, width, height, x, y) => {
// Update drag position to trigger canvas auto-extend during resize
this.setState({
dragPosition: { id, x, y, width, height },
});
};

handleResizeEnd = () => {
// Clear drag position when resize ends
this.setState({ dragPosition: null });
};

// Calculate the required canvas size based on all elements and current drag position
// Returns dimensions only when content extends beyond the default CSS size
getCanvasSize() {
const { elements, dragPosition } = this.state;
const padding = 50; // Extra padding to allow easy placement at edges

let maxRight = 0;
let maxBottom = 0;

// Calculate bounds from all elements
elements.forEach(el => {
const right = el.x + el.width;
const bottom = el.y + el.height;
if (right > maxRight) {
maxRight = right;
}
if (bottom > maxBottom) {
maxBottom = bottom;
}
});

// Include current drag position if dragging
if (dragPosition) {
const dragRight = dragPosition.x + dragPosition.width;
const dragBottom = dragPosition.y + dragPosition.height;
if (dragRight > maxRight) {
maxRight = dragRight;
}
if (dragBottom > maxBottom) {
maxBottom = dragBottom;
}
}

// Add padding to content bounds
const contentWidth = maxRight + padding;
const contentHeight = maxBottom + padding;

// Return the content-based dimensions (CSS handles minimum via width:100% and min-height)
return {
minWidth: contentWidth,
minHeight: contentHeight,
};
}

handleDeleteElement = (id) => {
this.setState(state => ({
elements: state.elements.filter(el => el.id !== id),
Expand Down Expand Up @@ -1065,13 +1142,30 @@ class CustomDashboard extends DashboardView {
wrapperClasses.push(styles.fullscreen);
}

// Calculate dynamic canvas size based on element positions
const canvasSize = this.getCanvasSize();

return (
<div className={wrapperClasses.join(' ')}>
<div
ref={this.canvasRef}
className={styles.canvas}
onClick={this.handleDeselectElement}
tabIndex={0}
>
{/* Invisible sizing element that expands the canvas when elements extend beyond */}
{(canvasSize.minWidth > 0 || canvasSize.minHeight > 0) && (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: canvasSize.minWidth,
height: canvasSize.minHeight,
pointerEvents: 'none',
}}
/>
)}
{elements.length === 0 && !isFullscreen ? (
<EmptyState
icon="canvas-outline"
Expand All @@ -1087,8 +1181,16 @@ class CustomDashboard extends DashboardView {
element={element}
isSelected={element.id === selectedElement}
onSelect={this.handleSelectElement}
onPositionChange={this.handlePositionChange}
onSizeChange={this.handleSizeChange}
onPositionChange={(id, x, y) => {
this.handleDragEnd();
this.handlePositionChange(id, x, y);
}}
onSizeChange={(id, width, height, x, y) => {
this.handleResizeEnd();
this.handleSizeChange(id, width, height, x, y);
}}
onDrag={this.handleDrag}
onResize={this.handleResize}
>
{this.renderElementContent(element)}
</CanvasElement>
Expand Down
Loading