Various P0 fixes
This commit is contained in:
parent
a3d85b8b3a
commit
9b00a345ad
|
|
@ -80,10 +80,7 @@ export const moveActionRequest = (payload: {
|
|||
};
|
||||
};
|
||||
|
||||
export const moveActionSuccess = (payload: {
|
||||
id: string;
|
||||
destinationPageId: string;
|
||||
}) => {
|
||||
export const moveActionSuccess = (payload: RestAction) => {
|
||||
return {
|
||||
type: ReduxActionTypes.MOVE_ACTION_SUCCESS,
|
||||
payload,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
MenuItem,
|
||||
Intent as BlueprintIntent,
|
||||
PopoverPosition,
|
||||
PopoverInteractionKind,
|
||||
} from "@blueprintjs/core";
|
||||
import { DropdownOption } from "widgets/DropdownWidget";
|
||||
import { ControlIconName, ControlIcons } from "icons/ControlIcons";
|
||||
|
|
@ -51,7 +52,9 @@ const DropdownItem = (option: ContextDropdownOption) => (
|
|||
popoverProps={{
|
||||
minimal: true,
|
||||
hoverCloseDelay: 0,
|
||||
hoverOpenDelay: 0,
|
||||
hoverOpenDelay: 300,
|
||||
interactionKind: PopoverInteractionKind.CLICK,
|
||||
position: PopoverPosition.RIGHT,
|
||||
modifiers: {
|
||||
arrow: {
|
||||
enabled: false,
|
||||
|
|
@ -84,9 +87,6 @@ export const ContextDropdown = (props: ContextDropdownProps) => {
|
|||
|
||||
return (
|
||||
<Dropdown
|
||||
popoverProps={{
|
||||
position: PopoverPosition.AUTO_END,
|
||||
}}
|
||||
items={props.options}
|
||||
itemRenderer={renderer}
|
||||
onItemSelect={noop}
|
||||
|
|
|
|||
|
|
@ -141,10 +141,21 @@ type Props = ReduxStateProps &
|
|||
input: Partial<WrappedFieldInputProps>;
|
||||
};
|
||||
|
||||
class DynamicAutocompleteInput extends Component<Props> {
|
||||
type State = {
|
||||
isFocused: boolean;
|
||||
};
|
||||
|
||||
class DynamicAutocompleteInput extends Component<Props, State> {
|
||||
textArea = React.createRef<HTMLTextAreaElement>();
|
||||
editor: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isFocused: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
if (this.textArea.current) {
|
||||
const options: EditorConfiguration = {};
|
||||
|
|
@ -168,6 +179,8 @@ class DynamicAutocompleteInput extends Component<Props> {
|
|||
});
|
||||
this.editor.on("change", _.debounce(this.handleChange, 100));
|
||||
this.editor.on("cursorActivity", this.handleAutocompleteVisibility);
|
||||
this.editor.on("focus", () => this.setState({ isFocused: true }));
|
||||
this.editor.on("blur", () => this.setState({ isFocused: false }));
|
||||
this.editor.setOption("hintOptions", {
|
||||
completeSingle: false,
|
||||
globalScope: this.props.dynamicData,
|
||||
|
|
@ -179,10 +192,11 @@ class DynamicAutocompleteInput extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(): void {
|
||||
componentDidUpdate(prevProps: Props): void {
|
||||
if (this.editor) {
|
||||
const editorValue = this.editor.getValue();
|
||||
let inputValue = this.props.input.value;
|
||||
// Safe update of value of the editor when value updated outside the editor
|
||||
if (typeof inputValue === "object") {
|
||||
inputValue = JSON.stringify(inputValue, null, 2);
|
||||
}
|
||||
|
|
@ -191,6 +205,13 @@ class DynamicAutocompleteInput extends Component<Props> {
|
|||
this.editor.setValue(inputValue);
|
||||
this.editor.setCursor(cursor);
|
||||
}
|
||||
// Update the dynamic bindings for autocomplete
|
||||
if (prevProps.dynamicData !== this.props.dynamicData) {
|
||||
this.editor.setOption("hintOptions", {
|
||||
completeSingle: false,
|
||||
globalScope: this.props.dynamicData,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +274,7 @@ class DynamicAutocompleteInput extends Component<Props> {
|
|||
const hasError = !!(meta && meta.error);
|
||||
let showError = false;
|
||||
if (this.editor) {
|
||||
showError = hasError && this.editor.hasFocus();
|
||||
showError = hasError && this.state.isFocused;
|
||||
}
|
||||
return (
|
||||
<ErrorTooltip message={meta ? meta.error : ""} isOpen={showError}>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
type Props = {};
|
||||
type State = { hasError: boolean };
|
||||
|
||||
const RetryLink = styled.span`
|
||||
color: ${props => props.theme.colors.primaryDarkest};
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
class ErrorBoundary extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
|
@ -20,8 +26,15 @@ class ErrorBoundary extends React.Component<Props, State> {
|
|||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
// You can render any custom fallback UI
|
||||
return <p>Oops, Something went wrong.</p>;
|
||||
return (
|
||||
<p>
|
||||
Oops, Something went wrong.
|
||||
<br />
|
||||
<RetryLink onClick={() => this.setState({ hasError: false })}>
|
||||
Click here to retry
|
||||
</RetryLink>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
rows: 1,
|
||||
columns: 8,
|
||||
widgetName: "Input",
|
||||
text: "",
|
||||
},
|
||||
SWITCH_WIDGET: {
|
||||
isOn: false,
|
||||
|
|
@ -115,6 +116,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
{ id: "3", label: "Option 3", value: "3" },
|
||||
],
|
||||
widgetName: "Dropdown",
|
||||
selectedIndex: 0,
|
||||
},
|
||||
CHECKBOX_WIDGET: {
|
||||
rows: 1,
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ const ApiEditorForm: React.FC<Props> = (props: Props) => {
|
|||
<FormRow>
|
||||
<TextField
|
||||
name="name"
|
||||
placeholder="API name (camel case)"
|
||||
placeholder="nameOfApi (camel case)"
|
||||
showError
|
||||
/>
|
||||
<ActionButtons>
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class ApiSidebar extends React.Component<Props> {
|
|||
.map(a => a.name);
|
||||
let name = action.name;
|
||||
if (pageApiNames.indexOf(action.name) > -1) {
|
||||
name = getNextEntityName(`${name}-`, pageApiNames);
|
||||
name = getNextEntityName(name, pageApiNames);
|
||||
}
|
||||
this.props.moveAction(itemId, destinationPageId, name, action.pageId);
|
||||
};
|
||||
|
|
@ -124,7 +124,7 @@ class ApiSidebar extends React.Component<Props> {
|
|||
.map(a => a.name);
|
||||
let name = `${action.name}Copy`;
|
||||
if (pageApiNames.indexOf(name) > -1) {
|
||||
name = getNextEntityName(`${name}`, pageApiNames);
|
||||
name = getNextEntityName(name, pageApiNames);
|
||||
}
|
||||
this.props.copyAction(itemId, destinationPageId, name);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,29 +60,34 @@ const PageName = styled.h5<{ isMain: boolean }>`
|
|||
width: 100%;
|
||||
height: 20px;
|
||||
padding-left: 5px;
|
||||
font-size: 13px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
border-right: 4px solid;
|
||||
margin: 10px 0;
|
||||
border-color: ${props =>
|
||||
props.isMain ? props.theme.colors.primary : "transparent"};
|
||||
`;
|
||||
|
||||
const PageDropContainer = styled.div<{ isActive: boolean }>`
|
||||
const PageDropContainer = styled.div`
|
||||
min-height: 32px;
|
||||
margin: 5px;
|
||||
background-color: ${props =>
|
||||
props.isActive ? props.theme.colors.paneCard : props.theme.colors.paneBG};
|
||||
background-color: ${props => props.theme.colors.paneBG};
|
||||
`;
|
||||
|
||||
const ItemsWrapper = styled.div`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const ItemRenderContainer = styled.div`
|
||||
flex: 1;
|
||||
const NoItemMessage = styled.span`
|
||||
color: #cacaca;
|
||||
padding-left: 12px;
|
||||
`;
|
||||
|
||||
const ItemContainer = styled.div<{ isSelected: boolean }>`
|
||||
const ItemContainer = styled.div<{
|
||||
isSelected: boolean;
|
||||
isDraggingOver: boolean;
|
||||
isBeingDragged: boolean;
|
||||
}>`
|
||||
height: 32px;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
|
|
@ -94,9 +99,14 @@ const ItemContainer = styled.div<{ isSelected: boolean }>`
|
|||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: ${props =>
|
||||
props.isSelected ? props.theme.colors.paneCard : props.theme.colors.paneBG}
|
||||
props.isSelected || props.isBeingDragged
|
||||
? props.theme.colors.paneCard
|
||||
: props.theme.colors.paneBG}
|
||||
:hover {
|
||||
background-color: ${props => props.theme.colors.paneCard};
|
||||
background-color: ${props =>
|
||||
props.isDraggingOver
|
||||
? props.theme.colors.paneBG
|
||||
: props.theme.colors.paneCard};
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
@ -299,98 +309,106 @@ class EditorSidebar extends React.Component<Props, State> {
|
|||
<PageDropContainer
|
||||
ref={provided.innerRef}
|
||||
{...provided.droppableProps}
|
||||
isActive={snapshot.isDraggingOver}
|
||||
>
|
||||
{provided.placeholder}
|
||||
<div
|
||||
style={{
|
||||
opacity: snapshot.isDraggingOver ? 0 : 1,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
{page.items.length === 0 && (
|
||||
<NoItemMessage>
|
||||
{"No item on this page yet"}
|
||||
</NoItemMessage>
|
||||
)}
|
||||
{page.items.map((item: Item, index) => (
|
||||
<ItemContainer
|
||||
<Draggable
|
||||
key={item.id}
|
||||
isSelected={item.id === selectedItemId}
|
||||
draggableId={item.id}
|
||||
index={index}
|
||||
>
|
||||
<Draggable
|
||||
draggableId={item.id}
|
||||
index={index}
|
||||
>
|
||||
{provided => (
|
||||
<ItemRenderContainer
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
onClick={() =>
|
||||
this.handleItemSelect(item.id)
|
||||
}
|
||||
>
|
||||
{itemRender(item)}
|
||||
</ItemRenderContainer>
|
||||
)}
|
||||
</Draggable>
|
||||
{this.state.itemDragging !== item.id && (
|
||||
<React.Fragment>
|
||||
<DraftIconIndicator
|
||||
isHidden={
|
||||
draftIds.indexOf(item.id) === -1
|
||||
}
|
||||
/>
|
||||
<ContextDropdown
|
||||
options={[
|
||||
{
|
||||
id: "copy",
|
||||
value: "copy",
|
||||
onSelect: () => null,
|
||||
label: "Copy to",
|
||||
children: pageWiseList.map(p => ({
|
||||
label: p.name,
|
||||
id: p.id,
|
||||
value: p.name,
|
||||
onSelect: () =>
|
||||
this.props.copyItem(
|
||||
item.id,
|
||||
p.id,
|
||||
{provided => (
|
||||
<ItemContainer
|
||||
isSelected={item.id === selectedItemId}
|
||||
isDraggingOver={snapshot.isDraggingOver}
|
||||
isBeingDragged={
|
||||
this.state.itemDragging === item.id
|
||||
}
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
onClick={() =>
|
||||
this.handleItemSelect(item.id)
|
||||
}
|
||||
>
|
||||
{itemRender(item)}
|
||||
{this.state.itemDragging !==
|
||||
item.id && (
|
||||
<React.Fragment>
|
||||
<DraftIconIndicator
|
||||
isHidden={
|
||||
draftIds.indexOf(item.id) === -1
|
||||
}
|
||||
/>
|
||||
<ContextDropdown
|
||||
options={[
|
||||
{
|
||||
id: "copy",
|
||||
value: "copy",
|
||||
onSelect: () => null,
|
||||
label: "Copy to",
|
||||
children: pageWiseList.map(
|
||||
p => ({
|
||||
label: p.name,
|
||||
id: p.id,
|
||||
value: p.name,
|
||||
onSelect: () =>
|
||||
this.props.copyItem(
|
||||
item.id,
|
||||
p.id,
|
||||
),
|
||||
}),
|
||||
),
|
||||
})),
|
||||
},
|
||||
{
|
||||
id: "move",
|
||||
value: "move",
|
||||
onSelect: () => null,
|
||||
label: "Move to",
|
||||
children: pageWiseList
|
||||
.filter(p => p.id !== page.id)
|
||||
.map(p => ({
|
||||
label: p.name,
|
||||
id: p.id,
|
||||
value: p.name,
|
||||
},
|
||||
{
|
||||
id: "move",
|
||||
value: "move",
|
||||
onSelect: () => null,
|
||||
label: "Move to",
|
||||
children: pageWiseList
|
||||
.filter(
|
||||
p => p.id !== page.id,
|
||||
)
|
||||
.map(p => ({
|
||||
label: p.name,
|
||||
id: p.id,
|
||||
value: p.name,
|
||||
onSelect: () =>
|
||||
this.props.moveItem(
|
||||
item.id,
|
||||
p.id,
|
||||
),
|
||||
})),
|
||||
},
|
||||
{
|
||||
id: "delete",
|
||||
value: "delete",
|
||||
onSelect: () =>
|
||||
this.props.moveItem(
|
||||
this.props.deleteItem(
|
||||
item.id,
|
||||
p.id,
|
||||
),
|
||||
})),
|
||||
},
|
||||
{
|
||||
id: "delete",
|
||||
value: "delete",
|
||||
onSelect: () =>
|
||||
this.props.deleteItem(item.id),
|
||||
label: "Delete",
|
||||
intent: "danger",
|
||||
},
|
||||
]}
|
||||
toggle={{
|
||||
type: "icon",
|
||||
icon: "MORE_HORIZONTAL_CONTROL",
|
||||
iconSize: theme.fontSizes[4],
|
||||
}}
|
||||
className="more"
|
||||
/>
|
||||
</React.Fragment>
|
||||
label: "Delete",
|
||||
intent: "danger",
|
||||
},
|
||||
]}
|
||||
toggle={{
|
||||
type: "icon",
|
||||
icon: "MORE_HORIZONTAL_CONTROL",
|
||||
iconSize: theme.fontSizes[4],
|
||||
}}
|
||||
className="more"
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</ItemContainer>
|
||||
)}
|
||||
</ItemContainer>
|
||||
</Draggable>
|
||||
))}
|
||||
</div>
|
||||
</PageDropContainer>
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ const Wrapper = styled.div<{ isVisible: boolean; showOnlySidebar?: boolean }>`
|
|||
background-color: ${props =>
|
||||
props.isVisible ? "rgba(0, 0, 0, 0.26)" : "transparent"};
|
||||
z-index: ${props => (props.isVisible ? 2 : -1)};
|
||||
transition-property: z-index;
|
||||
transition-delay: ${props => (props.isVisible ? "0" : "0.25s")};
|
||||
`;
|
||||
|
||||
const DrawerWrapper = styled.div<{
|
||||
|
|
@ -37,7 +35,6 @@ const DrawerWrapper = styled.div<{
|
|||
width: ${props => (props.showOnlySidebar ? "0px" : "75%")};
|
||||
height: 100%;
|
||||
box-shadow: -1px 2px 3px 0px ${props => props.theme.colors.paneBG};
|
||||
transition: 0.25s;
|
||||
`;
|
||||
|
||||
interface RouterState {
|
||||
|
|
|
|||
|
|
@ -105,6 +105,18 @@ const actionsReducer = createReducer(initialState, {
|
|||
return restAction;
|
||||
}),
|
||||
}),
|
||||
[ReduxActionTypes.MOVE_ACTION_SUCCESS]: (
|
||||
state: ActionDataState,
|
||||
action: ReduxAction<RestAction>,
|
||||
) => ({
|
||||
...state,
|
||||
data: state.data.map(restAction => {
|
||||
if (restAction.id === action.payload.id) {
|
||||
return action.payload;
|
||||
}
|
||||
return restAction;
|
||||
}),
|
||||
}),
|
||||
[ReduxActionErrorTypes.MOVE_ACTION_ERROR]: (
|
||||
state: ActionDataState,
|
||||
action: ReduxAction<{ id: string; originalPageId: string }>,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { createReducer } from "utils/AppsmithUtils";
|
||||
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { Datasource } from "api/DatasourcesApi";
|
||||
|
||||
export interface DatasourceDataState {
|
||||
|
|
@ -39,6 +43,14 @@ const datasourceReducer = createReducer(initialState, {
|
|||
list: state.list.concat(action.payload),
|
||||
};
|
||||
},
|
||||
[ReduxActionErrorTypes.CREATE_DATASOURCE_ERROR]: (
|
||||
state: DatasourceDataState,
|
||||
) => {
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default datasourceReducer;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import {
|
|||
getDynamicBindings,
|
||||
getDynamicValue,
|
||||
isDynamicValue,
|
||||
removeBindingsFromObject,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
import { getDataTree } from "selectors/entitiesSelector";
|
||||
|
|
@ -418,9 +419,13 @@ function* moveActionSaga(
|
|||
const actionObject: RestAction = dirty
|
||||
? drafts[action.payload.id]
|
||||
: yield select(getAction, action.payload.id);
|
||||
const withoutBindings = removeBindingsFromObject(actionObject);
|
||||
try {
|
||||
const response = yield ActionAPI.moveAction({
|
||||
action: { ...actionObject, name: action.payload.name },
|
||||
action: {
|
||||
...withoutBindings,
|
||||
name: action.payload.name,
|
||||
},
|
||||
destinationPageId: action.payload.destinationPageId,
|
||||
});
|
||||
|
||||
|
|
@ -431,7 +436,7 @@ function* moveActionSaga(
|
|||
intent: Intent.SUCCESS,
|
||||
});
|
||||
}
|
||||
yield put(moveActionSuccess(action.payload));
|
||||
yield put(moveActionSuccess(response.data));
|
||||
} catch (e) {
|
||||
AppToaster.show({
|
||||
message: `Error while moving action ${actionObject.name}`,
|
||||
|
|
@ -451,9 +456,12 @@ function* copyActionSaga(
|
|||
) {
|
||||
const drafts = yield select(state => state.ui.apiPane.drafts);
|
||||
const dirty = action.payload.id in drafts;
|
||||
const actionObject = dirty
|
||||
let actionObject = dirty
|
||||
? drafts[action.payload.id]
|
||||
: yield select(getAction, action.payload.id);
|
||||
if (action.payload.destinationPageId !== actionObject.pageId) {
|
||||
actionObject = removeBindingsFromObject(actionObject);
|
||||
}
|
||||
try {
|
||||
const copyAction = {
|
||||
...(_.omit(actionObject, "id") as RestAction),
|
||||
|
|
|
|||
|
|
@ -238,6 +238,18 @@ function* handleActionDeletedSaga(actionPayload: ReduxAction<{ id: string }>) {
|
|||
});
|
||||
}
|
||||
|
||||
function* handleMoveOrCopySaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||
const { id } = actionPayload.payload;
|
||||
const action = yield select(getAction, id);
|
||||
const { values }: { values: RestAction } = yield select(
|
||||
getFormData,
|
||||
API_EDITOR_FORM_NAME,
|
||||
);
|
||||
if (values.id === id) {
|
||||
yield put(initialize(API_EDITOR_FORM_NAME, action));
|
||||
}
|
||||
}
|
||||
|
||||
export default function* root() {
|
||||
yield all([
|
||||
takeEvery(ReduxActionTypes.INIT_API_PANE, initApiPaneSaga),
|
||||
|
|
@ -245,6 +257,8 @@ export default function* root() {
|
|||
takeEvery(ReduxActionTypes.CREATE_ACTION_SUCCESS, handleActionCreatedSaga),
|
||||
takeEvery(ReduxActionTypes.UPDATE_ACTION_SUCCESS, handleActionUpdatedSaga),
|
||||
takeEvery(ReduxActionTypes.DELETE_ACTION_SUCCESS, handleActionDeletedSaga),
|
||||
takeEvery(ReduxActionTypes.MOVE_ACTION_SUCCESS, handleMoveOrCopySaga),
|
||||
takeEvery(ReduxActionTypes.COPY_ACTION_SUCCESS, handleMoveOrCopySaga),
|
||||
// Intercepting the redux-form change actionType
|
||||
takeEvery(ReduxFormActionTypes.VALUE_CHANGE, formValueChangeSaga),
|
||||
takeEvery(ReduxFormActionTypes.ARRAY_REMOVE, formValueChangeSaga),
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ function* createDatasourceSaga(
|
|||
const response: GenericApiResponse<Datasource> = yield DatasourcesApi.createDatasource(
|
||||
actionPayload.payload,
|
||||
);
|
||||
if (response.responseMeta.success) {
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.CREATE_DATASOURCE_SUCCESS,
|
||||
payload: response.data,
|
||||
|
|
@ -49,7 +50,7 @@ function* createDatasourceSaga(
|
|||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.CREATE_DATASOURCE_ERROR,
|
||||
type: ReduxActionErrorTypes.CREATE_DATASOURCE_ERROR,
|
||||
payload: { error },
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ import unescapeJS from "unescape-js";
|
|||
import { NameBindingsWithData } from "selectors/nameBindingsWithDataSelector";
|
||||
import toposort from "toposort";
|
||||
|
||||
export const removeBindingsFromObject = (obj: object) => {
|
||||
const string = JSON.stringify(obj);
|
||||
const withBindings = string.replace(DATA_BIND_REGEX, "{{ }}");
|
||||
return JSON.parse(withBindings);
|
||||
};
|
||||
|
||||
export const isDynamicValue = (value: string): boolean =>
|
||||
DATA_BIND_REGEX.test(value);
|
||||
|
||||
|
|
@ -267,7 +273,7 @@ export function dependencySortedEvaluateDataTree(
|
|||
dependencyTree: Array<[string, string]>,
|
||||
parseValues: boolean,
|
||||
) {
|
||||
const tree = JSON.parse(JSON.stringify(dataTree));
|
||||
const tree = _.cloneDeep(dataTree);
|
||||
try {
|
||||
// sort dependencies
|
||||
const sortedDependencies = toposort(dependencyTree).reverse();
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ abstract class BaseWidget<
|
|||
this.props.widgetId === "0"
|
||||
}
|
||||
>
|
||||
{this.getPageView()}
|
||||
<ErrorBoundary>{this.getPageView()}</ErrorBoundary>
|
||||
</PositionedContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
return {
|
||||
placeholderText: VALIDATION_TYPES.TEXT,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
options: VALIDATION_TYPES.ARRAY,
|
||||
options: VALIDATION_TYPES.TABLE_DATA,
|
||||
selectionType: VALIDATION_TYPES.TEXT,
|
||||
selectedIndex: VALIDATION_TYPES.NUMBER,
|
||||
selectedIndexArr: VALIDATION_TYPES.ARRAY,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user