From e6214bd205f45b3137b3826c0391f4f5a7672174 Mon Sep 17 00:00:00 2001 From: navaneeth Date: Thu, 3 Jun 2021 12:56:35 +0530 Subject: [PATCH 01/38] Minor UI change for transformations --- frontend/src/Editor/QueryManager/Transformation.jsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/Editor/QueryManager/Transformation.jsx b/frontend/src/Editor/QueryManager/Transformation.jsx index 9a3ded69f1..710bccba87 100644 --- a/frontend/src/Editor/QueryManager/Transformation.jsx +++ b/frontend/src/Editor/QueryManager/Transformation.jsx @@ -38,8 +38,10 @@ return data.filter(row => row.amount > 1000);`; Transformations {!options.enableTransformation && ( -
- Transformations can be used to transform the results of queries. +
+
+ Transformations can be used to transform the results of queries. All the app variables are accessible from transformers and support JS libraries such as Lodash & Moment. Read documentation. +
)}

@@ -58,9 +60,6 @@ return data.filter(row => row.amount > 1000);`;
)} -
- All the app variables are accessible from transformers and support JS libraries such as Lodash & Moment. Read documentation. -
); }; From 6196051ffbf853356d99ceb1da73d5ce450edadd Mon Sep 17 00:00:00 2001 From: navaneeth Date: Thu, 3 Jun 2021 12:59:30 +0530 Subject: [PATCH 02/38] Removed the extra padding of codehinter input field --- frontend/src/Editor/QueryManager/Transformation.jsx | 2 +- frontend/src/_styles/theme.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Editor/QueryManager/Transformation.jsx b/frontend/src/Editor/QueryManager/Transformation.jsx index 710bccba87..5cdd9437d7 100644 --- a/frontend/src/Editor/QueryManager/Transformation.jsx +++ b/frontend/src/Editor/QueryManager/Transformation.jsx @@ -40,7 +40,7 @@ return data.filter(row => row.amount > 1000);`; {!options.enableTransformation && (
- Transformations can be used to transform the results of queries. All the app variables are accessible from transformers and support JS libraries such as Lodash & Moment. Read documentation. + Transformations can be used to transform the results of queries. All the app variables are accessible from transformers and supports JS libraries such as Lodash & Moment. Read documentation.
)} diff --git a/frontend/src/_styles/theme.scss b/frontend/src/_styles/theme.scss index b7391bd1b2..74c9c56fe1 100644 --- a/frontend/src/_styles/theme.scss +++ b/frontend/src/_styles/theme.scss @@ -1332,7 +1332,7 @@ body { .codehinter-default-input { font-family: 'Roboto', sans-serif; - padding: 0.0475rem .75rem; + padding: 0.0475rem 0rem; display: block; width: 100%; font-size: .875rem; From 03a71a6352aaa79babd39f3fb131198fdc1f743d Mon Sep 17 00:00:00 2001 From: navaneeth Date: Thu, 3 Jun 2021 18:35:01 +0530 Subject: [PATCH 03/38] =?UTF-8?q?Feature:=20Mobile=20layout=20=F0=9F=94=A5?= =?UTF-8?q?=F0=9F=94=A5=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Editor/BoxDragPreview.jsx | 5 +- frontend/src/Editor/Container.jsx | 93 +++++++++++++++++++------ frontend/src/Editor/CustomDragLayer.jsx | 14 ++-- frontend/src/Editor/DraggableBox.jsx | 59 ++++++++++++++-- frontend/src/Editor/Editor.jsx | 33 +++++++-- frontend/src/_styles/theme.scss | 1 - 6 files changed, 163 insertions(+), 42 deletions(-) diff --git a/frontend/src/Editor/BoxDragPreview.jsx b/frontend/src/Editor/BoxDragPreview.jsx index dfe497b5e1..1cfa332741 100644 --- a/frontend/src/Editor/BoxDragPreview.jsx +++ b/frontend/src/Editor/BoxDragPreview.jsx @@ -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; diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx index 29ccc02690..a223d10008 100644 --- a/frontend/src/Editor/Container.jsx +++ b/frontend/src/Editor/Container.jsx @@ -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 }} /> } diff --git a/frontend/src/Editor/CustomDragLayer.jsx b/frontend/src/Editor/CustomDragLayer.jsx index 0b4e6dda8a..eea664295e 100644 --- a/frontend/src/Editor/CustomDragLayer.jsx +++ b/frontend/src/Editor/CustomDragLayer.jsx @@ -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 ; + return ; default: return null; } @@ -76,7 +78,7 @@ export const CustomDragLayer = () => { return (
-
+
{renderItem()}
diff --git a/frontend/src/Editor/DraggableBox.jsx b/frontend/src/Editor/DraggableBox.jsx index 28b6582552..9cf7315684 100644 --- a/frontend/src/Editor/DraggableBox.jsx +++ b/frontend/src/Editor/DraggableBox.jsx @@ -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 (
{inCanvas ? ( @@ -126,8 +171,8 @@ export const DraggableBox = function DraggableBox({ setResizing(true)} @@ -153,9 +198,9 @@ export const DraggableBox = function DraggableBox({
+
+
+ + +
+ +
{app @@ -631,13 +652,14 @@ class Editor extends React.Component {
-
+
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); }} /> - +
Date: Thu, 3 Jun 2021 19:33:07 +0530 Subject: [PATCH 04/38] Fixed layout reset while switching layouts --- frontend/src/Editor/Container.jsx | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx index a223d10008..5d0efd7e49 100644 --- a/frontend/src/Editor/Container.jsx +++ b/frontend/src/Editor/Container.jsx @@ -204,17 +204,22 @@ export const Container = ({ width = width + deltaWidth; height = height + deltaHeight; - setBoxes( - update(boxes, { - [id]: { - $merge: { - layouts: { - [currentLayout]: { width, height, top, left } - } - } + let newBoxes = { + ...boxes, + [id]: { + ...boxes[id], + layouts: { + ...boxes[id]['layouts'], + [currentLayout]: { + ...boxes[id]['layouts'][currentLayout], + width, height, top, left + } } - }) - ); + } + }; + + + setBoxes(newBoxes); } function paramUpdated(id, param, value) { From 94bede4269d321da57e73a5847fdc62c39cba3c9 Mon Sep 17 00:00:00 2001 From: navaneeth Date: Thu, 3 Jun 2021 20:36:49 +0530 Subject: [PATCH 05/38] Feature: Switch visibility on devices --- frontend/src/Editor/Components/components.js | 8 +++++ frontend/src/Editor/Container.jsx | 7 ++-- frontend/src/Editor/Editor.jsx | 3 +- .../src/Editor/Inspector/Components/Table.jsx | 2 +- frontend/src/Editor/Inspector/Inspector.jsx | 33 +++++++++++++++++-- frontend/src/Editor/Viewer.jsx | 16 +++++++-- 6 files changed, 60 insertions(+), 9 deletions(-) diff --git a/frontend/src/Editor/Components/components.js b/frontend/src/Editor/Components/components.js index e631630b10..f04f1163e8 100644 --- a/frontend/src/Editor/Components/components.js +++ b/frontend/src/Editor/Components/components.js @@ -14,6 +14,10 @@ export const componentTypes = [ actionButtonBackgroundColor: { type: 'color', displayName: 'Background color'}, actionButtonTextColor: { type: 'color', displayName: 'Text color'} }, + others: { + showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '}, + showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'}, + }, defaultSize: { width: 810, height: 300 @@ -35,6 +39,10 @@ export const componentTypes = [ searchText: '' }, definition: { + others: { + showOnDesktop: { value: true }, + showOnMobile: { value : false } + }, properties: { title: { value: 'Table' }, visible: { value: true }, diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx index 5d0efd7e49..03ed7b71c1 100644 --- a/frontend/src/Editor/Container.jsx +++ b/frontend/src/Editor/Container.jsx @@ -218,7 +218,6 @@ export const Container = ({ } }; - setBoxes(newBoxes); } @@ -248,7 +247,11 @@ export const Container = ({ return (
{Object.keys(boxes).map((key) => { - if(!boxes[key].parent) { + + const box = boxes[key]; + const canShowInCurrentLayout = box.component.definition.others[currentLayout === 'mobile' ? 'showOnMobile' : 'showOnDesktop'].value; + + if(!box.parent && canShowInCurrentLayout) { return +
{renderElement(component, componentMeta, paramUpdated, dataQueries, 'data', 'properties', currentState, components)}
diff --git a/frontend/src/Editor/Inspector/Inspector.jsx b/frontend/src/Editor/Inspector/Inspector.jsx index fd5d1e9e5a..deb78a2695 100644 --- a/frontend/src/Editor/Inspector/Inspector.jsx +++ b/frontend/src/Editor/Inspector/Inspector.jsx @@ -19,7 +19,7 @@ export const Inspector = ({ currentState }) => { - const selectedComponent = { id: selectedComponentId, component: allComponents[selectedComponentId].component } + const selectedComponent = { id: selectedComponentId, component: allComponents[selectedComponentId].component, layouts: allComponents[selectedComponentId].layouts} const [component, setComponent] = useState(selectedComponent); const [components, setComponents] = useState(allComponents); @@ -68,6 +68,24 @@ export const Inspector = ({ componentDefinitionChanged(newComponent); } + function layoutPropertyChanged(param, attr, value, paramType) { + paramUpdated(param, attr, value, paramType); + + // User wants to show the widget on mobile devices + if(param.name === 'showOnMobile' && value === true) { + let newComponent = { + ...component + }; + newComponent['layouts'] = { + ...newComponent.layouts, + mobile: { top: 100, left: 0, width: 445, height: 500 } + } + + setComponent(newComponent); + componentDefinitionChanged(newComponent); + } + } + function eventUpdated(event, actionId) { let newDefinition = { ...component.component.definition }; newDefinition.events[event.name] = { actionId }; @@ -170,14 +188,25 @@ export const Inspector = ({ } {!['Table', 'Chart'].includes(componentMeta.component) && -
+
{Object.keys(componentMeta.properties).map((property) => renderElement(component, componentMeta, paramUpdated, dataQueries, property, 'properties', currentState, components))}
Style
{Object.keys(componentMeta.styles).map((style) => renderElement(component, componentMeta, paramUpdated, dataQueries, style, 'styles', currentState, components))}
Events
{Object.keys(componentMeta.events).map((eventName) => renderEvent(component, eventUpdated, dataQueries, eventOptionUpdated, eventName, componentMeta.events[eventName], currentState, components))} + + +
} + + {/* Show on desktop & show on mobile params */} +
Layout
+
+ {renderElement(component, componentMeta, layoutPropertyChanged, dataQueries, 'showOnDesktop', 'others', currentState, components)} + {renderElement(component, componentMeta, layoutPropertyChanged, dataQueries, 'showOnMobile', 'others', currentState, components)} +
+
diff --git a/frontend/src/Editor/Viewer.jsx b/frontend/src/Editor/Viewer.jsx index 5ecc953fbc..3b981ea19b 100644 --- a/frontend/src/Editor/Viewer.jsx +++ b/frontend/src/Editor/Viewer.jsx @@ -39,7 +39,10 @@ class Viewer extends React.Component { componentDidMount() { const id = this.props.match.params.id; - this.setState({isLoading: true}); + this.setState({ + isLoading: true, + currentLayout: 'mobile' + }); appService.getApp(id).then((data) => this.setState( { @@ -83,7 +86,13 @@ class Viewer extends React.Component { } render() { - const { appDefinition, showQueryConfirmation, currentState, isLoading } = this.state; + const { + appDefinition, + showQueryConfirmation, + currentState, + isLoading, + currentLayout + } = this.state; console.log('currentState', currentState); @@ -116,7 +125,7 @@ class Viewer extends React.Component {
-
+
false} // function not relevant in viewer @@ -124,6 +133,7 @@ class Viewer extends React.Component { appLoading={isLoading} onEvent={(eventName, options) => onEvent(this, eventName, options)} mode="view" + currentLayout={currentLayout} currentState={this.state.currentState} onComponentClick={(id, component) => onComponentClick(this, id, component)} onComponentOptionChanged={(component, optionName, value) => onComponentOptionChanged(this, component, optionName, value) From b23f09a8c635199791233c3a9a3e394ca03a2d60 Mon Sep 17 00:00:00 2001 From: navaneeth Date: Thu, 3 Jun 2021 20:37:07 +0530 Subject: [PATCH 06/38] Viewport config --- frontend/src/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/index.html b/frontend/src/index.html index 907f841ad1..be04040702 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -2,6 +2,7 @@ + ToolJet - Dashboard