2024-05-16 13:11:30 +00:00
|
|
|
import React, { Component } from "react";
|
2024-08-06 14:52:22 +00:00
|
|
|
import type { AppState } from "ee/reducers";
|
2024-05-16 13:11:30 +00:00
|
|
|
import { connect } from "react-redux";
|
|
|
|
|
import type { Placement } from "popper.js";
|
|
|
|
|
import * as Sentry from "@sentry/react";
|
|
|
|
|
import _, { toString } from "lodash";
|
|
|
|
|
import type { ControlProps } from "./BaseControl";
|
|
|
|
|
import BaseControl from "./BaseControl";
|
|
|
|
|
import styled from "styled-components";
|
|
|
|
|
import type { Indices } from "constants/Layers";
|
|
|
|
|
import EvaluatedValuePopup from "components/editorComponents/CodeEditor/EvaluatedValuePopup";
|
|
|
|
|
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
|
|
|
|
|
import type { CodeEditorExpected } from "components/editorComponents/CodeEditor";
|
|
|
|
|
import type { ColumnProperties } from "widgets/TableWidgetV2/component/Constants";
|
|
|
|
|
import { StickyType } from "widgets/TableWidgetV2/component/Constants";
|
|
|
|
|
import {
|
|
|
|
|
itemHeight,
|
|
|
|
|
noOfItemsToDisplay,
|
|
|
|
|
extraSpace,
|
|
|
|
|
} from "widgets/TableWidgetV2/component/Constants";
|
|
|
|
|
import {
|
|
|
|
|
createColumn,
|
|
|
|
|
isColumnTypeEditable,
|
|
|
|
|
reorderColumns,
|
|
|
|
|
} from "widgets/TableWidgetV2/widget/utilities";
|
|
|
|
|
import type { DataTree } from "entities/DataTree/dataTreeTypes";
|
|
|
|
|
import {
|
|
|
|
|
getDataTreeForAutocomplete,
|
|
|
|
|
getPathEvalErrors,
|
|
|
|
|
} from "selectors/dataTreeSelectors";
|
|
|
|
|
import type { EvaluationError } from "utils/DynamicBindingUtils";
|
|
|
|
|
import { isDynamicValue } from "utils/DynamicBindingUtils";
|
|
|
|
|
import { DraggableListCard } from "components/propertyControls/DraggableListCard";
|
|
|
|
|
import { ColumnTypes } from "widgets/TableWidgetV2/constants";
|
|
|
|
|
import { DraggableListControl } from "pages/Editor/PropertyPane/DraggableListControl";
|
|
|
|
|
|
|
|
|
|
const EmptyStateLabel = styled.div`
|
|
|
|
|
margin: 20px 0px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
color: var(--ads-v2-color-fg);
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
interface ReduxStateProps {
|
|
|
|
|
dynamicData: DataTree;
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2024-05-16 13:11:30 +00:00
|
|
|
datasources: any;
|
|
|
|
|
errors: EvaluationError[];
|
|
|
|
|
}
|
|
|
|
|
interface EvaluatedValueProps {
|
|
|
|
|
isFocused: boolean;
|
|
|
|
|
theme: EditorTheme;
|
|
|
|
|
popperPlacement?: Placement;
|
|
|
|
|
popperZIndex?: Indices;
|
|
|
|
|
dataTreePath?: string;
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2024-05-16 13:11:30 +00:00
|
|
|
evaluatedValue?: any;
|
|
|
|
|
expected?: CodeEditorExpected;
|
|
|
|
|
hideEvaluatedValue?: boolean;
|
|
|
|
|
useValidationMessage?: boolean;
|
|
|
|
|
children: JSX.Element;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type EvaluatedValuePopupWrapperProps = ReduxStateProps & EvaluatedValueProps;
|
|
|
|
|
|
|
|
|
|
type ColumnsType = Record<string, ColumnProperties>;
|
|
|
|
|
|
|
|
|
|
const getOriginalColumn = (
|
|
|
|
|
columns: ColumnsType,
|
|
|
|
|
index: number,
|
|
|
|
|
columnOrder?: string[],
|
|
|
|
|
): ColumnProperties | undefined => {
|
|
|
|
|
const reorderedColumns = reorderColumns(columns, columnOrder || []);
|
|
|
|
|
const column: ColumnProperties | undefined = Object.values(
|
|
|
|
|
reorderedColumns,
|
|
|
|
|
).find((column: ColumnProperties) => column.index === index);
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
return column;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const fixedHeight = itemHeight * noOfItemsToDisplay + extraSpace;
|
|
|
|
|
|
|
|
|
|
interface State {
|
|
|
|
|
focusedIndex: number | null;
|
|
|
|
|
duplicateColumnIds: string[];
|
|
|
|
|
hasScrollableList: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const LIST_CLASSNAME = "tablewidget-wds-primarycolumn-list";
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
class PrimaryColumnsControlWDS extends BaseControl<ControlProps, State> {
|
|
|
|
|
constructor(props: ControlProps) {
|
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
|
|
const columns: ColumnsType = props.propertyValue || {};
|
|
|
|
|
const columnOrder = Object.keys(columns);
|
|
|
|
|
const reorderedColumns = reorderColumns(columns, columnOrder);
|
|
|
|
|
const tableColumnLabels = _.map(reorderedColumns, "label");
|
|
|
|
|
const duplicateColumnIds = [];
|
|
|
|
|
|
|
|
|
|
for (let index = 0; index < tableColumnLabels.length; index++) {
|
|
|
|
|
const currLabel = tableColumnLabels[index] as string;
|
|
|
|
|
const duplicateValueIndex = tableColumnLabels.indexOf(currLabel);
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
if (duplicateValueIndex !== index) {
|
|
|
|
|
// get column id from columnOrder index
|
|
|
|
|
duplicateColumnIds.push(reorderedColumns[columnOrder[index]].id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
focusedIndex: null,
|
|
|
|
|
duplicateColumnIds,
|
|
|
|
|
hasScrollableList: false,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount(): void {
|
|
|
|
|
this.setHasScrollableList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidUpdate(prevProps: ControlProps): void {
|
|
|
|
|
/**
|
|
|
|
|
* On adding a new column the last column should get focused.
|
|
|
|
|
* If frozen columns are present then the focus should be on the newly added column
|
|
|
|
|
*/
|
|
|
|
|
if (
|
|
|
|
|
Object.keys(prevProps.propertyValue).length + 1 ===
|
|
|
|
|
Object.keys(this.props.propertyValue).length
|
|
|
|
|
) {
|
|
|
|
|
const columns = Object.keys(this.props.propertyValue);
|
|
|
|
|
|
|
|
|
|
const frozenColumnIndex = Object.keys(prevProps.propertyValue)
|
|
|
|
|
.map((column) => prevProps.propertyValue[column])
|
|
|
|
|
.filter((column) => column.sticky !== StickyType.RIGHT).length;
|
|
|
|
|
|
|
|
|
|
this.updateFocus(
|
|
|
|
|
frozenColumnIndex === 0 ? columns.length - 1 : frozenColumnIndex,
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setHasScrollableList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
// Get columns from widget properties
|
|
|
|
|
const columns: ColumnsType = this.props.propertyValue || {};
|
|
|
|
|
|
|
|
|
|
// If there are no columns, show empty state
|
|
|
|
|
if (Object.keys(columns).length === 0) {
|
|
|
|
|
return <EmptyStateLabel>Table columns will appear here</EmptyStateLabel>;
|
|
|
|
|
}
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
// Get an empty array of length of columns
|
|
|
|
|
let columnOrder: string[] = new Array(Object.keys(columns).length);
|
|
|
|
|
|
|
|
|
|
if (this.props.widgetProperties.columnOrder) {
|
|
|
|
|
columnOrder = this.props.widgetProperties.columnOrder;
|
|
|
|
|
} else {
|
|
|
|
|
columnOrder = Object.keys(columns);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const reorderedColumns = reorderColumns(columns, columnOrder);
|
|
|
|
|
|
|
|
|
|
const draggableComponentColumns = Object.values(reorderedColumns).map(
|
|
|
|
|
(column: ColumnProperties) => {
|
|
|
|
|
return {
|
|
|
|
|
label: column.label || "",
|
|
|
|
|
id: column.id,
|
|
|
|
|
isVisible: column.isVisible,
|
|
|
|
|
isDerived:
|
|
|
|
|
column.isDerived && column.columnType !== ColumnTypes.EDIT_ACTIONS,
|
|
|
|
|
index: column.index,
|
|
|
|
|
isDuplicateLabel: _.includes(
|
|
|
|
|
this.state.duplicateColumnIds,
|
|
|
|
|
column.id,
|
|
|
|
|
),
|
|
|
|
|
isChecked:
|
|
|
|
|
isColumnTypeEditable(column.columnType) && column.isEditable,
|
|
|
|
|
isCheckboxDisabled:
|
|
|
|
|
!isColumnTypeEditable(column.columnType) || column.isDerived,
|
|
|
|
|
isDragDisabled:
|
|
|
|
|
column.sticky === StickyType.LEFT ||
|
|
|
|
|
column.sticky === StickyType.RIGHT,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const column: ColumnProperties | undefined = Object.values(
|
|
|
|
|
reorderedColumns,
|
|
|
|
|
).find(
|
|
|
|
|
(column: ColumnProperties) => column.index === this.state.focusedIndex,
|
|
|
|
|
);
|
|
|
|
|
// show popup on duplicate column label input focused
|
|
|
|
|
const isFocused =
|
|
|
|
|
!_.isNull(this.state.focusedIndex) &&
|
|
|
|
|
_.includes(this.state.duplicateColumnIds, column?.id);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div className="flex pt-2 pb-2 justify-between">
|
|
|
|
|
<div>{Object.values(reorderedColumns).length} columns</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col w-full gap-1">
|
|
|
|
|
<EvaluatedValuePopupWrapper {...this.props} isFocused={isFocused}>
|
|
|
|
|
<DraggableListControl
|
|
|
|
|
className={LIST_CLASSNAME}
|
|
|
|
|
deleteOption={this.deleteOption}
|
|
|
|
|
fixedHeight={fixedHeight}
|
|
|
|
|
focusedIndex={this.state.focusedIndex}
|
|
|
|
|
itemHeight={itemHeight}
|
|
|
|
|
items={draggableComponentColumns}
|
|
|
|
|
keyAccessor="id"
|
|
|
|
|
onEdit={this.onEdit}
|
|
|
|
|
propertyPath={this.props.dataTreePath}
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2024-05-16 13:11:30 +00:00
|
|
|
renderComponent={(props: any) =>
|
|
|
|
|
DraggableListCard({
|
|
|
|
|
...props,
|
|
|
|
|
showCheckbox: false,
|
|
|
|
|
placeholder: "Column title",
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
toggleCheckbox={this.toggleCheckbox}
|
|
|
|
|
toggleVisibility={undefined}
|
|
|
|
|
updateFocus={this.updateFocus}
|
|
|
|
|
updateItems={this.updateItems}
|
|
|
|
|
updateOption={this.updateOption}
|
|
|
|
|
/>
|
|
|
|
|
</EvaluatedValuePopupWrapper>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addNewColumn = () => {
|
|
|
|
|
const column = createColumn(this.props.widgetProperties, "customColumn");
|
|
|
|
|
|
|
|
|
|
this.updateProperty(`${this.props.propertyName}.${column.id}`, column);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setHasScrollableList = () => {
|
|
|
|
|
const listElement = document.querySelector(`.${LIST_CLASSNAME}`);
|
|
|
|
|
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
const hasScrollableList =
|
|
|
|
|
listElement && listElement?.scrollHeight > listElement?.clientHeight;
|
|
|
|
|
|
|
|
|
|
if (hasScrollableList !== this.state.hasScrollableList) {
|
|
|
|
|
this.setState({
|
|
|
|
|
hasScrollableList: !!hasScrollableList,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onEdit = (index: number) => {
|
|
|
|
|
const columns: ColumnsType = this.props.propertyValue || {};
|
|
|
|
|
|
|
|
|
|
const originalColumn = getOriginalColumn(
|
|
|
|
|
columns,
|
|
|
|
|
index,
|
|
|
|
|
this.props.widgetProperties.columnOrder,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.props.openNextPanel({
|
|
|
|
|
...originalColumn,
|
|
|
|
|
propPaneId: this.props.widgetProperties.widgetId,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
//Used to reorder columns
|
|
|
|
|
updateItems = (items: Array<Record<string, unknown>>) => {
|
|
|
|
|
this.updateProperty(
|
|
|
|
|
"columnOrder",
|
|
|
|
|
items.map(({ id }) => id),
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
toggleVisibility = (index: number) => {
|
|
|
|
|
const columns: ColumnsType = this.props.propertyValue || {};
|
|
|
|
|
const originalColumn = getOriginalColumn(
|
|
|
|
|
columns,
|
|
|
|
|
index,
|
|
|
|
|
this.props.widgetProperties.columnOrder,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (originalColumn) {
|
|
|
|
|
this.updateProperty(
|
|
|
|
|
`${this.props.propertyName}.${originalColumn.id}.isVisible`,
|
|
|
|
|
!originalColumn.isVisible,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getToggleColumnEditablityUpdates = (
|
|
|
|
|
column: ColumnProperties,
|
|
|
|
|
propertyName: string,
|
|
|
|
|
checked: boolean,
|
|
|
|
|
): {
|
|
|
|
|
propertyName: string;
|
|
|
|
|
propertyValue: string;
|
|
|
|
|
}[] => {
|
|
|
|
|
const updates: {
|
|
|
|
|
propertyName: string;
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2024-05-16 13:11:30 +00:00
|
|
|
propertyValue: any;
|
|
|
|
|
}[] = [];
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
updates.push({
|
|
|
|
|
propertyName: `${propertyName}.${column.id}.isEditable`,
|
|
|
|
|
propertyValue: checked,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check whether isCellEditable property of the column has dynamic value
|
|
|
|
|
* if not, toggle isCellEditable value as well. We're doing this to smooth
|
|
|
|
|
* the user experience.
|
|
|
|
|
*/
|
|
|
|
|
if (!isDynamicValue(toString(column.isCellEditable))) {
|
|
|
|
|
updates.push({
|
|
|
|
|
propertyName: `${propertyName}.${column.id}.isCellEditable`,
|
|
|
|
|
propertyValue: checked,
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
return updates;
|
|
|
|
|
};
|
|
|
|
|
toggleCheckbox = (index: number, checked: boolean) => {
|
|
|
|
|
const columns: ColumnsType = this.props.propertyValue || {};
|
|
|
|
|
const originalColumn = getOriginalColumn(
|
|
|
|
|
columns,
|
|
|
|
|
index,
|
|
|
|
|
this.props.widgetProperties.columnOrder,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (originalColumn) {
|
|
|
|
|
this.batchUpdatePropertiesWithAssociatedUpdates(
|
|
|
|
|
this.getToggleColumnEditablityUpdates(
|
|
|
|
|
originalColumn,
|
|
|
|
|
this.props.propertyName,
|
|
|
|
|
checked,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
deleteOption = (index: number) => {
|
|
|
|
|
const columns: ColumnsType = this.props.propertyValue || {};
|
|
|
|
|
const columnOrder = this.props.widgetProperties.columnOrder || [];
|
|
|
|
|
|
|
|
|
|
const originalColumn = getOriginalColumn(columns, index, columnOrder);
|
|
|
|
|
|
|
|
|
|
if (originalColumn) {
|
|
|
|
|
const propertiesToDelete = [
|
|
|
|
|
`${this.props.propertyName}.${originalColumn.id}`,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const columnOrderIndex = columnOrder.findIndex(
|
|
|
|
|
(column: string) => column === originalColumn.id,
|
|
|
|
|
);
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
if (columnOrderIndex > -1)
|
|
|
|
|
propertiesToDelete.push(`columnOrder[${columnOrderIndex}]`);
|
|
|
|
|
|
|
|
|
|
this.deleteProperties(propertiesToDelete);
|
|
|
|
|
// if column deleted, clean up duplicateIndexes
|
|
|
|
|
let duplicateColumnIds = [...this.state.duplicateColumnIds];
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
duplicateColumnIds = duplicateColumnIds.filter(
|
|
|
|
|
(id) => id !== originalColumn.id,
|
|
|
|
|
);
|
|
|
|
|
this.setState({ duplicateColumnIds });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateOption = (index: number, updatedLabel: string) => {
|
|
|
|
|
const columns: ColumnsType = this.props.propertyValue || {};
|
|
|
|
|
const originalColumn = getOriginalColumn(
|
|
|
|
|
columns,
|
|
|
|
|
index,
|
|
|
|
|
this.props.widgetProperties.columnOrder,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (originalColumn) {
|
|
|
|
|
this.updateProperty(
|
|
|
|
|
`${this.props.propertyName}.${originalColumn.id}.label`,
|
|
|
|
|
updatedLabel,
|
|
|
|
|
);
|
|
|
|
|
// check entered label is unique or duplicate
|
|
|
|
|
const tableColumnLabels = _.map(columns, "label");
|
|
|
|
|
let duplicateColumnIds = [...this.state.duplicateColumnIds];
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
// if duplicate, add into array
|
|
|
|
|
if (_.includes(tableColumnLabels, updatedLabel)) {
|
|
|
|
|
duplicateColumnIds.push(originalColumn.id);
|
|
|
|
|
this.setState({ duplicateColumnIds });
|
|
|
|
|
} else {
|
|
|
|
|
duplicateColumnIds = duplicateColumnIds.filter(
|
|
|
|
|
(id) => id !== originalColumn.id,
|
|
|
|
|
);
|
|
|
|
|
this.setState({ duplicateColumnIds });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateFocus = (index: number, isFocused: boolean) => {
|
|
|
|
|
this.setState({ focusedIndex: isFocused ? index : null });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static getControlType() {
|
|
|
|
|
return "PRIMARY_COLUMNS_WDS";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default PrimaryColumnsControlWDS;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wrapper component on dragable primary columns
|
|
|
|
|
* render popup if primary column labels are not unique
|
|
|
|
|
* show unique name error in PRIMARY_COLUMNS
|
|
|
|
|
*/
|
|
|
|
|
class EvaluatedValuePopupWrapperClass extends Component<EvaluatedValuePopupWrapperProps> {
|
|
|
|
|
getPropertyValidation = (
|
|
|
|
|
dataTree: DataTree,
|
|
|
|
|
dataTreePath?: string,
|
|
|
|
|
): {
|
|
|
|
|
isInvalid: boolean;
|
|
|
|
|
errors: EvaluationError[];
|
|
|
|
|
pathEvaluatedValue: unknown;
|
|
|
|
|
} => {
|
|
|
|
|
const { errors } = this.props;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
if (!dataTreePath) {
|
|
|
|
|
return {
|
|
|
|
|
isInvalid: false,
|
|
|
|
|
errors: [],
|
|
|
|
|
pathEvaluatedValue: undefined,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const pathEvaluatedValue = _.get(dataTree, dataTreePath);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
isInvalid: errors.length > 0,
|
|
|
|
|
errors: errors,
|
|
|
|
|
pathEvaluatedValue,
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
render = () => {
|
|
|
|
|
const {
|
|
|
|
|
dataTreePath,
|
|
|
|
|
dynamicData,
|
|
|
|
|
evaluatedValue,
|
|
|
|
|
expected,
|
|
|
|
|
hideEvaluatedValue,
|
|
|
|
|
useValidationMessage,
|
|
|
|
|
} = this.props;
|
|
|
|
|
const { errors, isInvalid, pathEvaluatedValue } =
|
|
|
|
|
this.getPropertyValidation(dynamicData, dataTreePath);
|
|
|
|
|
let evaluated = evaluatedValue;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2024-05-16 13:11:30 +00:00
|
|
|
if (dataTreePath) {
|
|
|
|
|
evaluated = pathEvaluatedValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<EvaluatedValuePopup
|
|
|
|
|
errors={errors}
|
|
|
|
|
evaluatedValue={evaluated}
|
|
|
|
|
expected={expected}
|
|
|
|
|
hasError={isInvalid}
|
|
|
|
|
hideEvaluatedValue={hideEvaluatedValue}
|
|
|
|
|
isOpen={this.props.isFocused && isInvalid}
|
|
|
|
|
popperPlacement={this.props.popperPlacement}
|
|
|
|
|
popperZIndex={this.props.popperZIndex}
|
|
|
|
|
theme={this.props.theme || EditorTheme.LIGHT}
|
|
|
|
|
useValidationMessage={useValidationMessage}
|
|
|
|
|
>
|
|
|
|
|
{this.props.children}
|
|
|
|
|
</EvaluatedValuePopup>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const mapStateToProps = (
|
|
|
|
|
state: AppState,
|
|
|
|
|
{ dataTreePath }: EvaluatedValueProps,
|
|
|
|
|
): ReduxStateProps => {
|
|
|
|
|
return {
|
|
|
|
|
dynamicData: getDataTreeForAutocomplete(state),
|
|
|
|
|
datasources: state.entities.datasources,
|
|
|
|
|
errors: dataTreePath ? getPathEvalErrors(state, dataTreePath) : [],
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const EvaluatedValuePopupWrapper = Sentry.withProfiler(
|
|
|
|
|
connect(mapStateToProps)(EvaluatedValuePopupWrapperClass),
|
|
|
|
|
);
|