From e0706cf6e34e4d82b7fdad16103661c1f260214b Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Fri, 27 Sep 2019 13:38:31 +0530 Subject: [PATCH 1/3] Change location for save page notification --- app/client/src/constants/ApiConstants.tsx | 2 + .../src/constants/ReduxActionConstants.tsx | 4 +- app/client/src/pages/Editor/EditorHeader.tsx | 70 ++++++++++++------- app/client/src/pages/Editor/WidgetCard.tsx | 3 + app/client/src/pages/Editor/index.tsx | 26 ++----- .../src/reducers/uiReducers/editorReducer.tsx | 1 + app/client/src/sagas/PageSagas.tsx | 4 +- 7 files changed, 64 insertions(+), 46 deletions(-) diff --git a/app/client/src/constants/ApiConstants.tsx b/app/client/src/constants/ApiConstants.tsx index 88220ac5de..0492351902 100644 --- a/app/client/src/constants/ApiConstants.tsx +++ b/app/client/src/constants/ApiConstants.tsx @@ -35,11 +35,13 @@ export const getEditorConfigs = () => { return { currentPageId: "5d807e7f795dc6000482bc78", currentLayoutId: "5d807e7f795dc6000482bc77", + currentPageName: "page1", }; } else { return { currentPageId: "5d807e76795dc6000482bc76", currentLayoutId: "5d807e76795dc6000482bc75", + currentPageName: "page1", }; } }; diff --git a/app/client/src/constants/ReduxActionConstants.tsx b/app/client/src/constants/ReduxActionConstants.tsx index 712e8bd27d..5c84564080 100644 --- a/app/client/src/constants/ReduxActionConstants.tsx +++ b/app/client/src/constants/ReduxActionConstants.tsx @@ -48,7 +48,9 @@ export interface ReduxAction { export interface UpdateCanvasPayload { pageWidgetId: string; widgets: { [widgetId: string]: WidgetProps }; - layoutId: string; + currentLayoutId: string; + currentPageId: string; + currentPageName: string; } export interface ShowPropertyPanePayload { diff --git a/app/client/src/pages/Editor/EditorHeader.tsx b/app/client/src/pages/Editor/EditorHeader.tsx index ed47517185..bb3a96a1a5 100644 --- a/app/client/src/pages/Editor/EditorHeader.tsx +++ b/app/client/src/pages/Editor/EditorHeader.tsx @@ -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
; +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 ( +
+ + + {props.notificationText && } + {props.notificationText} + +
+ ); +}; export default EditorHeader; - -// const mapStateToProps = ( -// state: AppState, -// props: any, -// ): EditorHeaderReduxState => { -// return state; -// }; - -// const mapDispatchToProps = (dispatch: any) => { -// return {}; -// }; - -// export default connect( -// mapStateToProps, -// mapDispatchToProps, -// )(EditorHeader); diff --git a/app/client/src/pages/Editor/WidgetCard.tsx b/app/client/src/pages/Editor/WidgetCard.tsx index 4ef4f75858..ee1b8a6dec 100644 --- a/app/client/src/pages/Editor/WidgetCard.tsx +++ b/app/client/src/pages/Editor/WidgetCard.tsx @@ -29,6 +29,9 @@ export const Wrapper = styled.div` path { fill: ${props => props.theme.colors.textDefault}; } + rect { + stroke: ${props => props.theme.colors.textDefault}; + } } } & i { diff --git a/app/client/src/pages/Editor/index.tsx b/app/client/src/pages/Editor/index.tsx index 68390dbf71..6d3aef5d49 100644 --- a/app/client/src/pages/Editor/index.tsx +++ b/app/client/src/pages/Editor/index.tsx @@ -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 { 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 ( - + @@ -136,6 +121,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, }; }; diff --git a/app/client/src/reducers/uiReducers/editorReducer.tsx b/app/client/src/reducers/uiReducers/editorReducer.tsx index 693a4d24c7..7948d4410d 100644 --- a/app/client/src/reducers/uiReducers/editorReducer.tsx +++ b/app/client/src/reducers/uiReducers/editorReducer.tsx @@ -40,6 +40,7 @@ export interface EditorReduxState { pageWidgetId: string; currentPageId: string; currentLayoutId: string; + currentPageName: string; isSaving: boolean; } diff --git a/app/client/src/sagas/PageSagas.tsx b/app/client/src/sagas/PageSagas.tsx index 8c1a440852..efba4974db 100644 --- a/app/client/src/sagas/PageSagas.tsx +++ b/app/client/src/sagas/PageSagas.tsx @@ -44,8 +44,10 @@ export function* fetchPageSaga( ); 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)), From 062540e838ba314d03b891e916559a5e4bc1d118 Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Fri, 27 Sep 2019 21:35:33 +0530 Subject: [PATCH 2/3] Add global Saga to handle errors --- app/client/src/actions/pageActions.tsx | 16 -- .../src/actions/widgetCardsPaneActions.tsx | 9 +- app/client/src/api/PageApi.tsx | 2 +- app/client/src/constants/ApiConstants.tsx | 2 - .../src/constants/ReduxActionConstants.tsx | 28 ++- .../mockResponses/WidgetCardsPaneResponse.tsx | 188 +++++++++--------- app/client/src/pages/Editor/index.tsx | 5 +- app/client/src/reducers/index.tsx | 4 +- .../uiReducers/editorHeaderReducer.tsx | 9 - .../src/reducers/uiReducers/editorReducer.tsx | 10 +- .../src/reducers/uiReducers/errorReducer.tsx | 32 +++ app/client/src/reducers/uiReducers/index.tsx | 6 +- .../uiReducers/widgetCardsPaneReducer.tsx | 27 --- app/client/src/sagas/ErrorSagas.tsx | 38 ++++ app/client/src/sagas/PageSagas.tsx | 40 ++-- app/client/src/sagas/WidgetCardsPaneSagas.tsx | 8 +- app/client/src/sagas/index.tsx | 2 + app/client/src/utils/AppsmithSagaHelper.tsx | 27 +++ 18 files changed, 263 insertions(+), 190 deletions(-) delete mode 100644 app/client/src/reducers/uiReducers/editorHeaderReducer.tsx create mode 100644 app/client/src/reducers/uiReducers/errorReducer.tsx delete mode 100644 app/client/src/reducers/uiReducers/widgetCardsPaneReducer.tsx create mode 100644 app/client/src/sagas/ErrorSagas.tsx create mode 100644 app/client/src/utils/AppsmithSagaHelper.tsx diff --git a/app/client/src/actions/pageActions.tsx b/app/client/src/actions/pageActions.tsx index 32004458ca..ae0bfbf849 100644 --- a/app/client/src/actions/pageActions.tsx +++ b/app/client/src/actions/pageActions.tsx @@ -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; diff --git a/app/client/src/actions/widgetCardsPaneActions.tsx b/app/client/src/actions/widgetCardsPaneActions.tsx index ae393a5e0c..a3782ea18d 100644 --- a/app/client/src/actions/widgetCardsPaneActions.tsx +++ b/app/client/src/actions/widgetCardsPaneActions.tsx @@ -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, }; }; diff --git a/app/client/src/api/PageApi.tsx b/app/client/src/api/PageApi.tsx index 9814ae976d..d501fd82de 100644 --- a/app/client/src/api/PageApi.tsx +++ b/app/client/src/api/PageApi.tsx @@ -31,7 +31,7 @@ export type FetchPageResponse = ApiResponse & { }; }; -export interface SavePageResponse { +export interface SavePageResponse extends ApiResponse { pageId: string; } diff --git a/app/client/src/constants/ApiConstants.tsx b/app/client/src/constants/ApiConstants.tsx index 0492351902..594ffea494 100644 --- a/app/client/src/constants/ApiConstants.tsx +++ b/app/client/src/constants/ApiConstants.tsx @@ -45,5 +45,3 @@ export const getEditorConfigs = () => { }; } }; - -console.log("here", process.env.NODE_ENV); diff --git a/app/client/src/constants/ReduxActionConstants.tsx b/app/client/src/constants/ReduxActionConstants.tsx index 5c84564080..6cecce4af4 100644 --- a/app/client/src/constants/ReduxActionConstants.tsx +++ b/app/client/src/constants/ReduxActionConstants.tsx @@ -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,14 +36,31 @@ 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 { - type: ReduxActionType; + type: ReduxActionType | ReduxActionErrorType; payload: T; } +export interface ReduxActionErrorPayload { + message: string; + source?: string; +} + export interface UpdateCanvasPayload { pageWidgetId: string; widgets: { [widgetId: string]: WidgetProps }; diff --git a/app/client/src/mockResponses/WidgetCardsPaneResponse.tsx b/app/client/src/mockResponses/WidgetCardsPaneResponse.tsx index bfd64b112d..eb7239fdad 100644 --- a/app/client/src/mockResponses/WidgetCardsPaneResponse.tsx +++ b/app/client/src/mockResponses/WidgetCardsPaneResponse.tsx @@ -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; diff --git a/app/client/src/pages/Editor/index.tsx b/app/client/src/pages/Editor/index.tsx index 6d3aef5d49..fc55ebcace 100644 --- a/app/client/src/pages/Editor/index.tsx +++ b/app/client/src/pages/Editor/index.tsx @@ -107,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], diff --git a/app/client/src/reducers/index.tsx b/app/client/src/reducers/index.tsx index 4483e76eca..0b703388e1 100644 --- a/app/client/src/reducers/index.tsx +++ b/app/client/src/reducers/index.tsx @@ -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; diff --git a/app/client/src/reducers/uiReducers/editorHeaderReducer.tsx b/app/client/src/reducers/uiReducers/editorHeaderReducer.tsx deleted file mode 100644 index 76896fb8cf..0000000000 --- a/app/client/src/reducers/uiReducers/editorHeaderReducer.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { createReducer } from "../../utils/AppsmithUtils"; - -const initialState = {}; - -const editorHeaderReducer = createReducer(initialState, {}); - -// export interface EditorHeaderReduxState {} - -export default editorHeaderReducer; diff --git a/app/client/src/reducers/uiReducers/editorReducer.tsx b/app/client/src/reducers/uiReducers/editorReducer.tsx index 7948d4410d..952d322032 100644 --- a/app/client/src/reducers/uiReducers/editorReducer.tsx +++ b/app/client/src/reducers/uiReducers/editorReducer.tsx @@ -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, ) => { @@ -27,14 +30,11 @@ 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; - cards?: { + cards: { [id: string]: WidgetCardProps[]; }; pageWidgetId: string; diff --git a/app/client/src/reducers/uiReducers/errorReducer.tsx b/app/client/src/reducers/uiReducers/errorReducer.tsx new file mode 100644 index 0000000000..f715a3637e --- /dev/null +++ b/app/client/src/reducers/uiReducers/errorReducer.tsx @@ -0,0 +1,32 @@ +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, + ) => { + console.log(action.payload); + return { + sourceAction: action.payload.source, + message: action.payload.message, + }; + }, + [ReduxActionTypes.FLUSH_ERRORS]: () => { + return {}; + }, +}); + +export interface ErrorReduxState { + // Expiration? + sourceAction?: string; + message?: string; +} + +export default errorReducer; diff --git a/app/client/src/reducers/uiReducers/index.tsx b/app/client/src/reducers/uiReducers/index.tsx index d8312d0961..73b606e0f0 100644 --- a/app/client/src/reducers/uiReducers/index.tsx +++ b/app/client/src/reducers/uiReducers/index.tsx @@ -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; diff --git a/app/client/src/reducers/uiReducers/widgetCardsPaneReducer.tsx b/app/client/src/reducers/uiReducers/widgetCardsPaneReducer.tsx deleted file mode 100644 index 42dd6c5b9e..0000000000 --- a/app/client/src/reducers/uiReducers/widgetCardsPaneReducer.tsx +++ /dev/null @@ -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, - ) => { - return { cards: action.payload.cards }; - }, -}); - -export interface WidgetCardsPaneReduxState { - cards: { - [id: string]: WidgetCardProps[]; - }; -} - -export default widgetCardsPaneReducer; diff --git a/app/client/src/sagas/ErrorSagas.tsx b/app/client/src/sagas/ErrorSagas.tsx new file mode 100644 index 0000000000..6e3ba93c51 --- /dev/null +++ b/app/client/src/sagas/ErrorSagas.tsx @@ -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); +} diff --git a/app/client/src/sagas/PageSagas.tsx b/app/client/src/sagas/PageSagas.tsx index efba4974db..e63ef3918f 100644 --- a/app/client/src/sagas/PageSagas.tsx +++ b/app/client/src/sagas/PageSagas.tsx @@ -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,20 +21,22 @@ 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, ) { - 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), ); @@ -58,8 +56,12 @@ export function* fetchPageSaga( ]); } } catch (error) { - console.log(error); - yield put(fetchPageError(error)); + yield put({ + type: ReduxActionErrorTypes.FETCH_PAGE_ERROR, + payload: { + error, + }, + }); } } @@ -70,10 +72,17 @@ export function* savePageSaga(savePageAction: ReduxAction) { 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, + }, + }); } } @@ -89,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: { diff --git a/app/client/src/sagas/WidgetCardsPaneSagas.tsx b/app/client/src/sagas/WidgetCardsPaneSagas.tsx index d6cf112b1a..4d4a1b7f42 100644 --- a/app/client/src/sagas/WidgetCardsPaneSagas.tsx +++ b/app/client/src/sagas/WidgetCardsPaneSagas.tsx @@ -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 }); } } diff --git a/app/client/src/sagas/index.tsx b/app/client/src/sagas/index.tsx index 5ab51c8cd7..52593510e2 100644 --- a/app/client/src/sagas/index.tsx +++ b/app/client/src/sagas/index.tsx @@ -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), ]); } diff --git a/app/client/src/utils/AppsmithSagaHelper.tsx b/app/client/src/utils/AppsmithSagaHelper.tsx new file mode 100644 index 0000000000..c9e819329b --- /dev/null +++ b/app/client/src/utils/AppsmithSagaHelper.tsx @@ -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)); From 6c942abe2bb0375645f4ad7ca89aba27d862925b Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Mon, 30 Sep 2019 08:55:14 +0530 Subject: [PATCH 3/3] Remove dependencies from Readme.md. Fix #36, #37 --- app/client/README.md | 7 --- app/client/src/constants/WidgetConstants.tsx | 1 + .../editorComponents/DraggableComponent.tsx | 12 ++++- .../editorComponents/ResizableComponent.tsx | 8 +++- .../src/reducers/uiReducers/errorReducer.tsx | 1 - app/client/src/utils/helpers.tsx | 12 ----- app/client/src/widgets/BaseWidget.tsx | 26 ++++++----- app/client/src/widgets/ContainerWidget.tsx | 45 ++++++++++--------- 8 files changed, 56 insertions(+), 56 deletions(-) diff --git a/app/client/README.md b/app/client/README.md index c533c7c2ef..d20687e8ed 100755 --- a/app/client/README.md +++ b/app/client/README.md @@ -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). diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx index be21d05f84..05278c8c24 100644 --- a/app/client/src/constants/WidgetConstants.tsx +++ b/app/client/src/constants/WidgetConstants.tsx @@ -71,4 +71,5 @@ export const GridDefaults = { DEFAULT_WIDGET_HEIGHT: 100, DEFAULT_GRID_COLUMNS: 16, DEFAULT_GRID_ROWS: 32, + DEFAULT_GRID_ROW_HEIGHT: 40, }; diff --git a/app/client/src/editorComponents/DraggableComponent.tsx b/app/client/src/editorComponents/DraggableComponent.tsx index 1c634b5e6e..27e3986196 100644 --- a/app/client/src/editorComponents/DraggableComponent.tsx +++ b/app/client/src/editorComponents/DraggableComponent.tsx @@ -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 ( -
{ {props.children} -
+
); }; diff --git a/app/client/src/editorComponents/ResizableComponent.tsx b/app/client/src/editorComponents/ResizableComponent.tsx index 5d3bdd5d5b..59b6404d49 100644 --- a/app/client/src/editorComponents/ResizableComponent.tsx +++ b/app/client/src/editorComponents/ResizableComponent.tsx @@ -13,7 +13,13 @@ const ResizableContainer = styled(Resizable)` }}; `; -const CustomHandle = (props: any) =>
; +const DisplayHandleWrapper = styled.div` + display: none; + ${ResizableContainer}:hover & { + display: block; + } +`; +const CustomHandle = (props: any) => ; const BottomRightHandle = () => ( diff --git a/app/client/src/reducers/uiReducers/errorReducer.tsx b/app/client/src/reducers/uiReducers/errorReducer.tsx index f715a3637e..3cb81b3473 100644 --- a/app/client/src/reducers/uiReducers/errorReducer.tsx +++ b/app/client/src/reducers/uiReducers/errorReducer.tsx @@ -12,7 +12,6 @@ const errorReducer = createReducer(initialState, { state: ErrorReduxState, action: ReduxAction, ) => { - console.log(action.payload); return { sourceAction: action.payload.source, message: action.payload.message, diff --git a/app/client/src/utils/helpers.tsx b/app/client/src/utils/helpers.tsx index 9b0937a97b..885e5dcf00 100644 --- a/app/client/src/utils/helpers.tsx +++ b/app/client/src/utils/helpers.tsx @@ -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, - }; -}; diff --git a/app/client/src/widgets/BaseWidget.tsx b/app/client/src/widgets/BaseWidget.tsx index c0f3c33476..e7e9cd47b4 100644 --- a/app/client/src/widgets/BaseWidget.tsx +++ b/app/client/src/widgets/BaseWidget.tsx @@ -94,17 +94,21 @@ abstract class BaseWidget< getCanvasView(): JSX.Element { const style = this.getPositionStyle(); - return ( - - - {this.getPageView()} - - - ); + if (!this.props.parentId) { + return this.getPageView(); + } else { + return ( + + + {this.getPageView()} + + + ); + } } abstract getWidgetType(): WidgetType; diff --git a/app/client/src/widgets/ContainerWidget.tsx b/app/client/src/widgets/ContainerWidget.tsx index f19db96f12..97bd563f9d 100644 --- a/app/client/src/widgets/ContainerWidget.tsx +++ b/app/client/src/widgets/ContainerWidget.tsx @@ -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, @@ -34,21 +34,14 @@ class ContainerWidget extends BaseWidget< componentDidUpdate(previousProps: ContainerWidgetProps) { 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 = ( + + + {this.getPageView()} + + + ); + return ( - - - {this.getPageView()} - - + {this.props.parentId ? renderDraggableComponent : this.getPageView()} ); }