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 { RenderMode } from "../constants/WidgetConstants";
|
||||
import { WidgetProps, WidgetOperation } from "../widgets/BaseWidget";
|
||||
import { WidgetType } from "../constants/WidgetConstants";
|
||||
import {
|
||||
|
|
@ -11,10 +10,11 @@ import {
|
|||
} from "../constants/ReduxActionConstants";
|
||||
import { ContainerWidgetProps } from "../widgets/ContainerWidget";
|
||||
|
||||
export const fetchPage = (
|
||||
pageId: string,
|
||||
renderMode: RenderMode,
|
||||
): ReduxAction<FetchPageRequest> => {
|
||||
export const fetchPageList = () => ({
|
||||
type: ReduxActionTypes.FETCH_PAGE_LIST_INIT,
|
||||
});
|
||||
|
||||
export const fetchPage = (pageId: string): ReduxAction<FetchPageRequest> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PAGE,
|
||||
payload: {
|
||||
|
|
@ -93,9 +93,9 @@ export type WidgetMove = {
|
|||
topRow: number;
|
||||
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,
|
||||
as it has been dropped in another container somewhere.
|
||||
as it has been dropped in another container somewhere.
|
||||
*/
|
||||
newParentId: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export interface RestAction {
|
|||
|
||||
export interface ExecuteActionRequest extends APIRequest {
|
||||
actionId: string;
|
||||
dynamicBindingList?: Property[];
|
||||
params?: Property[];
|
||||
}
|
||||
|
||||
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 }>`
|
||||
color: ${props =>
|
||||
props.code.match(/2\d\d/) ? props.theme.colors.primary : "red"};
|
||||
|
|
@ -61,10 +51,10 @@ const LoadingScreen = styled.div`
|
|||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
color: white;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -138,17 +128,13 @@ const ApiResponseView = (props: Props) => {
|
|||
key: "body",
|
||||
title: "Response Body",
|
||||
panelComponent: (
|
||||
<ResponseBodyWrapper>
|
||||
{response.body && (
|
||||
<CodeEditor
|
||||
height={500}
|
||||
language={"json"}
|
||||
input={{
|
||||
value: JSON.stringify(response.body, null, 2),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</ResponseBodyWrapper>
|
||||
<CodeEditor
|
||||
height={500}
|
||||
language={"json"}
|
||||
input={{
|
||||
value: JSON.stringify(response.body, null, 2),
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ const CodeEditor = (props: Props) => {
|
|||
minimap: { enabled: false },
|
||||
readOnly: !props.input.onChange,
|
||||
};
|
||||
debugger;
|
||||
return (
|
||||
<Wrapper height={props.height}>
|
||||
<MonacoEditor
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import { required } from "../../utils/validation/common";
|
|||
import { apiPathValidation } from "../../utils/validation/ApiForm";
|
||||
|
||||
const Form = styled.form`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - ${props => props.theme.headerHeight});
|
||||
width: 100%;
|
||||
${FormLabel} {
|
||||
|
|
@ -40,6 +42,7 @@ const Form = styled.form`
|
|||
|
||||
const SecondaryWrapper = styled.div`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
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";
|
||||
|
||||
export const ReduxActionTypes: { [key: string]: string } = {
|
||||
INIT_APP_DATA: "INIT_APP_DATA",
|
||||
REPORT_ERROR: "REPORT_ERROR",
|
||||
FLUSH_ERRORS: "FLUSH_ERRORS",
|
||||
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_SUCCESS: "FETCH_PAGE_LIST_SUCCESS",
|
||||
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 const ReduxActionErrorTypes: { [key: string]: string } = {
|
||||
INIT_APP_DATA_ERROR: "INIT_APP_DATA_ERROR",
|
||||
API_ERROR: "API_ERROR",
|
||||
WIDGET_DELETE_ERROR: "WIDGET_DELETE_ERROR",
|
||||
WIDGET_MOVE_ERROR: "WIDGET_MOVE_ERROR",
|
||||
|
|
@ -101,6 +105,8 @@ export interface ReduxAction<T> {
|
|||
payload: T;
|
||||
}
|
||||
|
||||
export type ReduxActionWithoutPayload = Pick<ReduxAction<undefined>, "type">;
|
||||
|
||||
export interface ReduxActionErrorPayload {
|
||||
message: string;
|
||||
source?: string;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ import { AppState } from "../../reducers";
|
|||
import { RouteComponentProps } from "react-router";
|
||||
import { API_EDITOR_URL } from "../../constants/routes";
|
||||
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 { normalizeApiFormData } from "../../normalizers/ApiFormNormalizer";
|
||||
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
||||
|
|
@ -22,7 +20,6 @@ import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
|||
interface ReduxStateProps {
|
||||
actions: ActionDataState;
|
||||
formData: any;
|
||||
resources: ResourceDataState;
|
||||
}
|
||||
interface ReduxActionProps {
|
||||
submitForm: (name: string) => void;
|
||||
|
|
@ -32,7 +29,6 @@ interface ReduxActionProps {
|
|||
updateAction: (data: RestAction) => void;
|
||||
initialize: (formName: string, data?: Partial<RestAction>) => void;
|
||||
destroy: (formName: string) => void;
|
||||
fetchResources: () => void;
|
||||
}
|
||||
|
||||
type Props = ReduxActionProps &
|
||||
|
|
@ -41,9 +37,6 @@ type Props = ReduxActionProps &
|
|||
|
||||
class ApiEditor extends React.Component<Props> {
|
||||
componentDidMount(): void {
|
||||
if (!this.props.resources.list.length) {
|
||||
this.props.fetchResources();
|
||||
}
|
||||
const currentId = this.props.match.params.id;
|
||||
if (!currentId) return;
|
||||
if (!this.props.actions.data.length) {
|
||||
|
|
@ -111,7 +104,6 @@ class ApiEditor extends React.Component<Props> {
|
|||
const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
||||
actions: state.entities.actions,
|
||||
formData: getFormValues(API_EDITOR_FORM_NAME)(state),
|
||||
resources: state.entities.resources,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
||||
|
|
@ -123,7 +115,6 @@ const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
|||
initialize: (formName: string, data?: Partial<RestAction>) =>
|
||||
dispatch(initialize(formName, data)),
|
||||
destroy: (formName: string) => dispatch(destroy(formName)),
|
||||
fetchResources: () => dispatch(fetchResources()),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { connect } from "react-redux";
|
|||
import { RouteComponentProps } from "react-router";
|
||||
import styled from "styled-components";
|
||||
import { AppState } from "../../reducers";
|
||||
import { fetchActions } from "../../actions/actionActions";
|
||||
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
|
||||
import { API_EDITOR_ID_URL, API_EDITOR_URL } from "../../constants/routes";
|
||||
import { BaseButton } from "../../components/blueprint/ButtonComponent";
|
||||
|
|
@ -86,22 +85,9 @@ interface ReduxStateProps {
|
|||
actions: ActionDataState;
|
||||
}
|
||||
|
||||
interface ReduxActionProps {
|
||||
fetchActions: () => void;
|
||||
selectAction: (id: string) => void;
|
||||
}
|
||||
|
||||
type Props = ReduxStateProps &
|
||||
ReduxActionProps &
|
||||
RouteComponentProps<{ id: string }>;
|
||||
type Props = ReduxStateProps & RouteComponentProps<{ id: string }>;
|
||||
|
||||
class ApiSidebar extends React.Component<Props> {
|
||||
componentDidMount(): void {
|
||||
if (!this.props.actions.data.length) {
|
||||
this.props.fetchActions();
|
||||
}
|
||||
}
|
||||
|
||||
handleCreateNew = () => {
|
||||
const { history } = this.props;
|
||||
history.push(API_EDITOR_URL);
|
||||
|
|
@ -147,11 +133,4 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
|||
actions: state.entities.actions,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => ({
|
||||
fetchActions: () => dispatch(fetchActions()),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(ApiSidebar);
|
||||
export default connect(mapStateToProps)(ApiSidebar);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const Wrapper = styled.div`
|
|||
grid-template-columns: 1fr 4fr;
|
||||
width: ${props => props.theme.sidebarWidth};
|
||||
box-shadow: 0px 1px 3px ${props => props.theme.colors.paneBG};
|
||||
z-index: 20;
|
||||
`;
|
||||
|
||||
const NavBar = styled.div`
|
||||
|
|
|
|||
|
|
@ -11,20 +11,9 @@ import {
|
|||
} from "../../widgets/BaseWidget";
|
||||
import { ActionPayload } from "../../constants/ActionConstants";
|
||||
import { executeAction } from "../../actions/widgetActions";
|
||||
import { fetchPage, savePage, updateWidget } from "../../actions/pageActions";
|
||||
import {
|
||||
getPropertyPaneConfigsId,
|
||||
getCurrentLayoutId,
|
||||
getCurrentPageId,
|
||||
getDenormalizedDSL,
|
||||
getCurrentPageName,
|
||||
} from "../../selectors/editorSelectors";
|
||||
import { RenderModes } from "../../constants/WidgetConstants";
|
||||
import { savePage, updateWidget } from "../../actions/pageActions";
|
||||
import { getDenormalizedDSL } from "../../selectors/editorSelectors";
|
||||
import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
|
||||
import {
|
||||
EditorConfigIdsType,
|
||||
fetchEditorConfigs,
|
||||
} from "../../actions/configsActions";
|
||||
import { ReduxActionTypes } from "../../constants/ReduxActionConstants";
|
||||
import { updateWidgetProperty } from "../../actions/controlActions";
|
||||
|
||||
|
|
@ -56,7 +45,6 @@ const CanvasContainer = styled.section`
|
|||
|
||||
type EditorProps = {
|
||||
dsl: ContainerWidgetProps<WidgetProps> | any;
|
||||
fetchCanvasWidgets: Function;
|
||||
executeAction: (actionPayloads?: ActionPayload[]) => void;
|
||||
updateWidget: Function;
|
||||
updateWidgetProperty: (
|
||||
|
|
@ -65,64 +53,39 @@ type EditorProps = {
|
|||
propertyValue: any,
|
||||
) => void;
|
||||
savePageLayout: Function;
|
||||
currentPageName: string;
|
||||
currentPageId: string;
|
||||
currentLayoutId: string;
|
||||
showPropertyPane: (
|
||||
widgetId?: string,
|
||||
node?: HTMLDivElement,
|
||||
toggle?: boolean,
|
||||
) => void;
|
||||
fetchConfigs: Function;
|
||||
propertyPaneConfigsId: string;
|
||||
};
|
||||
|
||||
export const WidgetFunctionsContext: Context<WidgetFunctions> = createContext(
|
||||
{},
|
||||
);
|
||||
|
||||
class WidgetsEditor extends React.Component<EditorProps> {
|
||||
componentDidMount() {
|
||||
this.props.fetchConfigs({
|
||||
propertyPaneConfigsId: this.props.propertyPaneConfigsId,
|
||||
// widgetCardsPaneId: this.props.widgetCardsPaneId,
|
||||
// widgetConfigsId: this.props.widgetConfigsId,
|
||||
});
|
||||
this.props.fetchCanvasWidgets(this.props.currentPageId);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<WidgetFunctionsContext.Provider
|
||||
value={{
|
||||
executeAction: this.props.executeAction,
|
||||
updateWidget: this.props.updateWidget,
|
||||
updateWidgetProperty: this.props.updateWidgetProperty,
|
||||
}}
|
||||
>
|
||||
<EditorWrapper>
|
||||
<CanvasContainer>
|
||||
{this.props.dsl && (
|
||||
<Canvas
|
||||
dsl={this.props.dsl}
|
||||
showPropertyPane={this.props.showPropertyPane}
|
||||
/>
|
||||
)}
|
||||
</CanvasContainer>
|
||||
<PropertyPane />
|
||||
</EditorWrapper>
|
||||
</WidgetFunctionsContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
const WidgetsEditor = (props: EditorProps) => (
|
||||
<WidgetFunctionsContext.Provider
|
||||
value={{
|
||||
executeAction: props.executeAction,
|
||||
updateWidget: props.updateWidget,
|
||||
updateWidgetProperty: props.updateWidgetProperty,
|
||||
}}
|
||||
>
|
||||
<EditorWrapper>
|
||||
<CanvasContainer>
|
||||
{props.dsl && (
|
||||
<Canvas dsl={props.dsl} showPropertyPane={props.showPropertyPane} />
|
||||
)}
|
||||
</CanvasContainer>
|
||||
<PropertyPane />
|
||||
</EditorWrapper>
|
||||
</WidgetFunctionsContext.Provider>
|
||||
);
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
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)),
|
||||
executeAction: (actionPayloads?: ActionPayload[]) =>
|
||||
dispatch(executeAction(actionPayloads)),
|
||||
fetchCanvasWidgets: (pageId: string) =>
|
||||
dispatch(fetchPage(pageId, RenderModes.CANVAS)),
|
||||
updateWidget: (
|
||||
operation: WidgetOperation,
|
||||
widgetId: string,
|
||||
|
|
@ -147,8 +108,6 @@ const mapDispatchToProps = (dispatch: any) => {
|
|||
layoutId: string,
|
||||
dsl: ContainerWidgetProps<WidgetProps>,
|
||||
) => dispatch(savePage(pageId, layoutId, dsl)),
|
||||
fetchConfigs: (configsIds: EditorConfigIdsType) =>
|
||||
dispatch(fetchEditorConfigs(configsIds)),
|
||||
showPropertyPane: (
|
||||
widgetId?: string,
|
||||
node?: HTMLDivElement,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
PageListPayload,
|
||||
} from "../../constants/ReduxActionConstants";
|
||||
import { Dialog, Classes, AnchorButton } from "@blueprintjs/core";
|
||||
import { initAppData } from "../../actions/initActions";
|
||||
|
||||
type EditorProps = {
|
||||
currentPageName: string;
|
||||
|
|
@ -26,8 +27,8 @@ type EditorProps = {
|
|||
currentPageId: string;
|
||||
publishApplication: Function;
|
||||
previewPage: Function;
|
||||
initData: Function;
|
||||
createPage: Function;
|
||||
fetchPageList: Function;
|
||||
pages: PageListPayload;
|
||||
switchPage: (pageId: string) => void;
|
||||
isPublishing: boolean;
|
||||
|
|
@ -40,7 +41,7 @@ class Editor extends Component<EditorProps> {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchPageList();
|
||||
this.props.initData();
|
||||
}
|
||||
componentDidUpdate(currently: EditorProps) {
|
||||
const previously = this.props;
|
||||
|
|
@ -123,6 +124,7 @@ const mapStateToProps = (state: AppState) => ({
|
|||
|
||||
const mapDispatchToProps = (dispatch: any) => {
|
||||
return {
|
||||
initData: () => dispatch(initAppData()),
|
||||
publishApplication: (applicationId: string) => {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.PUBLISH_APPLICATION_INIT,
|
||||
|
|
@ -149,11 +151,6 @@ const mapDispatchToProps = (dispatch: any) => {
|
|||
},
|
||||
});
|
||||
},
|
||||
fetchPageList: () => {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.FETCH_PAGE_LIST_INIT,
|
||||
});
|
||||
},
|
||||
switchPage: (pageId: string) => {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.FETCH_PAGE,
|
||||
|
|
|
|||
|
|
@ -4,12 +4,9 @@ import {
|
|||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
} from "../../constants/ReduxActionConstants";
|
||||
import _ from "lodash";
|
||||
import { PageAction } from "../../constants/ActionConstants";
|
||||
import { RestAction } from "../../api/ActionAPI";
|
||||
|
||||
const initialState: ActionDataState = {
|
||||
list: {},
|
||||
data: [],
|
||||
isFetching: false,
|
||||
isRunning: false,
|
||||
|
|
@ -18,9 +15,6 @@ const initialState: ActionDataState = {
|
|||
};
|
||||
|
||||
export interface ActionDataState {
|
||||
list: {
|
||||
[name: string]: PageAction;
|
||||
};
|
||||
data: RestAction[];
|
||||
isFetching: boolean;
|
||||
isRunning: boolean;
|
||||
|
|
@ -29,15 +23,6 @@ export interface ActionDataState {
|
|||
}
|
||||
|
||||
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) => ({
|
||||
...state,
|
||||
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 propertyPaneConfigReducer from "./propertyPaneConfigReducer";
|
||||
import resourceReducer from "./resourcesReducer";
|
||||
import bindingsReducer from "./bindingsReducer";
|
||||
|
||||
const entityReducer = combineReducers({
|
||||
canvasWidgets: canvasWidgetsReducer,
|
||||
|
|
@ -15,5 +16,6 @@ const entityReducer = combineReducers({
|
|||
actions: actionsReducer,
|
||||
propertyConfig: propertyPaneConfigReducer,
|
||||
resources: resourceReducer,
|
||||
nameBindings: bindingsReducer,
|
||||
});
|
||||
export default entityReducer;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { WidgetConfigReducerState } from "./entityReducers/widgetConfigReducer";
|
|||
import { WidgetSidebarReduxState } from "./uiReducers/widgetSidebarReducer";
|
||||
import { ResourceDataState } from "./entityReducers/resourcesReducer";
|
||||
import { AppViewReduxState } from "./uiReducers/appViewReducer";
|
||||
import { BindingsDataState } from "./entityReducers/bindingsReducer";
|
||||
|
||||
const appReducer = combineReducers({
|
||||
entities: entityReducer,
|
||||
|
|
@ -39,5 +40,6 @@ export interface AppState {
|
|||
propertyConfig: PropertyPaneConfigState;
|
||||
widgetConfig: WidgetConfigReducerState;
|
||||
resources: ResourceDataState;
|
||||
nameBindings: BindingsDataState;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,36 +39,42 @@ const getDataTree = (state: AppState) => {
|
|||
return state.entities;
|
||||
};
|
||||
|
||||
const getAction = (state: AppState, actionId: string): PageAction => {
|
||||
return state.entities.actions.list[actionId];
|
||||
const getAction = (
|
||||
state: AppState,
|
||||
actionId: string,
|
||||
): RestAction | undefined => {
|
||||
return _.find(state.entities.actions.data, { id: actionId });
|
||||
};
|
||||
|
||||
export function* evaluateJSONPathSaga(jsonPath: string): any {
|
||||
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 executeActionRequest: ExecuteActionRequest = {
|
||||
actionId: apiAction.actionId,
|
||||
};
|
||||
if (!_.isNil(api.jsonPathKeys)) {
|
||||
const responses: any = yield all(
|
||||
api.jsonPathKeys.map((jsonPath: string) => {
|
||||
return call(evaluateJSONPathSaga, jsonPath);
|
||||
}),
|
||||
const values: any = _.flatten(
|
||||
yield all(
|
||||
api.jsonPathKeys.map((jsonPath: string) => {
|
||||
return call(evaluateJSONPathSaga, jsonPath);
|
||||
}),
|
||||
),
|
||||
);
|
||||
const dynamicBindingMap: Record<string, any> = _.keyBy(
|
||||
responses,
|
||||
(response: string, index: number) => {
|
||||
return api.jsonPathKeys ? api.jsonPathKeys[index] : undefined;
|
||||
},
|
||||
);
|
||||
executeActionRequest.dynamicBindingList = mapToPropList(dynamicBindingMap);
|
||||
const dynamicBindings: Record<string, string> = {};
|
||||
api.jsonPathKeys.forEach((key, i) => {
|
||||
dynamicBindings[key] = values[i];
|
||||
});
|
||||
executeActionRequest.params = mapToPropList(dynamicBindings);
|
||||
}
|
||||
yield ActionAPI.executeAction(executeActionRequest);
|
||||
return yield ActionAPI.executeAction(executeActionRequest);
|
||||
}
|
||||
|
||||
export function* executeActionSaga(action: ReduxAction<ActionPayload[]>) {
|
||||
|
|
@ -128,10 +134,9 @@ export function* fetchActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
|||
|
||||
export function* runActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||
const id = actionPayload.payload.id;
|
||||
const response: ActionApiResponse = yield ActionAPI.executeAction({
|
||||
const response: ActionApiResponse = yield call(executeAPIQueryActionSaga, {
|
||||
actionId: id,
|
||||
});
|
||||
|
||||
let payload = response;
|
||||
if (response.responseMeta && response.responseMeta.error) {
|
||||
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 applicationSagas from "./ApplicationSagas";
|
||||
import { watchResourcesSagas } from "./ResourcesSagas";
|
||||
import initSagas from "./InitSagas";
|
||||
import bindingsSagas from "./BindingsSagas";
|
||||
|
||||
export function* rootSaga() {
|
||||
yield all([
|
||||
spawn(initSagas),
|
||||
spawn(pageSagas),
|
||||
spawn(fetchWidgetCardsSaga),
|
||||
spawn(watchActionSagas),
|
||||
|
|
@ -17,5 +21,6 @@ export function* rootSaga() {
|
|||
spawn(configsSagas),
|
||||
spawn(watchResourcesSagas),
|
||||
spawn(applicationSagas),
|
||||
spawn(bindingsSagas),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
// import * as React from "react";
|
||||
declare module 'react-base-table';
|
||||
declare module "react-base-table";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user