Feature: Mobile layout 🔥🔥🔥

This commit is contained in:
navaneeth 2021-06-03 18:35:01 +05:30
parent 6196051ffb
commit 03a71a6352
6 changed files with 163 additions and 42 deletions

View file

@ -1,6 +1,6 @@
import React, { useEffect, useState, memo } from 'react';
export const BoxDragPreview = memo(function BoxDragPreview({ item }) {
export const BoxDragPreview = memo(function BoxDragPreview({ item, currentLayout }) {
const [tickTock, setTickTock] = useState(false);
useEffect(
@ -11,7 +11,8 @@ export const BoxDragPreview = memo(function BoxDragPreview({ item }) {
[tickTock]
);
let { width, height } = item;
const layouts = item.layouts;
let { width, height } = layouts ? item.layouts[currentLayout] : {};
if (item.id === undefined) {
width = item.component.defaultSize.width;

View file

@ -30,6 +30,7 @@ export const Container = ({
appLoading,
configHandleClicked,
zoomLevel,
currentLayout,
removeComponent
}) => {
const components = appDefinition.components || [];
@ -43,11 +44,11 @@ export const Container = ({
}, [components]);
const moveBox = useCallback(
(id, left, top) => {
(id, layouts) => {
setBoxes(
update(boxes, {
[id]: {
$merge: { left, top }
$merge: { layouts }
}
})
);
@ -86,6 +87,9 @@ export const Container = ({
return;
}
let layouts = item['layouts'];
const currentLayoutOptions = layouts ? layouts[currentLayout] : {};
let componentData = {};
let componentMeta = {};
let id = item.id;
@ -107,8 +111,30 @@ export const Container = ({
}
componentData = item.component;
left = Math.round(item.left + deltaX);
top = Math.round(item.top + deltaY);
left = Math.round(currentLayoutOptions.left + deltaX);
top = Math.round(currentLayoutOptions.top + deltaY);
if (snapToGrid) {
[left, top] = doSnapToGrid(left, top);
}
let newBoxes = {
...boxes,
[id]: {
...boxes[id],
layouts: {
...boxes[id]['layouts'],
[currentLayout]: {
...boxes[id]['layouts'][currentLayout],
top: top,
left: left,
}
}
}
};
setBoxes(newBoxes);
} else {
// This is a new component
componentMeta = componentTypes.find((component) => component.component === item.component.component);
@ -124,22 +150,32 @@ export const Container = ({
top = Math.round(currentOffset.y + (currentOffset.y * (1 - zoomLevel)) - offsetFromTopOfWindow);
id = uuidv4();
}
if (snapToGrid) {
[left, top] = doSnapToGrid(left, top);
}
setBoxes({
...boxes,
[id]: {
top: top,
left: left,
width: item.width > 0 ? item.width : componentMeta.defaultSize.width,
height: item.height > 0 ? item.height : componentMeta.defaultSize.height,
component: componentData
if (snapToGrid) {
[left, top] = doSnapToGrid(left, top);
}
});
setBoxes({
...boxes,
[id]: {
component: componentData,
layouts: {
[currentLayout]: {
top: top,
left: left,
width: componentMeta.defaultSize.width,
height: componentMeta.defaultSize.height,
},
mobile: {
top: 100,
left: 0,
width: 445,
height: 500
}
}
}
});
}
return undefined;
}
@ -153,18 +189,29 @@ export const Container = ({
let { x, y } = position;
let { left, top, width, height } = boxes[id];
const defaultData = {
top: 100,
left: 0,
width: 445,
height: 500
};
let { left, top, width, height } = boxes[id]['layouts'][currentLayout] || defaultData;
top = y;
left = x;
width = width + deltaWidth;
height = height + deltaHeight
height = height + deltaHeight;
setBoxes(
update(boxes, {
[id]: {
$merge: { width, height, top, left }
$merge: {
layouts: {
[currentLayout]: { width, height, top, left }
}
}
}
})
);
@ -214,6 +261,7 @@ export const Container = ({
zoomLevel={zoomLevel}
configHandleClicked={configHandleClicked}
removeComponent={removeComponent}
currentLayout={currentLayout}
containerProps={{
mode,
snapToGrid,
@ -227,7 +275,8 @@ export const Container = ({
appLoading,
zoomLevel,
configHandleClicked,
removeComponent
removeComponent,
currentLayout
}}
/>
}

View file

@ -13,7 +13,7 @@ const layerStyles = {
height: '100%'
};
function getItemStyles(delta, item, initialOffset, currentOffset) {
function getItemStyles(delta, item, initialOffset, currentOffset, currentLayout) {
if (!initialOffset || !currentOffset) {
return {
display: 'none'
@ -29,8 +29,10 @@ function getItemStyles(delta, item, initialOffset, currentOffset) {
const realCanvasDelta = realCanvasBoundingRect.x - canvasContainerBoundingRect.x;
if (id) { // Dragging within the canvas
x = Math.round(item.left + delta.x);
y = Math.round(item.top + delta.y);
x = Math.round(item.layouts[currentLayout].left + delta.x);
y = Math.round(item.layouts[currentLayout].top + delta.y);
} else { // New component being dragged from components sidebar
const offsetFromTopOfWindow = realCanvasBoundingRect.top;
const offsetFromLeftOfWindow = realCanvasBoundingRect.left;
@ -50,7 +52,7 @@ function getItemStyles(delta, item, initialOffset, currentOffset) {
WebkitTransform: transform
};
}
export const CustomDragLayer = () => {
export const CustomDragLayer = ({ currentLayout }) => {
const {
itemType, isDragging, item, initialOffset, currentOffset, delta
} = useDragLayer((monitor) => ({
@ -64,7 +66,7 @@ export const CustomDragLayer = () => {
function renderItem() {
switch (itemType) {
case ItemTypes.BOX:
return <BoxDragPreview item={item} />;
return <BoxDragPreview item={item} currentLayout={currentLayout}/>;
default:
return null;
}
@ -76,7 +78,7 @@ export const CustomDragLayer = () => {
return (
<div style={layerStyles}>
<div style={getItemStyles(delta, item, initialOffset, currentOffset)}>
<div style={getItemStyles(delta, item, initialOffset, currentOffset, currentLayout)}>
{renderItem()}
</div>
</div>

View file

@ -66,7 +66,9 @@ export const DraggableBox = function DraggableBox({
zoomLevel,
containerProps,
configHandleClicked,
removeComponent
removeComponent,
currentLayout,
layouts
}) {
const [isResizing, setResizing] = useState(false);
const [canDrag, setCanDrag] = useState(true);
@ -76,13 +78,13 @@ export const DraggableBox = function DraggableBox({
() => ({
type: ItemTypes.BOX,
item: {
id, left, top, width, height, title, component, zoomLevel, parent
id, title, component, zoomLevel, parent, layouts
},
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
}),
[id, left, top, height, width, title, component, index, zoomLevel, parent]
[id, title, component, index, zoomLevel, parent, layouts]
);
useEffect(() => {
@ -114,6 +116,49 @@ export const DraggableBox = function DraggableBox({
setCanDrag(newState);
}
const defaultData = {
top: 100,
left: 0,
width: 445,
height: 500
}
const layoutData = inCanvas ? layouts[currentLayout] || defaultData : defaultData;
const [currentLayoutOptions, setCurrentLayoutOptions] = useState(layoutData);
useEffect(() => {
console.log(layoutData)
setCurrentLayoutOptions(layoutData);
}, [layoutData.height, layoutData.width, layoutData.left, layoutData.top]);
// const [currentLayoutOptions, setCurrentLayoutOptions] = useState(layoutData);
// if(inCanvas && Object.keys(currentLayoutOptions).length === 0 ) {
// setCurrentLayoutOptions({
// top: 100,
// left: 0,
// width: 445,
// height: 500
// })
// }
// useEffect(() => {
// if(inCanvas) {
// if(Object.keys(layoutData).length === 0 ) {
// setCurrentLayoutOptions({
// top: 100,
// left: 0,
// width: 445,
// height: 500
// })
// } else {
// setCurrentLayoutOptions(layoutData);
// }
// }
// }, [layoutData]);
return (
<div>
{inCanvas ? (
@ -126,8 +171,8 @@ export const DraggableBox = function DraggableBox({
<Rnd
style={{ ...style }}
size={{ width: width + 6, height: height + 6 }}
position={{ x: left, y: top }}
size={{ width: currentLayoutOptions.width + 6, height: currentLayoutOptions.height + 6}}
position={{ x: currentLayoutOptions ? currentLayoutOptions.left : 0, y: currentLayoutOptions ? currentLayoutOptions.top : 0 }}
defaultSize={{}}
className={`resizer ${mouseOver ? 'resizer-active' : ''}`}
onResize={() => setResizing(true)}
@ -153,9 +198,9 @@ export const DraggableBox = function DraggableBox({
<Box
component={component}
id={id}
width={width}
width={currentLayoutOptions.width}
height={currentLayoutOptions.height}
mode={mode}
height={height}
changeCanDrag={changeCanDrag}
inCanvas={inCanvas}
paramUpdated={paramUpdated}

View file

@ -60,6 +60,7 @@ class Editor extends React.Component {
showQueryEditor: true,
showLeftSidebar: true,
zoomLevel: 1.0,
currentLayout: 'desktop',
appDefinition: {
components: null
},
@ -393,8 +394,7 @@ class Editor extends React.Component {
currentState,
isLoading,
zoomLevel,
previewLoading,
queryPreviewData
currentLayout,
} = this.state;
const appLink = `/applications/${appId}`;
@ -489,6 +489,27 @@ class Editor extends React.Component {
/>
</button>
</div>
<div className="layout-buttons">
<div class="btn-group" role="group" aria-label="Basic example">
<button
type="button"
class="btn btn-light"
onClick={() => this.setState({ currentLayout: 'desktop' })}
disabled={currentLayout === 'desktop'}
>
<img src="https://www.svgrepo.com/show/108320/desktop.svg" width="12" height="12" />
</button>
<button
type="button"
class="btn btn-light"
onClick={() => this.setState({ currentLayout: 'mobile' })}
disabled={currentLayout === 'mobile'}
>
<img src="https://www.svgrepo.com/show/80383/touch-screen-mobile-device.svg" width="12" height="12" />
</button>
</div>
</div>
<div className="navbar-nav flex-row order-md-last">
<div className="nav-item dropdown d-none d-md-flex me-3">
{app
@ -631,13 +652,14 @@ class Editor extends React.Component {
</Resizable>
<div className="main">
<div className="canvas-container align-items-center" style={{ transform: `scale(${zoomLevel})` }}>
<div className="canvas-area">
<div className="canvas-area" style={{width: currentLayout === 'desktop' ? '1292px' : '450px'}}>
<Container
appDefinition={appDefinition}
appDefinitionChanged={this.appDefinitionChanged}
snapToGrid={true}
mode={'edit'}
zoomLevel={zoomLevel}
currentLayout={currentLayout}
appLoading={isLoading}
onEvent={(eventName, options) => onEvent(this, eventName, options)}
onComponentOptionChanged={(component, optionName, value) => onComponentOptionChanged(this, component, optionName, value)
@ -653,7 +675,10 @@ class Editor extends React.Component {
onComponentClick(this, id, component);
}}
/>
<CustomDragLayer snapToGrid={true} />
<CustomDragLayer
snapToGrid={true}
currentLayout={currentLayout}
/>
</div>
</div>
<div

View file

@ -270,7 +270,6 @@ body {
}
.canvas-area {
width: 1292px;
min-height: 2400px;
background: #edeff5;
margin: 0px auto;