Fix: Tabs widget refactor with new nested property validation (#4014)
* dip * test cases first commit * Adding Tabs migrator. * fixing tests. * bug fix. * selected tab fix * missed commit * fixing bugs * Fixing tab name bugs. * close property pane when dragging or resizing * migration changes. * release rebase changes. * adding List factory * remove dynamic bindings on deleting tabs. * Adding validation messages for nested properties as well * fixing validation issue. * tabs visibility validation. * missed commit * Fixing broken cypress tests. * Fixing broken tests.
This commit is contained in:
parent
0b2bd452df
commit
8f7cc87801
|
|
@ -22,10 +22,13 @@ describe("Container Widget Functionality", function() {
|
|||
/**
|
||||
* @param{Text} Random Colour
|
||||
*/
|
||||
cy.testCodeMirror(this.data.colour);
|
||||
cy.get(widgetsPage.backgroundcolorPicker)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.xpath(widgetsPage.greenColor).click();
|
||||
cy.get(widgetsPage.containerD)
|
||||
.should("have.css", "background-color")
|
||||
.and("eq", this.data.rgbValue);
|
||||
.and("eq", "rgb(3, 179, 101)");
|
||||
/**
|
||||
* @param{toggleButton Css} Assert to be checked
|
||||
*/
|
||||
|
|
@ -41,7 +44,7 @@ describe("Container Widget Functionality", function() {
|
|||
cy.get(widgetsPage.containerD)
|
||||
.eq(0)
|
||||
.should("have.css", "background-color")
|
||||
.and("eq", this.data.rgbValue);
|
||||
.and("eq", "rgb(3, 179, 101)");
|
||||
});
|
||||
afterEach(() => {
|
||||
// put your clean up code if any
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
"verticalCenter": ".t--icon-tab-CENTER",
|
||||
"verticalBottom": ".t--icon-tab-BOTTOM",
|
||||
"textColor": ".t--property-control-textcolor input",
|
||||
"backgroundcolorPicker": ".t--property-control-backgroundcolor input",
|
||||
"greenColor": "//div[@color='rgb(3, 179, 101)']",
|
||||
"toggleJsColor": ".t--property-control-textcolor .t--js-toggle",
|
||||
"backgroundColor": ".t--property-control-cellbackground input",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module.exports = {
|
|||
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node", "css"],
|
||||
moduleDirectories: ["node_modules", "src", "test"],
|
||||
transformIgnorePatterns: [
|
||||
"<rootDir>/node_modules/(?!codemirror|react-dnd|dnd-core|@babel|(@blueprintjs/core/lib/esnext)|(@blueprintjs/core/lib/esm)|@github)",
|
||||
"<rootDir>/node_modules/(?!codemirror|react-dnd|dnd-core|@babel|(@blueprintjs/core/lib/esnext)|(@blueprintjs/core/lib/esm)|@github|lodash-es)",
|
||||
],
|
||||
moduleNameMapper: {
|
||||
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js",
|
||||
|
|
@ -23,6 +23,7 @@ module.exports = {
|
|||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
|
||||
"<rootDir>/test/__mocks__/fileMock.js",
|
||||
"^worker-loader!": "<rootDir>/test/__mocks__/workerMock.js",
|
||||
"^!!raw-loader!": "<rootDir>/test/__mocks__/derivedMock.js",
|
||||
"test/(.*)": "<rootDir>/test/$1",
|
||||
},
|
||||
globals: {
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
"start-prod": "REACT_APP_ENVIRONMENT=PRODUCTION craco start",
|
||||
"cytest": "REACT_APP_TESTING=TESTING REACT_APP_ENVIRONMENT=DEVELOPMENT craco start & ./node_modules/.bin/cypress open",
|
||||
"test:unit": "$(npm bin)/jest -b --colors --no-cache --coverage --collectCoverage=true --coverageDirectory='../../' --coverageReporters='json-summary'",
|
||||
"test:jest": "$(npm bin)/jest --watch",
|
||||
"storybook": "start-storybook -p 9009 -s public",
|
||||
"build-storybook": "build-storybook -s public"
|
||||
},
|
||||
|
|
@ -212,6 +213,7 @@
|
|||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"eslint-plugin-react": "^7.21.3",
|
||||
"eslint-plugin-react-hooks": "^2.3.0",
|
||||
"factory.ts": "^0.5.1",
|
||||
"jest-canvas-mock": "^2.3.1",
|
||||
"mocha": "^7.1.0",
|
||||
"mocha-junit-reporter": "^1.23.3",
|
||||
|
|
|
|||
|
|
@ -227,12 +227,23 @@ export type WidgetAddChildren = {
|
|||
}>;
|
||||
};
|
||||
|
||||
export type WidgetUpdateProperty = {
|
||||
widgetId: string;
|
||||
propertyPath: string;
|
||||
propertyValue: any;
|
||||
};
|
||||
|
||||
export const updateWidget = (
|
||||
operation: WidgetOperation,
|
||||
widgetId: string,
|
||||
payload: any,
|
||||
): ReduxAction<
|
||||
WidgetAddChild | WidgetMove | WidgetResize | WidgetDelete | WidgetAddChildren
|
||||
| WidgetAddChild
|
||||
| WidgetMove
|
||||
| WidgetResize
|
||||
| WidgetDelete
|
||||
| WidgetAddChildren
|
||||
| WidgetUpdateProperty
|
||||
> => {
|
||||
return {
|
||||
type: ReduxActionTypes["WIDGET_" + operation],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import React, { RefObject, ReactNode, useEffect, useRef } from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { ComponentProps } from "./BaseComponent";
|
||||
import { TabsWidgetProps, TabContainerWidgetProps } from "widgets/TabsWidget";
|
||||
import {
|
||||
TabsWidgetProps,
|
||||
TabContainerWidgetProps,
|
||||
} from "widgets/Tabs/TabsWidget";
|
||||
import { generateClassName, getCanvasClassName } from "utils/generators";
|
||||
import { getBorderCSSShorthand } from "constants/DefaultTheme";
|
||||
import ScrollIndicator from "components/ads/ScrollIndicator";
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ class PrimaryColumnsControl extends BaseControl<ControlProps> {
|
|||
|
||||
this.props.openNextPanel({
|
||||
...originalColumn,
|
||||
widgetId: this.props.widgetProperties.widgetId,
|
||||
propPaneId: this.props.widgetProperties.widgetId,
|
||||
});
|
||||
};
|
||||
//Used to reorder columns
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import BaseControl, { ControlProps } from "./BaseControl";
|
||||
import {
|
||||
StyledHiddenIcon,
|
||||
StyledInputGroup,
|
||||
StyledPropertyPaneButton,
|
||||
StyledVisibleIcon,
|
||||
StyledDragIcon,
|
||||
StyledDeleteIcon,
|
||||
StyledEditIcon,
|
||||
} from "./StyledControls";
|
||||
import styled from "constants/DefaultTheme";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
|
|
@ -63,12 +62,15 @@ type RenderComponentProps = {
|
|||
deleteOption: (index: number) => void;
|
||||
updateOption: (index: number, value: string) => void;
|
||||
toggleVisibility?: (index: number) => void;
|
||||
onEdit?: (props: any) => void;
|
||||
};
|
||||
|
||||
function TabControlComponent(props: RenderComponentProps) {
|
||||
const { deleteOption, updateOption, item, index, toggleVisibility } = props;
|
||||
const { deleteOption, updateOption, item, index } = props;
|
||||
const debouncedUpdate = debounce(updateOption, 1000);
|
||||
const [visibility, setVisibility] = useState(item.isVisible);
|
||||
const handleChange = useCallback(() => props.onEdit && props.onEdit(index), [
|
||||
index,
|
||||
]);
|
||||
return (
|
||||
<ItemWrapper>
|
||||
<StyledDragIcon height={20} width={20} />
|
||||
|
|
@ -89,29 +91,12 @@ function TabControlComponent(props: RenderComponentProps) {
|
|||
deleteOption(index);
|
||||
}}
|
||||
/>
|
||||
{visibility || visibility === undefined ? (
|
||||
<StyledVisibleIcon
|
||||
className="t--show-tab-btn"
|
||||
<StyledEditIcon
|
||||
className="t--edit-column-btn"
|
||||
height={20}
|
||||
width={20}
|
||||
marginRight={36}
|
||||
onClick={() => {
|
||||
setVisibility(!visibility);
|
||||
toggleVisibility && toggleVisibility(index);
|
||||
}}
|
||||
onClick={handleChange}
|
||||
/>
|
||||
) : (
|
||||
<StyledHiddenIcon
|
||||
className="t--show-tab-btn"
|
||||
height={20}
|
||||
width={20}
|
||||
marginRight={36}
|
||||
onClick={() => {
|
||||
setVisibility(!visibility);
|
||||
toggleVisibility && toggleVisibility(index);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</ItemWrapper>
|
||||
);
|
||||
}
|
||||
|
|
@ -148,15 +133,37 @@ class TabControl extends BaseControl<ControlProps> {
|
|||
}
|
||||
}
|
||||
|
||||
updateItems = (items: Array<Record<string, unknown>>) => {
|
||||
this.updateProperty(this.props.propertyName, items);
|
||||
updateItems = (items: Array<Record<string, any>>) => {
|
||||
const tabsObj = items.reduce((obj: any, each: any, index: number) => {
|
||||
obj[each.id] = {
|
||||
...each,
|
||||
index,
|
||||
};
|
||||
return obj;
|
||||
}, {});
|
||||
this.updateProperty(this.props.propertyName, tabsObj);
|
||||
};
|
||||
|
||||
onEdit = (index: number) => {
|
||||
const tabs: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
}> = Object.values(this.props.propertyValue);
|
||||
const tabToChange = tabs[index];
|
||||
this.props.openNextPanel({
|
||||
index,
|
||||
...tabToChange,
|
||||
propPaneId: this.props.widgetProperties.widgetId,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const tabs: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
}> = _.isString(this.props.propertyValue) ? [] : this.props.propertyValue;
|
||||
}> = _.isString(this.props.propertyValue)
|
||||
? []
|
||||
: Object.values(this.props.propertyValue);
|
||||
return (
|
||||
<TabsWrapper>
|
||||
<DroppableComponent
|
||||
|
|
@ -167,6 +174,7 @@ class TabControl extends BaseControl<ControlProps> {
|
|||
updateOption={this.updateOption}
|
||||
updateItems={this.updateItems}
|
||||
toggleVisibility={this.toggleVisibility}
|
||||
onEdit={this.onEdit}
|
||||
/>
|
||||
<StyledPropertyPaneButtonWrapper>
|
||||
<StyledPropertyPaneButton
|
||||
|
|
@ -204,51 +212,52 @@ class TabControl extends BaseControl<ControlProps> {
|
|||
};
|
||||
|
||||
deleteOption = (index: number) => {
|
||||
let tabs: Array<Record<string, unknown>> = this.props.propertyValue.slice();
|
||||
if (tabs.length === 1) return;
|
||||
delete tabs[index];
|
||||
tabs = tabs.filter(Boolean);
|
||||
this.updateProperty(this.props.propertyName, tabs);
|
||||
const tabsArray: any = Object.values(this.props.propertyValue);
|
||||
const itemId = tabsArray[index].id;
|
||||
if (tabsArray && tabsArray.length === 1) return;
|
||||
const updatedArray = tabsArray.filter((eachItem: any, i: number) => {
|
||||
return i !== index;
|
||||
});
|
||||
const updatedObj = updatedArray.reduce(
|
||||
(obj: any, each: any, index: number) => {
|
||||
obj[each.id] = {
|
||||
...each,
|
||||
index,
|
||||
};
|
||||
return obj;
|
||||
},
|
||||
{},
|
||||
);
|
||||
this.deleteProperties([`${this.props.propertyName}.${itemId}.isVisible`]);
|
||||
this.updateProperty(this.props.propertyName, updatedObj);
|
||||
};
|
||||
|
||||
updateOption = (index: number, updatedLabel: string) => {
|
||||
const tabs: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
}> = this.props.propertyValue;
|
||||
const updatedTabs = tabs.map((tab, tabIndex) => {
|
||||
if (index === tabIndex) {
|
||||
return {
|
||||
...tab,
|
||||
label: updatedLabel,
|
||||
};
|
||||
}
|
||||
return tab;
|
||||
});
|
||||
this.updateProperty(this.props.propertyName, updatedTabs);
|
||||
const tabsArray: any = Object.values(this.props.propertyValue);
|
||||
const itemId = tabsArray[index].id;
|
||||
this.updateProperty(
|
||||
`${this.props.propertyName}.${itemId}.label`,
|
||||
updatedLabel,
|
||||
);
|
||||
};
|
||||
|
||||
addOption = () => {
|
||||
let tabs: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
widgetId: string;
|
||||
isVisible: boolean;
|
||||
}> = this.props.propertyValue;
|
||||
let tabs = this.props.propertyValue;
|
||||
const tabsArray = Object.values(tabs);
|
||||
const newTabId = generateReactKey({ prefix: "tab" });
|
||||
const newTabLabel = getNextEntityName(
|
||||
"Tab ",
|
||||
tabs.map((tab) => tab.label),
|
||||
tabsArray.map((tab: any) => tab.label),
|
||||
);
|
||||
tabs = [
|
||||
tabs = {
|
||||
...tabs,
|
||||
{
|
||||
[newTabId]: {
|
||||
id: newTabId,
|
||||
label: newTabLabel,
|
||||
widgetId: generateReactKey(),
|
||||
isVisible: true,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
this.updateProperty(this.props.propertyName, tabs);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ const FIELD_VALUES: Record<
|
|||
CANVAS_WIDGET: {},
|
||||
ICON_WIDGET: {},
|
||||
SKELETON_WIDGET: {},
|
||||
TABS_MIGRATOR_WIDGET: {},
|
||||
CONTAINER_WIDGET: {
|
||||
backgroundColor: "string",
|
||||
isVisible: "boolean",
|
||||
|
|
@ -61,8 +62,6 @@ const FIELD_VALUES: Record<
|
|||
// onSelectionChange: "Function Call",
|
||||
},
|
||||
TABS_WIDGET: {
|
||||
tabs:
|
||||
"Array<{ label: string, id: string(unique), widgetId: string(unique) }>",
|
||||
selectedTab: "string",
|
||||
isVisible: "boolean",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ export const HelpMap = {
|
|||
path: "",
|
||||
searchKey: "Tabs",
|
||||
},
|
||||
TABS_MIGRATOR_WIDGET: {
|
||||
path: "",
|
||||
searchKey: "",
|
||||
},
|
||||
MODAL_WIDGET: {
|
||||
path: "",
|
||||
searchKey: "",
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
UNDO_DELETE_WIDGET: "UNDO_DELETE_WIDGET",
|
||||
CUT_SELECTED_WIDGET: "CUT_SELECTED_WIDGET",
|
||||
WIDGET_ADD_CHILDREN: "WIDGET_ADD_CHILDREN",
|
||||
WIDGET_UPDATE_PROPERTY: "WIDGET_UPDATE_PROPERTY",
|
||||
SET_EVALUATED_TREE: "SET_EVALUATED_TREE",
|
||||
SET_EVALUATION_INVERSE_DEPENDENCY_MAP:
|
||||
"SET_EVALUATION_INVERSE_DEPENDENCY_MAP",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export enum WidgetTypes {
|
|||
SKELETON_WIDGET = "SKELETON_WIDGET",
|
||||
LIST_WIDGET = "LIST_WIDGET",
|
||||
SWITCH_WIDGET = "SWITCH_WIDGET",
|
||||
TABS_MIGRATOR_WIDGET = "TABS_MIGRATOR_WIDGET",
|
||||
}
|
||||
|
||||
export type WidgetType = keyof typeof WidgetTypes;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ export enum VALIDATION_TYPES {
|
|||
DEFAULT_DATE = "DEFAULT_DATE",
|
||||
MIN_DATE = "MIN_DATE",
|
||||
MAX_DATE = "MAX_DATE",
|
||||
TABS_DATA = "TABS_DATA",
|
||||
LIST_DATA = "LIST_DATA",
|
||||
CHART_SERIES_DATA = "CHART_SERIES_DATA",
|
||||
CUSTOM_FUSION_CHARTS_DATA = "CUSTOM_FUSION_CHARTS_DATA",
|
||||
|
|
@ -30,6 +29,7 @@ export enum VALIDATION_TYPES {
|
|||
LAT_LONG = "LAT_LONG",
|
||||
TABLE_PAGE_NO = "TABLE_PAGE_NO",
|
||||
ROW_INDICES = "ROW_INDICES",
|
||||
TABS_DATA = "TABS_DATA",
|
||||
}
|
||||
|
||||
export type ValidationResponse = {
|
||||
|
|
@ -43,6 +43,7 @@ export type Validator = (
|
|||
value: any,
|
||||
props: WidgetProps,
|
||||
dataTree?: DataTree,
|
||||
property?: string,
|
||||
) => ValidationResponse;
|
||||
|
||||
export const ISO_DATE_FORMAT = "YYYY-MM-DDTHH:mm:ss.sssZ";
|
||||
|
|
|
|||
|
|
@ -236,10 +236,22 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
columns: 8,
|
||||
shouldScrollContents: false,
|
||||
widgetName: "Tabs",
|
||||
tabs: [
|
||||
{ label: "Tab 1", id: "tab1", widgetId: "", isVisible: true },
|
||||
{ label: "Tab 2", id: "tab2", widgetId: "", isVisible: true },
|
||||
],
|
||||
tabsObj: {
|
||||
tab1: {
|
||||
label: "Tab 1",
|
||||
id: "tab1",
|
||||
widgetId: "",
|
||||
isVisible: true,
|
||||
index: 0,
|
||||
},
|
||||
tab2: {
|
||||
label: "Tab 2",
|
||||
id: "tab2",
|
||||
widgetId: "",
|
||||
isVisible: true,
|
||||
index: 1,
|
||||
},
|
||||
},
|
||||
shouldShowTabs: true,
|
||||
defaultTab: "Tab 1",
|
||||
blueprint: {
|
||||
|
|
@ -247,18 +259,18 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
{
|
||||
type: BlueprintOperationTypes.MODIFY_PROPS,
|
||||
fn: (widget: WidgetProps & { children?: WidgetProps[] }) => {
|
||||
const tabs = [...widget.tabs];
|
||||
|
||||
const newTabs = tabs.map((tab: any) => {
|
||||
const tabs = Object.values({ ...widget.tabsObj });
|
||||
const tabsObj = tabs.reduce((obj: any, tab: any) => {
|
||||
const newTab = { ...tab };
|
||||
newTab.widgetId = generateReactKey();
|
||||
return newTab;
|
||||
});
|
||||
obj[newTab.id] = newTab;
|
||||
return obj;
|
||||
}, {});
|
||||
const updatePropertyMap = [
|
||||
{
|
||||
widgetId: widget.widgetId,
|
||||
propertyName: "tabs",
|
||||
propertyValue: newTabs,
|
||||
propertyName: "tabsObj",
|
||||
propertyValue: tabsObj,
|
||||
},
|
||||
];
|
||||
return updatePropertyMap;
|
||||
|
|
@ -266,7 +278,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
},
|
||||
],
|
||||
},
|
||||
version: 1,
|
||||
version: 2,
|
||||
},
|
||||
MODAL_WIDGET: {
|
||||
rows: 6,
|
||||
|
|
@ -511,6 +523,13 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
widgetName: "Skeleton",
|
||||
version: 1,
|
||||
},
|
||||
TABS_MIGRATOR_WIDGET: {
|
||||
isLoading: true,
|
||||
rows: 1,
|
||||
columns: 1,
|
||||
widgetName: "Skeleton",
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.LIST_WIDGET]: {
|
||||
backgroundColor: "",
|
||||
itemBackgroundColor: "white",
|
||||
|
|
|
|||
|
|
@ -68,7 +68,10 @@ export const CurrentPageEntityProperties = memo(
|
|||
case ENTITY_TYPE.WIDGET:
|
||||
const type: Exclude<
|
||||
Partial<WidgetType>,
|
||||
"CANVAS_WIDGET" | "ICON_WIDGET" | "SKELETON_WIDGET"
|
||||
| "CANVAS_WIDGET"
|
||||
| "ICON_WIDGET"
|
||||
| "SKELETON_WIDGET"
|
||||
| "TABS_MIGRATOR_WIDGET"
|
||||
> = entity.type;
|
||||
config = entityDefinitions[type];
|
||||
if (!config) {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,10 @@ export const EntityProperties = memo(
|
|||
case ENTITY_TYPE.WIDGET:
|
||||
const type: Exclude<
|
||||
Partial<WidgetType>,
|
||||
"CANVAS_WIDGET" | "ICON_WIDGET" | "SKELETON_WIDGET"
|
||||
| "CANVAS_WIDGET"
|
||||
| "ICON_WIDGET"
|
||||
| "SKELETON_WIDGET"
|
||||
| "TABS_MIGRATOR_WIDGET"
|
||||
> = entity.type;
|
||||
config = entityDefinitions[type];
|
||||
if (!config) {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export const EntityName = forwardRef(
|
|||
) {
|
||||
const parent = state.entities.canvasWidgets[widget.parentId];
|
||||
if (parent.type === WidgetTypes.TABS_WIDGET) {
|
||||
return parent.tabs;
|
||||
return Object.values(parent.tabsObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,16 +33,15 @@ export const WidgetContextMenu = (props: {
|
|||
// If the widget is a tab we are updating the `tabs` of the property of the widget
|
||||
// This is similar to deleting a tab from the property pane
|
||||
if (widget.tabName && parentWidget.type === WidgetTypes.TABS_WIDGET) {
|
||||
const filteredTabs = parentWidget.tabs.filter(
|
||||
(tab: any) => tab.widgetId !== widgetId,
|
||||
);
|
||||
|
||||
const tabsObj = { ...parentWidget.tabsObj };
|
||||
delete tabsObj[widget.tabId];
|
||||
const filteredTabs = Object.values(tabsObj);
|
||||
if (widget.parentId && !!filteredTabs.length) {
|
||||
dispatch(
|
||||
updateWidgetPropertyRequest(
|
||||
widget.parentId,
|
||||
"tabs",
|
||||
filteredTabs,
|
||||
"tabsObj",
|
||||
tabsObj,
|
||||
RenderModes.CANVAS,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export const PanelPropertiesEditor = (
|
|||
}, [widgetProperties, panelParentPropertyPath, panelProps, panelConfig]);
|
||||
|
||||
const panelConfigs = useMemo(() => {
|
||||
if (currentIndex) {
|
||||
if (currentIndex !== undefined) {
|
||||
let path: string | undefined = undefined;
|
||||
if (isString(currentIndex)) {
|
||||
path = `${panelParentPropertyPath}.${currentIndex}`;
|
||||
|
|
@ -147,7 +147,7 @@ export const PanelPropertiesEditor = (
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (panelProps.widgetId !== widgetProperties.widgetId) {
|
||||
if (panelProps.propPaneId !== widgetProperties.widgetId) {
|
||||
props.closePanel();
|
||||
}
|
||||
}, [widgetProperties.widgetId]);
|
||||
|
|
|
|||
|
|
@ -249,12 +249,13 @@ const PropertyControl = memo((props: Props) => {
|
|||
let validationMessage = "";
|
||||
if (widgetProperties) {
|
||||
isValid = widgetProperties.invalidProps
|
||||
? !(propertyName in widgetProperties.invalidProps)
|
||||
? !_.has(widgetProperties.invalidProps, propertyName)
|
||||
: true;
|
||||
validationMessage = widgetProperties.validationMessages
|
||||
? propertyName in widgetProperties.validationMessages
|
||||
? widgetProperties.validationMessages[propertyName]
|
||||
: ""
|
||||
const validationMsgPresent =
|
||||
widgetProperties.validationMessages &&
|
||||
_.has(widgetProperties.validationMessages, propertyName);
|
||||
validationMessage = validationMsgPresent
|
||||
? _.get(widgetProperties.validationMessages, propertyName)
|
||||
: "";
|
||||
}
|
||||
return { isValid, validationMessage };
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { FilePickerWidgetProps } from "../../widgets/FilepickerWidget";
|
|||
import {
|
||||
TabsWidgetProps,
|
||||
TabContainerWidgetProps,
|
||||
} from "../../widgets/TabsWidget";
|
||||
} from "../../widgets/Tabs/TabsWidget";
|
||||
import { ChartWidgetProps } from "widgets/ChartWidget";
|
||||
import { FormWidgetProps } from "widgets/FormWidget";
|
||||
import { FormButtonWidgetProps } from "widgets/FormButtonWidget";
|
||||
|
|
@ -70,6 +70,8 @@ export interface WidgetConfigReducerState {
|
|||
FILE_PICKER_WIDGET: Partial<FilePickerWidgetProps> & WidgetConfigProps;
|
||||
TABS_WIDGET: Partial<TabsWidgetProps<TabContainerWidgetProps>> &
|
||||
WidgetConfigProps;
|
||||
TABS_MIGRATOR_WIDGET: Partial<TabsWidgetProps<TabContainerWidgetProps>> &
|
||||
WidgetConfigProps;
|
||||
MODAL_WIDGET: Partial<ModalWidgetProps> & WidgetConfigProps;
|
||||
CHART_WIDGET: Partial<ChartWidgetProps> & WidgetConfigProps;
|
||||
FORM_WIDGET: Partial<FormWidgetProps> & WidgetConfigProps;
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ export function* fetchPageListSaga(
|
|||
}
|
||||
}
|
||||
|
||||
const getCanvasWidgetsPayload = (
|
||||
export const getCanvasWidgetsPayload = (
|
||||
pageResponse: FetchPageResponse,
|
||||
): UpdateCanvasPayload => {
|
||||
const normalizedResponse = CanvasWidgetsNormalizer.normalize(
|
||||
|
|
@ -596,13 +596,14 @@ export function* updateWidgetNameSaga(
|
|||
|
||||
// TODO(abhinav): Why do we need to jump through these hoops just to
|
||||
// change the tab name? Figure out a better design to make this moot.
|
||||
const tabs:
|
||||
| Array<{
|
||||
const tabsObj: Record<
|
||||
string,
|
||||
{
|
||||
id: string;
|
||||
widgetId: string;
|
||||
label: string;
|
||||
}>
|
||||
| undefined = yield select((state: AppState) => {
|
||||
}
|
||||
> = yield select((state: AppState) => {
|
||||
// Check if this widget exists in the canvas widgets
|
||||
if (state.entities.canvasWidgets.hasOwnProperty(action.payload.id)) {
|
||||
// If it does assign it to a variable
|
||||
|
|
@ -617,7 +618,7 @@ export function* updateWidgetNameSaga(
|
|||
// Check if this parent is a TABS_WIDGET
|
||||
if (parent.type === WidgetTypes.TABS_WIDGET) {
|
||||
// If it is return the tabs property
|
||||
return parent.tabs;
|
||||
return parent.tabsObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -626,7 +627,8 @@ export function* updateWidgetNameSaga(
|
|||
});
|
||||
|
||||
// If we're trying to update the name of a tab in the TABS_WIDGET
|
||||
if (tabs !== undefined) {
|
||||
if (tabsObj !== undefined) {
|
||||
const tabs: any = Object.values(tabsObj);
|
||||
// Get all canvas widgets
|
||||
const stateWidgets = yield select(getWidgets);
|
||||
// Shallow copy canvas widgets as they're immutable
|
||||
|
|
@ -641,14 +643,19 @@ export function* updateWidgetNameSaga(
|
|||
// Shallow copy the parent widget so that we can update the properties
|
||||
const parent = { ...widgets[parentId] };
|
||||
// Update the tabs property of the parent tabs widget
|
||||
parent.tabs = tabs.map(
|
||||
(tab: { widgetId: string; label: string; id: string }) => {
|
||||
if (tab.widgetId === action.payload.id) {
|
||||
return { ...tab, label: action.payload.newName };
|
||||
}
|
||||
return tab;
|
||||
},
|
||||
const tabToChange = tabs.find(
|
||||
(each: any) => each.widgetId === action.payload.id,
|
||||
);
|
||||
const updatedTab = {
|
||||
...tabToChange,
|
||||
label: action.payload.newName,
|
||||
};
|
||||
parent.tabsObj = {
|
||||
...parent.tabsObj,
|
||||
[updatedTab.id]: {
|
||||
...updatedTab,
|
||||
},
|
||||
};
|
||||
// replace the parent widget in the canvas widgets
|
||||
widgets[parentId] = parent;
|
||||
// Update and save the new widgets
|
||||
|
|
|
|||
|
|
@ -593,20 +593,21 @@ export function* undoDeleteSaga(action: ReduxAction<{ widgetId: string }>) {
|
|||
widget.type === WidgetTypes.CANVAS_WIDGET &&
|
||||
widget.parentId
|
||||
) {
|
||||
const parent = { ...widgets[widget.parentId] };
|
||||
if (parent.tabs) {
|
||||
parent.tabs = parent.tabs.slice();
|
||||
const parent = cloneDeep(widgets[widget.parentId]);
|
||||
if (parent.tabsObj) {
|
||||
try {
|
||||
parent.tabs.push({
|
||||
const tabs = Object.values(parent.tabsObj);
|
||||
parent.tabsObj[widget.tabId] = {
|
||||
id: widget.tabId,
|
||||
widgetId: widget.widgetId,
|
||||
label: widget.tabName || widget.widgetName,
|
||||
});
|
||||
isVisible: true,
|
||||
};
|
||||
widgets = {
|
||||
...widgets,
|
||||
[widget.parentId]: {
|
||||
...widgets[widget.parentId],
|
||||
tabs: parent.tabs,
|
||||
tabsObj: parent.tabsObj,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
|
|
@ -866,7 +867,7 @@ function* setWidgetDynamicPropertySaga(
|
|||
) {
|
||||
const { isDynamic, propertyPath, widgetId } = action.payload;
|
||||
const stateWidget: WidgetProps = yield select(getWidget, widgetId);
|
||||
let widget = { ...stateWidget };
|
||||
let widget = cloneDeep({ ...stateWidget });
|
||||
const propertyValue = _.get(widget, propertyPath);
|
||||
let dynamicPropertyPathList = getWidgetDynamicPropertyPathList(widget);
|
||||
if (isDynamic) {
|
||||
|
|
@ -1041,6 +1042,9 @@ function* removeWidgetProperties(widget: WidgetProps, paths: string[]) {
|
|||
let dynamicBindingPathList: DynamicPath[] = getEntityDynamicBindingPathList(
|
||||
widget,
|
||||
);
|
||||
let dynamicPropertyPathList: DynamicPath[] = getWidgetDynamicPropertyPathList(
|
||||
widget,
|
||||
);
|
||||
|
||||
paths.forEach((propertyPath) => {
|
||||
dynamicTriggerPathList = dynamicTriggerPathList.filter((dynamicPath) => {
|
||||
|
|
@ -1050,10 +1054,18 @@ function* removeWidgetProperties(widget: WidgetProps, paths: string[]) {
|
|||
dynamicBindingPathList = dynamicBindingPathList.filter((dynamicPath) => {
|
||||
return !isChildPropertyPath(propertyPath, dynamicPath.key);
|
||||
});
|
||||
|
||||
dynamicPropertyPathList = dynamicPropertyPathList.filter(
|
||||
(dynamicPath) => {
|
||||
return !isChildPropertyPath(propertyPath, dynamicPath.key);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
widget.dynamicBindingPathList = dynamicBindingPathList;
|
||||
widget.dynamicTriggerPathList = dynamicTriggerPathList;
|
||||
widget.dynamicPropertyPathList = dynamicPropertyPathList;
|
||||
|
||||
paths.forEach((propertyPath) => {
|
||||
widget = unsetPropertyPath(widget, propertyPath) as WidgetProps;
|
||||
});
|
||||
|
|
@ -1389,14 +1401,15 @@ function* pasteWidgetSaga() {
|
|||
}
|
||||
|
||||
// Update the tabs for the tabs widget.
|
||||
if (widget.tabs && widget.type === WidgetTypes.TABS_WIDGET) {
|
||||
if (widget.tabsObj && widget.type === WidgetTypes.TABS_WIDGET) {
|
||||
try {
|
||||
const tabs = widget.tabs;
|
||||
const tabs = Object.values(widget.tabsObj);
|
||||
if (Array.isArray(tabs)) {
|
||||
widget.tabs = tabs.map((tab) => {
|
||||
widget.tabsObj = tabs.reduce((obj: any, tab) => {
|
||||
tab.widgetId = widgetIdMap[tab.widgetId];
|
||||
return tab;
|
||||
});
|
||||
obj[tab.id] = tab;
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
} catch (error) {
|
||||
log.debug("Error updating tabs", error);
|
||||
|
|
@ -1692,6 +1705,10 @@ export default function* widgetOperationSagas() {
|
|||
ReduxActionTypes.UPDATE_WIDGET_PROPERTY_REQUEST,
|
||||
updateWidgetPropertySaga,
|
||||
),
|
||||
takeEvery(
|
||||
ReduxActionTypes.WIDGET_UPDATE_PROPERTY,
|
||||
updateWidgetPropertySaga,
|
||||
),
|
||||
takeEvery(
|
||||
ReduxActionTypes.SET_WIDGET_DYNAMIC_PROPERTY,
|
||||
setWidgetDynamicPropertySaga,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,12 @@ export const getWidgetPropsForPropertyPane = createSelector(
|
|||
},
|
||||
);
|
||||
|
||||
const isResizingorDragging = (state: AppState) =>
|
||||
state.ui.widgetDragResize.isResizing || state.ui.widgetDragResize.isDragging;
|
||||
|
||||
export const getIsPropertyPaneVisible = createSelector(
|
||||
getPropertyPaneState,
|
||||
(pane: PropertyPaneReduxState) => !!(pane.isVisible && pane.widgetId),
|
||||
isResizingorDragging,
|
||||
(pane: PropertyPaneReduxState, isResizingorDragging: boolean) =>
|
||||
!!(!isResizingorDragging && pane.isVisible && pane.widgetId),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { migrateIncorrectDynamicBindingPathLists } from "utils/migrations/Incorr
|
|||
import * as Sentry from "@sentry/react";
|
||||
import { migrateTextStyleFromTextWidget } from "./migrations/TextWidgetReplaceTextStyle";
|
||||
import { nextAvailableRowInContainer } from "entities/Widget/utils";
|
||||
import { DATA_BIND_REGEX_GLOBAL } from "constants/BindingsConstants";
|
||||
|
||||
export type WidgetOperationParams = {
|
||||
operation: WidgetOperation;
|
||||
|
|
@ -333,6 +334,111 @@ const rteDefaultValueMigration = (
|
|||
return currentDSL;
|
||||
};
|
||||
|
||||
function migrateTabsDataUsingMigrator(
|
||||
currentDSL: ContainerWidgetProps<WidgetProps>,
|
||||
) {
|
||||
if (currentDSL.type === WidgetTypes.TABS_WIDGET && currentDSL.version === 1) {
|
||||
try {
|
||||
currentDSL.type = WidgetTypes.TABS_MIGRATOR_WIDGET;
|
||||
currentDSL.version = 1;
|
||||
} catch (error) {
|
||||
Sentry.captureException({
|
||||
message: "Tabs Migration Failed",
|
||||
oldData: currentDSL.tabs,
|
||||
});
|
||||
currentDSL.tabsObj = {};
|
||||
delete currentDSL.tabs;
|
||||
}
|
||||
}
|
||||
if (currentDSL.children && currentDSL.children.length) {
|
||||
currentDSL.children = currentDSL.children.map(migrateTabsDataUsingMigrator);
|
||||
}
|
||||
return currentDSL;
|
||||
}
|
||||
|
||||
export function migrateTabsData(currentDSL: ContainerWidgetProps<WidgetProps>) {
|
||||
if (
|
||||
[WidgetTypes.TABS_WIDGET, WidgetTypes.TABS_MIGRATOR_WIDGET].includes(
|
||||
currentDSL.type as any,
|
||||
) &&
|
||||
currentDSL.version === 1
|
||||
) {
|
||||
try {
|
||||
currentDSL.type = WidgetTypes.TABS_WIDGET;
|
||||
const isTabsDataBinded = isString(currentDSL.tabs);
|
||||
currentDSL.dynamicPropertyPathList =
|
||||
currentDSL.dynamicPropertyPathList || [];
|
||||
currentDSL.dynamicBindingPathList =
|
||||
currentDSL.dynamicBindingPathList || [];
|
||||
|
||||
if (isTabsDataBinded) {
|
||||
const tabsString = currentDSL.tabs.replace(
|
||||
DATA_BIND_REGEX_GLOBAL,
|
||||
(word: any) => `"${word}"`,
|
||||
);
|
||||
try {
|
||||
currentDSL.tabs = JSON.parse(tabsString);
|
||||
} catch (error) {
|
||||
return migrateTabsDataUsingMigrator(currentDSL);
|
||||
}
|
||||
const dynamicPropsList = currentDSL.tabs
|
||||
.filter((each: any) => DATA_BIND_REGEX_GLOBAL.test(each.isVisible))
|
||||
.map((each: any) => {
|
||||
return { key: `tabsObj.${each.id}.isVisible` };
|
||||
});
|
||||
const dynamicBindablePropsList = currentDSL.tabs.map((each: any) => {
|
||||
return { key: `tabsObj.${each.id}.isVisible` };
|
||||
});
|
||||
currentDSL.dynamicPropertyPathList = [
|
||||
...currentDSL.dynamicPropertyPathList,
|
||||
...dynamicPropsList,
|
||||
];
|
||||
currentDSL.dynamicBindingPathList = [
|
||||
...currentDSL.dynamicBindingPathList,
|
||||
...dynamicBindablePropsList,
|
||||
];
|
||||
}
|
||||
currentDSL.dynamicPropertyPathList = currentDSL.dynamicPropertyPathList.filter(
|
||||
(each) => {
|
||||
return each.key !== "tabs";
|
||||
},
|
||||
);
|
||||
currentDSL.dynamicBindingPathList = currentDSL.dynamicBindingPathList.filter(
|
||||
(each) => {
|
||||
return each.key !== "tabs";
|
||||
},
|
||||
);
|
||||
currentDSL.tabsObj = currentDSL.tabs.reduce(
|
||||
(obj: any, tab: any, index: number) => {
|
||||
obj = {
|
||||
...obj,
|
||||
[tab.id]: {
|
||||
...tab,
|
||||
isVisible: tab.isVisible === undefined ? true : tab.isVisible,
|
||||
index,
|
||||
},
|
||||
};
|
||||
return obj;
|
||||
},
|
||||
{},
|
||||
);
|
||||
currentDSL.version = 2;
|
||||
delete currentDSL.tabs;
|
||||
} catch (error) {
|
||||
Sentry.captureException({
|
||||
message: "Tabs Migration Failed",
|
||||
oldData: currentDSL.tabs,
|
||||
});
|
||||
currentDSL.tabsObj = {};
|
||||
delete currentDSL.tabs;
|
||||
}
|
||||
}
|
||||
if (currentDSL.children && currentDSL.children.length) {
|
||||
currentDSL.children = currentDSL.children.map(migrateTabsData);
|
||||
}
|
||||
return currentDSL;
|
||||
}
|
||||
|
||||
// A rudimentary transform function which updates the DSL based on its version.
|
||||
function migrateOldChartData(currentDSL: ContainerWidgetProps<WidgetProps>) {
|
||||
if (currentDSL.type === WidgetTypes.CHART_WIDGET) {
|
||||
|
|
@ -543,6 +649,11 @@ const transformDSL = (currentDSL: ContainerWidgetProps<WidgetProps>) => {
|
|||
currentDSL.version = 17;
|
||||
}
|
||||
|
||||
if (currentDSL.version === 17) {
|
||||
currentDSL = migrateTabsData(currentDSL);
|
||||
currentDSL.version = 18;
|
||||
}
|
||||
|
||||
return currentDSL;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ import TabsWidget, {
|
|||
TabsWidgetProps,
|
||||
TabContainerWidgetProps,
|
||||
ProfiledTabsWidget,
|
||||
} from "widgets/TabsWidget";
|
||||
} from "widgets/Tabs/TabsWidget";
|
||||
import {
|
||||
ModalWidgetProps,
|
||||
ProfiledModalWidget,
|
||||
|
|
@ -100,6 +100,9 @@ import SwitchWidget, {
|
|||
ProfiledSwitchWidget,
|
||||
SwitchWidgetProps,
|
||||
} from "widgets/SwitchWidget";
|
||||
import TabsMigratorWidget, {
|
||||
ProfiledTabsMigratorWidget,
|
||||
} from "widgets/Tabs/TabsMigrator";
|
||||
export default class WidgetBuilderRegistry {
|
||||
static registerWidgetBuilders() {
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
|
|
@ -296,6 +299,20 @@ export default class WidgetBuilderRegistry {
|
|||
TabsWidget.getMetaPropertiesMap(),
|
||||
TabsWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
"TABS_MIGRATOR_WIDGET",
|
||||
{
|
||||
buildWidget(
|
||||
widgetProps: TabsWidgetProps<TabContainerWidgetProps>,
|
||||
): JSX.Element {
|
||||
return <ProfiledTabsMigratorWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
TabsMigratorWidget.getDerivedPropertiesMap(),
|
||||
TabsMigratorWidget.getDefaultPropertiesMap(),
|
||||
TabsMigratorWidget.getMetaPropertiesMap(),
|
||||
TabsMigratorWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.MODAL_WIDGET,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -170,7 +170,6 @@ export const entityDefinitions = {
|
|||
},
|
||||
TABS_WIDGET: {
|
||||
isVisible: isVisible,
|
||||
tabs: "[tabs]",
|
||||
selectedTab: "string",
|
||||
},
|
||||
MODAL_WIDGET: {
|
||||
|
|
|
|||
110
app/client/src/widgets/Tabs/TabsMigrator.tsx
Normal file
110
app/client/src/widgets/Tabs/TabsMigrator.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import BaseWidget, { WidgetState } from "widgets/BaseWidget";
|
||||
import { TabContainerWidgetProps, TabsWidgetProps } from "./TabsWidget";
|
||||
import React from "react";
|
||||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import withMeta from "widgets/MetaHOC";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { migrateTabsData } from "utils/WidgetPropsUtils";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class TabsMigratorWidget extends BaseWidget<
|
||||
TabsWidgetProps<TabContainerWidgetProps>,
|
||||
WidgetState
|
||||
> {
|
||||
getPageView() {
|
||||
return <></>;
|
||||
}
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "General",
|
||||
children: [
|
||||
{
|
||||
helpText: "Takes an array of tab names to render tabs",
|
||||
propertyName: "tabs",
|
||||
isJSConvertible: true,
|
||||
label: "Tabs",
|
||||
controlType: "TABS_INPUT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TABS_DATA,
|
||||
},
|
||||
{
|
||||
propertyName: "shouldShowTabs",
|
||||
helpText:
|
||||
"Hides the tabs so that different widgets can be displayed based on the default tab",
|
||||
label: "Show Tabs",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "defaultTab",
|
||||
helpText: "Selects a tab name specified by default",
|
||||
placeholderText: "Enter tab name",
|
||||
label: "Default Tab",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.SELECTED_TAB,
|
||||
},
|
||||
{
|
||||
propertyName: "shouldScrollContents",
|
||||
label: "Scroll Contents",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "Visible",
|
||||
helpText: "Controls the visibility of the widget",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "Actions",
|
||||
children: [
|
||||
{
|
||||
helpText: "Triggers an action when the button is clicked",
|
||||
propertyName: "onTabSelected",
|
||||
label: "onTabSelected",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
componentDidMount() {
|
||||
if (this.props.evaluatedValues) {
|
||||
const tabsDsl = cloneDeep(this.props);
|
||||
const migratedTabsDsl = migrateTabsData(tabsDsl);
|
||||
this.batchUpdateWidgetProperty({
|
||||
modify: {
|
||||
tabsObj: migratedTabsDsl.tabsObj,
|
||||
type: WidgetTypes.TABS_WIDGET,
|
||||
version: 2,
|
||||
dynamicPropertyPathList: migratedTabsDsl.dynamicPropertyPathList,
|
||||
dynamicBindingPathList: migratedTabsDsl.dynamicBindingPathList,
|
||||
},
|
||||
remove: ["tabs"],
|
||||
});
|
||||
}
|
||||
}
|
||||
getWidgetType(): WidgetType {
|
||||
return "TABS_MIGRATOR_WIDGET";
|
||||
}
|
||||
}
|
||||
export default TabsMigratorWidget;
|
||||
export const ProfiledTabsMigratorWidget = Sentry.withProfiler(
|
||||
withMeta(TabsMigratorWidget),
|
||||
);
|
||||
98
app/client/src/widgets/Tabs/TabsWidget.test.tsx
Normal file
98
app/client/src/widgets/Tabs/TabsWidget.test.tsx
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import {
|
||||
buildChildren,
|
||||
widgetCanvasFactory,
|
||||
} from "test/factories/WidgetFactoryUtils";
|
||||
import { render, fireEvent } from "test/testUtils";
|
||||
|
||||
import Canvas from "pages/Editor/Canvas";
|
||||
import React from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { editorInitializer } from "utils/EditorUtils";
|
||||
import { initCanvasLayout } from "actions/pageActions";
|
||||
import { getCanvasWidgetsPayload } from "sagas/PageSagas";
|
||||
import { noop } from "utils/AppsmithUtils";
|
||||
|
||||
Element.prototype.scrollTo = noop;
|
||||
const SetCanvas = ({ dsl, children }: any) => {
|
||||
const dispatch = useDispatch();
|
||||
const mockResp: any = {
|
||||
data: {
|
||||
id: "asa",
|
||||
name: "App",
|
||||
applicationId: "asa",
|
||||
layouts: [
|
||||
{
|
||||
id: "w323",
|
||||
dsl,
|
||||
layoutOnLoadActions: [],
|
||||
layoutActions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const canvasWidgetsPayload = getCanvasWidgetsPayload(mockResp);
|
||||
dispatch(initCanvasLayout(canvasWidgetsPayload));
|
||||
return <>{children}</>;
|
||||
};
|
||||
describe("Tabs widget functional cases", () => {
|
||||
it("Should render 2 tabs by default", () => {
|
||||
editorInitializer();
|
||||
const children: any = buildChildren([{ type: "TABS_WIDGET" }]);
|
||||
const dsl: any = widgetCanvasFactory.build({
|
||||
children,
|
||||
});
|
||||
const component = render(
|
||||
<SetCanvas dsl={dsl}>
|
||||
<Canvas dsl={dsl}></Canvas>
|
||||
</SetCanvas>,
|
||||
);
|
||||
const tab1 = component.queryByText("Tab 1");
|
||||
const tab2 = component.queryByText("Tab 2");
|
||||
expect(tab1).toBeDefined();
|
||||
expect(tab2).toBeDefined();
|
||||
});
|
||||
|
||||
it("Should render components inside tabs by default", () => {
|
||||
editorInitializer();
|
||||
const tab1Children = buildChildren([
|
||||
{ type: "SWITCH_WIDGET", label: "Tab1 Switch" },
|
||||
{ type: "CHECKBOX_WIDGET", label: "Tab1 Checkbox" },
|
||||
]);
|
||||
const tab2Children = buildChildren([
|
||||
{ type: "INPUT_WIDGET", text: "Tab2 Text" },
|
||||
{ type: "BUTTON_WIDGET", label: "Tab2 Button" },
|
||||
]);
|
||||
const children: any = buildChildren([{ type: "TABS_WIDGET" }]);
|
||||
children[0].children[0].children = tab1Children;
|
||||
children[0].children[1].children = tab2Children;
|
||||
const dsl: any = widgetCanvasFactory.build({
|
||||
children,
|
||||
});
|
||||
const component = render(
|
||||
<SetCanvas dsl={dsl}>
|
||||
<Canvas dsl={dsl}></Canvas>
|
||||
</SetCanvas>,
|
||||
);
|
||||
const tab1 = component.queryByText("Tab 1");
|
||||
const tab2: any = component.queryByText("Tab 2");
|
||||
expect(tab1).toBeDefined();
|
||||
expect(tab2).toBeDefined();
|
||||
let tab1Switch = component.queryByText("Tab1 Switch");
|
||||
let tab1Checkbox = component.queryByText("Tab1 Checkbox");
|
||||
let tab2Input = component.queryByText("Tab2 Text");
|
||||
let tab2Button = component.queryByText("Tab2 Button");
|
||||
expect(tab1Switch).toBeDefined();
|
||||
expect(tab1Checkbox).toBeDefined();
|
||||
expect(tab2Input).toBeNull();
|
||||
expect(tab2Button).toBeNull();
|
||||
fireEvent.click(tab2);
|
||||
tab1Switch = component.queryByText("Tab1 Switch");
|
||||
tab1Checkbox = component.queryByText("Tab1 Checkbox");
|
||||
tab2Input = component.queryByText("Tab2 Text");
|
||||
tab2Button = component.queryByText("Tab2 Button");
|
||||
expect(tab1Switch).toBeNull();
|
||||
expect(tab1Checkbox).toBeNull();
|
||||
expect(tab2Input).toBeDefined();
|
||||
expect(tab2Button).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import TabsComponent from "components/designSystems/appsmith/TabsComponent";
|
||||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import WidgetFactory from "utils/WidgetFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import _ from "lodash";
|
||||
|
|
@ -9,7 +9,7 @@ import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
|||
import { WidgetOperations } from "widgets/BaseWidget";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import withMeta, { WithMeta } from "./MetaHOC";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class TabsWidget extends BaseWidget<
|
||||
TabsWidgetProps<TabContainerWidgetProps>,
|
||||
|
|
@ -22,13 +22,47 @@ class TabsWidget extends BaseWidget<
|
|||
children: [
|
||||
{
|
||||
helpText: "Takes an array of tab names to render tabs",
|
||||
propertyName: "tabs",
|
||||
isJSConvertible: true,
|
||||
propertyName: "tabsObj",
|
||||
isJSConvertible: false,
|
||||
label: "Tabs",
|
||||
controlType: "TABS_INPUT",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
panelConfig: {
|
||||
editableTitle: true,
|
||||
titlePropertyName: "label",
|
||||
panelIdPropertyName: "id",
|
||||
updateHook: (
|
||||
props: any,
|
||||
propertyPath: string,
|
||||
propertyValue: string,
|
||||
) => {
|
||||
return [
|
||||
{
|
||||
propertyPath,
|
||||
propertyValue,
|
||||
},
|
||||
];
|
||||
},
|
||||
children: [
|
||||
{
|
||||
sectionName: "Tab Control",
|
||||
children: [
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "Visible",
|
||||
helpText: "Controls the visibility of the widget",
|
||||
controlType: "SWITCH",
|
||||
useValidationMessage: true,
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TABS_DATA,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "defaultTab",
|
||||
|
|
@ -97,7 +131,9 @@ class TabsWidget extends BaseWidget<
|
|||
|
||||
static getDerivedPropertiesMap() {
|
||||
return {
|
||||
selectedTab: `{{_.find(this.tabs, { widgetId: this.selectedTabWidgetId }).label}}`,
|
||||
selectedTab: `{{_.find(Object.values(this.tabsObj), {
|
||||
widgetId: this.selectedTabWidgetId,
|
||||
}).label}}`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -152,8 +188,11 @@ class TabsWidget extends BaseWidget<
|
|||
}
|
||||
|
||||
addTabContainer = (widgetIds: string[]) => {
|
||||
const tabs = Object.values(this.props.tabsObj || {});
|
||||
widgetIds.forEach((newWidgetId: string) => {
|
||||
const tab = this.props.tabs.find((tab) => tab.widgetId === newWidgetId);
|
||||
const tab = _.find(tabs, {
|
||||
widgetId: newWidgetId,
|
||||
});
|
||||
if (tab) {
|
||||
const columns =
|
||||
(this.props.rightColumn - this.props.leftColumn) *
|
||||
|
|
@ -186,6 +225,18 @@ class TabsWidget extends BaseWidget<
|
|||
});
|
||||
};
|
||||
|
||||
updateTabContainerNames = () => {
|
||||
this.props.children.forEach((each) => {
|
||||
const tab = this.props.tabsObj[each.tabId];
|
||||
if (tab && each.tabName !== tab.label) {
|
||||
this.updateWidget(WidgetOperations.UPDATE_PROPERTY, each.widgetId, {
|
||||
propertyPath: "tabName",
|
||||
propertyValue: tab.label,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
removeTabContainer = (widgetIds: string[]) => {
|
||||
widgetIds.forEach((widgetIdToRemove: string) => {
|
||||
this.updateWidget(WidgetOperations.DELETE, widgetIdToRemove, {
|
||||
|
|
@ -196,17 +247,17 @@ class TabsWidget extends BaseWidget<
|
|||
|
||||
componentDidUpdate(prevProps: TabsWidgetProps<TabContainerWidgetProps>) {
|
||||
if (
|
||||
Array.isArray(this.props.tabs) &&
|
||||
JSON.stringify(this.props.tabs) !== JSON.stringify(prevProps.tabs)
|
||||
JSON.stringify(this.props.tabsObj) !== JSON.stringify(prevProps.tabsObj)
|
||||
) {
|
||||
const tabWidgetIds = this.props.tabs.map((tab) => tab.widgetId);
|
||||
const tabWidgetIds = Object.values(this.props.tabsObj).map(
|
||||
(tab) => tab.widgetId,
|
||||
);
|
||||
const childWidgetIds = this.props.children
|
||||
.filter(Boolean)
|
||||
.map((child) => child.widgetId);
|
||||
// If the tabs and children are different,
|
||||
// add and/or remove tab container widgets
|
||||
|
||||
if (!this.props.invalidProps?.tabs) {
|
||||
if (_.xor(childWidgetIds, tabWidgetIds).length > 0) {
|
||||
const widgetIdsToRemove: string[] = _.without(
|
||||
childWidgetIds,
|
||||
|
|
@ -216,18 +267,27 @@ class TabsWidget extends BaseWidget<
|
|||
tabWidgetIds,
|
||||
...childWidgetIds,
|
||||
);
|
||||
if (widgetIdsToCreate && widgetIdsToCreate.length) {
|
||||
this.addTabContainer(widgetIdsToCreate);
|
||||
}
|
||||
if (widgetIdsToRemove && widgetIdsToRemove.length) {
|
||||
this.removeTabContainer(widgetIdsToRemove);
|
||||
}
|
||||
}
|
||||
this.updateTabContainerNames();
|
||||
|
||||
// If all tabs were removed.
|
||||
if (tabWidgetIds.length === 0) {
|
||||
const newTabContainerWidgetId = generateReactKey();
|
||||
const tabs = [
|
||||
{ id: "tab1", widgetId: newTabContainerWidgetId, label: "Tab 1" },
|
||||
];
|
||||
this.updateWidgetProperty("tabs", tabs);
|
||||
}
|
||||
const tabs = {
|
||||
tab1: {
|
||||
id: "tab1",
|
||||
widgetId: newTabContainerWidgetId,
|
||||
label: "Tab 1",
|
||||
index: 0,
|
||||
},
|
||||
};
|
||||
this.updateWidgetProperty("tabsObj", tabs);
|
||||
}
|
||||
}
|
||||
const visibleTabs = this.getVisibleTabs();
|
||||
|
|
@ -276,7 +336,8 @@ class TabsWidget extends BaseWidget<
|
|||
}
|
||||
|
||||
generateTabContainers = () => {
|
||||
const { tabs, widgetId } = this.props;
|
||||
const { tabsObj, widgetId } = this.props;
|
||||
const tabs = Object.values(tabsObj || {});
|
||||
const childWidgetIds = this.props.children
|
||||
?.filter(Boolean)
|
||||
.map((child) => child.widgetId);
|
||||
|
|
@ -312,10 +373,13 @@ class TabsWidget extends BaseWidget<
|
|||
};
|
||||
|
||||
getVisibleTabs = () => {
|
||||
if (Array.isArray(this.props.tabs)) {
|
||||
return this.props.tabs.filter(
|
||||
(tab) => tab.isVisible === undefined || tab.isVisible === true,
|
||||
);
|
||||
const tabs = Object.values(this.props.tabsObj || {});
|
||||
if (tabs.length) {
|
||||
return tabs
|
||||
.filter(
|
||||
(tab) => tab.isVisible === undefined || !!tab.isVisible === true,
|
||||
)
|
||||
.sort((tab1, tab2) => tab1.index - tab2.index);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
|
@ -323,7 +387,7 @@ class TabsWidget extends BaseWidget<
|
|||
componentDidMount() {
|
||||
const visibleTabs = this.getVisibleTabs();
|
||||
// If we have a defaultTab
|
||||
if (this.props.defaultTab && this.props.tabs?.length) {
|
||||
if (this.props.defaultTab && Object.keys(this.props.tabsObj || {}).length) {
|
||||
// Find the default Tab object
|
||||
const selectedTab = _.find(visibleTabs, {
|
||||
label: this.props.defaultTab,
|
||||
|
|
@ -345,7 +409,10 @@ class TabsWidget extends BaseWidget<
|
|||
selectedTabWidgetId,
|
||||
);
|
||||
}
|
||||
} else if (!this.props.selectedTabWidgetId && this.props.tabs?.length) {
|
||||
} else if (
|
||||
!this.props.selectedTabWidgetId &&
|
||||
Object.keys(this.props.tabsObj || {}).length
|
||||
) {
|
||||
// If no tab is selected
|
||||
// Select the first tab in the tabs list.
|
||||
this.props.updateWidgetMetaProperty(
|
||||
|
|
@ -372,6 +439,16 @@ export interface TabsWidgetProps<T extends TabContainerWidgetProps>
|
|||
widgetId: string;
|
||||
isVisible?: boolean;
|
||||
}>;
|
||||
tabsObj: Record<
|
||||
string,
|
||||
{
|
||||
id: string;
|
||||
label: string;
|
||||
widgetId: string;
|
||||
isVisible?: boolean;
|
||||
index: number;
|
||||
}
|
||||
>;
|
||||
shouldShowTabs: boolean;
|
||||
children: T[];
|
||||
snapColumns?: number;
|
||||
|
|
@ -741,18 +741,15 @@ export const VALIDATORS: Record<VALIDATION_TYPES, Validator> = {
|
|||
value: any,
|
||||
props: WidgetProps,
|
||||
): ValidationResponse => {
|
||||
const tabs =
|
||||
props.tabs && isString(props.tabs)
|
||||
? JSON.parse(props.tabs)
|
||||
: props.tabs && Array.isArray(props.tabs)
|
||||
? props.tabs
|
||||
: [];
|
||||
const tabs: any = props.tabsObj
|
||||
? Object.values(props.tabsObj)
|
||||
: props.tabs || [];
|
||||
const tabNames = tabs.map((i: { label: string; id: string }) => i.label);
|
||||
const isValidTabName = tabNames.includes(value);
|
||||
return {
|
||||
isValid: isValidTabName,
|
||||
parsed: value,
|
||||
message: isValidTabName ? "" : `Invalid tab name.`,
|
||||
parsed: isValidTabName ? value : "",
|
||||
message: isValidTabName ? "" : `Tab name provided does not exist.`,
|
||||
};
|
||||
},
|
||||
[VALIDATION_TYPES.DEFAULT_OPTION_VALUE]: (
|
||||
|
|
|
|||
3
app/client/test/__mocks__/derivedMock.js
Normal file
3
app/client/test/__mocks__/derivedMock.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import widgetPropertyFns from "!!raw-loader!./derived.js";
|
||||
|
||||
export default widgetPropertyFns;
|
||||
28
app/client/test/factories/WidgetFactoryUtils.ts
Normal file
28
app/client/test/factories/WidgetFactoryUtils.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { makeFactory } from "factory.ts";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
import defaultTemplate from "../../src/templates/default";
|
||||
import { WidgetTypeFactories } from "./Widgets/WidgetTypeFactories";
|
||||
const defaultMainContainer: ContainerWidgetProps<WidgetProps> = {
|
||||
...(defaultTemplate as any),
|
||||
renderMode: "PAGE",
|
||||
version: 1,
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
export const mainContainerFactory = makeFactory({ ...defaultMainContainer });
|
||||
export const widgetCanvasFactory = makeFactory(mainContainerFactory.build());
|
||||
const buildChild = (child: Partial<WidgetProps>): WidgetProps => {
|
||||
return WidgetTypeFactories[child.type || "CANVAS_WIDGET"].build({
|
||||
...child,
|
||||
});
|
||||
};
|
||||
export const buildChildren = (children: Partial<WidgetProps>[]) => {
|
||||
try {
|
||||
return children.map((child) => {
|
||||
return buildChild(child);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Check if child widget data provided");
|
||||
}
|
||||
};
|
||||
31
app/client/test/factories/Widgets/ButtonFactory.ts
Normal file
31
app/client/test/factories/Widgets/ButtonFactory.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const ButtonFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
widgetName: Factory.each((i) => `Button${i + 1}`),
|
||||
rightColumn: 12,
|
||||
onClick: "",
|
||||
isDefaultClickDisabled: true,
|
||||
widgetId: generateReactKey(),
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
topRow: 1,
|
||||
bottomRow: 2,
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
type: "BUTTON_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
parentId: "0",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 10,
|
||||
dynamicTriggerPathList: [
|
||||
{
|
||||
key: "onClick",
|
||||
},
|
||||
],
|
||||
text: "Test Button Text",
|
||||
isDisabled: false,
|
||||
version: 1,
|
||||
renderMode: "CANVAS",
|
||||
});
|
||||
25
app/client/test/factories/Widgets/CanvasFactory.ts
Normal file
25
app/client/test/factories/Widgets/CanvasFactory.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const CanvasFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
backgroundColor: "none",
|
||||
rightColumn: 1224,
|
||||
snapColumns: 16,
|
||||
detachFromLayout: true,
|
||||
topRow: 0,
|
||||
bottomRow: 1280,
|
||||
containerStyle: "none",
|
||||
snapRows: 33,
|
||||
parentRowSpace: 1,
|
||||
type: "CANVAS_WIDGET",
|
||||
canExtend: true,
|
||||
minHeight: 1292,
|
||||
parentColumnSpace: 1,
|
||||
dynamicBindingPathList: [],
|
||||
leftColumn: 0,
|
||||
widgetName: Factory.each((i) => `Canvas${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
61
app/client/test/factories/Widgets/ChartFactory.ts
Normal file
61
app/client/test/factories/Widgets/ChartFactory.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const ChartFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
chartType: "LINE_CHART",
|
||||
chartName: "Sales on working days",
|
||||
allowHorizontalScroll: false,
|
||||
chartData: [
|
||||
{
|
||||
seriesName: "Sales",
|
||||
data: [
|
||||
{
|
||||
x: "Mon",
|
||||
y: 10000,
|
||||
},
|
||||
{
|
||||
x: "Tue",
|
||||
y: 12000,
|
||||
},
|
||||
{
|
||||
x: "Wed",
|
||||
y: 32000,
|
||||
},
|
||||
{
|
||||
x: "Thu",
|
||||
y: 28000,
|
||||
},
|
||||
{
|
||||
x: "Fri",
|
||||
y: 14000,
|
||||
},
|
||||
{
|
||||
x: "Sat",
|
||||
y: 19000,
|
||||
},
|
||||
{
|
||||
x: "Sun",
|
||||
y: 36000,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
xAxisName: "Last Week",
|
||||
yAxisName: "Total Order Revenue $",
|
||||
type: "CHART_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 71.75,
|
||||
parentRowSpace: 38,
|
||||
leftColumn: 2,
|
||||
rightColumn: 8,
|
||||
topRow: 1,
|
||||
bottomRow: 9,
|
||||
parentId: "rglduihhzk",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Chart${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
23
app/client/test/factories/Widgets/CheckboxFactory.ts
Normal file
23
app/client/test/factories/Widgets/CheckboxFactory.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const CheckboxFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
label: "Label",
|
||||
defaultCheckedState: true,
|
||||
type: "CHECKBOX_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 71.75,
|
||||
parentRowSpace: 38,
|
||||
leftColumn: 10,
|
||||
rightColumn: 13,
|
||||
topRow: 4,
|
||||
bottomRow: 5,
|
||||
parentId: "e3tq9qwta6",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Checkbox${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
25
app/client/test/factories/Widgets/ContainerFactory.ts
Normal file
25
app/client/test/factories/Widgets/ContainerFactory.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const ContainerFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
backgroundColor: "#FFFFFF",
|
||||
widgetName: Factory.each((i) => `Container${(i+1)}` ),
|
||||
type: "CONTAINER_WIDGET",
|
||||
containerStyle: "card",
|
||||
isVisible: true,
|
||||
isLoading: false,
|
||||
parentColumnSpace: 75.25,
|
||||
parentRowSpace: 38,
|
||||
dynamicBindingPathList: [],
|
||||
leftColumn: 0,
|
||||
rightColumn: 8,
|
||||
topRow: 0,
|
||||
bottomRow: 9,
|
||||
snapColumns: 16,
|
||||
orientation: "VERTICAL",
|
||||
children: [],
|
||||
version: 1,
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
});
|
||||
47
app/client/test/factories/Widgets/DatepickerFactory.ts
Normal file
47
app/client/test/factories/Widgets/DatepickerFactory.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const OldDatepickerFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
widgetName: Factory.each((i) => `OldDatePicker${i + 1}`),
|
||||
rightColumn: 11,
|
||||
dateFormat: "DD/MM/YYYY",
|
||||
topRow: 7,
|
||||
bottomRow: 8,
|
||||
isValid: "{{ DatePicker1.isRequired ? !!DatePicker1.selectedDate : true }}",
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
datePickerType: "DATE_PICKER",
|
||||
label: "From Date",
|
||||
type: "DATE_PICKER_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
isLoading: false,
|
||||
enableTimePicker: true,
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 3,
|
||||
isDisabled: false,
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
|
||||
export const DatepickerFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
widgetName: Factory.each((i) => `DatePicker${i + 1}`),
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
datePickerType: "DATE_PICKER",
|
||||
label: "",
|
||||
dateFormat: "DD/MM/YYYY HH:mm",
|
||||
defaultDate: "2021-02-05T10:53:12.791Z",
|
||||
version: 2,
|
||||
type: "DATE_PICKER_WIDGET2",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 74,
|
||||
parentRowSpace: 40,
|
||||
leftColumn: 5,
|
||||
rightColumn: 10,
|
||||
topRow: 0,
|
||||
bottomRow: 1,
|
||||
widgetId: generateReactKey(),
|
||||
parentId: "0",
|
||||
});
|
||||
29
app/client/test/factories/Widgets/DropdownFactory.ts
Normal file
29
app/client/test/factories/Widgets/DropdownFactory.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const DropdownFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
label: "",
|
||||
selectionType: "SINGLE_SELECT",
|
||||
options: [
|
||||
{ label: "Vegetarian", value: "VEG" },
|
||||
{ label: "Non-Vegetarian", value: "NON_VEG" },
|
||||
{ label: "Vegan", value: "VEGAN" },
|
||||
],
|
||||
defaultOptionValue: "VEG",
|
||||
type: "DROP_DOWN_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 74,
|
||||
parentRowSpace: 40,
|
||||
leftColumn: 10,
|
||||
rightColumn: 15,
|
||||
topRow: 1,
|
||||
bottomRow: 2,
|
||||
parentId: "0",
|
||||
widgetId: generateReactKey(),
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Dropdown${i + 1}`),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
25
app/client/test/factories/Widgets/FilepickerFactory.ts
Normal file
25
app/client/test/factories/Widgets/FilepickerFactory.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const FilepickerFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
rightColumn: 8,
|
||||
isDefaultClickDisabled: true,
|
||||
topRow: 1,
|
||||
bottomRow: 2,
|
||||
isValid: "{{ FilePicker1.isRequired ? FilePicker1.files.length > 0 : true }}",
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
label: "Upload Files",
|
||||
maxFileSize: "",
|
||||
type: "FILE_PICKER_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
isLoading: false,
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 4,
|
||||
files: [],
|
||||
widgetName: Factory.each((i) => `FilePicker${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
24
app/client/test/factories/Widgets/FormButtonFactory.ts
Normal file
24
app/client/test/factories/Widgets/FormButtonFactory.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const FormButtonFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
text: "Reset",
|
||||
isDefaultClickDisabled: true,
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
disabledWhenInvalid: false,
|
||||
resetFormOnClick: true,
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
isLoading: false,
|
||||
leftColumn: 8,
|
||||
rightColumn: 12,
|
||||
topRow: 12,
|
||||
bottomRow: 13,
|
||||
parentId: "qrqizehc5b",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `FormButton${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
217
app/client/test/factories/Widgets/FormFactory.ts
Normal file
217
app/client/test/factories/Widgets/FormFactory.ts
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
{
|
||||
}
|
||||
|
||||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const FormFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
backgroundColor: "Gray",
|
||||
rightColumn: 11,
|
||||
topRow: 0,
|
||||
bottomRow: 13,
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
type: "FORM_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
type: "CANVAS_WIDGET",
|
||||
props: {
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 12,
|
||||
},
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
type: "TEXT_WIDGET",
|
||||
props: {
|
||||
text: "Title",
|
||||
textStyle: "HEADING",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 4,
|
||||
},
|
||||
position: {
|
||||
top: 11,
|
||||
left: 12,
|
||||
},
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
props: {
|
||||
resetFormOnClick: false,
|
||||
disabledWhenInvalid: true,
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
text: "Submit",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 4,
|
||||
},
|
||||
position: {
|
||||
top: 11,
|
||||
left: 8,
|
||||
},
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
props: {
|
||||
resetFormOnClick: true,
|
||||
disabledWhenInvalid: false,
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
text: "Reset",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
detachFromLayout: true,
|
||||
children: [],
|
||||
containerStyle: "none",
|
||||
canExtend: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
isLoading: false,
|
||||
parentColumnSpace: 71.75,
|
||||
leftColumn: 5,
|
||||
children: [
|
||||
{
|
||||
widgetName: "Canvas1",
|
||||
rightColumn: 430.5,
|
||||
detachFromLayout: true,
|
||||
widgetId: "nxlutw2g3v",
|
||||
containerStyle: "none",
|
||||
topRow: 0,
|
||||
bottomRow: 494,
|
||||
parentRowSpace: 1,
|
||||
isVisible: true,
|
||||
canExtend: false,
|
||||
type: "CANVAS_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 12,
|
||||
},
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
type: "TEXT_WIDGET",
|
||||
props: {
|
||||
text: "Title",
|
||||
textStyle: "HEADING",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 4,
|
||||
},
|
||||
position: {
|
||||
top: 11,
|
||||
left: 12,
|
||||
},
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
props: {
|
||||
resetFormOnClick: false,
|
||||
disabledWhenInvalid: true,
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
text: "Submit",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 4,
|
||||
},
|
||||
position: {
|
||||
top: 11,
|
||||
left: 8,
|
||||
},
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
props: {
|
||||
resetFormOnClick: true,
|
||||
disabledWhenInvalid: false,
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
text: "Reset",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
minHeight: 494,
|
||||
isLoading: false,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
children: [
|
||||
{
|
||||
isLoading: false,
|
||||
widgetName: "Text1",
|
||||
rightColumn: 12,
|
||||
leftColumn: 0,
|
||||
widgetId: "uvz6hzdz7c",
|
||||
topRow: 0,
|
||||
bottomRow: 1,
|
||||
isVisible: true,
|
||||
text: "Title",
|
||||
textStyle: "HEADING",
|
||||
type: "TEXT_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
},
|
||||
{
|
||||
resetFormOnClick: false,
|
||||
widgetName: "FormButton1",
|
||||
rightColumn: 16,
|
||||
isDefaultClickDisabled: true,
|
||||
widgetId: "tf20n9k4z2",
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
topRow: 11,
|
||||
bottomRow: 12,
|
||||
isVisible: true,
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
isLoading: false,
|
||||
disabledWhenInvalid: true,
|
||||
leftColumn: 12,
|
||||
text: "Submit",
|
||||
},
|
||||
{
|
||||
resetFormOnClick: true,
|
||||
widgetName: "FormButton2",
|
||||
rightColumn: 12,
|
||||
isDefaultClickDisabled: true,
|
||||
widgetId: "6xnpe13jie",
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
topRow: 11,
|
||||
bottomRow: 12,
|
||||
isVisible: true,
|
||||
type: "FORM_BUTTON_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
isLoading: false,
|
||||
disabledWhenInvalid: false,
|
||||
leftColumn: 8,
|
||||
text: "Reset",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
widgetName: Factory.each((i) => `Form${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
23
app/client/test/factories/Widgets/IconFactory.ts
Normal file
23
app/client/test/factories/Widgets/IconFactory.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const IconFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
rightColumn: 16,
|
||||
onClick: "",
|
||||
color: "#040627",
|
||||
iconName: "cross",
|
||||
topRow: 0,
|
||||
bottomRow: 1,
|
||||
isVisible: true,
|
||||
type: "ICON_WIDGET",
|
||||
parentId: "dma7flgdrm",
|
||||
isLoading: false,
|
||||
leftColumn: 15,
|
||||
iconSize: 24,
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Icon${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
24
app/client/test/factories/Widgets/ImageFactory.ts
Normal file
24
app/client/test/factories/Widgets/ImageFactory.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const ImageFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
defaultImage:
|
||||
"https://res.cloudinary.com/drako999/image/upload/v1589196259/default.png",
|
||||
imageShape: "RECTANGLE",
|
||||
image: "",
|
||||
widgetName: Factory.each((i) => `Image${i + 1}`),
|
||||
type: "IMAGE_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 34.6875,
|
||||
parentRowSpace: 38,
|
||||
leftColumn: 6,
|
||||
rightColumn: 10,
|
||||
topRow: 2,
|
||||
bottomRow: 5,
|
||||
parentId: "bxekwxgc1i",
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
30
app/client/test/factories/Widgets/InputFactory.ts
Normal file
30
app/client/test/factories/Widgets/InputFactory.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const InputFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
widgetName: Factory.each((i) => `Input${i + 1}`),
|
||||
onTextChanged: "",
|
||||
rightColumn: 11,
|
||||
widgetId: generateReactKey(),
|
||||
topRow: 6,
|
||||
bottomRow: 7,
|
||||
isValid: "",
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
label: "Test Input Label",
|
||||
type: "INPUT_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
parentId: "iw4o07jvik",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 6,
|
||||
dynamicTriggerPathList: [
|
||||
{
|
||||
key: "onTextChange",
|
||||
},
|
||||
],
|
||||
inputType: "",
|
||||
placeholderText: "",
|
||||
defaultText: "",
|
||||
});
|
||||
23
app/client/test/factories/Widgets/ListFactory.ts
Normal file
23
app/client/test/factories/Widgets/ListFactory.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const ListFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
image: "",
|
||||
defaultImage: "",
|
||||
type: "LIST_WIDGET",
|
||||
parentId: "Container1",
|
||||
parentColumnSpace: 2,
|
||||
parentRowSpace: 3,
|
||||
leftColumn: 2,
|
||||
rightColumn: 3,
|
||||
topRow: 1,
|
||||
bottomRow: 3,
|
||||
isLoading: false,
|
||||
items: [],
|
||||
disablePropertyPane: false,
|
||||
widgetName: Factory.each((i) => `List${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
32
app/client/test/factories/Widgets/MapFactory.ts
Normal file
32
app/client/test/factories/Widgets/MapFactory.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const MapFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
enableSearch: true,
|
||||
zoomLevel: 50,
|
||||
enablePickLocation: true,
|
||||
allowZoom: true,
|
||||
mapCenter: {
|
||||
lat: 20.593684,
|
||||
long: 78.96288,
|
||||
},
|
||||
defaultMarkers:
|
||||
'[\n {\n "lat: -34.397,\n "long: 150.644,\n "title: "Test A"\n }\n]',
|
||||
type: "MAP_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 71.75,
|
||||
parentRowSpace: 38,
|
||||
leftColumn: 3,
|
||||
rightColumn: 11,
|
||||
topRow: 0,
|
||||
bottomRow: 12,
|
||||
parentId: "yt4ouwn0sk",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Map${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
270
app/client/test/factories/Widgets/ModalFactory.ts
Normal file
270
app/client/test/factories/Widgets/ModalFactory.ts
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const ModalFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
rightColumn: 0,
|
||||
detachFromLayout: true,
|
||||
topRow: 0,
|
||||
bottomRow: 0,
|
||||
parentRowSpace: 1,
|
||||
isVisible: false,
|
||||
canOutsideClickClose: true,
|
||||
type: "MODAL_WIDGET",
|
||||
canEscapeKeyClose: true,
|
||||
parentId: "0",
|
||||
shouldScrollContents: true,
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
type: "CANVAS_WIDGET",
|
||||
props: {
|
||||
shouldScrollContents: false,
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 1,
|
||||
},
|
||||
position: {
|
||||
top: 0,
|
||||
left: 15,
|
||||
},
|
||||
type: "ICON_WIDGET",
|
||||
props: {
|
||||
color: "#040627",
|
||||
iconName: "cross",
|
||||
iconSize: 24,
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 15,
|
||||
},
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
type: "TEXT_WIDGET",
|
||||
props: {
|
||||
text: "Modal Title",
|
||||
textStyle: "HEADING",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 3,
|
||||
},
|
||||
position: {
|
||||
top: 4,
|
||||
left: 10,
|
||||
},
|
||||
type: "BUTTON_WIDGET",
|
||||
props: {
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
text: "Cancel",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 3,
|
||||
},
|
||||
position: {
|
||||
top: 4,
|
||||
left: 13,
|
||||
},
|
||||
type: "BUTTON_WIDGET",
|
||||
props: {
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
text: "Confirm",
|
||||
},
|
||||
},
|
||||
],
|
||||
operations: [
|
||||
{
|
||||
type: "MODIFY_PROPS",
|
||||
},
|
||||
],
|
||||
},
|
||||
detachFromLayout: true,
|
||||
children: [],
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
canExtend: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
isLoading: false,
|
||||
parentColumnSpace: 1,
|
||||
size: "MODAL_SMALL",
|
||||
leftColumn: 0,
|
||||
children: [
|
||||
{
|
||||
widgetName: "Canvas1",
|
||||
rightColumn: 0,
|
||||
detachFromLayout: true,
|
||||
widgetId: "dma7flgdrm",
|
||||
topRow: 0,
|
||||
bottomRow: 0,
|
||||
parentRowSpace: 1,
|
||||
isVisible: true,
|
||||
canExtend: true,
|
||||
type: "CANVAS_WIDGET",
|
||||
parentId: "s8mtp5krfz",
|
||||
shouldScrollContents: false,
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 1,
|
||||
},
|
||||
position: {
|
||||
top: 0,
|
||||
left: 15,
|
||||
},
|
||||
type: "ICON_WIDGET",
|
||||
props: {
|
||||
color: "#040627",
|
||||
iconName: "cross",
|
||||
iconSize: 24,
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 15,
|
||||
},
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
type: "TEXT_WIDGET",
|
||||
props: {
|
||||
text: "Modal Title",
|
||||
textStyle: "HEADING",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 3,
|
||||
},
|
||||
position: {
|
||||
top: 4,
|
||||
left: 10,
|
||||
},
|
||||
type: "BUTTON_WIDGET",
|
||||
props: {
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
text: "Cancel",
|
||||
},
|
||||
},
|
||||
{
|
||||
size: {
|
||||
rows: 1,
|
||||
cols: 3,
|
||||
},
|
||||
position: {
|
||||
top: 4,
|
||||
left: 13,
|
||||
},
|
||||
type: "BUTTON_WIDGET",
|
||||
props: {
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
text: "Confirm",
|
||||
},
|
||||
},
|
||||
],
|
||||
operations: [
|
||||
{
|
||||
type: "MODIFY_PROPS",
|
||||
},
|
||||
],
|
||||
},
|
||||
minHeight: 0,
|
||||
isLoading: false,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
children: [
|
||||
{
|
||||
widgetName: "Icon1",
|
||||
rightColumn: 16,
|
||||
onClick: "{{closeModal('TestModal')}}",
|
||||
color: "#040627",
|
||||
iconName: "cross",
|
||||
widgetId: "n5fc0ven2a",
|
||||
topRow: 0,
|
||||
bottomRow: 1,
|
||||
isVisible: true,
|
||||
type: "ICON_WIDGET",
|
||||
parentId: "dma7flgdrm",
|
||||
isLoading: false,
|
||||
leftColumn: 15,
|
||||
iconSize: 24,
|
||||
},
|
||||
{
|
||||
isLoading: false,
|
||||
widgetName: "Text1",
|
||||
rightColumn: 15,
|
||||
leftColumn: 0,
|
||||
widgetId: "s818l5hhvq",
|
||||
topRow: 0,
|
||||
bottomRow: 1,
|
||||
isVisible: true,
|
||||
text: "Modal Title",
|
||||
textStyle: "HEADING",
|
||||
type: "TEXT_WIDGET",
|
||||
parentId: "dma7flgdrm",
|
||||
},
|
||||
{
|
||||
widgetName: "Button1",
|
||||
rightColumn: 13,
|
||||
isDefaultClickDisabled: true,
|
||||
widgetId: "io777lh7bc",
|
||||
buttonStyle: "SECONDARY_BUTTON",
|
||||
topRow: 4,
|
||||
bottomRow: 5,
|
||||
isVisible: true,
|
||||
type: "BUTTON_WIDGET",
|
||||
parentId: "dma7flgdrm",
|
||||
isLoading: false,
|
||||
leftColumn: 10,
|
||||
text: "Cancel",
|
||||
isDisabled: false,
|
||||
},
|
||||
{
|
||||
widgetName: "Button2",
|
||||
rightColumn: 16,
|
||||
isDefaultClickDisabled: true,
|
||||
widgetId: "gexp49bfyb",
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
topRow: 4,
|
||||
bottomRow: 5,
|
||||
isVisible: true,
|
||||
type: "BUTTON_WIDGET",
|
||||
parentId: "dma7flgdrm",
|
||||
isLoading: false,
|
||||
leftColumn: 13,
|
||||
text: "Confirm",
|
||||
isDisabled: false,
|
||||
},
|
||||
],
|
||||
isDisabled: false,
|
||||
},
|
||||
],
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Modal${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
42
app/client/test/factories/Widgets/RadiogroupFactory.ts
Normal file
42
app/client/test/factories/Widgets/RadiogroupFactory.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const RadiogroupFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
rightColumn: 16,
|
||||
topRow: 3,
|
||||
bottomRow: 5,
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
label: "Test Radio",
|
||||
type: "RADIO_GROUP_WIDGET",
|
||||
isLoading: false,
|
||||
defaultOptionValue: "1",
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 12,
|
||||
dynamicTriggerPathList: [{
|
||||
key: "onSelectionChange"
|
||||
}],
|
||||
onSelectionChange: "{{navigateTo()}}",
|
||||
options: [
|
||||
{
|
||||
id: "1",
|
||||
label: "jarvis",
|
||||
value: "1"
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
label: "marvel",
|
||||
value: "2"
|
||||
},
|
||||
{
|
||||
label: "iron",
|
||||
value: "4"
|
||||
}
|
||||
],
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `RadioGroup${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
29
app/client/test/factories/Widgets/RichTextFactory.ts
Normal file
29
app/client/test/factories/Widgets/RichTextFactory.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const RichTextFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
rightColumn: 11,
|
||||
topRow: 3,
|
||||
bottomRow: 8,
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
type: "RICH_TEXT_EDITOR_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 3,
|
||||
dynamicTriggerPathList: [
|
||||
{
|
||||
key: "onTextChange",
|
||||
},
|
||||
],
|
||||
defaultText: "",
|
||||
text: "This is the initial <b>content</b> of the editor",
|
||||
isDisabled: false,
|
||||
onTextChange: "{{navigateTo()}}",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `RichText${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
19
app/client/test/factories/Widgets/SkeletonFactory.ts
Normal file
19
app/client/test/factories/Widgets/SkeletonFactory.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const SkeletonFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
bottomRow: 0,
|
||||
isLoading: false,
|
||||
leftColumn: 0,
|
||||
parentColumnSpace: 0,
|
||||
parentRowSpace: 0,
|
||||
rightColumn: 0,
|
||||
topRow: 0,
|
||||
type: "SKELETON_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Skeleton${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
22
app/client/test/factories/Widgets/SwitchFactory.ts
Normal file
22
app/client/test/factories/Widgets/SwitchFactory.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const SwitchFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
label: "Switch",
|
||||
defaultSwitchState: true,
|
||||
widgetName: Factory.each((i) => `Switch${(i+1)}` ),
|
||||
type: "SWITCH_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 71.75,
|
||||
parentRowSpace: 38,
|
||||
leftColumn: 10,
|
||||
rightColumn: 13,
|
||||
topRow: 18,
|
||||
bottomRow: 19,
|
||||
parentId: "e3tq9qwta6",
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
111
app/client/test/factories/Widgets/TableFactory.ts
Normal file
111
app/client/test/factories/Widgets/TableFactory.ts
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const TableFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
label: "Data",
|
||||
widgetName: Factory.each((i) => `Table${i + 1}`),
|
||||
|
||||
searchKey: "",
|
||||
tableData:
|
||||
'[\n {\n "id: 2381224,\n "email: "michael.lawson@reqres.in",\n "userName: "Michael Lawson",\n "productName: "Chicken Sandwich",\n "orderAmount: 4.99\n },\n {\n "id: 2736212,\n "email: "lindsay.ferguson@reqres.in",\n "userName: "Lindsay Ferguson",\n "productName: "Tuna Salad",\n "orderAmount: 9.99\n },\n {\n "id: 6788734,\n "email: "tobias.funke@reqres.in",\n "userName: "Tobias Funke",\n "productName: "Beef steak",\n "orderAmount: 19.99\n }\n]',
|
||||
type: "TABLE_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 74,
|
||||
parentRowSpace: 40,
|
||||
leftColumn: 2,
|
||||
rightColumn: 10,
|
||||
topRow: 12,
|
||||
bottomRow: 19,
|
||||
parentId: "0",
|
||||
widgetId: generateReactKey(),
|
||||
dynamicBindingPathList: [],
|
||||
primaryColumns: {
|
||||
id: {
|
||||
index: 0,
|
||||
width: 150,
|
||||
id: "id",
|
||||
horizontalAlignment: "LEFT",
|
||||
verticalAlignment: "CENTER",
|
||||
columnType: "text",
|
||||
textColor: "#4E5D78",
|
||||
textSize: "PARAGRAPH",
|
||||
fontStyle: "NORMAL",
|
||||
enableFilter: true,
|
||||
enableSort: true,
|
||||
isVisible: true,
|
||||
isDerived: false,
|
||||
label: "id",
|
||||
computedValue: "",
|
||||
},
|
||||
email: {
|
||||
index: 1,
|
||||
width: 150,
|
||||
id: "email",
|
||||
horizontalAlignment: "LEFT",
|
||||
verticalAlignment: "CENTER",
|
||||
columnType: "text",
|
||||
textColor: "#4E5D78",
|
||||
textSize: "PARAGRAPH",
|
||||
fontStyle: "NORMAL",
|
||||
enableFilter: true,
|
||||
enableSort: true,
|
||||
isVisible: true,
|
||||
isDerived: false,
|
||||
label: "email",
|
||||
computedValue: "",
|
||||
},
|
||||
userName: {
|
||||
index: 2,
|
||||
width: 150,
|
||||
id: "userName",
|
||||
horizontalAlignment: "LEFT",
|
||||
verticalAlignment: "CENTER",
|
||||
columnType: "text",
|
||||
textColor: "#4E5D78",
|
||||
textSize: "PARAGRAPH",
|
||||
fontStyle: "NORMAL",
|
||||
enableFilter: true,
|
||||
enableSort: true,
|
||||
isVisible: true,
|
||||
isDerived: false,
|
||||
label: "userName",
|
||||
computedValue: "",
|
||||
},
|
||||
productName: {
|
||||
index: 3,
|
||||
width: 150,
|
||||
id: "productName",
|
||||
horizontalAlignment: "LEFT",
|
||||
verticalAlignment: "CENTER",
|
||||
columnType: "text",
|
||||
textColor: "#4E5D78",
|
||||
textSize: "PARAGRAPH",
|
||||
fontStyle: "NORMAL",
|
||||
enableFilter: true,
|
||||
enableSort: true,
|
||||
isVisible: true,
|
||||
isDerived: false,
|
||||
label: "productName",
|
||||
computedValue: "",
|
||||
},
|
||||
orderAmount: {
|
||||
index: 4,
|
||||
width: 150,
|
||||
id: "orderAmount",
|
||||
horizontalAlignment: "LEFT",
|
||||
verticalAlignment: "CENTER",
|
||||
columnType: "text",
|
||||
textColor: "#4E5D78",
|
||||
textSize: "PARAGRAPH",
|
||||
fontStyle: "NORMAL",
|
||||
enableFilter: true,
|
||||
enableSort: true,
|
||||
isVisible: true,
|
||||
isDerived: false,
|
||||
label: "orderAmount",
|
||||
computedValue: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
145
app/client/test/factories/Widgets/TabsFactory.ts
Normal file
145
app/client/test/factories/Widgets/TabsFactory.ts
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const OldTabsFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
shouldScrollContents: false,
|
||||
tabs: [
|
||||
{
|
||||
label: "Tab 1",
|
||||
id: "tab1",
|
||||
widgetId: "o9ody00ep7",
|
||||
},
|
||||
{
|
||||
label: "Tab 2",
|
||||
id: "tab2",
|
||||
widgetId: "plhuaxd4lo",
|
||||
},
|
||||
],
|
||||
shouldShowTabs: true,
|
||||
defaultTab: "Tab 1",
|
||||
type: "TABS_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 74,
|
||||
parentRowSpace: 40,
|
||||
leftColumn: 1,
|
||||
rightColumn: 9,
|
||||
topRow: 12,
|
||||
bottomRow: 19,
|
||||
parentId: "0",
|
||||
children: [
|
||||
{
|
||||
type: "CANVAS_WIDGET",
|
||||
tabId: "tab1",
|
||||
tabName: "Tab 1",
|
||||
widgetId: "o9ody00ep7",
|
||||
parentId: "jd83uvbkmp",
|
||||
detachFromLayout: true,
|
||||
children: [],
|
||||
parentRowSpace: 1,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
rightColumn: 592,
|
||||
topRow: 0,
|
||||
bottomRow: 280,
|
||||
isLoading: false,
|
||||
widgetName: "Canvas1",
|
||||
renderMode: "CANVAS",
|
||||
},
|
||||
{
|
||||
type: "CANVAS_WIDGET",
|
||||
tabId: "tab2",
|
||||
tabName: "Tab 2",
|
||||
widgetId: "plhuaxd4lo",
|
||||
parentId: "jd83uvbkmp",
|
||||
detachFromLayout: true,
|
||||
children: [],
|
||||
parentRowSpace: 1,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
rightColumn: 592,
|
||||
topRow: 0,
|
||||
bottomRow: 280,
|
||||
isLoading: false,
|
||||
widgetName: "Canvas1",
|
||||
renderMode: "CANVAS",
|
||||
},
|
||||
],
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Tabs${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
|
||||
export const TabsFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
shouldScrollContents: false,
|
||||
tabsObj: {
|
||||
tab1: {
|
||||
label: "Tab 1",
|
||||
id: "tab1",
|
||||
widgetId: "o9ody00ep7",
|
||||
},
|
||||
tab2: {
|
||||
label: "Tab 2",
|
||||
id: "tab2",
|
||||
widgetId: "plhuaxd4lo",
|
||||
},
|
||||
},
|
||||
shouldShowTabs: true,
|
||||
defaultTab: "Tab 1",
|
||||
type: "TABS_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 74,
|
||||
parentRowSpace: 40,
|
||||
leftColumn: 1,
|
||||
rightColumn: 9,
|
||||
topRow: 12,
|
||||
bottomRow: 19,
|
||||
parentId: "0",
|
||||
children: [
|
||||
{
|
||||
type: "CANVAS_WIDGET",
|
||||
tabId: "tab1",
|
||||
tabName: "Tab 1",
|
||||
widgetId: "o9ody00ep7",
|
||||
parentId: "jd83uvbkmp",
|
||||
detachFromLayout: true,
|
||||
children: [],
|
||||
parentRowSpace: 1,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
rightColumn: 592,
|
||||
topRow: 0,
|
||||
bottomRow: 280,
|
||||
isLoading: false,
|
||||
widgetName: "Canvas1",
|
||||
renderMode: "CANVAS",
|
||||
},
|
||||
{
|
||||
type: "CANVAS_WIDGET",
|
||||
tabId: "tab2",
|
||||
tabName: "Tab 2",
|
||||
widgetId: "plhuaxd4lo",
|
||||
parentId: "jd83uvbkmp",
|
||||
detachFromLayout: true,
|
||||
children: [],
|
||||
parentRowSpace: 1,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
rightColumn: 592,
|
||||
topRow: 0,
|
||||
bottomRow: 280,
|
||||
isLoading: false,
|
||||
widgetName: "Canvas1",
|
||||
renderMode: "CANVAS",
|
||||
},
|
||||
],
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Tabs${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
31
app/client/test/factories/Widgets/TextFactory.ts
Normal file
31
app/client/test/factories/Widgets/TextFactory.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const TextFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
widgetName: Factory.each((i) => `Text${(i+1)}`),
|
||||
rightColumn: 12,
|
||||
onClick: "",
|
||||
isDefaultClickDisabled: true,
|
||||
widgetId: generateReactKey(),
|
||||
buttonStyle: "PRIMARY_BUTTON",
|
||||
topRow: 1,
|
||||
bottomRow: 2,
|
||||
parentRowSpace: 38,
|
||||
isVisible: true,
|
||||
type: "BUTTON_WIDGET",
|
||||
dynamicBindingPathList: [],
|
||||
parentId: "0",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 34.6875,
|
||||
leftColumn: 10,
|
||||
dynamicTriggerPathList: [
|
||||
{
|
||||
key: "onClick",
|
||||
},
|
||||
],
|
||||
text: "Test Button Text",
|
||||
isDisabled: false,
|
||||
version: 1,
|
||||
renderMode: "CANVAS",
|
||||
});
|
||||
23
app/client/test/factories/Widgets/VideoFactory.ts
Normal file
23
app/client/test/factories/Widgets/VideoFactory.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import * as Factory from "factory.ts";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const VideoFactory = Factory.Sync.makeFactory<WidgetProps>({
|
||||
isVisible: true,
|
||||
url: "https://www.youtube.com/watch?v=mzqK0QIZRLs",
|
||||
autoPlay: false,
|
||||
type: "VIDEO_WIDGET",
|
||||
isLoading: false,
|
||||
parentColumnSpace: 74,
|
||||
parentRowSpace: 40,
|
||||
leftColumn: 1,
|
||||
rightColumn: 8,
|
||||
topRow: 17,
|
||||
bottomRow: 24,
|
||||
parentId: "0",
|
||||
dynamicBindingPathList: [],
|
||||
widgetName: Factory.each((i) => `Video${i + 1}`),
|
||||
widgetId: generateReactKey(),
|
||||
renderMode: "CANVAS",
|
||||
version: 1,
|
||||
});
|
||||
53
app/client/test/factories/Widgets/WidgetTypeFactories.ts
Normal file
53
app/client/test/factories/Widgets/WidgetTypeFactories.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { SwitchFactory } from "./SwitchFactory";
|
||||
import { ButtonFactory } from "./ButtonFactory";
|
||||
import { TextFactory } from "./TextFactory";
|
||||
import { ImageFactory } from "./ImageFactory";
|
||||
import { InputFactory } from "./InputFactory";
|
||||
import { TableFactory } from "./TableFactory";
|
||||
import { OldDatepickerFactory, DatepickerFactory } from "./DatepickerFactory";
|
||||
import { ContainerFactory } from "./ContainerFactory";
|
||||
import { DropdownFactory } from "./DropdownFactory";
|
||||
import { CheckboxFactory } from "./CheckboxFactory";
|
||||
import { RadiogroupFactory } from "./RadiogroupFactory";
|
||||
import { OldTabsFactory, TabsFactory } from "./TabsFactory";
|
||||
import { ModalFactory } from "./ModalFactory";
|
||||
import { RichTextFactory } from "./RichTextFactory";
|
||||
import { ChartFactory } from "./ChartFactory";
|
||||
import { FormFactory } from "./FormFactory";
|
||||
import { FormButtonFactory } from "./FormButtonFactory";
|
||||
import { MapFactory } from "./MapFactory";
|
||||
import { CanvasFactory } from "./CanvasFactory";
|
||||
import { IconFactory } from "./IconFactory";
|
||||
import { FilepickerFactory } from "./FilepickerFactory";
|
||||
import { VideoFactory } from "./VideoFactory";
|
||||
import { SkeletonFactory } from "./SkeletonFactory";
|
||||
import { ListFactory } from "./ListFactory";
|
||||
|
||||
export const WidgetTypeFactories = {
|
||||
SWITCH_WIDGET: SwitchFactory,
|
||||
BUTTON_WIDGET: ButtonFactory,
|
||||
TEXT_WIDGET: TextFactory,
|
||||
IMAGE_WIDGET: ImageFactory,
|
||||
INPUT_WIDGET: InputFactory,
|
||||
CONTAINER_WIDGET: ContainerFactory,
|
||||
DATE_PICKER_WIDGET: OldDatepickerFactory,
|
||||
DATE_PICKER_WIDGET2: DatepickerFactory,
|
||||
TABLE_WIDGET: TableFactory,
|
||||
DROP_DOWN_WIDGET: DropdownFactory,
|
||||
CHECKBOX_WIDGET: CheckboxFactory,
|
||||
RADIO_GROUP_WIDGET: RadiogroupFactory,
|
||||
TABS_WIDGET: TabsFactory,
|
||||
TABS_MIGRATOR_WIDGET: OldTabsFactory,
|
||||
MODAL_WIDGET: ModalFactory,
|
||||
RICH_TEXT_EDITOR_WIDGET: RichTextFactory,
|
||||
CHART_WIDGET: ChartFactory,
|
||||
FORM_WIDGET: FormFactory,
|
||||
FORM_BUTTON_WIDGET: FormButtonFactory,
|
||||
MAP_WIDGET: MapFactory,
|
||||
CANVAS_WIDGET: CanvasFactory,
|
||||
ICON_WIDGET: IconFactory,
|
||||
FILE_PICKER_WIDGET: FilepickerFactory,
|
||||
VIDEO_WIDGET: VideoFactory,
|
||||
SKELETON_WIDGET: SkeletonFactory,
|
||||
LIST_WIDGET: ListFactory,
|
||||
};
|
||||
|
|
@ -7,6 +7,8 @@ import { getCurrentThemeDetails } from "../src/selectors/themeSelectors";
|
|||
import * as customQueries from "./customQueries";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { AppState } from "reducers";
|
||||
import { DndProvider } from "react-dnd";
|
||||
import TouchBackend from "react-dnd-touch-backend";
|
||||
|
||||
const customRender = (
|
||||
ui: ReactElement,
|
||||
|
|
@ -25,7 +27,14 @@ const customRender = (
|
|||
return render(
|
||||
<BrowserRouter>
|
||||
<Provider store={reduxStore}>
|
||||
<DndProvider
|
||||
backend={TouchBackend}
|
||||
options={{
|
||||
enableMouseEvents: true,
|
||||
}}
|
||||
>
|
||||
<ThemeProvider theme={defaultTheme}>{ui}</ThemeProvider>
|
||||
</DndProvider>
|
||||
</Provider>
|
||||
</BrowserRouter>,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8162,6 +8162,14 @@ extsprintf@^1.2.0:
|
|||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
|
||||
factory.ts@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/factory.ts/-/factory.ts-0.5.1.tgz#4bab72d8457078906aa6ab396c0d341e8a3ab382"
|
||||
integrity sha512-jwAq8w7MmxUojIFzKezMwTzDc5QoxcqzAA8+n9A0EAWBje2CRHUeBrW9x/ioV2DRjHgkHX7i0G0ipfDhlatIQw==
|
||||
dependencies:
|
||||
clone-deep "^4.0.1"
|
||||
source-map-support "^0.5.9"
|
||||
|
||||
fast-deep-equal@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
||||
|
|
@ -15637,7 +15645,7 @@ source-map-resolve@^0.6.0:
|
|||
atob "^2.1.2"
|
||||
decode-uri-component "^0.2.0"
|
||||
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19:
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.12, source-map-support@~0.5.19:
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||
dependencies:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user