Merge branch 'dynamic-binding-scaffold' into 'release'
Dynamic binding scaffold See merge request theappsmith/internal-tools-client!104
This commit is contained in:
commit
ecbd6cd067
17
app/client/src/actions/bindingActions.ts
Normal file
17
app/client/src/actions/bindingActions.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import {
|
||||||
|
ReduxAction,
|
||||||
|
ReduxActionTypes,
|
||||||
|
ReduxActionWithoutPayload,
|
||||||
|
} from "../constants/ReduxActionConstants";
|
||||||
|
import { NamePathBindingMap } from "../constants/BindingsConstants";
|
||||||
|
|
||||||
|
export const createUpdateBindingsMap = (): ReduxActionWithoutPayload => ({
|
||||||
|
type: ReduxActionTypes.CREATE_UPDATE_BINDINGS_MAP_INIT,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const bindingsMapSuccess = (
|
||||||
|
map: NamePathBindingMap,
|
||||||
|
): ReduxAction<NamePathBindingMap> => ({
|
||||||
|
type: ReduxActionTypes.CREATE_UPDATE_BINDINGS_MAP_SUCCESS,
|
||||||
|
payload: map,
|
||||||
|
});
|
||||||
8
app/client/src/actions/initActions.ts
Normal file
8
app/client/src/actions/initActions.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {
|
||||||
|
ReduxActionTypes,
|
||||||
|
ReduxActionWithoutPayload,
|
||||||
|
} from "../constants/ReduxActionConstants";
|
||||||
|
|
||||||
|
export const initAppData = (): ReduxActionWithoutPayload => ({
|
||||||
|
type: ReduxActionTypes.INIT_APP_DATA,
|
||||||
|
});
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { FetchPageRequest } from "../api/PageApi";
|
import { FetchPageRequest } from "../api/PageApi";
|
||||||
import { RenderMode } from "../constants/WidgetConstants";
|
|
||||||
import { WidgetProps, WidgetOperation } from "../widgets/BaseWidget";
|
import { WidgetProps, WidgetOperation } from "../widgets/BaseWidget";
|
||||||
import { WidgetType } from "../constants/WidgetConstants";
|
import { WidgetType } from "../constants/WidgetConstants";
|
||||||
import {
|
import {
|
||||||
|
|
@ -11,10 +10,11 @@ import {
|
||||||
} from "../constants/ReduxActionConstants";
|
} from "../constants/ReduxActionConstants";
|
||||||
import { ContainerWidgetProps } from "../widgets/ContainerWidget";
|
import { ContainerWidgetProps } from "../widgets/ContainerWidget";
|
||||||
|
|
||||||
export const fetchPage = (
|
export const fetchPageList = () => ({
|
||||||
pageId: string,
|
type: ReduxActionTypes.FETCH_PAGE_LIST_INIT,
|
||||||
renderMode: RenderMode,
|
});
|
||||||
): ReduxAction<FetchPageRequest> => {
|
|
||||||
|
export const fetchPage = (pageId: string): ReduxAction<FetchPageRequest> => {
|
||||||
return {
|
return {
|
||||||
type: ReduxActionTypes.FETCH_PAGE,
|
type: ReduxActionTypes.FETCH_PAGE,
|
||||||
payload: {
|
payload: {
|
||||||
|
|
@ -93,9 +93,9 @@ export type WidgetMove = {
|
||||||
topRow: number;
|
topRow: number;
|
||||||
parentId: string;
|
parentId: string;
|
||||||
/*
|
/*
|
||||||
If newParentId is different from what we have in redux store,
|
If newParentId is different from what we have in redux store,
|
||||||
then we have to delete this,
|
then we have to delete this,
|
||||||
as it has been dropped in another container somewhere.
|
as it has been dropped in another container somewhere.
|
||||||
*/
|
*/
|
||||||
newParentId: string;
|
newParentId: string;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export interface RestAction {
|
||||||
|
|
||||||
export interface ExecuteActionRequest extends APIRequest {
|
export interface ExecuteActionRequest extends APIRequest {
|
||||||
actionId: string;
|
actionId: string;
|
||||||
dynamicBindingList?: Property[];
|
params?: Property[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExecuteActionResponse extends ApiResponse {
|
export interface ExecuteActionResponse extends ApiResponse {
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,6 @@ const ResponseMetaInfo = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ResponseBodyWrapper = styled.span`
|
|
||||||
max-height: 100%;
|
|
||||||
&&& {
|
|
||||||
textarea,
|
|
||||||
pre {
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const StatusCodeText = styled(BaseText)<{ code: string }>`
|
const StatusCodeText = styled(BaseText)<{ code: string }>`
|
||||||
color: ${props =>
|
color: ${props =>
|
||||||
props.code.match(/2\d\d/) ? props.theme.colors.primary : "red"};
|
props.code.match(/2\d\d/) ? props.theme.colors.primary : "red"};
|
||||||
|
|
@ -61,10 +51,10 @@ const LoadingScreen = styled.div`
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(255, 255, 255, 0.6);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
color: white;
|
color: black;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -138,17 +128,13 @@ const ApiResponseView = (props: Props) => {
|
||||||
key: "body",
|
key: "body",
|
||||||
title: "Response Body",
|
title: "Response Body",
|
||||||
panelComponent: (
|
panelComponent: (
|
||||||
<ResponseBodyWrapper>
|
<CodeEditor
|
||||||
{response.body && (
|
height={500}
|
||||||
<CodeEditor
|
language={"json"}
|
||||||
height={500}
|
input={{
|
||||||
language={"json"}
|
value: JSON.stringify(response.body, null, 2),
|
||||||
input={{
|
}}
|
||||||
value: JSON.stringify(response.body, null, 2),
|
/>
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ResponseBodyWrapper>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ const CodeEditor = (props: Props) => {
|
||||||
minimap: { enabled: false },
|
minimap: { enabled: false },
|
||||||
readOnly: !props.input.onChange,
|
readOnly: !props.input.onChange,
|
||||||
};
|
};
|
||||||
debugger;
|
|
||||||
return (
|
return (
|
||||||
<Wrapper height={props.height}>
|
<Wrapper height={props.height}>
|
||||||
<MonacoEditor
|
<MonacoEditor
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ import { required } from "../../utils/validation/common";
|
||||||
import { apiPathValidation } from "../../utils/validation/ApiForm";
|
import { apiPathValidation } from "../../utils/validation/ApiForm";
|
||||||
|
|
||||||
const Form = styled.form`
|
const Form = styled.form`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
height: calc(100vh - ${props => props.theme.headerHeight});
|
height: calc(100vh - ${props => props.theme.headerHeight});
|
||||||
width: 100%;
|
width: 100%;
|
||||||
${FormLabel} {
|
${FormLabel} {
|
||||||
|
|
@ -40,6 +42,7 @@ const Form = styled.form`
|
||||||
|
|
||||||
const SecondaryWrapper = styled.div`
|
const SecondaryWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
border-top: 1px solid #d0d7dd;
|
border-top: 1px solid #d0d7dd;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
||||||
1
app/client/src/constants/BindingsConstants.ts
Normal file
1
app/client/src/constants/BindingsConstants.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export type NamePathBindingMap = Record<string, string>;
|
||||||
|
|
@ -2,6 +2,7 @@ import { WidgetProps, WidgetCardProps } from "../widgets/BaseWidget";
|
||||||
import { RefObject } from "react";
|
import { RefObject } from "react";
|
||||||
|
|
||||||
export const ReduxActionTypes: { [key: string]: string } = {
|
export const ReduxActionTypes: { [key: string]: string } = {
|
||||||
|
INIT_APP_DATA: "INIT_APP_DATA",
|
||||||
REPORT_ERROR: "REPORT_ERROR",
|
REPORT_ERROR: "REPORT_ERROR",
|
||||||
FLUSH_ERRORS: "FLUSH_ERRORS",
|
FLUSH_ERRORS: "FLUSH_ERRORS",
|
||||||
UPDATE_CANVAS: "UPDATE_CANVAS",
|
UPDATE_CANVAS: "UPDATE_CANVAS",
|
||||||
|
|
@ -64,11 +65,14 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
||||||
FETCH_PAGE_LIST_INIT: "FETCH_PAGE_LIST_INIT",
|
FETCH_PAGE_LIST_INIT: "FETCH_PAGE_LIST_INIT",
|
||||||
FETCH_PAGE_LIST_SUCCESS: "FETCH_PAGE_LIST_SUCCESS",
|
FETCH_PAGE_LIST_SUCCESS: "FETCH_PAGE_LIST_SUCCESS",
|
||||||
INITIALIZE_PAGE_VIEWER: "INITIALIZE_PAGE_VIEWER",
|
INITIALIZE_PAGE_VIEWER: "INITIALIZE_PAGE_VIEWER",
|
||||||
|
CREATE_UPDATE_BINDINGS_MAP_INIT: "CREATE_UPDATE_BINDINGS_MAP_INIT",
|
||||||
|
CREATE_UPDATE_BINDINGS_MAP_SUCCESS: "CREATE_UPDATE_BINDINGS_MAP_SUCCESS",
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReduxActionType = (typeof ReduxActionTypes)[keyof typeof ReduxActionTypes];
|
export type ReduxActionType = (typeof ReduxActionTypes)[keyof typeof ReduxActionTypes];
|
||||||
|
|
||||||
export const ReduxActionErrorTypes: { [key: string]: string } = {
|
export const ReduxActionErrorTypes: { [key: string]: string } = {
|
||||||
|
INIT_APP_DATA_ERROR: "INIT_APP_DATA_ERROR",
|
||||||
API_ERROR: "API_ERROR",
|
API_ERROR: "API_ERROR",
|
||||||
WIDGET_DELETE_ERROR: "WIDGET_DELETE_ERROR",
|
WIDGET_DELETE_ERROR: "WIDGET_DELETE_ERROR",
|
||||||
WIDGET_MOVE_ERROR: "WIDGET_MOVE_ERROR",
|
WIDGET_MOVE_ERROR: "WIDGET_MOVE_ERROR",
|
||||||
|
|
@ -101,6 +105,8 @@ export interface ReduxAction<T> {
|
||||||
payload: T;
|
payload: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ReduxActionWithoutPayload = Pick<ReduxAction<undefined>, "type">;
|
||||||
|
|
||||||
export interface ReduxActionErrorPayload {
|
export interface ReduxActionErrorPayload {
|
||||||
message: string;
|
message: string;
|
||||||
source?: string;
|
source?: string;
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ import { AppState } from "../../reducers";
|
||||||
import { RouteComponentProps } from "react-router";
|
import { RouteComponentProps } from "react-router";
|
||||||
import { API_EDITOR_URL } from "../../constants/routes";
|
import { API_EDITOR_URL } from "../../constants/routes";
|
||||||
import { API_EDITOR_FORM_NAME } from "../../constants/forms";
|
import { API_EDITOR_FORM_NAME } from "../../constants/forms";
|
||||||
import { ResourceDataState } from "../../reducers/entityReducers/resourcesReducer";
|
|
||||||
import { fetchResources } from "../../actions/resourcesActions";
|
|
||||||
import { FORM_INITIAL_VALUES } from "../../constants/ApiEditorConstants";
|
import { FORM_INITIAL_VALUES } from "../../constants/ApiEditorConstants";
|
||||||
import { normalizeApiFormData } from "../../normalizers/ApiFormNormalizer";
|
import { normalizeApiFormData } from "../../normalizers/ApiFormNormalizer";
|
||||||
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
||||||
|
|
@ -22,7 +20,6 @@ import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
||||||
interface ReduxStateProps {
|
interface ReduxStateProps {
|
||||||
actions: ActionDataState;
|
actions: ActionDataState;
|
||||||
formData: any;
|
formData: any;
|
||||||
resources: ResourceDataState;
|
|
||||||
}
|
}
|
||||||
interface ReduxActionProps {
|
interface ReduxActionProps {
|
||||||
submitForm: (name: string) => void;
|
submitForm: (name: string) => void;
|
||||||
|
|
@ -32,7 +29,6 @@ interface ReduxActionProps {
|
||||||
updateAction: (data: RestAction) => void;
|
updateAction: (data: RestAction) => void;
|
||||||
initialize: (formName: string, data?: Partial<RestAction>) => void;
|
initialize: (formName: string, data?: Partial<RestAction>) => void;
|
||||||
destroy: (formName: string) => void;
|
destroy: (formName: string) => void;
|
||||||
fetchResources: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = ReduxActionProps &
|
type Props = ReduxActionProps &
|
||||||
|
|
@ -41,9 +37,6 @@ type Props = ReduxActionProps &
|
||||||
|
|
||||||
class ApiEditor extends React.Component<Props> {
|
class ApiEditor extends React.Component<Props> {
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
if (!this.props.resources.list.length) {
|
|
||||||
this.props.fetchResources();
|
|
||||||
}
|
|
||||||
const currentId = this.props.match.params.id;
|
const currentId = this.props.match.params.id;
|
||||||
if (!currentId) return;
|
if (!currentId) return;
|
||||||
if (!this.props.actions.data.length) {
|
if (!this.props.actions.data.length) {
|
||||||
|
|
@ -111,7 +104,6 @@ class ApiEditor extends React.Component<Props> {
|
||||||
const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
||||||
actions: state.entities.actions,
|
actions: state.entities.actions,
|
||||||
formData: getFormValues(API_EDITOR_FORM_NAME)(state),
|
formData: getFormValues(API_EDITOR_FORM_NAME)(state),
|
||||||
resources: state.entities.resources,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
||||||
|
|
@ -123,7 +115,6 @@ const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
||||||
initialize: (formName: string, data?: Partial<RestAction>) =>
|
initialize: (formName: string, data?: Partial<RestAction>) =>
|
||||||
dispatch(initialize(formName, data)),
|
dispatch(initialize(formName, data)),
|
||||||
destroy: (formName: string) => dispatch(destroy(formName)),
|
destroy: (formName: string) => dispatch(destroy(formName)),
|
||||||
fetchResources: () => dispatch(fetchResources()),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { connect } from "react-redux";
|
||||||
import { RouteComponentProps } from "react-router";
|
import { RouteComponentProps } from "react-router";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { AppState } from "../../reducers";
|
import { AppState } from "../../reducers";
|
||||||
import { fetchActions } from "../../actions/actionActions";
|
|
||||||
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
||||||
import { API_EDITOR_ID_URL, API_EDITOR_URL } from "../../constants/routes";
|
import { API_EDITOR_ID_URL, API_EDITOR_URL } from "../../constants/routes";
|
||||||
import { BaseButton } from "../../components/blueprint/ButtonComponent";
|
import { BaseButton } from "../../components/blueprint/ButtonComponent";
|
||||||
|
|
@ -86,22 +85,9 @@ interface ReduxStateProps {
|
||||||
actions: ActionDataState;
|
actions: ActionDataState;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReduxActionProps {
|
type Props = ReduxStateProps & RouteComponentProps<{ id: string }>;
|
||||||
fetchActions: () => void;
|
|
||||||
selectAction: (id: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = ReduxStateProps &
|
|
||||||
ReduxActionProps &
|
|
||||||
RouteComponentProps<{ id: string }>;
|
|
||||||
|
|
||||||
class ApiSidebar extends React.Component<Props> {
|
class ApiSidebar extends React.Component<Props> {
|
||||||
componentDidMount(): void {
|
|
||||||
if (!this.props.actions.data.length) {
|
|
||||||
this.props.fetchActions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCreateNew = () => {
|
handleCreateNew = () => {
|
||||||
const { history } = this.props;
|
const { history } = this.props;
|
||||||
history.push(API_EDITOR_URL);
|
history.push(API_EDITOR_URL);
|
||||||
|
|
@ -147,11 +133,4 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
||||||
actions: state.entities.actions,
|
actions: state.entities.actions,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any) => ({
|
export default connect(mapStateToProps)(ApiSidebar);
|
||||||
fetchActions: () => dispatch(fetchActions()),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps,
|
|
||||||
)(ApiSidebar);
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const Wrapper = styled.div`
|
||||||
grid-template-columns: 1fr 4fr;
|
grid-template-columns: 1fr 4fr;
|
||||||
width: ${props => props.theme.sidebarWidth};
|
width: ${props => props.theme.sidebarWidth};
|
||||||
box-shadow: 0px 1px 3px ${props => props.theme.colors.paneBG};
|
box-shadow: 0px 1px 3px ${props => props.theme.colors.paneBG};
|
||||||
|
z-index: 20;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const NavBar = styled.div`
|
const NavBar = styled.div`
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,9 @@ import {
|
||||||
} from "../../widgets/BaseWidget";
|
} from "../../widgets/BaseWidget";
|
||||||
import { ActionPayload } from "../../constants/ActionConstants";
|
import { ActionPayload } from "../../constants/ActionConstants";
|
||||||
import { executeAction } from "../../actions/widgetActions";
|
import { executeAction } from "../../actions/widgetActions";
|
||||||
import { fetchPage, savePage, updateWidget } from "../../actions/pageActions";
|
import { savePage, updateWidget } from "../../actions/pageActions";
|
||||||
import {
|
import { getDenormalizedDSL } from "../../selectors/editorSelectors";
|
||||||
getPropertyPaneConfigsId,
|
|
||||||
getCurrentLayoutId,
|
|
||||||
getCurrentPageId,
|
|
||||||
getDenormalizedDSL,
|
|
||||||
getCurrentPageName,
|
|
||||||
} from "../../selectors/editorSelectors";
|
|
||||||
import { RenderModes } from "../../constants/WidgetConstants";
|
|
||||||
import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
|
import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
|
||||||
import {
|
|
||||||
EditorConfigIdsType,
|
|
||||||
fetchEditorConfigs,
|
|
||||||
} from "../../actions/configsActions";
|
|
||||||
import { ReduxActionTypes } from "../../constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "../../constants/ReduxActionConstants";
|
||||||
import { updateWidgetProperty } from "../../actions/controlActions";
|
import { updateWidgetProperty } from "../../actions/controlActions";
|
||||||
|
|
||||||
|
|
@ -56,7 +45,6 @@ const CanvasContainer = styled.section`
|
||||||
|
|
||||||
type EditorProps = {
|
type EditorProps = {
|
||||||
dsl: ContainerWidgetProps<WidgetProps> | any;
|
dsl: ContainerWidgetProps<WidgetProps> | any;
|
||||||
fetchCanvasWidgets: Function;
|
|
||||||
executeAction: (actionPayloads?: ActionPayload[]) => void;
|
executeAction: (actionPayloads?: ActionPayload[]) => void;
|
||||||
updateWidget: Function;
|
updateWidget: Function;
|
||||||
updateWidgetProperty: (
|
updateWidgetProperty: (
|
||||||
|
|
@ -65,64 +53,39 @@ type EditorProps = {
|
||||||
propertyValue: any,
|
propertyValue: any,
|
||||||
) => void;
|
) => void;
|
||||||
savePageLayout: Function;
|
savePageLayout: Function;
|
||||||
currentPageName: string;
|
|
||||||
currentPageId: string;
|
|
||||||
currentLayoutId: string;
|
|
||||||
showPropertyPane: (
|
showPropertyPane: (
|
||||||
widgetId?: string,
|
widgetId?: string,
|
||||||
node?: HTMLDivElement,
|
node?: HTMLDivElement,
|
||||||
toggle?: boolean,
|
toggle?: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
fetchConfigs: Function;
|
|
||||||
propertyPaneConfigsId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WidgetFunctionsContext: Context<WidgetFunctions> = createContext(
|
export const WidgetFunctionsContext: Context<WidgetFunctions> = createContext(
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
class WidgetsEditor extends React.Component<EditorProps> {
|
const WidgetsEditor = (props: EditorProps) => (
|
||||||
componentDidMount() {
|
<WidgetFunctionsContext.Provider
|
||||||
this.props.fetchConfigs({
|
value={{
|
||||||
propertyPaneConfigsId: this.props.propertyPaneConfigsId,
|
executeAction: props.executeAction,
|
||||||
// widgetCardsPaneId: this.props.widgetCardsPaneId,
|
updateWidget: props.updateWidget,
|
||||||
// widgetConfigsId: this.props.widgetConfigsId,
|
updateWidgetProperty: props.updateWidgetProperty,
|
||||||
});
|
}}
|
||||||
this.props.fetchCanvasWidgets(this.props.currentPageId);
|
>
|
||||||
}
|
<EditorWrapper>
|
||||||
|
<CanvasContainer>
|
||||||
render(): React.ReactNode {
|
{props.dsl && (
|
||||||
return (
|
<Canvas dsl={props.dsl} showPropertyPane={props.showPropertyPane} />
|
||||||
<WidgetFunctionsContext.Provider
|
)}
|
||||||
value={{
|
</CanvasContainer>
|
||||||
executeAction: this.props.executeAction,
|
<PropertyPane />
|
||||||
updateWidget: this.props.updateWidget,
|
</EditorWrapper>
|
||||||
updateWidgetProperty: this.props.updateWidgetProperty,
|
</WidgetFunctionsContext.Provider>
|
||||||
}}
|
);
|
||||||
>
|
|
||||||
<EditorWrapper>
|
|
||||||
<CanvasContainer>
|
|
||||||
{this.props.dsl && (
|
|
||||||
<Canvas
|
|
||||||
dsl={this.props.dsl}
|
|
||||||
showPropertyPane={this.props.showPropertyPane}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CanvasContainer>
|
|
||||||
<PropertyPane />
|
|
||||||
</EditorWrapper>
|
|
||||||
</WidgetFunctionsContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState) => {
|
const mapStateToProps = (state: AppState) => {
|
||||||
return {
|
return {
|
||||||
dsl: getDenormalizedDSL(state),
|
dsl: getDenormalizedDSL(state),
|
||||||
currentPageId: getCurrentPageId(state),
|
|
||||||
currentLayoutId: getCurrentLayoutId(state),
|
|
||||||
currentPageName: getCurrentPageName(state),
|
|
||||||
propertyPaneConfigsId: getPropertyPaneConfigsId(state),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -135,8 +98,6 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||||
) => dispatch(updateWidgetProperty(widgetId, propertyName, propertyValue)),
|
) => dispatch(updateWidgetProperty(widgetId, propertyName, propertyValue)),
|
||||||
executeAction: (actionPayloads?: ActionPayload[]) =>
|
executeAction: (actionPayloads?: ActionPayload[]) =>
|
||||||
dispatch(executeAction(actionPayloads)),
|
dispatch(executeAction(actionPayloads)),
|
||||||
fetchCanvasWidgets: (pageId: string) =>
|
|
||||||
dispatch(fetchPage(pageId, RenderModes.CANVAS)),
|
|
||||||
updateWidget: (
|
updateWidget: (
|
||||||
operation: WidgetOperation,
|
operation: WidgetOperation,
|
||||||
widgetId: string,
|
widgetId: string,
|
||||||
|
|
@ -147,8 +108,6 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||||
layoutId: string,
|
layoutId: string,
|
||||||
dsl: ContainerWidgetProps<WidgetProps>,
|
dsl: ContainerWidgetProps<WidgetProps>,
|
||||||
) => dispatch(savePage(pageId, layoutId, dsl)),
|
) => dispatch(savePage(pageId, layoutId, dsl)),
|
||||||
fetchConfigs: (configsIds: EditorConfigIdsType) =>
|
|
||||||
dispatch(fetchEditorConfigs(configsIds)),
|
|
||||||
showPropertyPane: (
|
showPropertyPane: (
|
||||||
widgetId?: string,
|
widgetId?: string,
|
||||||
node?: HTMLDivElement,
|
node?: HTMLDivElement,
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
PageListPayload,
|
PageListPayload,
|
||||||
} from "../../constants/ReduxActionConstants";
|
} from "../../constants/ReduxActionConstants";
|
||||||
import { Dialog, Classes, AnchorButton } from "@blueprintjs/core";
|
import { Dialog, Classes, AnchorButton } from "@blueprintjs/core";
|
||||||
|
import { initAppData } from "../../actions/initActions";
|
||||||
|
|
||||||
type EditorProps = {
|
type EditorProps = {
|
||||||
currentPageName: string;
|
currentPageName: string;
|
||||||
|
|
@ -26,8 +27,8 @@ type EditorProps = {
|
||||||
currentPageId: string;
|
currentPageId: string;
|
||||||
publishApplication: Function;
|
publishApplication: Function;
|
||||||
previewPage: Function;
|
previewPage: Function;
|
||||||
|
initData: Function;
|
||||||
createPage: Function;
|
createPage: Function;
|
||||||
fetchPageList: Function;
|
|
||||||
pages: PageListPayload;
|
pages: PageListPayload;
|
||||||
switchPage: (pageId: string) => void;
|
switchPage: (pageId: string) => void;
|
||||||
isPublishing: boolean;
|
isPublishing: boolean;
|
||||||
|
|
@ -40,7 +41,7 @@ class Editor extends Component<EditorProps> {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.fetchPageList();
|
this.props.initData();
|
||||||
}
|
}
|
||||||
componentDidUpdate(currently: EditorProps) {
|
componentDidUpdate(currently: EditorProps) {
|
||||||
const previously = this.props;
|
const previously = this.props;
|
||||||
|
|
@ -123,6 +124,7 @@ const mapStateToProps = (state: AppState) => ({
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any) => {
|
const mapDispatchToProps = (dispatch: any) => {
|
||||||
return {
|
return {
|
||||||
|
initData: () => dispatch(initAppData()),
|
||||||
publishApplication: (applicationId: string) => {
|
publishApplication: (applicationId: string) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ReduxActionTypes.PUBLISH_APPLICATION_INIT,
|
type: ReduxActionTypes.PUBLISH_APPLICATION_INIT,
|
||||||
|
|
@ -149,11 +151,6 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fetchPageList: () => {
|
|
||||||
dispatch({
|
|
||||||
type: ReduxActionTypes.FETCH_PAGE_LIST_INIT,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
switchPage: (pageId: string) => {
|
switchPage: (pageId: string) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ReduxActionTypes.FETCH_PAGE,
|
type: ReduxActionTypes.FETCH_PAGE,
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,9 @@ import {
|
||||||
ReduxAction,
|
ReduxAction,
|
||||||
ReduxActionErrorTypes,
|
ReduxActionErrorTypes,
|
||||||
} from "../../constants/ReduxActionConstants";
|
} from "../../constants/ReduxActionConstants";
|
||||||
import _ from "lodash";
|
|
||||||
import { PageAction } from "../../constants/ActionConstants";
|
|
||||||
import { RestAction } from "../../api/ActionAPI";
|
import { RestAction } from "../../api/ActionAPI";
|
||||||
|
|
||||||
const initialState: ActionDataState = {
|
const initialState: ActionDataState = {
|
||||||
list: {},
|
|
||||||
data: [],
|
data: [],
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
isRunning: false,
|
isRunning: false,
|
||||||
|
|
@ -18,9 +15,6 @@ const initialState: ActionDataState = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ActionDataState {
|
export interface ActionDataState {
|
||||||
list: {
|
|
||||||
[name: string]: PageAction;
|
|
||||||
};
|
|
||||||
data: RestAction[];
|
data: RestAction[];
|
||||||
isFetching: boolean;
|
isFetching: boolean;
|
||||||
isRunning: boolean;
|
isRunning: boolean;
|
||||||
|
|
@ -29,15 +23,6 @@ export interface ActionDataState {
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionsReducer = createReducer(initialState, {
|
const actionsReducer = createReducer(initialState, {
|
||||||
[ReduxActionTypes.LOAD_CANVAS_ACTIONS]: (
|
|
||||||
state: ActionDataState,
|
|
||||||
action: ReduxAction<PageAction[]>,
|
|
||||||
) => {
|
|
||||||
const actionMap = _.mapKeys(action.payload, (action: PageAction) => {
|
|
||||||
return action.id;
|
|
||||||
});
|
|
||||||
return { ...state, list: { ...actionMap } };
|
|
||||||
},
|
|
||||||
[ReduxActionTypes.FETCH_ACTIONS_INIT]: (state: ActionDataState) => ({
|
[ReduxActionTypes.FETCH_ACTIONS_INIT]: (state: ActionDataState) => ({
|
||||||
...state,
|
...state,
|
||||||
isFetching: true,
|
isFetching: true,
|
||||||
|
|
|
||||||
19
app/client/src/reducers/entityReducers/bindingsReducer.ts
Normal file
19
app/client/src/reducers/entityReducers/bindingsReducer.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { createReducer } from "../../utils/AppsmithUtils";
|
||||||
|
import {
|
||||||
|
ReduxActionTypes,
|
||||||
|
ReduxAction,
|
||||||
|
} from "../../constants/ReduxActionConstants";
|
||||||
|
import { NamePathBindingMap } from "../../constants/BindingsConstants";
|
||||||
|
|
||||||
|
export type BindingsDataState = NamePathBindingMap;
|
||||||
|
|
||||||
|
const initialState: BindingsDataState = {};
|
||||||
|
|
||||||
|
const bindingsReducer = createReducer(initialState, {
|
||||||
|
[ReduxActionTypes.CREATE_UPDATE_BINDINGS_MAP_SUCCESS]: (
|
||||||
|
state: BindingsDataState,
|
||||||
|
action: ReduxAction<NamePathBindingMap>,
|
||||||
|
) => action.payload,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default bindingsReducer;
|
||||||
|
|
@ -6,6 +6,7 @@ import widgetConfigReducer from "./widgetConfigReducer";
|
||||||
import actionsReducer from "./actionsReducer";
|
import actionsReducer from "./actionsReducer";
|
||||||
import propertyPaneConfigReducer from "./propertyPaneConfigReducer";
|
import propertyPaneConfigReducer from "./propertyPaneConfigReducer";
|
||||||
import resourceReducer from "./resourcesReducer";
|
import resourceReducer from "./resourcesReducer";
|
||||||
|
import bindingsReducer from "./bindingsReducer";
|
||||||
|
|
||||||
const entityReducer = combineReducers({
|
const entityReducer = combineReducers({
|
||||||
canvasWidgets: canvasWidgetsReducer,
|
canvasWidgets: canvasWidgetsReducer,
|
||||||
|
|
@ -15,5 +16,6 @@ const entityReducer = combineReducers({
|
||||||
actions: actionsReducer,
|
actions: actionsReducer,
|
||||||
propertyConfig: propertyPaneConfigReducer,
|
propertyConfig: propertyPaneConfigReducer,
|
||||||
resources: resourceReducer,
|
resources: resourceReducer,
|
||||||
|
nameBindings: bindingsReducer,
|
||||||
});
|
});
|
||||||
export default entityReducer;
|
export default entityReducer;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { WidgetConfigReducerState } from "./entityReducers/widgetConfigReducer";
|
||||||
import { WidgetSidebarReduxState } from "./uiReducers/widgetSidebarReducer";
|
import { WidgetSidebarReduxState } from "./uiReducers/widgetSidebarReducer";
|
||||||
import { ResourceDataState } from "./entityReducers/resourcesReducer";
|
import { ResourceDataState } from "./entityReducers/resourcesReducer";
|
||||||
import { AppViewReduxState } from "./uiReducers/appViewReducer";
|
import { AppViewReduxState } from "./uiReducers/appViewReducer";
|
||||||
|
import { BindingsDataState } from "./entityReducers/bindingsReducer";
|
||||||
|
|
||||||
const appReducer = combineReducers({
|
const appReducer = combineReducers({
|
||||||
entities: entityReducer,
|
entities: entityReducer,
|
||||||
|
|
@ -39,5 +40,6 @@ export interface AppState {
|
||||||
propertyConfig: PropertyPaneConfigState;
|
propertyConfig: PropertyPaneConfigState;
|
||||||
widgetConfig: WidgetConfigReducerState;
|
widgetConfig: WidgetConfigReducerState;
|
||||||
resources: ResourceDataState;
|
resources: ResourceDataState;
|
||||||
|
nameBindings: BindingsDataState;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,36 +39,42 @@ const getDataTree = (state: AppState) => {
|
||||||
return state.entities;
|
return state.entities;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAction = (state: AppState, actionId: string): PageAction => {
|
const getAction = (
|
||||||
return state.entities.actions.list[actionId];
|
state: AppState,
|
||||||
|
actionId: string,
|
||||||
|
): RestAction | undefined => {
|
||||||
|
return _.find(state.entities.actions.data, { id: actionId });
|
||||||
};
|
};
|
||||||
|
|
||||||
export function* evaluateJSONPathSaga(jsonPath: string): any {
|
export function* evaluateJSONPathSaga(jsonPath: string): any {
|
||||||
const dataTree = yield select(getDataTree);
|
const dataTree = yield select(getDataTree);
|
||||||
return JSONPath({ path: jsonPath, json: dataTree });
|
const splitPath = jsonPath.split(".");
|
||||||
|
const bindingPath = dataTree.nameBindings[splitPath[0]];
|
||||||
|
const fullPath = `${bindingPath}.${splitPath.slice(1).join(".")}`;
|
||||||
|
return JSONPath({ path: fullPath, json: dataTree });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* executeAPIQueryActionSaga(apiAction: ActionPayload) {
|
export function* executeAPIQueryActionSaga(apiAction: { actionId: string }) {
|
||||||
const api: PageAction = yield select(getAction, apiAction.actionId);
|
const api: PageAction = yield select(getAction, apiAction.actionId);
|
||||||
|
|
||||||
const executeActionRequest: ExecuteActionRequest = {
|
const executeActionRequest: ExecuteActionRequest = {
|
||||||
actionId: apiAction.actionId,
|
actionId: apiAction.actionId,
|
||||||
};
|
};
|
||||||
if (!_.isNil(api.jsonPathKeys)) {
|
if (!_.isNil(api.jsonPathKeys)) {
|
||||||
const responses: any = yield all(
|
const values: any = _.flatten(
|
||||||
api.jsonPathKeys.map((jsonPath: string) => {
|
yield all(
|
||||||
return call(evaluateJSONPathSaga, jsonPath);
|
api.jsonPathKeys.map((jsonPath: string) => {
|
||||||
}),
|
return call(evaluateJSONPathSaga, jsonPath);
|
||||||
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const dynamicBindingMap: Record<string, any> = _.keyBy(
|
const dynamicBindings: Record<string, string> = {};
|
||||||
responses,
|
api.jsonPathKeys.forEach((key, i) => {
|
||||||
(response: string, index: number) => {
|
dynamicBindings[key] = values[i];
|
||||||
return api.jsonPathKeys ? api.jsonPathKeys[index] : undefined;
|
});
|
||||||
},
|
executeActionRequest.params = mapToPropList(dynamicBindings);
|
||||||
);
|
|
||||||
executeActionRequest.dynamicBindingList = mapToPropList(dynamicBindingMap);
|
|
||||||
}
|
}
|
||||||
yield ActionAPI.executeAction(executeActionRequest);
|
return yield ActionAPI.executeAction(executeActionRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* executeActionSaga(action: ReduxAction<ActionPayload[]>) {
|
export function* executeActionSaga(action: ReduxAction<ActionPayload[]>) {
|
||||||
|
|
@ -128,10 +134,9 @@ export function* fetchActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||||
|
|
||||||
export function* runActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
export function* runActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||||
const id = actionPayload.payload.id;
|
const id = actionPayload.payload.id;
|
||||||
const response: ActionApiResponse = yield ActionAPI.executeAction({
|
const response: ActionApiResponse = yield call(executeAPIQueryActionSaga, {
|
||||||
actionId: id,
|
actionId: id,
|
||||||
});
|
});
|
||||||
|
|
||||||
let payload = response;
|
let payload = response;
|
||||||
if (response.responseMeta && response.responseMeta.error) {
|
if (response.responseMeta && response.responseMeta.error) {
|
||||||
payload = {
|
payload = {
|
||||||
|
|
|
||||||
26
app/client/src/sagas/BindingsSagas.ts
Normal file
26
app/client/src/sagas/BindingsSagas.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { all, select, takeLatest, put } from "redux-saga/effects";
|
||||||
|
import { ReduxActionTypes } from "../constants/ReduxActionConstants";
|
||||||
|
import { AppState } from "../reducers";
|
||||||
|
import { bindingsMapSuccess } from "../actions/bindingActions";
|
||||||
|
|
||||||
|
function* createUpdateBindingsMapData() {
|
||||||
|
const data: AppState = yield select();
|
||||||
|
const map: Record<string, string> = {};
|
||||||
|
data.entities.actions.data.forEach(action => {
|
||||||
|
map[action.name] = `$.apiData.${action.id}`;
|
||||||
|
});
|
||||||
|
Object.keys(data.entities.canvasWidgets).forEach(widgetId => {
|
||||||
|
const name = data.entities.canvasWidgets[widgetId].widgetName;
|
||||||
|
map[name] = `$.canvasWidgets.${widgetId}`;
|
||||||
|
});
|
||||||
|
yield put(bindingsMapSuccess(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function* watchBindingsSagas() {
|
||||||
|
yield all([
|
||||||
|
takeLatest(
|
||||||
|
ReduxActionTypes.CREATE_UPDATE_BINDINGS_MAP_INIT,
|
||||||
|
createUpdateBindingsMapData,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
37
app/client/src/sagas/InitSagas.ts
Normal file
37
app/client/src/sagas/InitSagas.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { all, select, put, takeLatest, take } from "redux-saga/effects";
|
||||||
|
import { ReduxActionTypes } from "../constants/ReduxActionConstants";
|
||||||
|
import {
|
||||||
|
getPropertyPaneConfigsId,
|
||||||
|
getCurrentPageId,
|
||||||
|
} from "../selectors/editorSelectors";
|
||||||
|
import { fetchEditorConfigs } from "../actions/configsActions";
|
||||||
|
import { fetchPage, fetchPageList } from "../actions/pageActions";
|
||||||
|
import { fetchActions } from "../actions/actionActions";
|
||||||
|
import { fetchResources } from "../actions/resourcesActions";
|
||||||
|
import { createUpdateBindingsMap } from "../actions/bindingActions";
|
||||||
|
|
||||||
|
function* fetchAppDataSaga() {
|
||||||
|
// Step 1: Start getting all the data needed by the app
|
||||||
|
const propertyPaneConfigsId = yield select(getPropertyPaneConfigsId);
|
||||||
|
const currentPageId = yield select(getCurrentPageId);
|
||||||
|
yield all([
|
||||||
|
put(fetchPageList()),
|
||||||
|
put(fetchEditorConfigs(propertyPaneConfigsId)),
|
||||||
|
put(fetchPage(currentPageId)),
|
||||||
|
put(fetchActions()),
|
||||||
|
put(fetchResources()),
|
||||||
|
]);
|
||||||
|
// Step 2: Wait for all data to be in the state
|
||||||
|
yield all([
|
||||||
|
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||||
|
take(ReduxActionTypes.UPDATE_CANVAS),
|
||||||
|
take(ReduxActionTypes.FETCH_ACTIONS_SUCCESS),
|
||||||
|
take(ReduxActionTypes.FETCH_RESOURCES_SUCCESS),
|
||||||
|
]);
|
||||||
|
// Step 3: Create the bindings map;
|
||||||
|
yield put(createUpdateBindingsMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function* watchInitSagas() {
|
||||||
|
yield all([takeLatest(ReduxActionTypes.INIT_APP_DATA, fetchAppDataSaga)]);
|
||||||
|
}
|
||||||
|
|
@ -7,8 +7,12 @@ import errorSagas from "./ErrorSagas";
|
||||||
import configsSagas from "./ConfigsSagas";
|
import configsSagas from "./ConfigsSagas";
|
||||||
import applicationSagas from "./ApplicationSagas";
|
import applicationSagas from "./ApplicationSagas";
|
||||||
import { watchResourcesSagas } from "./ResourcesSagas";
|
import { watchResourcesSagas } from "./ResourcesSagas";
|
||||||
|
import initSagas from "./InitSagas";
|
||||||
|
import bindingsSagas from "./BindingsSagas";
|
||||||
|
|
||||||
export function* rootSaga() {
|
export function* rootSaga() {
|
||||||
yield all([
|
yield all([
|
||||||
|
spawn(initSagas),
|
||||||
spawn(pageSagas),
|
spawn(pageSagas),
|
||||||
spawn(fetchWidgetCardsSaga),
|
spawn(fetchWidgetCardsSaga),
|
||||||
spawn(watchActionSagas),
|
spawn(watchActionSagas),
|
||||||
|
|
@ -17,5 +21,6 @@ export function* rootSaga() {
|
||||||
spawn(configsSagas),
|
spawn(configsSagas),
|
||||||
spawn(watchResourcesSagas),
|
spawn(watchResourcesSagas),
|
||||||
spawn(applicationSagas),
|
spawn(applicationSagas),
|
||||||
|
spawn(bindingsSagas),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// import * as React from "react";
|
// import * as React from "react";
|
||||||
declare module 'react-base-table';
|
declare module "react-base-table";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user