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/Components/components.js b/frontend/src/Editor/Components/components.js index e631630b10..151488ae60 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 }, @@ -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, diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx index 29ccc02690..3ba6243b12 100644 --- a/frontend/src/Editor/Container.jsx +++ b/frontend/src/Editor/Container.jsx @@ -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 (