ToolJet/frontend/src/Editor/SubContainer.jsx

578 lines
18 KiB
React
Raw Normal View History

/* eslint-disable import/no-named-as-default */
import React, { useCallback, useState, useEffect, useRef } from 'react';
2021-05-09 18:06:11 +00:00
import { useDrop, useDragLayer } from 'react-dnd';
import { ItemTypes } from './ItemTypes';
import { DraggableBox } from './DraggableBox';
import update from 'immutability-helper';
const produce = require('immer').default;
import _ from 'lodash';
import { componentTypes } from './WidgetManager/components';
import { addNewWidgetToTheEditor } from '@/_helpers/appUtils';
import { resolveReferences } from '@/_helpers/utils';
import { useCurrentState } from '@/_stores/currentStateStore';
import { useAppVersionStore } from '@/_stores/appVersionStore';
import { shallow } from 'zustand/shallow';
import { useMounted } from '@/_hooks/use-mount';
const NO_OF_GRIDS = 43;
2021-05-09 18:06:11 +00:00
export const SubContainer = ({
mode,
snapToGrid,
onComponentClick,
onEvent,
appDefinition,
appDefinitionChanged,
onComponentOptionChanged,
onComponentOptionsChanged,
appLoading,
zoomLevel,
parent,
parentRef,
setSelectedComponent,
deviceWindowWidth,
selectedComponent,
currentLayout,
removeComponent,
darkMode,
containerCanvasWidth,
readOnly,
customResolvables,
parentComponent,
onComponentHover,
hoveredComponent,
Feature/component property validation (#2782) * Initial architecture for component property validation * Coerce to default and log invalid properties * eslint rule:frontend for specifying the path to the @types/ * removes comment for eslint-disable-next-line * reverts 27946f1 & adding a temporary fix * Remove incorrect property validations * Avoid race condiiton in setting state for error logs * Fix issue where only one error got logged * Flush out any errors that are logged * Remove unnecessary console.log * Add validations for Table properties * Add support for multiple validations * Add validation for chart component * Add validation for modal * Set default value common to all validation schemas for component properties * Add validations for password widget * Add validations for datepicker * Add information about default value on validation error message * Remove unwanted console.log * Do not validate properties on Viewer * Use meta information from widget config instead of component state to validate * Do not coerce to default values while validating * Do not validate existing components * Update package-lock.json in sync with develop * Add validation for general properties * Add support for size validation of component properties and styles * Add support for min and max spec in size validation * Support pattern validation for string properties * Make size validation specifiable along with type specification * Component validation optimizations * Remove unnecessary comments * Remove unnecessary default value param from validation * Fixed visibility style validation bug * Added custom validation to PDF & Custom component * property/style validation statistics * values changed to string * validation button group widget * bugfix * Added property validation to timeline widget * Added visibility prop validation to timeline widget * steps property/style validation * svg component property validation * component property validation numberinput * bugfix * validation textarea * validation vertical divider * property validation html widget * validation :: checkbox * image property validation * validation :: rangeslider widget * validation :: circular progress bar * validation spinner * added props and style validation * tags validation * validation :: pagination * timer :: validation * validation :: toggle * validation :: divider * validation :: radiobutton * added props and style validation * validation:: iframe * validation :: password input * validation:: code editor * validation :: listview * validation :: star rating * validation :: modal * validation :: qrscanner * validation :: datepicker * multiselect :: validation * added union validation for border radius * added props and style validation * added props and styles validation * added props and styles validations * added props and styles validations * added props and style validations * added props and styles validations * added prop and style validations * added props and styles validations * Added ID validation to steps widget * Removed default value * Added validation key to SVG widget * Removed default value * table validations * table validations * removing default value * removing defaultval * removing default val * removing default val * padding validation update * updating number validation * updatin number validation * validation updates * border validation * border radius validation * number input validation * validation updates * border radius validation * validation update * Updated misspelled schema text * Updated Tabs validation schema * Updated tooltip element schema * Updated validation for multi select * Updated validation for dropdown * Updated validation for text widget * Rectified mispelled validation * Fixed : validation not working for format * Added Array validation to chart widget * format prop bug fix * draft complete :: table validation * Fixed misspelled text * Don't validate properties that are not defined on widgetConfig Co-authored-by: arpitnath <arpitnath42@gmail.com> Co-authored-by: Kavin Venkatachalam <kavin.saratha@gmail.com> Co-authored-by: stepinfwd <stepinfwd@gmail.com> Co-authored-by: manishkushare <kushare.manish9@gmail.com> Co-authored-by: Kavin Venkatachalam <50441969+kavinvenkatachalam@users.noreply.github.com>
2022-07-19 13:21:45 +00:00
sideBarDebugger,
selectedComponents,
onOptionChange,
exposedVariables,
addDefaultChildren = false,
height = '100%',
Feature/multi page applications (Task ID - CU-2h1bfvw) (#4729) * Add routes for multi-page apps * Modify Editor, Viewer and Inspector to accept new app structure * Show a page selector on left side bar * Align component deletion logic with new app schema * Make subcontainer work with multi-page apps * Load components state properly in viewer * Use UUID instead of handle for pages * Display sidebar on viewer to switch pages * Add proper URL suffixing for pages in viewer * Add action to switch page * Revert translation file back to its pre-existing linting * Fix bug that caused modal to not open/close * Add support for query params in page switch * Fix the issue that caused navigation to fail while accessed via slug * Add missing SwitchPage file * Add support for page level variables * Add migration to convert existing apps to new schema * Add rollback for converting multi-page definitions back to single-page * Fix migration for multi-page apps * Adapt import/export service for multi-pages * [improvements] Multi-page applications (#4755) * UI updates for page selector popup card * delete page * delete page check: if only one page exits * switch to home page if the selected page is removed * adds and switch to new page * updating page name * updates to home page and starting page * handle updating the home page when home page is deleted * search box for filtering pages and minor style updates for the page handler card * header search box style fixes * for creating a new page, page handle needs to be unique * seperating into smaller components * updated pinned icon for page selector styles and settinf styles * Leftsidebar header ui component * handle dark theme * page handle ui and dark theme fixes for page menu * page handler edit modal * pinned state and update pinned state for menu options triggered * dark theme fixes for edit modal * handle on update should not be empty or prev * page handler updater * added loading state for saving * handles cancels * fixes slug ui * fixes crash for older app versions * updates the query params when handle gets an update * update homePage to homePageId * removes console.log * go back to the popover for modal close * fixes: Difficult to select page * fixes: Difficult to select the three-dot menu * fixes: on visiting the root url, navigate to homepage on viewer * adds tooltip for url * updates the page selector sidebar with sync with query manager * refactor and cleanup * refactor and cleanup * Compute component state when page is switched * modal should not close on click outside * disable save button if there is not change in the page handle input * should show/hide page menu when hovered * page icon * updates delete icon for disabled state * query manager should always be on top of page selector * checks if homePage key exists in pages def * updates page handler menu * updates the clear icon * page handler menu position * page handler menu position * handle icon * alert msg * global settings handler for updating viewer page navigation * show/hode page navigation for viewer * info text for toggle * Multipages:with sortable list [DnD] (#4783) * applied sortable list * on sort updates the definitions * fixies: app crash for dnd * viwer: canvas width should be 100% when navigation drawer is disbaled * fixes: homepage/startpage reload * clean up Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * Multipage UI viewer (#4801) * new ui changes for viewer pages * fixes postions for debugger and datasources popover * removes console.log * Multipage : hide page and unhide page feature (#4803) * adds: ability to hide pages * hides pages in viewer * unhide page * hide icon * allow accessing hidden pages from url * add: duplicate page (#4802) * add: duplicate page * do not copy the same references from the original page * page name and page handler should be unique for duplicate pages too * Add support for on-page-load events * Add icon from page settings menu item * Convert existing templates to multi-page schema * error logs for page level and app level errors (#4842) * Adapt comments feature for multi-pages * [Bugfix] multipage - page menu interactions (#4844) * fixes: menu popup interaction * fixes: on modal input focus, we switch the page * Adapt multi-player to multi-pages * Add editingPageId to ymap * Log self, others and editor props in real-time avatar generation * Save editing page id to appDef * Add editingPageId to presence in RealtimeCursors * adds no results ui for empty search results (#4869) * page icon updated (#4870) * fixes:Version switching crashes if the target version does not contain the current page (#4868) * Remove unnecessary setting of editingPageId on ymap * Remove unnecessary console.log * [Bugfix] Multipages: widget inspector event popover unmounts (#4887) * introduced a local state for events * cleaned up inspector.jsx * fixes: table widget inspector event accordion * Do not run switchPage twice when viewer is loaded * Preview should open the currently editing page * Properly place navigation and canvas in viewer * Update app definition whenever event manager changes are made * Add support for browser back and forward button in multi-pages * Rename handleBackButton to handlePageSwitchingBasedOnURLparam * Add support for cut/copy/paste and clone * Fix the crash caused by boxShadow * Add support for background colors in viewer in multi-pages * Run queries to be run on load on viewer, in multi-pages * Fix issue that caused inspector popovers to collapse * resolves workspace vars in viewer mode (#4892) * Multipage : Navigation for Mobile-ui (#4814) * refactored to components * burger menu for mobile ui * merge conflict fix for hidden pages * hamburger menu positioned in the header * viewer header reafctored * viewer mobile page manu styles * handles dark theme * mobile menu with dark mode toggle in the footer * components are moved to page level, handle for mobile layout * style fixes * removing unwanted code block * dark theme fixes * style fixes * fixes: events are sortable (#4895) * fixes: events are sortable * Remove uneccesarily repeated call of setEvents in EventManager Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * renamed settings to Event handlers (#4898) * updates the page setting title to Page Events * temp commit * Add support for setting max width in percentage * fixes: paramUpdates for boxes: 🙌🏻 * [Bugfix] Multipage - viewer canvas dark theme (#4897) * fixes: darktheme bg for viewer canvas * reverts canvas size * Fix for inspector bouncing back to previous values * resolves pages variables in pythong and js transformation (#4905) * csa support to event manager for pages (#4907) * Add support for setting canvas width in percentages * Persist page level variables across page switches * latest definitions is merged with the current appdef (#4914) * latest definitions is merged with the current appdef * mutating the local obj * cleanup * iterate through pages for new versions are created Co-authored-by: Arpit <arpitnath42@gmail.com>
2022-12-08 12:21:09 +00:00
currentPageId,
childComponents = null,
listmode = null,
columns = 1,
2021-05-09 18:06:11 +00:00
}) => {
//Todo add custom resolve vars for other widgets too
const mounted = useMounted();
const widgetResolvables = Object.freeze({
Listview: 'listItem',
});
const customResolverVariable = widgetResolvables[parentComponent?.component];
const currentState = useCurrentState();
const { enableReleasedVersionPopupState, isVersionReleased } = useAppVersionStore(
(state) => ({
enableReleasedVersionPopupState: state.actions.enableReleasedVersionPopupState,
isVersionReleased: state.isVersionReleased,
}),
shallow
);
const gridWidth = getContainerCanvasWidth() / NO_OF_GRIDS;
const [_containerCanvasWidth, setContainerCanvasWidth] = useState(0);
useEffect(() => {
if (parentRef.current) {
const canvasWidth = getContainerCanvasWidth();
setContainerCanvasWidth(canvasWidth);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [parentRef, getContainerCanvasWidth(), listmode]);
2021-05-09 18:06:11 +00:00
zoomLevel = zoomLevel || 1;
// eslint-disable-next-line react-hooks/exhaustive-deps
Feature/multi page applications (Task ID - CU-2h1bfvw) (#4729) * Add routes for multi-page apps * Modify Editor, Viewer and Inspector to accept new app structure * Show a page selector on left side bar * Align component deletion logic with new app schema * Make subcontainer work with multi-page apps * Load components state properly in viewer * Use UUID instead of handle for pages * Display sidebar on viewer to switch pages * Add proper URL suffixing for pages in viewer * Add action to switch page * Revert translation file back to its pre-existing linting * Fix bug that caused modal to not open/close * Add support for query params in page switch * Fix the issue that caused navigation to fail while accessed via slug * Add missing SwitchPage file * Add support for page level variables * Add migration to convert existing apps to new schema * Add rollback for converting multi-page definitions back to single-page * Fix migration for multi-page apps * Adapt import/export service for multi-pages * [improvements] Multi-page applications (#4755) * UI updates for page selector popup card * delete page * delete page check: if only one page exits * switch to home page if the selected page is removed * adds and switch to new page * updating page name * updates to home page and starting page * handle updating the home page when home page is deleted * search box for filtering pages and minor style updates for the page handler card * header search box style fixes * for creating a new page, page handle needs to be unique * seperating into smaller components * updated pinned icon for page selector styles and settinf styles * Leftsidebar header ui component * handle dark theme * page handle ui and dark theme fixes for page menu * page handler edit modal * pinned state and update pinned state for menu options triggered * dark theme fixes for edit modal * handle on update should not be empty or prev * page handler updater * added loading state for saving * handles cancels * fixes slug ui * fixes crash for older app versions * updates the query params when handle gets an update * update homePage to homePageId * removes console.log * go back to the popover for modal close * fixes: Difficult to select page * fixes: Difficult to select the three-dot menu * fixes: on visiting the root url, navigate to homepage on viewer * adds tooltip for url * updates the page selector sidebar with sync with query manager * refactor and cleanup * refactor and cleanup * Compute component state when page is switched * modal should not close on click outside * disable save button if there is not change in the page handle input * should show/hide page menu when hovered * page icon * updates delete icon for disabled state * query manager should always be on top of page selector * checks if homePage key exists in pages def * updates page handler menu * updates the clear icon * page handler menu position * page handler menu position * handle icon * alert msg * global settings handler for updating viewer page navigation * show/hode page navigation for viewer * info text for toggle * Multipages:with sortable list [DnD] (#4783) * applied sortable list * on sort updates the definitions * fixies: app crash for dnd * viwer: canvas width should be 100% when navigation drawer is disbaled * fixes: homepage/startpage reload * clean up Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * Multipage UI viewer (#4801) * new ui changes for viewer pages * fixes postions for debugger and datasources popover * removes console.log * Multipage : hide page and unhide page feature (#4803) * adds: ability to hide pages * hides pages in viewer * unhide page * hide icon * allow accessing hidden pages from url * add: duplicate page (#4802) * add: duplicate page * do not copy the same references from the original page * page name and page handler should be unique for duplicate pages too * Add support for on-page-load events * Add icon from page settings menu item * Convert existing templates to multi-page schema * error logs for page level and app level errors (#4842) * Adapt comments feature for multi-pages * [Bugfix] multipage - page menu interactions (#4844) * fixes: menu popup interaction * fixes: on modal input focus, we switch the page * Adapt multi-player to multi-pages * Add editingPageId to ymap * Log self, others and editor props in real-time avatar generation * Save editing page id to appDef * Add editingPageId to presence in RealtimeCursors * adds no results ui for empty search results (#4869) * page icon updated (#4870) * fixes:Version switching crashes if the target version does not contain the current page (#4868) * Remove unnecessary setting of editingPageId on ymap * Remove unnecessary console.log * [Bugfix] Multipages: widget inspector event popover unmounts (#4887) * introduced a local state for events * cleaned up inspector.jsx * fixes: table widget inspector event accordion * Do not run switchPage twice when viewer is loaded * Preview should open the currently editing page * Properly place navigation and canvas in viewer * Update app definition whenever event manager changes are made * Add support for browser back and forward button in multi-pages * Rename handleBackButton to handlePageSwitchingBasedOnURLparam * Add support for cut/copy/paste and clone * Fix the crash caused by boxShadow * Add support for background colors in viewer in multi-pages * Run queries to be run on load on viewer, in multi-pages * Fix issue that caused inspector popovers to collapse * resolves workspace vars in viewer mode (#4892) * Multipage : Navigation for Mobile-ui (#4814) * refactored to components * burger menu for mobile ui * merge conflict fix for hidden pages * hamburger menu positioned in the header * viewer header reafctored * viewer mobile page manu styles * handles dark theme * mobile menu with dark mode toggle in the footer * components are moved to page level, handle for mobile layout * style fixes * removing unwanted code block * dark theme fixes * style fixes * fixes: events are sortable (#4895) * fixes: events are sortable * Remove uneccesarily repeated call of setEvents in EventManager Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * renamed settings to Event handlers (#4898) * updates the page setting title to Page Events * temp commit * Add support for setting max width in percentage * fixes: paramUpdates for boxes: 🙌🏻 * [Bugfix] Multipage - viewer canvas dark theme (#4897) * fixes: darktheme bg for viewer canvas * reverts canvas size * Fix for inspector bouncing back to previous values * resolves pages variables in pythong and js transformation (#4905) * csa support to event manager for pages (#4907) * Add support for setting canvas width in percentages * Persist page level variables across page switches * latest definitions is merged with the current appdef (#4914) * latest definitions is merged with the current appdef * mutating the local obj * cleanup * iterate through pages for new versions are created Co-authored-by: Arpit <arpitnath42@gmail.com>
2022-12-08 12:21:09 +00:00
const allComponents = appDefinition ? appDefinition.pages[currentPageId].components : {};
const isParentModal =
(allComponents[parent]?.component?.component === 'Modal' ||
allComponents[parent]?.component?.component === 'Form' ||
allComponents[parent]?.component?.component === 'Container') ??
false;
2021-05-09 18:06:11 +00:00
const getChildWidgets = (components) => {
let childWidgets = [];
Object.keys(components).forEach((key) => {
if (components[key].parent === parent) {
childWidgets[key] = { ...components[key], component: { ...components[key]['component'], parent } };
}
});
return childWidgets;
};
2021-05-09 18:06:11 +00:00
const [boxes, setBoxes] = useState(allComponents);
const [childWidgets, setChildWidgets] = useState(() => getChildWidgets(allComponents));
2021-05-09 18:06:11 +00:00
const [isDragging, setIsDragging] = useState(false);
const [isResizing, setIsResizing] = useState(false);
// const [subContainerHeight, setSubContainerHeight] = useState('100%'); //used to determine the height of the sub container for modal
const subContainerHeightRef = useRef(height ?? '100%');
2021-05-09 18:06:11 +00:00
useEffect(() => {
setBoxes(allComponents);
setChildWidgets(() => getChildWidgets(allComponents));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allComponents, parent]);
2021-05-09 18:06:11 +00:00
useEffect(() => {
if (mounted) {
//find children with parent prop
const children = Object.keys(allComponents).filter((key) => {
if (key === parent) return false;
return allComponents[key].parent === parent;
});
if (children.length === 0 && addDefaultChildren === true) {
const defaultChildren = _.cloneDeep(parentComponent)['defaultChildren'];
const childrenBoxes = {};
const parentId =
parentComponent.component !== 'Tabs'
? parentRef.current.id
: parentRef.current.id?.substring(0, parentRef.current.id.lastIndexOf('-'));
const _allComponents = JSON.parse(JSON.stringify(allComponents));
defaultChildren.forEach((child) => {
const { componentName, layout, incrementWidth, properties, accessorKey, tab, defaultValue, styles } = child;
const componentMeta = componentTypes.find((component) => component.component === componentName);
const componentData = JSON.parse(JSON.stringify(componentMeta));
const width = layout.width ? layout.width : (componentMeta.defaultSize.width * 100) / NO_OF_GRIDS;
const height = layout.height ? layout.height : componentMeta.defaultSize.height;
const newComponentDefinition = {
...componentData.definition.properties,
};
if (_.isArray(properties) && properties.length > 0) {
properties.forEach((prop) => {
const accessor = customResolverVariable
? `{{${customResolverVariable}.${accessorKey}}}`
: defaultValue[prop] || '';
_.set(newComponentDefinition, prop, {
value: accessor,
});
});
_.set(componentData, 'definition.properties', newComponentDefinition);
}
if (_.isArray(styles) && styles.length > 0) {
styles.forEach((prop) => {
const accessor = customResolverVariable
? `{{${customResolverVariable}.${accessorKey}}}`
: defaultValue[prop] || '';
_.set(newComponentDefinition, prop, {
value: accessor,
});
});
_.set(componentData, 'definition.styles', newComponentDefinition);
}
const newComponent = addNewWidgetToTheEditor(
componentData,
{},
{ ..._allComponents, ...childrenBoxes },
{},
currentLayout,
snapToGrid,
zoomLevel,
true,
true
);
_.set(childrenBoxes, newComponent.id, {
component: newComponent.component,
parent: parentComponent.component === 'Tabs' ? parentId + '-' + tab : parentId,
layouts: {
[currentLayout]: {
...layout,
width: incrementWidth ? width * incrementWidth : width,
height: height,
},
},
});
});
_allComponents[parentId] = {
...allComponents[parentId],
withDefaultChildren: false,
};
setBoxes({
..._allComponents,
...childrenBoxes,
});
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mounted]);
2021-05-09 18:06:11 +00:00
const moveBox = useCallback(
(id, left, top) => {
setBoxes(
update(boxes, {
[id]: {
$merge: { left, top },
},
2021-05-09 18:06:11 +00:00
})
);
},
[boxes]
);
useEffect(() => {
if (appDefinitionChanged) {
Feature/multi page applications (Task ID - CU-2h1bfvw) (#4729) * Add routes for multi-page apps * Modify Editor, Viewer and Inspector to accept new app structure * Show a page selector on left side bar * Align component deletion logic with new app schema * Make subcontainer work with multi-page apps * Load components state properly in viewer * Use UUID instead of handle for pages * Display sidebar on viewer to switch pages * Add proper URL suffixing for pages in viewer * Add action to switch page * Revert translation file back to its pre-existing linting * Fix bug that caused modal to not open/close * Add support for query params in page switch * Fix the issue that caused navigation to fail while accessed via slug * Add missing SwitchPage file * Add support for page level variables * Add migration to convert existing apps to new schema * Add rollback for converting multi-page definitions back to single-page * Fix migration for multi-page apps * Adapt import/export service for multi-pages * [improvements] Multi-page applications (#4755) * UI updates for page selector popup card * delete page * delete page check: if only one page exits * switch to home page if the selected page is removed * adds and switch to new page * updating page name * updates to home page and starting page * handle updating the home page when home page is deleted * search box for filtering pages and minor style updates for the page handler card * header search box style fixes * for creating a new page, page handle needs to be unique * seperating into smaller components * updated pinned icon for page selector styles and settinf styles * Leftsidebar header ui component * handle dark theme * page handle ui and dark theme fixes for page menu * page handler edit modal * pinned state and update pinned state for menu options triggered * dark theme fixes for edit modal * handle on update should not be empty or prev * page handler updater * added loading state for saving * handles cancels * fixes slug ui * fixes crash for older app versions * updates the query params when handle gets an update * update homePage to homePageId * removes console.log * go back to the popover for modal close * fixes: Difficult to select page * fixes: Difficult to select the three-dot menu * fixes: on visiting the root url, navigate to homepage on viewer * adds tooltip for url * updates the page selector sidebar with sync with query manager * refactor and cleanup * refactor and cleanup * Compute component state when page is switched * modal should not close on click outside * disable save button if there is not change in the page handle input * should show/hide page menu when hovered * page icon * updates delete icon for disabled state * query manager should always be on top of page selector * checks if homePage key exists in pages def * updates page handler menu * updates the clear icon * page handler menu position * page handler menu position * handle icon * alert msg * global settings handler for updating viewer page navigation * show/hode page navigation for viewer * info text for toggle * Multipages:with sortable list [DnD] (#4783) * applied sortable list * on sort updates the definitions * fixies: app crash for dnd * viwer: canvas width should be 100% when navigation drawer is disbaled * fixes: homepage/startpage reload * clean up Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * Multipage UI viewer (#4801) * new ui changes for viewer pages * fixes postions for debugger and datasources popover * removes console.log * Multipage : hide page and unhide page feature (#4803) * adds: ability to hide pages * hides pages in viewer * unhide page * hide icon * allow accessing hidden pages from url * add: duplicate page (#4802) * add: duplicate page * do not copy the same references from the original page * page name and page handler should be unique for duplicate pages too * Add support for on-page-load events * Add icon from page settings menu item * Convert existing templates to multi-page schema * error logs for page level and app level errors (#4842) * Adapt comments feature for multi-pages * [Bugfix] multipage - page menu interactions (#4844) * fixes: menu popup interaction * fixes: on modal input focus, we switch the page * Adapt multi-player to multi-pages * Add editingPageId to ymap * Log self, others and editor props in real-time avatar generation * Save editing page id to appDef * Add editingPageId to presence in RealtimeCursors * adds no results ui for empty search results (#4869) * page icon updated (#4870) * fixes:Version switching crashes if the target version does not contain the current page (#4868) * Remove unnecessary setting of editingPageId on ymap * Remove unnecessary console.log * [Bugfix] Multipages: widget inspector event popover unmounts (#4887) * introduced a local state for events * cleaned up inspector.jsx * fixes: table widget inspector event accordion * Do not run switchPage twice when viewer is loaded * Preview should open the currently editing page * Properly place navigation and canvas in viewer * Update app definition whenever event manager changes are made * Add support for browser back and forward button in multi-pages * Rename handleBackButton to handlePageSwitchingBasedOnURLparam * Add support for cut/copy/paste and clone * Fix the crash caused by boxShadow * Add support for background colors in viewer in multi-pages * Run queries to be run on load on viewer, in multi-pages * Fix issue that caused inspector popovers to collapse * resolves workspace vars in viewer mode (#4892) * Multipage : Navigation for Mobile-ui (#4814) * refactored to components * burger menu for mobile ui * merge conflict fix for hidden pages * hamburger menu positioned in the header * viewer header reafctored * viewer mobile page manu styles * handles dark theme * mobile menu with dark mode toggle in the footer * components are moved to page level, handle for mobile layout * style fixes * removing unwanted code block * dark theme fixes * style fixes * fixes: events are sortable (#4895) * fixes: events are sortable * Remove uneccesarily repeated call of setEvents in EventManager Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * renamed settings to Event handlers (#4898) * updates the page setting title to Page Events * temp commit * Add support for setting max width in percentage * fixes: paramUpdates for boxes: 🙌🏻 * [Bugfix] Multipage - viewer canvas dark theme (#4897) * fixes: darktheme bg for viewer canvas * reverts canvas size * Fix for inspector bouncing back to previous values * resolves pages variables in pythong and js transformation (#4905) * csa support to event manager for pages (#4907) * Add support for setting canvas width in percentages * Persist page level variables across page switches * latest definitions is merged with the current appdef (#4914) * latest definitions is merged with the current appdef * mutating the local obj * cleanup * iterate through pages for new versions are created Co-authored-by: Arpit <arpitnath42@gmail.com>
2022-12-08 12:21:09 +00:00
const newDefinition = {
...appDefinition,
pages: {
...appDefinition.pages,
[currentPageId]: {
...appDefinition.pages[currentPageId],
components: boxes,
},
},
};
appDefinitionChanged(newDefinition);
2021-05-09 18:06:11 +00:00
}
// eslint-disable-next-line react-hooks/exhaustive-deps
2021-05-09 18:06:11 +00:00
}, [boxes]);
const { draggingState } = useDragLayer((monitor) => {
// TODO: Need to move to a performant version of the block below
if (monitor.getItem()) {
if (monitor.getItem().id === undefined) {
if (parentRef.current) {
const currentOffset = monitor.getSourceClientOffset();
if (currentOffset) {
const canvasBoundingRect = parentRef?.current
?.getElementsByClassName('real-canvas')[0]
?.getBoundingClientRect();
if (!canvasBoundingRect) return { draggingState: false };
if (
currentOffset.x > canvasBoundingRect.x &&
currentOffset.x < canvasBoundingRect.x + canvasBoundingRect.width
) {
return { draggingState: true };
}
}
}
}
}
if (monitor.isDragging() && monitor.getItem().parent) {
if (monitor.getItem().parent === parent) {
return { draggingState: true };
} else {
return { draggingState: false };
}
} else {
return { draggingState: false };
}
});
2021-05-09 18:06:11 +00:00
useEffect(() => {
setIsDragging(draggingState);
}, [draggingState]);
function convertXToPercentage(x, canvasWidth) {
return (x * 100) / canvasWidth;
}
2021-05-09 18:06:11 +00:00
const [, drop] = useDrop(
() => ({
accept: ItemTypes.BOX,
drop(item, monitor) {
const componentMeta = componentTypes.find((component) => component.component === item.component.component);
2021-05-09 18:06:11 +00:00
const canvasBoundingRect = parentRef.current.getElementsByClassName('real-canvas')[0].getBoundingClientRect();
const newComponent = addNewWidgetToTheEditor(
componentMeta,
monitor,
boxes,
canvasBoundingRect,
item.currentLayout,
snapToGrid,
zoomLevel,
true
);
2021-05-09 18:06:11 +00:00
setBoxes({
...boxes,
[newComponent.id]: {
component: newComponent.component,
parent: parentRef.current.id,
layouts: {
...newComponent.layout,
},
withDefaultChildren: newComponent.withDefaultChildren,
},
2021-05-09 18:06:11 +00:00
});
setSelectedComponent(newComponent.id, newComponent.component);
2021-05-09 18:06:11 +00:00
return undefined;
},
2021-05-09 18:06:11 +00:00
}),
[moveBox]
);
function getContainerCanvasWidth() {
if (containerCanvasWidth !== undefined) {
if (listmode == 'grid') return containerCanvasWidth / columns - 2;
else return containerCanvasWidth - 2;
}
let width = 0;
if (parentRef.current) {
const realCanvas = parentRef.current.getElementsByClassName('real-canvas')[0];
if (realCanvas) {
const canvasBoundingRect = realCanvas.getBoundingClientRect();
width = canvasBoundingRect.width;
}
}
return width;
}
function onDragStop(e, componentId, direction, currentLayout) {
if (isVersionReleased) {
enableReleasedVersionPopupState();
return;
}
const canvasWidth = getContainerCanvasWidth();
const nodeBounds = direction.node.getBoundingClientRect();
const canvasBounds = parentRef.current.getElementsByClassName('real-canvas')[0].getBoundingClientRect();
// Computing the left offset
const leftOffset = nodeBounds.x - canvasBounds.x;
const currentLeftOffset = boxes[componentId].layouts[currentLayout].left;
const leftDiff = currentLeftOffset - convertXToPercentage(leftOffset, canvasWidth);
const topDiff = boxes[componentId].layouts[currentLayout].top - (nodeBounds.y - canvasBounds.y);
let newBoxes = { ...boxes };
const subContainerHeight = canvasBounds.height - 30;
if (selectedComponents) {
for (const selectedComponent of selectedComponents) {
newBoxes = produce(newBoxes, (draft) => {
const topOffset = draft[selectedComponent.id].layouts[currentLayout].top;
const leftOffset = draft[selectedComponent.id].layouts[currentLayout].left;
draft[selectedComponent.id].layouts[currentLayout].top = topOffset - topDiff;
draft[selectedComponent.id].layouts[currentLayout].left = leftOffset - leftDiff;
});
const componentBottom =
newBoxes[selectedComponent.id].layouts[currentLayout].top +
newBoxes[selectedComponent.id].layouts[currentLayout].height;
if (isParentModal && subContainerHeight <= componentBottom) {
subContainerHeightRef.current = subContainerHeight + 100;
}
}
}
setChildWidgets(() => getChildWidgets(newBoxes));
setBoxes(newBoxes);
}
function onResizeStop(id, e, direction, ref, d, position) {
if (isVersionReleased) {
enableReleasedVersionPopupState();
return;
}
const deltaWidth = Math.round(d.width / gridWidth) * gridWidth;
2021-05-09 18:06:11 +00:00
const deltaHeight = d.height;
if (deltaWidth === 0 && deltaHeight === 0) {
return;
}
let { x, y } = position;
x = Math.round(x / gridWidth) * gridWidth;
const defaultData = {
top: 100,
left: 0,
width: 445,
height: 500,
};
let { left, top, width, height } = boxes[id]['layouts'][currentLayout] || defaultData;
top = y;
if (deltaWidth !== 0) {
// onResizeStop is triggered for a single click on the border, therefore this conditional logic
// should not be removed.
left = (x * 100) / _containerCanvasWidth;
}
width = width + (deltaWidth * NO_OF_GRIDS) / _containerCanvasWidth;
height = height + deltaHeight;
let newBoxes = {
...boxes,
[id]: {
...boxes[id],
layouts: {
...boxes[id]['layouts'],
[currentLayout]: {
...boxes[id]['layouts'][currentLayout],
width,
height,
top,
left,
},
},
},
};
setBoxes(newBoxes);
2021-05-09 18:06:11 +00:00
}
function paramUpdated(id, param, value) {
if (Object.keys(value).length > 0) {
Feature/multi page applications (Task ID - CU-2h1bfvw) (#4729) * Add routes for multi-page apps * Modify Editor, Viewer and Inspector to accept new app structure * Show a page selector on left side bar * Align component deletion logic with new app schema * Make subcontainer work with multi-page apps * Load components state properly in viewer * Use UUID instead of handle for pages * Display sidebar on viewer to switch pages * Add proper URL suffixing for pages in viewer * Add action to switch page * Revert translation file back to its pre-existing linting * Fix bug that caused modal to not open/close * Add support for query params in page switch * Fix the issue that caused navigation to fail while accessed via slug * Add missing SwitchPage file * Add support for page level variables * Add migration to convert existing apps to new schema * Add rollback for converting multi-page definitions back to single-page * Fix migration for multi-page apps * Adapt import/export service for multi-pages * [improvements] Multi-page applications (#4755) * UI updates for page selector popup card * delete page * delete page check: if only one page exits * switch to home page if the selected page is removed * adds and switch to new page * updating page name * updates to home page and starting page * handle updating the home page when home page is deleted * search box for filtering pages and minor style updates for the page handler card * header search box style fixes * for creating a new page, page handle needs to be unique * seperating into smaller components * updated pinned icon for page selector styles and settinf styles * Leftsidebar header ui component * handle dark theme * page handle ui and dark theme fixes for page menu * page handler edit modal * pinned state and update pinned state for menu options triggered * dark theme fixes for edit modal * handle on update should not be empty or prev * page handler updater * added loading state for saving * handles cancels * fixes slug ui * fixes crash for older app versions * updates the query params when handle gets an update * update homePage to homePageId * removes console.log * go back to the popover for modal close * fixes: Difficult to select page * fixes: Difficult to select the three-dot menu * fixes: on visiting the root url, navigate to homepage on viewer * adds tooltip for url * updates the page selector sidebar with sync with query manager * refactor and cleanup * refactor and cleanup * Compute component state when page is switched * modal should not close on click outside * disable save button if there is not change in the page handle input * should show/hide page menu when hovered * page icon * updates delete icon for disabled state * query manager should always be on top of page selector * checks if homePage key exists in pages def * updates page handler menu * updates the clear icon * page handler menu position * page handler menu position * handle icon * alert msg * global settings handler for updating viewer page navigation * show/hode page navigation for viewer * info text for toggle * Multipages:with sortable list [DnD] (#4783) * applied sortable list * on sort updates the definitions * fixies: app crash for dnd * viwer: canvas width should be 100% when navigation drawer is disbaled * fixes: homepage/startpage reload * clean up Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * Multipage UI viewer (#4801) * new ui changes for viewer pages * fixes postions for debugger and datasources popover * removes console.log * Multipage : hide page and unhide page feature (#4803) * adds: ability to hide pages * hides pages in viewer * unhide page * hide icon * allow accessing hidden pages from url * add: duplicate page (#4802) * add: duplicate page * do not copy the same references from the original page * page name and page handler should be unique for duplicate pages too * Add support for on-page-load events * Add icon from page settings menu item * Convert existing templates to multi-page schema * error logs for page level and app level errors (#4842) * Adapt comments feature for multi-pages * [Bugfix] multipage - page menu interactions (#4844) * fixes: menu popup interaction * fixes: on modal input focus, we switch the page * Adapt multi-player to multi-pages * Add editingPageId to ymap * Log self, others and editor props in real-time avatar generation * Save editing page id to appDef * Add editingPageId to presence in RealtimeCursors * adds no results ui for empty search results (#4869) * page icon updated (#4870) * fixes:Version switching crashes if the target version does not contain the current page (#4868) * Remove unnecessary setting of editingPageId on ymap * Remove unnecessary console.log * [Bugfix] Multipages: widget inspector event popover unmounts (#4887) * introduced a local state for events * cleaned up inspector.jsx * fixes: table widget inspector event accordion * Do not run switchPage twice when viewer is loaded * Preview should open the currently editing page * Properly place navigation and canvas in viewer * Update app definition whenever event manager changes are made * Add support for browser back and forward button in multi-pages * Rename handleBackButton to handlePageSwitchingBasedOnURLparam * Add support for cut/copy/paste and clone * Fix the crash caused by boxShadow * Add support for background colors in viewer in multi-pages * Run queries to be run on load on viewer, in multi-pages * Fix issue that caused inspector popovers to collapse * resolves workspace vars in viewer mode (#4892) * Multipage : Navigation for Mobile-ui (#4814) * refactored to components * burger menu for mobile ui * merge conflict fix for hidden pages * hamburger menu positioned in the header * viewer header reafctored * viewer mobile page manu styles * handles dark theme * mobile menu with dark mode toggle in the footer * components are moved to page level, handle for mobile layout * style fixes * removing unwanted code block * dark theme fixes * style fixes * fixes: events are sortable (#4895) * fixes: events are sortable * Remove uneccesarily repeated call of setEvents in EventManager Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * renamed settings to Event handlers (#4898) * updates the page setting title to Page Events * temp commit * Add support for setting max width in percentage * fixes: paramUpdates for boxes: 🙌🏻 * [Bugfix] Multipage - viewer canvas dark theme (#4897) * fixes: darktheme bg for viewer canvas * reverts canvas size * Fix for inspector bouncing back to previous values * resolves pages variables in pythong and js transformation (#4905) * csa support to event manager for pages (#4907) * Add support for setting canvas width in percentages * Persist page level variables across page switches * latest definitions is merged with the current appdef (#4914) * latest definitions is merged with the current appdef * mutating the local obj * cleanup * iterate through pages for new versions are created Co-authored-by: Arpit <arpitnath42@gmail.com>
2022-12-08 12:21:09 +00:00
setBoxes((boxes) => {
return update(boxes, {
2021-05-09 18:06:11 +00:00
[id]: {
$merge: {
component: {
...boxes[id].component,
definition: {
...boxes[id].component.definition,
properties: {
...boxes[id].component.definition.properties,
[param]: value,
},
},
},
},
},
Feature/multi page applications (Task ID - CU-2h1bfvw) (#4729) * Add routes for multi-page apps * Modify Editor, Viewer and Inspector to accept new app structure * Show a page selector on left side bar * Align component deletion logic with new app schema * Make subcontainer work with multi-page apps * Load components state properly in viewer * Use UUID instead of handle for pages * Display sidebar on viewer to switch pages * Add proper URL suffixing for pages in viewer * Add action to switch page * Revert translation file back to its pre-existing linting * Fix bug that caused modal to not open/close * Add support for query params in page switch * Fix the issue that caused navigation to fail while accessed via slug * Add missing SwitchPage file * Add support for page level variables * Add migration to convert existing apps to new schema * Add rollback for converting multi-page definitions back to single-page * Fix migration for multi-page apps * Adapt import/export service for multi-pages * [improvements] Multi-page applications (#4755) * UI updates for page selector popup card * delete page * delete page check: if only one page exits * switch to home page if the selected page is removed * adds and switch to new page * updating page name * updates to home page and starting page * handle updating the home page when home page is deleted * search box for filtering pages and minor style updates for the page handler card * header search box style fixes * for creating a new page, page handle needs to be unique * seperating into smaller components * updated pinned icon for page selector styles and settinf styles * Leftsidebar header ui component * handle dark theme * page handle ui and dark theme fixes for page menu * page handler edit modal * pinned state and update pinned state for menu options triggered * dark theme fixes for edit modal * handle on update should not be empty or prev * page handler updater * added loading state for saving * handles cancels * fixes slug ui * fixes crash for older app versions * updates the query params when handle gets an update * update homePage to homePageId * removes console.log * go back to the popover for modal close * fixes: Difficult to select page * fixes: Difficult to select the three-dot menu * fixes: on visiting the root url, navigate to homepage on viewer * adds tooltip for url * updates the page selector sidebar with sync with query manager * refactor and cleanup * refactor and cleanup * Compute component state when page is switched * modal should not close on click outside * disable save button if there is not change in the page handle input * should show/hide page menu when hovered * page icon * updates delete icon for disabled state * query manager should always be on top of page selector * checks if homePage key exists in pages def * updates page handler menu * updates the clear icon * page handler menu position * page handler menu position * handle icon * alert msg * global settings handler for updating viewer page navigation * show/hode page navigation for viewer * info text for toggle * Multipages:with sortable list [DnD] (#4783) * applied sortable list * on sort updates the definitions * fixies: app crash for dnd * viwer: canvas width should be 100% when navigation drawer is disbaled * fixes: homepage/startpage reload * clean up Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * Multipage UI viewer (#4801) * new ui changes for viewer pages * fixes postions for debugger and datasources popover * removes console.log * Multipage : hide page and unhide page feature (#4803) * adds: ability to hide pages * hides pages in viewer * unhide page * hide icon * allow accessing hidden pages from url * add: duplicate page (#4802) * add: duplicate page * do not copy the same references from the original page * page name and page handler should be unique for duplicate pages too * Add support for on-page-load events * Add icon from page settings menu item * Convert existing templates to multi-page schema * error logs for page level and app level errors (#4842) * Adapt comments feature for multi-pages * [Bugfix] multipage - page menu interactions (#4844) * fixes: menu popup interaction * fixes: on modal input focus, we switch the page * Adapt multi-player to multi-pages * Add editingPageId to ymap * Log self, others and editor props in real-time avatar generation * Save editing page id to appDef * Add editingPageId to presence in RealtimeCursors * adds no results ui for empty search results (#4869) * page icon updated (#4870) * fixes:Version switching crashes if the target version does not contain the current page (#4868) * Remove unnecessary setting of editingPageId on ymap * Remove unnecessary console.log * [Bugfix] Multipages: widget inspector event popover unmounts (#4887) * introduced a local state for events * cleaned up inspector.jsx * fixes: table widget inspector event accordion * Do not run switchPage twice when viewer is loaded * Preview should open the currently editing page * Properly place navigation and canvas in viewer * Update app definition whenever event manager changes are made * Add support for browser back and forward button in multi-pages * Rename handleBackButton to handlePageSwitchingBasedOnURLparam * Add support for cut/copy/paste and clone * Fix the crash caused by boxShadow * Add support for background colors in viewer in multi-pages * Run queries to be run on load on viewer, in multi-pages * Fix issue that caused inspector popovers to collapse * resolves workspace vars in viewer mode (#4892) * Multipage : Navigation for Mobile-ui (#4814) * refactored to components * burger menu for mobile ui * merge conflict fix for hidden pages * hamburger menu positioned in the header * viewer header reafctored * viewer mobile page manu styles * handles dark theme * mobile menu with dark mode toggle in the footer * components are moved to page level, handle for mobile layout * style fixes * removing unwanted code block * dark theme fixes * style fixes * fixes: events are sortable (#4895) * fixes: events are sortable * Remove uneccesarily repeated call of setEvents in EventManager Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com> * renamed settings to Event handlers (#4898) * updates the page setting title to Page Events * temp commit * Add support for setting max width in percentage * fixes: paramUpdates for boxes: 🙌🏻 * [Bugfix] Multipage - viewer canvas dark theme (#4897) * fixes: darktheme bg for viewer canvas * reverts canvas size * Fix for inspector bouncing back to previous values * resolves pages variables in pythong and js transformation (#4905) * csa support to event manager for pages (#4907) * Add support for setting canvas width in percentages * Persist page level variables across page switches * latest definitions is merged with the current appdef (#4914) * latest definitions is merged with the current appdef * mutating the local obj * cleanup * iterate through pages for new versions are created Co-authored-by: Arpit <arpitnath42@gmail.com>
2022-12-08 12:21:09 +00:00
});
});
2021-05-09 18:06:11 +00:00
}
}
const styles = {
width: '100%',
height: subContainerHeightRef.current,
position: 'absolute',
backgroundSize: `${gridWidth}px 10px`,
};
function onComponentOptionChangedForSubcontainer(component, optionName, value, componentId = '') {
if (typeof value === 'function' && _.findKey(exposedVariables, optionName)) {
return Promise.resolve();
}
onOptionChange && onOptionChange({ component, optionName, value, componentId });
return onComponentOptionChanged(component, optionName, value);
}
function customRemoveComponent(component) {
removeComponent(component);
}
function checkParentVisibility() {
let elem = parentRef.current;
if (elem?.className === 'tab-content') {
elem = parentRef.current?.parentElement;
}
if (elem?.style?.display !== 'none') return true;
return false;
}
2021-05-09 18:06:11 +00:00
return (
<div
ref={drop}
style={styles}
id={`canvas-${parent}`}
className={`real-canvas ${(isDragging || isResizing) && !readOnly ? 'show-grid' : ''}`}
>
{checkParentVisibility() &&
Object.keys(childWidgets).map((key) => {
const addDefaultChildren = childWidgets[key]['withDefaultChildren'] || false;
const box = childWidgets[key];
const canShowInCurrentLayout =
box.component.definition.others[currentLayout === 'mobile' ? 'showOnMobile' : 'showOnDesktop'].value;
if (box.parent && resolveReferences(canShowInCurrentLayout, currentState)) {
return (
<DraggableBox
onComponentClick={onComponentClick}
onEvent={onEvent}
onComponentOptionChanged={onComponentOptionChangedForSubcontainer}
onComponentOptionsChanged={onComponentOptionsChanged}
key={key}
onResizeStop={onResizeStop}
onDragStop={onDragStop}
paramUpdated={paramUpdated}
id={key}
allComponents={allComponents}
{...childWidgets[key]}
mode={mode}
resizingStatusChanged={(status) => setIsResizing(status)}
draggingStatusChanged={(status) => setIsDragging(status)}
inCanvas={true}
zoomLevel={zoomLevel}
setSelectedComponent={setSelectedComponent}
selectedComponent={selectedComponent}
deviceWindowWidth={deviceWindowWidth}
isSelectedComponent={
mode === 'edit' ? selectedComponents.find((component) => component.id === key) : false
}
removeComponent={customRemoveComponent}
canvasWidth={_containerCanvasWidth}
readOnly={readOnly}
darkMode={darkMode}
customResolvables={customResolvables}
onComponentHover={onComponentHover}
hoveredComponent={hoveredComponent}
parentId={parentComponent?.name}
sideBarDebugger={sideBarDebugger}
isMultipleComponentsSelected={selectedComponents?.length > 1 ? true : false}
exposedVariables={exposedVariables ?? {}}
childComponents={childComponents[key]}
containerProps={{
mode,
snapToGrid,
onComponentClick,
onEvent,
appDefinition,
appDefinitionChanged,
currentState,
onComponentOptionChanged,
onComponentOptionsChanged,
appLoading,
zoomLevel,
setSelectedComponent,
removeComponent,
currentLayout,
deviceWindowWidth,
selectedComponents,
darkMode,
readOnly,
onComponentHover,
hoveredComponent,
sideBarDebugger,
addDefaultChildren,
currentPageId,
childComponents,
}}
/>
);
}
})}
2021-05-09 18:06:11 +00:00
{appLoading && (
<div className="mx-auto mt-5 w-50 p-5">
<center>
<div className="progress progress-sm w-50">
<div className="progress-bar progress-bar-indeterminate"></div>
</div>
</center>
</div>
)}
</div>
);
};