PromucFlow_constructor/app/client/src/components/formControls/DynamicTextFieldControl.tsx
Pranav Kanade 3547976dc7
[Feature] new nav sniping mode (#5746)
* added sniping mode toggle option to header

* added cover to components on hover in sniping mode

* fixed the transition time

* using filled icon

* Show dependencies in action pane

* Added a wrapper to make a widget snipeable

* removed older parts of sniping from Positioned Container

* removed onclick action from snipeable wrapper

* Showing widget name in different color

* Added a mechanism to send user to sniping mode from successful API screen

* created new property pane saga to bind the data

* Fix datasource list width issue

* Fix sidebar going out of view when the response is a table

* Minor refactor

* Show add widgets section on the sidebar

* Stop showing autocomplete option after adding a widget

* fetching pageId, appId from store

* Get suggested widget from response

* Fix table data not getting evaluated after adding binding

* Fix property pane going below the entity explorer while navigating from query/api pane

* Fix width of sidepane shifting for apis

* Fix vertical margins of connections

* Fix api pane suggested widget showing up for errors

* Fix margins

* can show select in canvas btn in sidebar

* can get the action object at the end to bind the data

* updated saga and action names

* can bind data to table

* Use themes

* Use new image url for Table widget

* Added conditional mapping for sniping mode binding.

* updated the widget name tags and seq of calls to open property pane

* pushed all sniping mode decoration to header

* moved setting sniping mode logic to editor reducer

* Added keyboard short cut to get out of sniping mode

* updated reset sniping mechanism

* removed a divider line

* if there are no relationships, will not show the complete section

* Connect Data will automatically show relevant tab in integrations

* Update list and dropdown image urls

* Remove create table button

* no wrapping bind to text

* minor review considerations

* showing the widget name to left in sniping mode

* can set data to datepicker

* will not show snipe btn if there are no widgets in canvas

* Changes for multiple suggested widgets

* removed dependency of sniping from suggested widgets

* Added analytics events for sniping mode

* logic for binding data to a widget, moved to snipeable component

* changed binding widget func from capture to onClick and took care of sniping from widget wrapper too.

* added tests to check sniping mode for table

* updated test spec

* minor fix

* Fix copy changes

* Update test to use table widget from suggested widget list

* if fails to bind will generate warning and keep user in sniping mode

* in sniping mode will only show name plate if it is under focus

* fixed the test case

* added a comment

* minor fix to capture on click event in sniping mode

* updated text

* Hide connections UI when there are no connections

* Increase width to 90%

* Show placeholder text and back button in sidepane

* Show tooltip on hover

* Add analyitcs events for suggested widgets and connections

* Update label based on whether widgets are there or not

* binding related changes

* renamed the saga file containing sinping mode sagas

* Changes for inspect entity

* Revert "binding related changes" temporarily

This reverts commit 54ae9667fecf24bc3cf9912a5356d06600b25c84.

* Update suggested widgets url

* Update table url

* Fix chart data field not getting evaluated

* a minor fix to show proper tool tip when user hovers on widget name

* Show sidepane when there is output

* Update locators

* Use constants for messages

* Update file name to ApiRightPane

* Remove delay

* Revert "Revert "binding related changes" temporarily"

This reverts commit ee7f75e83218137250b4b9a28fcf63080c185150.

* Fix width

* Fix overlap

Co-authored-by: Akash N <akash@codemonk.in>
2021-07-26 22:14:10 +05:30

160 lines
4.4 KiB
TypeScript

import React from "react";
import { formValueSelector, change } from "redux-form";
import { connect } from "react-redux";
import BaseControl, { ControlProps } from "./BaseControl";
import { ControlType } from "constants/PropertyControlConstants";
import FormLabel from "components/editorComponents/FormLabel";
import DynamicTextField from "components/editorComponents/form/fields/DynamicTextField";
import {
EditorSize,
EditorModes,
TabBehaviour,
} from "components/editorComponents/CodeEditor/EditorConfig";
import { QUERY_EDITOR_FORM_NAME } from "constants/forms";
import { AppState } from "reducers";
import styled from "styled-components";
import TemplateMenu from "pages/Editor/QueryEditor/TemplateMenu";
import { QUERY_BODY_FIELD } from "constants/QueryEditorConstants";
import { getPluginResponseTypes } from "selectors/entitiesSelector";
import history from "utils/history";
import {
convertObjectToQueryParams,
getQueryParams,
} from "utils/AppsmithUtils";
import { actionPathFromName } from "components/formControls/utils";
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
const Wrapper = styled.div`
width: 75%;
.dynamic-text-field {
border-radius: 4px;
font-size: 14px;
min-height: calc(100vh / 4);
}
&& {
.CodeMirror-lines {
padding: 10px;
}
}
`;
interface DynamicTextControlState {
showTemplateMenu: boolean;
}
class DynamicTextControl extends BaseControl<
DynamicTextFieldProps,
DynamicTextControlState
> {
constructor(props: DynamicTextFieldProps) {
super(props);
this.state = {
showTemplateMenu: true,
};
}
getControlType(): ControlType {
return "QUERY_DYNAMIC_TEXT";
}
render() {
const {
actionName,
configProperty,
evaluationSubstitutionType,
label,
placeholderText,
responseType,
} = this.props;
const dataTreePath = actionPathFromName(actionName, configProperty);
const isNewQuery =
new URLSearchParams(window.location.search).get("showTemplate") ===
"true";
const showTemplate =
isNewQuery && this.state.showTemplateMenu && this.props.pluginId;
const mode =
responseType === "TABLE"
? EditorModes.SQL_WITH_BINDING
: EditorModes.JSON_WITH_BINDING;
return (
<Wrapper>
<FormLabel>{label}</FormLabel>
{showTemplate ? (
<TemplateMenu
createTemplate={(templateString) => {
this.setState(
{
showTemplateMenu: false,
},
() =>
this.props.createTemplate(
templateString,
this.props.formName,
),
);
}}
pluginId={this.props.pluginId}
/>
) : (
<DynamicTextField
className="dynamic-text-field"
dataTreePath={dataTreePath}
evaluationSubstitutionType={evaluationSubstitutionType}
mode={mode}
name={this.props.configProperty}
placeholder={placeholderText}
size={EditorSize.EXTENDED}
tabBehaviour={TabBehaviour.INDENT}
/>
)}
</Wrapper>
);
}
}
export interface DynamicTextFieldProps extends ControlProps {
actionName: string;
createTemplate: (template: any, formName: string) => any;
pluginId: string;
responseType: string;
placeholderText?: string;
evaluationSubstitutionType: EvaluationSubstitutionType;
mutedHinting?: boolean;
}
const mapStateToProps = (state: AppState, props: DynamicTextFieldProps) => {
const valueSelector = formValueSelector(
props.formName || QUERY_EDITOR_FORM_NAME,
);
const actionName = valueSelector(state, "name");
const pluginId = valueSelector(state, "datasource.pluginId");
const responseTypes = getPluginResponseTypes(state);
return {
actionName,
pluginId,
responseType: responseTypes[pluginId],
};
};
const mapDispatchToProps = (dispatch: any) => ({
createTemplate: (template: any, formName: string) => {
const params = getQueryParams();
if (params.showTemplate) {
params.showTemplate = "false";
}
history.replace({
...window.location,
search: convertObjectToQueryParams(params),
});
dispatch(
change(formName || QUERY_EDITOR_FORM_NAME, QUERY_BODY_FIELD, template),
);
},
});
export default connect(mapStateToProps, mapDispatchToProps)(DynamicTextControl);