Merge branch 'feature/canvas-fixes-1' into 'release'
Fixes: Saving notification, global error handling, show controls on hover, fixed row height See merge request theappsmith/internal-tools-client!36
This commit is contained in:
commit
a308337172
|
|
@ -1,10 +1,3 @@
|
|||
## GIT Commit Hooks
|
||||
|
||||
This project has scripts to ESLint fix and Prettier write the code on the git commit hook.
|
||||
It is recommended to install ESLint and Prettier global for successful git commits
|
||||
|
||||
`yarn global add eslint`
|
||||
`yarn global add prettier`
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { FetchPageRequest } from "../api/PageApi";
|
||||
import { ResponseMeta } from "../api/ApiResponses";
|
||||
import { RenderMode } from "../constants/WidgetConstants";
|
||||
import { WidgetProps, WidgetOperation } from "../widgets/BaseWidget";
|
||||
import { WidgetType } from "../constants/WidgetConstants";
|
||||
|
|
@ -8,7 +7,6 @@ import {
|
|||
ReduxAction,
|
||||
UpdateCanvasPayload,
|
||||
SavePagePayload,
|
||||
SavePageErrorPayload,
|
||||
SavePageSuccessPayload,
|
||||
} from "../constants/ReduxActionConstants";
|
||||
import { ContainerWidgetProps } from "../widgets/ContainerWidget";
|
||||
|
|
@ -26,13 +24,6 @@ export const fetchPage = (
|
|||
};
|
||||
};
|
||||
|
||||
export const fetchPageError = (payload: ResponseMeta) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PAGE_ERROR,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const addWidget = (
|
||||
pageId: string,
|
||||
widget: WidgetProps,
|
||||
|
|
@ -86,13 +77,6 @@ export const savePageSuccess = (payload: SavePageSuccessPayload) => {
|
|||
};
|
||||
};
|
||||
|
||||
export const savePageError = (payload: SavePageErrorPayload) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SAVE_PAGE_ERROR,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export type WidgetAddChild = {
|
||||
widgetId: string;
|
||||
type: WidgetType;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import { ReduxActionTypes } from "../constants/ReduxActionConstants";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
} from "../constants/ReduxActionConstants";
|
||||
import { WidgetCardProps } from "../widgets/BaseWidget";
|
||||
|
||||
export const fetchWidgetCards = () => {
|
||||
|
|
@ -9,7 +12,7 @@ export const fetchWidgetCards = () => {
|
|||
|
||||
export const errorFetchingWidgetCards = (error: any) => {
|
||||
return {
|
||||
type: ReduxActionTypes.ERROR_FETCHING_WIDGET_CARDS,
|
||||
type: ReduxActionErrorTypes.FETCH_WIDGET_CARDS_ERROR,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
|
@ -18,7 +21,7 @@ export const successFetchingWidgetCards = (cards: {
|
|||
[id: string]: WidgetCardProps[];
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SUCCESS_FETCHING_WIDGET_CARDS,
|
||||
type: ReduxActionTypes.FETCH_WIDGET_CARDS_SUCCESS,
|
||||
cards,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export type FetchPageResponse = ApiResponse & {
|
|||
};
|
||||
};
|
||||
|
||||
export interface SavePageResponse {
|
||||
export interface SavePageResponse extends ApiResponse {
|
||||
pageId: string;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ export const getEditorConfigs = () => {
|
|||
return {
|
||||
currentPageId: "5d807e7f795dc6000482bc78",
|
||||
currentLayoutId: "5d807e7f795dc6000482bc77",
|
||||
currentPageName: "page1",
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
currentPageId: "5d807e76795dc6000482bc76",
|
||||
currentLayoutId: "5d807e76795dc6000482bc75",
|
||||
currentPageName: "page1",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
console.log("here", process.env.NODE_ENV);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { WidgetProps, WidgetCardProps } from "../widgets/BaseWidget";
|
||||
|
||||
export const ReduxActionTypes: { [key: string]: string } = {
|
||||
REPORT_ERROR: "REPORT_ERROR",
|
||||
FLUSH_ERRORS: "FLUSH_ERRORS",
|
||||
UPDATE_CANVAS: "UPDATE_CANVAS",
|
||||
FETCH_CANVAS: "FETCH_CANVAS",
|
||||
CLEAR_CANVAS: "CLEAR_CANVAS",
|
||||
|
|
@ -16,8 +18,7 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
LOAD_PROPERTY_CONFIG: "LOAD_PROPERTY_CONFIG",
|
||||
PUBLISH: "PUBLISH",
|
||||
FETCH_WIDGET_CARDS: "FETCH_WIDGET_CARDS",
|
||||
SUCCESS_FETCHING_WIDGET_CARDS: "SUCCESS_FETCHING_WIDGET_CARDS",
|
||||
ERROR_FETCHING_WIDGET_CARDS: "ERROR_FETCHING_WIDGET_CARDS",
|
||||
FETCH_WIDGET_CARDS_SUCCESS: "FETCH_WIDGET_CARDS_SUCCESS",
|
||||
ADD_PAGE_WIDGET: "ADD_PAGE_WIDGET",
|
||||
REMOVE_PAGE_WIDGET: "REMOVE_PAGE_WIDGET",
|
||||
LOAD_API_RESPONSE: "LOAD_API_RESPONSE",
|
||||
|
|
@ -26,8 +27,6 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
LOAD_CANVAS_ACTIONS: "LOAD_CANVAS_ACTIONS",
|
||||
SAVE_PAGE_INIT: "SAVE_PAGE_INIT",
|
||||
SAVE_PAGE_SUCCESS: "SAVE_PAGE_SUCCESS",
|
||||
SAVE_PAGE_ERROR: "SAVE_PAGE_ERROR",
|
||||
FETCH_PAGE_ERROR: "FETCH_PAGE_ERROR",
|
||||
UPDATE_LAYOUT: "UPDATE_LAYOUT",
|
||||
WIDGET_ADD_CHILD: "WIDGET_ADD_CHILD",
|
||||
WIDGET_REMOVE_CHILD: "WIDGET_REMOVE_CHILD",
|
||||
|
|
@ -37,18 +36,37 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
SHOW_PROPERTY_PANE: "SHOW_PROPERTY_PANE",
|
||||
UPDATE_WIDGET_PROPERTY: "UPDATE_WIDGET_PROPERTY",
|
||||
};
|
||||
|
||||
export type ReduxActionType = (typeof ReduxActionTypes)[keyof typeof ReduxActionTypes];
|
||||
|
||||
export const ReduxActionErrorTypes: { [key: string]: string } = {
|
||||
API_ERROR: "API_ERROR",
|
||||
WIDGET_DELETE_ERROR: "WIDGET_DELETE_ERROR",
|
||||
WIDGET_MOVE_ERROR: "WIDGET_MOVE_ERROR",
|
||||
WIDGET_RESIZE_ERROR: "WIDGET_RESIZE_ERROR",
|
||||
WIDGET_REMOVE_CHILD_ERROR: "WIDGET_REMOVE_CHILD_ERROR",
|
||||
WIDGET_ADD_CHILD_ERROR: "WIDGET_ADD_CHILD_ERROR",
|
||||
FETCH_PAGE_ERROR: "FETCH_PAGE_ERROR",
|
||||
SAVE_PAGE_ERROR: "SAVE_PAGE_ERROR",
|
||||
FETCH_WIDGET_CARDS_ERROR: "FETCH_WIDGET_CARDS_ERROR",
|
||||
};
|
||||
export type ReduxActionErrorType = (typeof ReduxActionErrorTypes)[keyof typeof ReduxActionErrorTypes];
|
||||
|
||||
export interface ReduxAction<T> {
|
||||
type: ReduxActionType;
|
||||
type: ReduxActionType | ReduxActionErrorType;
|
||||
payload: T;
|
||||
}
|
||||
|
||||
export interface ReduxActionErrorPayload {
|
||||
message: string;
|
||||
source?: string;
|
||||
}
|
||||
|
||||
export interface UpdateCanvasPayload {
|
||||
pageWidgetId: string;
|
||||
widgets: { [widgetId: string]: WidgetProps };
|
||||
layoutId: string;
|
||||
currentLayoutId: string;
|
||||
currentPageId: string;
|
||||
currentPageName: string;
|
||||
}
|
||||
|
||||
export interface ShowPropertyPanePayload {
|
||||
|
|
|
|||
|
|
@ -71,4 +71,5 @@ export const GridDefaults = {
|
|||
DEFAULT_WIDGET_HEIGHT: 100,
|
||||
DEFAULT_GRID_COLUMNS: 16,
|
||||
DEFAULT_GRID_ROWS: 32,
|
||||
DEFAULT_GRID_ROW_HEIGHT: 40,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,17 +6,25 @@ import { useDrag, DragPreviewImage, DragSourceMonitor } from "react-dnd";
|
|||
import blankImage from "../assets/images/blank.png";
|
||||
import { ContainerProps } from "./ContainerComponent";
|
||||
|
||||
const DraggableWrapper = styled.div`
|
||||
&:hover > div {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
const DragHandle = styled.div`
|
||||
position: absolute;
|
||||
left: ${props => props.theme.spaces[2]}px;
|
||||
top: -${props => props.theme.spaces[8]}px;
|
||||
cursor: move;
|
||||
display: none;
|
||||
`;
|
||||
|
||||
const DeleteControl = styled.div`
|
||||
position: absolute;
|
||||
right: ${props => props.theme.spaces[2]}px;
|
||||
top: -${props => props.theme.spaces[8]}px;
|
||||
display: none;
|
||||
`;
|
||||
|
||||
type DraggableComponentProps = WidgetProps & ContainerProps;
|
||||
|
|
@ -35,7 +43,7 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
return (
|
||||
<React.Fragment>
|
||||
<DragPreviewImage src={blankImage} connect={preview} />
|
||||
<div
|
||||
<DraggableWrapper
|
||||
ref={preview}
|
||||
style={{
|
||||
display: isDragging ? "none" : "flex",
|
||||
|
|
@ -56,7 +64,7 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
<Icon icon="trash" iconSize={20} />
|
||||
</DeleteControl>
|
||||
{props.children}
|
||||
</div>
|
||||
</DraggableWrapper>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,13 @@ const ResizableContainer = styled(Resizable)`
|
|||
}};
|
||||
`;
|
||||
|
||||
const CustomHandle = (props: any) => <div {...props} />;
|
||||
const DisplayHandleWrapper = styled.div`
|
||||
display: none;
|
||||
${ResizableContainer}:hover & {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
const CustomHandle = (props: any) => <DisplayHandleWrapper {...props} />;
|
||||
const BottomRightHandle = () => (
|
||||
<CustomHandle>
|
||||
<Icon iconSize={15} icon="arrow-bottom-right" />
|
||||
|
|
|
|||
|
|
@ -1,99 +1,99 @@
|
|||
import { WidgetCardsPaneReduxState } from "../reducers/uiReducers/widgetCardsPaneReducer";
|
||||
import { WidgetCardProps } from "../widgets/BaseWidget";
|
||||
import { generateReactKey } from "../utils/generators";
|
||||
|
||||
const WidgetCardsPaneResponse: WidgetCardsPaneReduxState = {
|
||||
cards: {
|
||||
common: [
|
||||
{
|
||||
type: "TEXT_WIDGET",
|
||||
icon: "icon-text",
|
||||
widgetCardName: "Text",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "BUTTON_WIDGET",
|
||||
icon: "icon-button",
|
||||
widgetCardName: "Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "SPINNER_WIDGET",
|
||||
icon: "icon-switch",
|
||||
widgetCardName: "Spinner",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "CONTAINER_WIDGET",
|
||||
icon: "icon-container",
|
||||
widgetCardName: "Container",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
form: [
|
||||
{
|
||||
type: "BUTTON_WIDGET",
|
||||
icon: "icon-button",
|
||||
widgetCardName: "Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "BUTTON_WIDGET",
|
||||
icon: "icon-button",
|
||||
widgetCardName: "Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "DROP_DOWN_WIDGET",
|
||||
icon: "icon-dropdown",
|
||||
widgetCardName: "Dropdown",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "DATE_PICKER_WIDGET",
|
||||
icon: "icon-datepicker",
|
||||
widgetCardName: "DatePicker",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "RADIO_GROUP_WIDGET",
|
||||
icon: "icon-radio",
|
||||
widgetCardName: "Radio Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "SWITCH_WIDGET",
|
||||
icon: "icon-switch",
|
||||
widgetCardName: "Toggle",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
view: [
|
||||
{
|
||||
type: "TEXT_WIDGET",
|
||||
icon: "icon-text",
|
||||
widgetCardName: "Text",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "CONTAINER_WIDGET",
|
||||
icon: "icon-container",
|
||||
widgetCardName: "Container",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "SPINNER_WIDGET",
|
||||
icon: "icon-spinner",
|
||||
widgetCardName: "Spinner",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "TABLE_WIDGET",
|
||||
icon: "icon-table",
|
||||
widgetCardName: "Table",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
},
|
||||
const WidgetCardsPaneResponse: {
|
||||
[id: string]: WidgetCardProps[];
|
||||
} = {
|
||||
common: [
|
||||
{
|
||||
type: "TEXT_WIDGET",
|
||||
icon: "icon-text",
|
||||
widgetCardName: "Text",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "BUTTON_WIDGET",
|
||||
icon: "icon-button",
|
||||
widgetCardName: "Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "SPINNER_WIDGET",
|
||||
icon: "icon-switch",
|
||||
widgetCardName: "Spinner",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "CONTAINER_WIDGET",
|
||||
icon: "icon-container",
|
||||
widgetCardName: "Container",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
form: [
|
||||
{
|
||||
type: "BUTTON_WIDGET",
|
||||
icon: "icon-button",
|
||||
widgetCardName: "Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "BUTTON_WIDGET",
|
||||
icon: "icon-button",
|
||||
widgetCardName: "Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "DROP_DOWN_WIDGET",
|
||||
icon: "icon-dropdown",
|
||||
widgetCardName: "Dropdown",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "DATE_PICKER_WIDGET",
|
||||
icon: "icon-datepicker",
|
||||
widgetCardName: "DatePicker",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "RADIO_GROUP_WIDGET",
|
||||
icon: "icon-radio",
|
||||
widgetCardName: "Radio Button",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "SWITCH_WIDGET",
|
||||
icon: "icon-switch",
|
||||
widgetCardName: "Toggle",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
view: [
|
||||
{
|
||||
type: "TEXT_WIDGET",
|
||||
icon: "icon-text",
|
||||
widgetCardName: "Text",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "CONTAINER_WIDGET",
|
||||
icon: "icon-container",
|
||||
widgetCardName: "Container",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "SPINNER_WIDGET",
|
||||
icon: "icon-spinner",
|
||||
widgetCardName: "Spinner",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "TABLE_WIDGET",
|
||||
icon: "icon-table",
|
||||
widgetCardName: "Table",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default WidgetCardsPaneResponse;
|
||||
|
|
|
|||
|
|
@ -1,35 +1,57 @@
|
|||
import React, { Component } from "react";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
// import { connect } from "react-redux";
|
||||
// import { AppState } from "../../reducers";
|
||||
// import { EditorHeaderReduxState } from "../../reducers/uiReducers/editorHeaderReducer";
|
||||
import { Breadcrumbs, IBreadcrumbProps, Spinner } from "@blueprintjs/core";
|
||||
|
||||
const Header = styled.header`
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
padding: 0px 30px;
|
||||
box-shadow: 0px 0px 3px #ccc;
|
||||
background: #fff;
|
||||
font-size: ${props => props.theme.fontSizes[1]}px;
|
||||
`;
|
||||
|
||||
class EditorHeader extends Component {
|
||||
render() {
|
||||
return <Header></Header>;
|
||||
const NotificationText = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
`;
|
||||
|
||||
const StretchedBreadCrumb = styled(Breadcrumbs)`
|
||||
flex-grow: 10;
|
||||
* {
|
||||
font-family: ${props => props.theme.fonts[0]};
|
||||
font-size: ${props => props.theme.fontSizes[2]}px;
|
||||
}
|
||||
}
|
||||
li:after {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.71 7.29l-4-4a1.003 1.003 0 0 0-1.42 1.42L8.59 8 5.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l4-4c.18-.18.29-.43.29-.71 0-.28-.11-.53-.29-.71z' fill='rgba(92,112,128,1)'/%3E%3C/svg%3E");
|
||||
}
|
||||
`;
|
||||
|
||||
type EditorHeaderProps = {
|
||||
notificationText?: string;
|
||||
pageName: string;
|
||||
};
|
||||
|
||||
export const EditorHeader = (props: EditorHeaderProps) => {
|
||||
const navigation: IBreadcrumbProps[] = [
|
||||
{ href: "#", icon: "folder-close", text: "appsmith-dev" },
|
||||
{ href: "#", icon: "folder-close", text: "application" },
|
||||
{ icon: "page-layout", text: props.pageName, current: true },
|
||||
];
|
||||
|
||||
return (
|
||||
<Header>
|
||||
<StretchedBreadCrumb items={navigation} />
|
||||
<NotificationText>
|
||||
{props.notificationText && <Spinner size={Spinner.SIZE_SMALL} />}
|
||||
<span>{props.notificationText}</span>
|
||||
</NotificationText>
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditorHeader;
|
||||
|
||||
// const mapStateToProps = (
|
||||
// state: AppState,
|
||||
// props: any,
|
||||
// ): EditorHeaderReduxState => {
|
||||
// return state;
|
||||
// };
|
||||
|
||||
// const mapDispatchToProps = (dispatch: any) => {
|
||||
// return {};
|
||||
// };
|
||||
|
||||
// export default connect(
|
||||
// mapStateToProps,
|
||||
// mapDispatchToProps,
|
||||
// )(EditorHeader);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ export const Wrapper = styled.div`
|
|||
path {
|
||||
fill: ${props => props.theme.colors.textDefault};
|
||||
}
|
||||
rect {
|
||||
stroke: ${props => props.theme.colors.textDefault};
|
||||
}
|
||||
}
|
||||
}
|
||||
& i {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React, { Component } from "react";
|
||||
import { Position, Toaster } from "@blueprintjs/core";
|
||||
import { connect } from "react-redux";
|
||||
import styled from "styled-components";
|
||||
import Canvas from "./Canvas";
|
||||
|
|
@ -20,10 +19,6 @@ import { executeAction } from "../../actions/widgetActions";
|
|||
import { ActionPayload } from "../../constants/ActionConstants";
|
||||
import PropertyPane from "./PropertyPane";
|
||||
|
||||
const SaveToast = Toaster.create({
|
||||
position: Position.TOP,
|
||||
});
|
||||
|
||||
const CanvasContainer = styled.section`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
|
@ -60,7 +55,7 @@ type EditorProps = {
|
|||
updateWidget: Function;
|
||||
cards: { [id: string]: WidgetCardProps[] } | any;
|
||||
savePageLayout: Function;
|
||||
page: string;
|
||||
currentPageName: string;
|
||||
currentPageId: string;
|
||||
currentLayoutId: string;
|
||||
isSaving: boolean;
|
||||
|
|
@ -71,23 +66,13 @@ class Editor extends Component<EditorProps> {
|
|||
this.props.fetchCanvasWidgets(this.props.currentPageId);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: EditorProps) {
|
||||
if (this.props.isSaving && prevProps.isSaving !== this.props.isSaving) {
|
||||
SaveToast.clear();
|
||||
SaveToast.show({ message: "Saving Page..." });
|
||||
} else if (
|
||||
!this.props.isSaving &&
|
||||
prevProps.isSaving !== this.props.isSaving
|
||||
) {
|
||||
SaveToast.clear();
|
||||
SaveToast.show({ message: "Page Saved" });
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EditorHeader></EditorHeader>
|
||||
<EditorHeader
|
||||
notificationText={this.props.isSaving ? "Saving page..." : undefined}
|
||||
pageName={this.props.currentPageName}
|
||||
/>
|
||||
<EditorWrapper>
|
||||
<WidgetCardsPane cards={this.props.cards} />
|
||||
<CanvasContainer>
|
||||
|
|
@ -122,8 +107,9 @@ const mapStateToProps = (state: AppState): EditorReduxState => {
|
|||
);
|
||||
const configs = state.entities.widgetConfig.config;
|
||||
|
||||
const cards = state.ui.widgetCardsPane.cards;
|
||||
Object.keys(cards).forEach((group: string) => {
|
||||
const cards = state.ui.editor.cards;
|
||||
const groups: string[] = Object.keys(cards);
|
||||
groups.forEach((group: string) => {
|
||||
cards[group] = cards[group].map((widget: WidgetCardProps) => ({
|
||||
...widget,
|
||||
...configs[widget.type],
|
||||
|
|
@ -136,6 +122,7 @@ const mapStateToProps = (state: AppState): EditorReduxState => {
|
|||
pageWidgetId: state.ui.editor.pageWidgetId,
|
||||
currentPageId: state.ui.editor.currentPageId,
|
||||
currentLayoutId: state.ui.editor.currentLayoutId,
|
||||
currentPageName: state.ui.editor.currentPageName,
|
||||
isSaving: state.ui.editor.isSaving,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { combineReducers } from "redux";
|
|||
import entityReducer from "./entityReducers";
|
||||
import uiReducer from "./uiReducers";
|
||||
import { CanvasWidgetsReduxState } from "./entityReducers/canvasWidgetsReducer";
|
||||
import { WidgetCardsPaneReduxState } from "./uiReducers/widgetCardsPaneReducer";
|
||||
import { EditorReduxState } from "./uiReducers/editorReducer";
|
||||
import { ErrorReduxState } from "./uiReducers/errorReducer";
|
||||
import { APIDataState } from "./entityReducers/apiDataReducer";
|
||||
import { QueryDataState } from "./entityReducers/queryDataReducer";
|
||||
import { ActionDataState } from "./entityReducers/actionsReducer";
|
||||
|
|
@ -20,9 +20,9 @@ export default appReducer;
|
|||
|
||||
export interface AppState {
|
||||
ui: {
|
||||
widgetCardsPane: WidgetCardsPaneReduxState;
|
||||
editor: EditorReduxState;
|
||||
propertyPane: PropertyPaneReduxState;
|
||||
errors: ErrorReduxState;
|
||||
};
|
||||
entities: {
|
||||
canvasWidgets: CanvasWidgetsReduxState;
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
import { createReducer } from "../../utils/AppsmithUtils";
|
||||
|
||||
const initialState = {};
|
||||
|
||||
const editorHeaderReducer = createReducer(initialState, {});
|
||||
|
||||
// export interface EditorHeaderReduxState {}
|
||||
|
||||
export default editorHeaderReducer;
|
||||
|
|
@ -7,15 +7,18 @@ import {
|
|||
} from "../../constants/ReduxActionConstants";
|
||||
import { WidgetCardProps, WidgetProps } from "../../widgets/BaseWidget";
|
||||
import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
|
||||
import WidgetCardsPaneResponse from "../../mockResponses/WidgetCardsPaneResponse";
|
||||
|
||||
const editorConfigs = getEditorConfigs();
|
||||
const initialState: EditorReduxState = {
|
||||
pageWidgetId: "0",
|
||||
...editorConfigs,
|
||||
isSaving: false,
|
||||
cards: WidgetCardsPaneResponse,
|
||||
};
|
||||
|
||||
const editorReducer = createReducer(initialState, {
|
||||
[ReduxActionTypes.SUCCESS_FETCHING_WIDGET_CARDS]: (
|
||||
[ReduxActionTypes.FETCH_WIDGET_CARDS_SUCCESS]: (
|
||||
state: EditorReduxState,
|
||||
action: ReduxAction<LoadWidgetCardsPanePayload>,
|
||||
) => {
|
||||
|
|
@ -27,19 +30,17 @@ const editorReducer = createReducer(initialState, {
|
|||
[ReduxActionTypes.SAVE_PAGE_SUCCESS]: (state: EditorReduxState) => {
|
||||
return { ...state, isSaving: false };
|
||||
},
|
||||
[ReduxActionTypes.SAVE_PAGE_ERROR]: (state: EditorReduxState) => {
|
||||
return { ...state, isSaving: false };
|
||||
},
|
||||
});
|
||||
|
||||
export interface EditorReduxState {
|
||||
dsl?: ContainerWidgetProps<WidgetProps>;
|
||||
cards?: {
|
||||
cards: {
|
||||
[id: string]: WidgetCardProps[];
|
||||
};
|
||||
pageWidgetId: string;
|
||||
currentPageId: string;
|
||||
currentLayoutId: string;
|
||||
currentPageName: string;
|
||||
isSaving: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
31
app/client/src/reducers/uiReducers/errorReducer.tsx
Normal file
31
app/client/src/reducers/uiReducers/errorReducer.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { createReducer } from "../../utils/AppsmithUtils";
|
||||
import {
|
||||
ReduxAction,
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorPayload,
|
||||
} from "../../constants/ReduxActionConstants";
|
||||
|
||||
const initialState: ErrorReduxState = { sourceAction: "", message: "" };
|
||||
|
||||
const errorReducer = createReducer(initialState, {
|
||||
[ReduxActionTypes.REPORT_ERROR]: (
|
||||
state: ErrorReduxState,
|
||||
action: ReduxAction<ReduxActionErrorPayload>,
|
||||
) => {
|
||||
return {
|
||||
sourceAction: action.payload.source,
|
||||
message: action.payload.message,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.FLUSH_ERRORS]: () => {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
|
||||
export interface ErrorReduxState {
|
||||
// Expiration?
|
||||
sourceAction?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export default errorReducer;
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
import { combineReducers } from "redux";
|
||||
import widgetCardsPaneReducer from "./widgetCardsPaneReducer";
|
||||
import editorHeaderReducer from "./editorHeaderReducer";
|
||||
import editorReducer from "./editorReducer";
|
||||
import errorReducer from "./errorReducer";
|
||||
import propertyPaneReducer from "./propertyPaneReducer";
|
||||
|
||||
const uiReducer = combineReducers({
|
||||
widgetCardsPane: widgetCardsPaneReducer,
|
||||
editorHeader: editorHeaderReducer,
|
||||
editor: editorReducer,
|
||||
errors: errorReducer,
|
||||
propertyPane: propertyPaneReducer,
|
||||
});
|
||||
export default uiReducer;
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import { createReducer } from "../../utils/AppsmithUtils";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxAction,
|
||||
LoadWidgetCardsPanePayload,
|
||||
} from "../../constants/ReduxActionConstants";
|
||||
import { WidgetCardProps } from "../../widgets/BaseWidget";
|
||||
import WidgetCardsPaneResponse from "../../mockResponses/WidgetCardsPaneResponse";
|
||||
|
||||
const initialState: WidgetCardsPaneReduxState = WidgetCardsPaneResponse;
|
||||
|
||||
const widgetCardsPaneReducer = createReducer(initialState, {
|
||||
[ReduxActionTypes.ERROR_FETCHING_WIDGET_CARDS]: (
|
||||
state: WidgetCardsPaneReduxState,
|
||||
action: ReduxAction<LoadWidgetCardsPanePayload>,
|
||||
) => {
|
||||
return { cards: action.payload.cards };
|
||||
},
|
||||
});
|
||||
|
||||
export interface WidgetCardsPaneReduxState {
|
||||
cards: {
|
||||
[id: string]: WidgetCardProps[];
|
||||
};
|
||||
}
|
||||
|
||||
export default widgetCardsPaneReducer;
|
||||
38
app/client/src/sagas/ErrorSagas.tsx
Normal file
38
app/client/src/sagas/ErrorSagas.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
ReduxAction,
|
||||
} from "../constants/ReduxActionConstants";
|
||||
|
||||
import { ApiResponse } from "../api/ApiResponses";
|
||||
import { put, takeLatest } from "redux-saga/effects";
|
||||
|
||||
export function* validateResponse(response: ApiResponse) {
|
||||
if (response.responseMeta.success) {
|
||||
return true;
|
||||
} else {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.API_ERROR,
|
||||
payload: {
|
||||
error: response.responseMeta.error,
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function* errorSaga(errorAction: ReduxAction<{ error: any }>) {
|
||||
// Just a pass through for now.
|
||||
// Add procedures to customize errors here
|
||||
yield put({
|
||||
type: ReduxActionTypes.REPORT_ERROR,
|
||||
payload: {
|
||||
message: errorAction.payload.error,
|
||||
source: errorAction.type,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default function* errorSagas() {
|
||||
yield takeLatest(Object.values(ReduxActionErrorTypes), errorSaga);
|
||||
}
|
||||
|
|
@ -1,15 +1,11 @@
|
|||
import CanvasWidgetsNormalizer from "../normalizers/CanvasWidgetsNormalizer";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
ReduxAction,
|
||||
UpdateCanvasPayload,
|
||||
} from "../constants/ReduxActionConstants";
|
||||
import {
|
||||
updateCanvas,
|
||||
savePageError,
|
||||
savePageSuccess,
|
||||
fetchPageError,
|
||||
} from "../actions/pageActions";
|
||||
import { updateCanvas, savePageSuccess } from "../actions/pageActions";
|
||||
import PageApi, {
|
||||
FetchPageResponse,
|
||||
SavePageResponse,
|
||||
|
|
@ -25,27 +21,31 @@ import {
|
|||
takeEvery,
|
||||
all,
|
||||
} from "redux-saga/effects";
|
||||
|
||||
import { extractCurrentDSL } from "../utils/WidgetPropsUtils";
|
||||
import { getEditorConfigs } from "./selectors";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
|
||||
export function* fetchPageSaga(
|
||||
pageRequestAction: ReduxAction<FetchPageRequest>,
|
||||
) {
|
||||
const pageRequest = pageRequestAction.payload;
|
||||
try {
|
||||
const pageRequest = pageRequestAction.payload;
|
||||
const fetchPageResponse: FetchPageResponse = yield call(
|
||||
PageApi.fetchPage,
|
||||
pageRequest,
|
||||
);
|
||||
|
||||
if (fetchPageResponse.responseMeta.success) {
|
||||
const isValidResponse = yield validateResponse(fetchPageResponse);
|
||||
if (isValidResponse) {
|
||||
const normalizedResponse = CanvasWidgetsNormalizer.normalize(
|
||||
extractCurrentDSL(fetchPageResponse),
|
||||
);
|
||||
const canvasWidgetsPayload: UpdateCanvasPayload = {
|
||||
pageWidgetId: normalizedResponse.result,
|
||||
currentPageName: fetchPageResponse.data.name,
|
||||
currentPageId: fetchPageResponse.data.id,
|
||||
widgets: normalizedResponse.entities.canvasWidgets,
|
||||
layoutId: fetchPageResponse.data.layouts[0].id, // TODO(abhinav): Handle for multiple layouts
|
||||
currentLayoutId: fetchPageResponse.data.layouts[0].id, // TODO(abhinav): Handle for multiple layouts
|
||||
};
|
||||
yield all([
|
||||
put(updateCanvas(canvasWidgetsPayload)),
|
||||
|
|
@ -56,8 +56,12 @@ export function* fetchPageSaga(
|
|||
]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
yield put(fetchPageError(error));
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_PAGE_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,10 +72,17 @@ export function* savePageSaga(savePageAction: ReduxAction<SavePageRequest>) {
|
|||
PageApi.savePage,
|
||||
savePageRequest,
|
||||
);
|
||||
yield put(savePageSuccess(savePageResponse));
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
yield put(savePageError(err));
|
||||
const isValidResponse = validateResponse(savePageResponse);
|
||||
if (isValidResponse) {
|
||||
yield put(savePageSuccess(savePageResponse));
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.SAVE_PAGE_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +98,6 @@ export function* saveLayoutSaga(
|
|||
{ canvasWidgets: widgets },
|
||||
);
|
||||
const editorConfigs = yield select(getEditorConfigs) as any;
|
||||
console.log(editorConfigs);
|
||||
yield put({
|
||||
type: ReduxActionTypes.SAVE_PAGE_INIT,
|
||||
payload: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
// import CanvasWidgetsNormalizer from "../normalizers/CanvasWidgetsNormalizer"
|
||||
import { ReduxActionTypes } from "../constants/ReduxActionConstants";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
} from "../constants/ReduxActionConstants";
|
||||
import WidgetCardsPaneApi, {
|
||||
WidgetCardsPaneResponse,
|
||||
} from "../api/WidgetCardsPaneApi";
|
||||
|
|
@ -13,7 +15,7 @@ export function* fetchWidgetCards() {
|
|||
]);
|
||||
yield put(successFetchingWidgetCards(widgetCards.cards));
|
||||
} catch (err) {
|
||||
yield put({ type: ReduxActionTypes.ERROR_FETCHING_WIDGET_CARDS, err });
|
||||
yield put({ type: ReduxActionErrorTypes.FETCH_WIDGET_CARDS_ERROR, err });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import pageSagas from "../sagas/PageSagas";
|
|||
import { fetchWidgetCardsSaga } from "./WidgetCardsPaneSagas";
|
||||
import { watchExecuteActionSaga } from "./ActionSagas";
|
||||
import widgetOperationSagas from "./WidgetOperationSagas";
|
||||
import errorSagas from "./ErrorSagas";
|
||||
|
||||
export function* rootSaga() {
|
||||
yield all([
|
||||
|
|
@ -10,5 +11,6 @@ export function* rootSaga() {
|
|||
spawn(fetchWidgetCardsSaga),
|
||||
spawn(watchExecuteActionSaga),
|
||||
spawn(widgetOperationSagas),
|
||||
spawn(errorSagas),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
27
app/client/src/utils/AppsmithSagaHelper.tsx
Normal file
27
app/client/src/utils/AppsmithSagaHelper.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import {
|
||||
call as ReduxSagaCall,
|
||||
select as ReduxSagaSelect,
|
||||
put as ReduxSagaPut,
|
||||
takeLatest as ReduxSagaTakeLatest,
|
||||
takeEvery as ReduxSagaTakeEvery,
|
||||
all as ReduxSagaAll,
|
||||
} from "redux-saga/effects";
|
||||
|
||||
function* safe(effect: any) {
|
||||
try {
|
||||
return yield effect;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
export const call = (fn: any, ...args: unknown[]) =>
|
||||
safe(ReduxSagaCall(fn, ...args));
|
||||
export const select = (state: any, ...args: any[]) =>
|
||||
safe(ReduxSagaSelect(state, ...args));
|
||||
export const put = (action: any) => safe(ReduxSagaPut(action));
|
||||
export const takeLatest = (pattern: any, worker: any) =>
|
||||
safe(ReduxSagaTakeLatest(pattern, worker));
|
||||
export const takeEvery = (pattern: any, worker: any) =>
|
||||
safe(ReduxSagaTakeEvery(pattern, worker));
|
||||
export const all = (args: unknown[]) => safe(ReduxSagaAll(args));
|
||||
|
|
@ -8,15 +8,3 @@ export const snapToGrid = (
|
|||
const snappedY = Math.floor(y / rowHeight);
|
||||
return [snappedX, snappedY];
|
||||
};
|
||||
|
||||
export const getRowColSizes = (
|
||||
rowCount: number,
|
||||
columnCount: number,
|
||||
width: number,
|
||||
height: number,
|
||||
): { rowHeight: number; columnWidth: number } => {
|
||||
return {
|
||||
columnWidth: width / columnCount,
|
||||
rowHeight: height / rowCount,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,17 +94,21 @@ abstract class BaseWidget<
|
|||
|
||||
getCanvasView(): JSX.Element {
|
||||
const style = this.getPositionStyle();
|
||||
return (
|
||||
<DraggableComponent
|
||||
{...this.props}
|
||||
style={{ ...style }}
|
||||
orientation={"VERTICAL"}
|
||||
>
|
||||
<ResizableComponent style={{ ...style }} {...this.props}>
|
||||
{this.getPageView()}
|
||||
</ResizableComponent>
|
||||
</DraggableComponent>
|
||||
);
|
||||
if (!this.props.parentId) {
|
||||
return this.getPageView();
|
||||
} else {
|
||||
return (
|
||||
<DraggableComponent
|
||||
{...this.props}
|
||||
style={{ ...style }}
|
||||
orientation={"VERTICAL"}
|
||||
>
|
||||
<ResizableComponent style={{ ...style }} {...this.props}>
|
||||
{this.getPageView()}
|
||||
</ResizableComponent>
|
||||
</DraggableComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract getWidgetType(): WidgetType;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { GridDefaults } from "../constants/WidgetConstants";
|
|||
import DraggableComponent from "../editorComponents/DraggableComponent";
|
||||
import ResizableComponent from "../editorComponents/ResizableComponent";
|
||||
|
||||
const { DEFAULT_GRID_COLUMNS, DEFAULT_GRID_ROWS } = GridDefaults;
|
||||
const { DEFAULT_GRID_COLUMNS, DEFAULT_GRID_ROW_HEIGHT } = GridDefaults;
|
||||
|
||||
class ContainerWidget extends BaseWidget<
|
||||
ContainerWidgetProps<WidgetProps>,
|
||||
|
|
@ -34,21 +34,14 @@ class ContainerWidget extends BaseWidget<
|
|||
componentDidUpdate(previousProps: ContainerWidgetProps<WidgetProps>) {
|
||||
super.componentDidUpdate(previousProps);
|
||||
let snapColumnSpace = this.state.snapColumnSpace;
|
||||
let snapRowSpace = this.state.snapRowSpace;
|
||||
if (this.state.componentWidth)
|
||||
snapColumnSpace =
|
||||
this.state.componentWidth /
|
||||
(this.props.snapColumns || DEFAULT_GRID_COLUMNS);
|
||||
if (this.state.componentHeight)
|
||||
snapRowSpace =
|
||||
this.state.componentHeight / (this.props.snapRows || DEFAULT_GRID_ROWS);
|
||||
if (
|
||||
this.state.snapColumnSpace !== snapColumnSpace ||
|
||||
this.state.snapRowSpace !== snapRowSpace
|
||||
) {
|
||||
if (this.state.snapColumnSpace !== snapColumnSpace) {
|
||||
this.setState({
|
||||
snapColumnSpace,
|
||||
snapRowSpace,
|
||||
snapRowSpace: DEFAULT_GRID_ROW_HEIGHT,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -79,9 +72,8 @@ class ContainerWidget extends BaseWidget<
|
|||
);
|
||||
}
|
||||
|
||||
getCanvasView() {
|
||||
const style = this.getPositionStyle();
|
||||
const occupiedSpaces: OccupiedSpace[] | null = this.props.children
|
||||
getOccupiedSpaces(): OccupiedSpace[] | null {
|
||||
return this.props.children
|
||||
? this.props.children.map(child => ({
|
||||
id: child.widgetId,
|
||||
left: child.leftColumn,
|
||||
|
|
@ -90,6 +82,23 @@ class ContainerWidget extends BaseWidget<
|
|||
right: child.rightColumn,
|
||||
}))
|
||||
: null;
|
||||
}
|
||||
getCanvasView() {
|
||||
const style = this.getPositionStyle();
|
||||
const occupiedSpaces = this.getOccupiedSpaces();
|
||||
|
||||
const renderDraggableComponent = (
|
||||
<DraggableComponent
|
||||
style={{ ...style, xPosition: 0, yPosition: 0 }}
|
||||
{...this.props}
|
||||
orientation={"VERTICAL"}
|
||||
>
|
||||
<ResizableComponent style={{ ...style }} {...this.props}>
|
||||
{this.getPageView()}
|
||||
</ResizableComponent>
|
||||
</DraggableComponent>
|
||||
);
|
||||
|
||||
return (
|
||||
<DropTargetComponent
|
||||
{...this.props}
|
||||
|
|
@ -99,15 +108,7 @@ class ContainerWidget extends BaseWidget<
|
|||
...style,
|
||||
}}
|
||||
>
|
||||
<DraggableComponent
|
||||
style={{ ...style, xPosition: 0, yPosition: 0 }}
|
||||
{...this.props}
|
||||
orientation={"VERTICAL"}
|
||||
>
|
||||
<ResizableComponent style={{ ...style }} {...this.props}>
|
||||
{this.getPageView()}
|
||||
</ResizableComponent>
|
||||
</DraggableComponent>
|
||||
{this.props.parentId ? renderDraggableComponent : this.getPageView()}
|
||||
</DropTargetComponent>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user