Merge branch 'feature/mobile-layout' into develop

This commit is contained in:
navaneeth 2021-06-03 22:50:46 +05:30
commit d09e6eed73
12 changed files with 368 additions and 63 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

@ -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 },
@ -85,6 +93,10 @@ export const componentTypes = [
width: 120,
height: 30
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
text: { type: 'code', displayName: 'Button Text' },
loadingState: { type: 'code', displayName: 'Loading State'}
@ -98,6 +110,10 @@ export const componentTypes = [
},
exposedVariables: {},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
text: { value: `Button` },
visible: { value: true },
@ -125,6 +141,10 @@ export const componentTypes = [
width: 600,
height: 400
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
title: { type: 'string', displayName: 'Title' },
data: { type: 'json', displayName: 'Data' },
@ -145,6 +165,10 @@ export const componentTypes = [
show: null
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
title: { value: 'This title can be changed' },
markerColor: { value: '#CDE1F8' },
@ -174,6 +198,10 @@ export const componentTypes = [
width: 600,
height: 400
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
title: { type: 'string', displayName: 'Title' },
size: { type: 'select', displayName: 'Modal size', options: [
@ -190,6 +218,10 @@ export const componentTypes = [
show: null
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
title: { value: 'This title can be changed' },
size: { value: 'md' },
@ -211,6 +243,10 @@ export const componentTypes = [
width: 200,
height: 30
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
placeholder: { type: 'code', displayName: 'Placeholder' }
},
@ -222,6 +258,10 @@ export const componentTypes = [
value: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
placeholder: { value: 'Placeholder text' }
},
@ -242,6 +282,10 @@ export const componentTypes = [
width: 150,
height: 30
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
format: { type: 'code', displayName: 'Format' },
enableTime: { type: 'code', displayName: 'Enable time selection?' },
@ -255,6 +299,10 @@ export const componentTypes = [
value: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
format: { value: 'DD/MM/YYYY' },
enableTime: { value: '{{false}}' },
@ -277,6 +325,10 @@ export const componentTypes = [
width: 100,
height: 60
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
label: { type: 'code', displayName: 'Label' }
},
@ -289,6 +341,10 @@ export const componentTypes = [
},
exposedVariables: {},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
label: { value: 'Checkbox label' }
},
@ -318,6 +374,10 @@ export const componentTypes = [
width: 250,
height: 100
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
value: { type: 'code', displayName: 'Default value' },
placeholder: { type: 'code', displayName: 'Placeholder' }
@ -330,6 +390,10 @@ export const componentTypes = [
value: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
value: { value: '' },
placeholder: { value: 'Placeholder text' }
@ -351,6 +415,10 @@ export const componentTypes = [
width: 300,
height: 32
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
format: { type: 'code', displayName: 'Format' }
},
@ -363,6 +431,10 @@ export const componentTypes = [
startDate: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
format: { value: 'DD/MM/YYYY' }
},
@ -379,6 +451,10 @@ export const componentTypes = [
displayName: 'Text',
description: 'Display markdown or HTML',
component: 'Text',
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
text: { type: 'code', displayName: 'Text' },
loadingState: { type: 'code', displayName: 'Show loading state' }
@ -395,6 +471,10 @@ export const componentTypes = [
},
exposedVariables: {},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
text: { value: 'Text goes here !' },
visible: { value: true },
@ -417,6 +497,10 @@ export const componentTypes = [
height: 200
},
component: 'Image',
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
source: { type: 'code', displayName: 'URL' },
},
@ -428,6 +512,10 @@ export const componentTypes = [
},
exposedVariables: {},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
source: { value: 'https://www.svgrepo.com/show/34217/image.svg' },
visible: { value: true }
@ -449,6 +537,10 @@ export const componentTypes = [
height: 200
},
component: 'Container',
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
},
events: {},
@ -457,6 +549,10 @@ export const componentTypes = [
},
exposedVariables: {},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
visible: { value: true }
},
@ -475,6 +571,10 @@ export const componentTypes = [
height: 30
},
component: 'DropDown',
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
label: { type: 'code', displayName: 'Label' },
value: { type: 'code', displayName: 'Default value' },
@ -491,6 +591,10 @@ export const componentTypes = [
value: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
label: { value: 'Select' },
value: { value: '' },
@ -515,6 +619,10 @@ export const componentTypes = [
height: 60
},
component: 'Multiselect',
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
label: { type: 'code', displayName: 'Label' },
value: { type: 'code', displayName: 'Default value' },
@ -531,6 +639,10 @@ export const componentTypes = [
values: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
label: { value: 'Select' },
values: { value: '[]' },
@ -555,6 +667,10 @@ export const componentTypes = [
width: 600,
height: 210
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
placeholder: { type: 'code', displayName: 'Placeholder' }
},
@ -566,6 +682,10 @@ export const componentTypes = [
value: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
placeholder: { value: 'Placeholder text' }
},
@ -586,6 +706,10 @@ export const componentTypes = [
width: 400,
height: 400
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop? '},
showOnMobile: { type: 'toggle', displayName: 'Show on mobile?'},
},
properties: {
initialLocation: { type: 'code', displayName: 'Initial location', tip: 'This location will be the initial center of the map', options: {
mode: 'javascript',
@ -612,6 +736,10 @@ export const componentTypes = [
center: {}
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value : false }
},
properties: {
initialLocation: { value: `{
"lat": 40.7128,

View file

@ -7,11 +7,7 @@ import update from 'immutability-helper';
import { componentTypes } from './Components/components';
import { computeComponentName } from '@/_helpers/utils';
const styles = {
width: 1292,
height: 2400,
position: 'absolute'
};
function uuidv4() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
@ -30,8 +26,18 @@ export const Container = ({
appLoading,
configHandleClicked,
zoomLevel,
removeComponent
currentLayout,
removeComponent,
deviceWindowWidth,
scaleValue
}) => {
const styles = {
width: currentLayout === 'mobile' ? deviceWindowWidth : 1292,
height: 2400,
position: 'absolute'
};
const components = appDefinition.components || [];
const [boxes, setBoxes] = useState(components);
@ -43,11 +49,11 @@ export const Container = ({
}, [components]);
const moveBox = useCallback(
(id, left, top) => {
(id, layouts) => {
setBoxes(
update(boxes, {
[id]: {
$merge: { left, top }
$merge: { layouts }
}
})
);
@ -86,6 +92,9 @@ export const Container = ({
return;
}
let layouts = item['layouts'];
const currentLayoutOptions = layouts ? layouts[item.currentLayout] : {};
let componentData = {};
let componentMeta = {};
let id = item.id;
@ -107,8 +116,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'],
[item.currentLayout]: {
...boxes[id]['layouts'][item.currentLayout],
top: top,
left: left,
}
}
}
};
setBoxes(newBoxes);
} else {
// This is a new component
componentMeta = componentTypes.find((component) => component.component === item.component.component);
@ -124,22 +155,31 @@ 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);
}
});
if(item.currentLayout === 'mobile') {
componentData.definition.others.showOnDesktop.value = false;
componentData.definition.others.showOnMobile.value = true;
}
setBoxes({
...boxes,
[id]: {
component: componentData,
layouts: {
[item.currentLayout]: {
top: top,
left: left,
width: componentMeta.defaultSize.width,
height: componentMeta.defaultSize.height,
}
}
}
});
}
return undefined;
}
@ -153,21 +193,36 @@ 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 }
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) {
@ -196,7 +251,11 @@ export const Container = ({
return (
<div ref={drop} style={styles} className={`real-canvas ${isDragging || isResizing ? ' show-grid' : ''}`}>
{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 <DraggableBox
onComponentClick={onComponentClick}
onEvent={onEvent}
@ -214,6 +273,8 @@ export const Container = ({
zoomLevel={zoomLevel}
configHandleClicked={configHandleClicked}
removeComponent={removeComponent}
currentLayout={currentLayout}
scaleValue={scaleValue}
containerProps={{
mode,
snapToGrid,
@ -227,7 +288,9 @@ export const Container = ({
appLoading,
zoomLevel,
configHandleClicked,
removeComponent
removeComponent,
currentLayout,
scaleValue
}}
/>
}

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,10 @@ export const DraggableBox = function DraggableBox({
zoomLevel,
containerProps,
configHandleClicked,
removeComponent
removeComponent,
currentLayout,
layouts,
scaleValue
}) {
const [isResizing, setResizing] = useState(false);
const [canDrag, setCanDrag] = useState(true);
@ -76,13 +79,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, currentLayout
},
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
}),
[id, left, top, height, width, title, component, index, zoomLevel, parent]
[id, title, component, index, zoomLevel, parent, layouts, currentLayout]
);
useEffect(() => {
@ -114,6 +117,21 @@ 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]);
return (
<div>
{inCanvas ? (
@ -126,8 +144,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 * scaleValue + 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 +171,9 @@ export const DraggableBox = function DraggableBox({
<Box
component={component}
id={id}
width={width}
width={currentLayoutOptions.width * scaleValue}
height={currentLayoutOptions.height}
mode={mode}
height={height}
changeCanDrag={changeCanDrag}
inCanvas={inCanvas}
paramUpdated={paramUpdated}

View file

@ -60,6 +60,9 @@ class Editor extends React.Component {
showQueryEditor: true,
showLeftSidebar: true,
zoomLevel: 1.0,
currentLayout: 'desktop',
scaleValue: 1,
deviceWindowWidth: 450,
appDefinition: {
components: null
},
@ -249,7 +252,8 @@ class Editor extends React.Component {
...this.state.appDefinition.components,
[newDefinition.id]: {
...this.state.appDefinition.components[newDefinition.id],
component: newDefinition.component
component: newDefinition.component,
layouts: newDefinition.layouts
}
}
}
@ -393,8 +397,9 @@ class Editor extends React.Component {
currentState,
isLoading,
zoomLevel,
previewLoading,
queryPreviewData
currentLayout,
deviceWindowWidth,
scaleValue
} = this.state;
const appLink = `/applications/${appId}`;
@ -489,6 +494,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 +657,16 @@ 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}
deviceWindowWidth={deviceWindowWidth}
scaleValue={scaleValue}
appLoading={isLoading}
onEvent={(eventName, options) => onEvent(this, eventName, options)}
onComponentOptionChanged={(component, optionName, value) => onComponentOptionChanged(this, component, optionName, value)
@ -653,7 +682,10 @@ class Editor extends React.Component {
onComponentClick(this, id, component);
}}
/>
<CustomDragLayer snapToGrid={true} />
<CustomDragLayer
snapToGrid={true}
currentLayout={currentLayout}
/>
</div>
</div>
<div
@ -795,6 +827,7 @@ class Editor extends React.Component {
<WidgetManager
componentTypes={componentTypes}
zoomLevel={zoomLevel}
currentLayout={currentLayout}
></WidgetManager>
)}
</div>

View file

@ -338,7 +338,7 @@ class Table extends React.Component {
const actions = component.component.definition.properties.actions || { value: [] };
return (
<div className="properties-container p-2 mb-5 pb-3" key={this.props.component.id}>
<div className="properties-container p-2 " key={this.props.component.id}>
{renderElement(component, componentMeta, paramUpdated, dataQueries, 'data', 'properties', currentState, components)}
<div className="field mb-2 mt-3">

View file

@ -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,32 @@ 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
};
const { width, height } = newComponent.layouts['desktop'];
newComponent['layouts'] = {
...newComponent.layouts,
mobile: {
top: 100,
left: 0,
width: Math.min(width, 445),
height: height
}
}
setComponent(newComponent);
componentDefinitionChanged(newComponent);
}
}
function eventUpdated(event, actionId) {
let newDefinition = { ...component.component.definition };
newDefinition.events[event.name] = { actionId };
@ -170,14 +196,25 @@ export const Inspector = ({
}
{!['Table', 'Chart'].includes(componentMeta.component) &&
<div className="properties-container p-2 mb-5 pb-3">
<div className="properties-container p-2">
{Object.keys(componentMeta.properties).map((property) => renderElement(component, componentMeta, paramUpdated, dataQueries, property, 'properties', currentState, components))}
<div class="hr-text">Style</div>
{Object.keys(componentMeta.styles).map((style) => renderElement(component, componentMeta, paramUpdated, dataQueries, style, 'styles', currentState, components))}
<div class="hr-text">Events</div>
{Object.keys(componentMeta.events).map((eventName) => renderEvent(component, eventUpdated, dataQueries, eventOptionUpdated, eventName, componentMeta.events[eventName], currentState, components))}
</div>
}
{/* Show on desktop & show on mobile params */}
<div class="hr-text">Layout</div>
<div className="properties-container p-2 pb-3 mb-5">
{renderElement(component, componentMeta, layoutPropertyChanged, dataQueries, 'showOnDesktop', 'others', currentState, components)}
{renderElement(component, componentMeta, layoutPropertyChanged, dataQueries, 'showOnMobile', 'others', currentState, components)}
</div>
<div className="widget-documentation-link p-2">
<a href={`https://docs.tooljet.io/docs/widgets/${componentMeta.name.toLowerCase()}`} target="_blank">
<small>

View file

@ -39,7 +39,17 @@ class Viewer extends React.Component {
componentDidMount() {
const id = this.props.match.params.id;
this.setState({isLoading: true});
const deviceWindowWidth = window.screen.width;
const isMobileDevice = deviceWindowWidth < 600;
let scaleValue = isMobileDevice ? deviceWindowWidth / 450 : 1;
this.setState({
isLoading: true,
deviceWindowWidth,
scaleValue,
currentLayout: isMobileDevice ? 'mobile' : 'desktop'
});
appService.getApp(id).then((data) => this.setState(
{
@ -83,7 +93,15 @@ class Viewer extends React.Component {
}
render() {
const { appDefinition, showQueryConfirmation, currentState, isLoading } = this.state;
const {
appDefinition,
showQueryConfirmation,
currentState,
isLoading,
currentLayout,
deviceWindowWidth,
scaleValue
} = this.state;
console.log('currentState', currentState);
@ -116,7 +134,7 @@ class Viewer extends React.Component {
<div className="sub-section">
<div className="main">
<div className="canvas-container align-items-center">
<div className="canvas-area">
<div className="canvas-area" style={{width: currentLayout === 'desktop' ? '1292px' : `${deviceWindowWidth}px`}}>
<Container
appDefinition={appDefinition}
appDefinitionChanged={() => false} // function not relevant in viewer
@ -124,6 +142,9 @@ class Viewer extends React.Component {
appLoading={isLoading}
onEvent={(eventName, options) => onEvent(this, eventName, options)}
mode="view"
scaleValue={scaleValue}
deviceWindowWidth={deviceWindowWidth}
currentLayout={currentLayout}
currentState={this.state.currentState}
onComponentClick={(id, component) => onComponentClick(this, id, component)}
onComponentOptionChanged={(component, optionName, value) => onComponentOptionChanged(this, component, optionName, value)

View file

@ -5,7 +5,8 @@ import { result } from 'lodash';
export const WidgetManager = function WidgetManager({
componentTypes,
zoomLevel
zoomLevel,
currentLayout
}) {
const [filteredComponents, setFilteredComponents] = useState(componentTypes);
@ -21,7 +22,7 @@ export const WidgetManager = function WidgetManager({
}
function renderComponentCard(component, index) {
return <DraggableBox key={index} index={index} component={component} zoomLevel={zoomLevel}/>;
return <DraggableBox key={index} index={index} component={component} zoomLevel={zoomLevel} currentLayout={currentLayout} />;
};
return <div className="components-container m-2">

View file

@ -270,7 +270,6 @@ body {
}
.canvas-area {
width: 1292px;
min-height: 2400px;
background: #edeff5;
margin: 0px auto;
@ -424,6 +423,7 @@ body {
height: 100%;
width: 100%;
position: fixed;
left: 0;
overflow-y: auto;
overflow-x: auto;
-webkit-box-pack: center;

View file

@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ToolJet - Dashboard</title>
<style>