[WIP] Add widget cards pane component

This commit is contained in:
Abhinav Jha 2019-08-21 18:19:16 +05:30
parent e9610d0248
commit 57ad5991c3
18 changed files with 222 additions and 79 deletions

16
app/client/Concepts.md Normal file
View File

@ -0,0 +1,16 @@
Concepts
========
Widgets
- WidgetProperties
- WIDGET_PROPERTY_LABEL (STRING)
- WIDGET_PROPERTY_TYPE (STRING)
- WIDGET_PROPERTY_DEFAULT (STRING)
- WIDGET_PROPERTY_ENABLED (BOOLEAN)
- WIDGET_PROPERTY_META
- ALLOWED_VALUES (LIST<STRING>)
- Components
- WidgetCards
- WIDGET_TYPE (STRING)
- WIDGET_CARD_LABEL (STRING)
- WIDGET_CARD_ENABLED (BOOLEAN)
- WIDGET_CARD_ICON (UTF-16)

View File

@ -0,0 +1,25 @@
import {
ReduxAction,
ActionTypes
} from "../constants/ActionConstants"
import { IWidgetCardProps } from '../widgets/BaseWidget'
export const fetchWidgetCards = () => {
return {
type: ActionTypes.FETCH_WIDGET_CARDS
}
}
export const errorFetchingWidgetCards = (error: T) => {
return {
type: ActionTypes.ERROR_FETCHING_WIDGET_CARDS,
error
}
}
export const successFetchingWidgetCards = (cards: <string, IWidgetCardProps[]>) => {
return {
type: ActionTypes.SUCCESS_FETCHING_WIDGET_CARDS,
cards
}
}

View File

@ -30,7 +30,8 @@ class PageApi extends Api {
static savePage(savePageRequest: SavePageRequest): Promise<PageResponse> {
return Api.post(PageApi.url, undefined, savePageRequest)
}
}
export default PageApi

View File

@ -0,0 +1,19 @@
import Api from "./Api"
import { IWidgetCardProps } from "../widgets/BaseWidget"
import { IContainerWidgetProps } from "../widgets/ContainerWidget"
import { ApiResponse } from "./ApiResponses"
export interface WidgetCardsPaneResponse {
cards : Map<string, IWidgetCardProps[]>
}
export interface WidgetCardsPaneRequest {}
class WidgetCardsPaneApi extends Api {
static url: string = "/widgetCards"
static fetchWidgetCards(): Promise<WidgetCardsPaneResponse> {
return Api.get(WidgetCardsPaneApi.url, {})
}
}
export default WidgetCardsPaneApi

View File

@ -1,5 +1,5 @@
import ContainerWidget from "../widgets/ContainerWidget"
import { IWidgetProps } from "../widgets/BaseWidget"
import { IWidgetProps, IWidgetCardProps } from "../widgets/BaseWidget"
export type ActionType =
| "UPDATE_CANVAS"
@ -14,6 +14,9 @@ export type ActionType =
| "PUBLISH"
| "UNDO_CANVAS_ACTION"
| "REDO_CANVAS_ACTION"
| "FETCH_WIDGET_CARDS"
| "SUCCESS_FETCHING_WIDGET_CARDS"
| "ERROR_FETCHING_WIDGET_CARDS"
export const ActionTypes: { [id: string]: ActionType } = {
UPDATE_CANVAS: "UPDATE_CANVAS",
@ -27,7 +30,9 @@ export const ActionTypes: { [id: string]: ActionType } = {
ZOOM_OUT_CANVAS: "ZOOM_OUT_CANVAS",
UNDO_CANVAS_ACTION: "UNDO_CANVAS_ACTION",
REDO_CANVAS_ACTION: "REDO_CANVAS_ACTION",
PUBLISH: "PUBLISH"
PUBLISH: "PUBLISH",
SUCCESS_FETCHING_WIDGET_CARDS: "SUCCESS_FETCHING_WIDGET_CARDS",
ERROR_FETCHING_WIDGET_CARDS: "ERROR_FETCHING_WIDGET_CARDS"
}
export interface ReduxAction<T> {
@ -44,4 +49,6 @@ export interface LoadWidgetPanePayload {
widgets: IWidgetProps[]
}
export interface LoadWidgetCardsPanePayload {
cards: { [id: string] : IWidgetCardProps[] }
}

View File

@ -5,8 +5,9 @@ export type ContentType = "application/json" | "application/x-www-form-urlencode
export type EncodingType = "gzip"
export const PROD_BASE_URL = "https://mobtools.com/api/"
export const MOCK_BASE_URL = "https://12064212-8b45-4d81-882a-7a044f3c9555.mock.pstmn.io"
export const STAGE_BASE_URL = "https://14157cb0-190f-4082-a791-886a8df05930.mock.pstmn.io"
export const BASE_URL = STAGE_BASE_URL
export const BASE_URL = MOCK_BASE_URL
export const REQUEST_TIMEOUT_MS = 2000
export const REQUEST_HEADERS: ApiHeaders = {
Accept: "application/json",

View File

@ -13,6 +13,8 @@ export type WidgetType =
| "NUMERIC_INPUT_WIDGET"
| "CHECKBOX_WIDGET"
| "RADIO_GROUP_WIDGET"
| "INPUT_WIDGET"
| "TOGGLE_WIDGET"
export type ContainerOrientation = "HORIZONTAL" | "VERTICAL"
export type PositionType = "ABSOLUTE" | "CONTAINER_DIRECTION"
export type CSSUnit =

View File

@ -0,0 +1,78 @@
import { WidgetCardsPaneReduxState } from "../reducers/uiReducers/widgetCardsPaneReducer";
const WidgetCardsPaneResponse: WidgetCardsPaneReduxState = {
cards: {
common: [
{
widgetType: "BUTTON_WIDGET",
icon: "\f243",
label: "Button",
groups: ["common", "form"]
},
{
widgetType: "INPUT_WIDGET",
icon: "\f243",
label: "Input",
groups: ["common", "form"]
},
{
widgetType: "TOGGLE_WIDGET",
icon: "\f205",
label: "Toggle",
groups: ["common", "view"]
}
],
form: [
{
widgetType: "BUTTON_WIDGET",
icon: "\f243",
label: "Button",
groups: ["common", "form"]
},
{
widgetType: "INPUT_WIDGET",
icon: "\f243",
label: "Input",
groups: ["common", "form"]
}
],
view: [
{
widgetType: "TOGGLE_WIDGET",
icon: "\f205",
label: "Toggle",
groups: ["common", "view"]
}
]
}
};
// const WidgetPaneResponse: WidgetPaneReduxState = {
// widgets: [
// {
// widgetType: "BUTTON_WIDGET",
// text: "Lorem Ipsum",
// renderMode: RenderModes.COMPONENT_PANE,
// bottomRow: 50,
// widgetId: "wp1",
// rightColumn: 200
// },
// {
// widgetType: "TEXT_WIDGET",
// text: "Lorem Ipsum",
// renderMode: RenderModes.COMPONENT_PANE,
// bottomRow: 50,
// widgetId: "wp2",
// rightColumn: 200
// },
// {
// widgetType: "SPINNER_WIDGET",
// renderMode: RenderModes.COMPONENT_PANE,
// backgroundColor: "#434343",
// bottomRow: 50,
// widgetId: "wp3",
// rightColumn: 200
// }
// ]
// }
export default WidgetCardsPaneResponse;

View File

@ -1,33 +0,0 @@
import { WidgetPaneReduxState } from "../reducers/uiReducers/widgetPaneReducer"
import { RenderModes } from "../constants/WidgetConstants"
const WidgetPaneResponse: WidgetPaneReduxState = {
widgets: [
{
widgetType: "BUTTON_WIDGET",
text: "Lorem Ipsum",
renderMode: RenderModes.COMPONENT_PANE,
bottomRow: 50,
widgetId: "wp1",
rightColumn: 200
},
{
widgetType: "TEXT_WIDGET",
text: "Lorem Ipsum",
renderMode: RenderModes.COMPONENT_PANE,
bottomRow: 50,
widgetId: "wp2",
rightColumn: 200
},
{
widgetType: "SPINNER_WIDGET",
renderMode: RenderModes.COMPONENT_PANE,
backgroundColor: "#434343",
bottomRow: 50,
widgetId: "wp3",
rightColumn: 200
}
]
}
export default WidgetPaneResponse

View File

@ -1,23 +1,22 @@
import React, { Component } from "react"
import { connect } from "react-redux"
import { AppState } from "../../reducers"
import WidgetFactory from "../../utils/WidgetFactory"
import { WidgetPaneReduxState } from "../../reducers/uiReducers/widgetPaneReducer";
import { IWidgetProps } from "../../widgets/BaseWidget";
import { WidgetCardsPaneReduxState } from "../../reducers/uiReducers/widgetCardsPaneReducer";
class WidgetPane extends Component<WidgetPaneReduxState> {
class WidgetCardsPane extends Component<WidgetCardsPaneReduxState> {
render() {
const groups = Object.keys(this.props.cards)
return (<div style={{ width: "300px", backgroundColor: "#fff", borderRadius: "5px", boxShadow: "0px 0px 3px #ccc", padding: "5px 10px", display: "flex", flexFlow: "row wrap" }}>
{this.props.widgets.map((widget: IWidgetProps) => {
{groups.map((group: string) => {
})}
</div>)
}
}
const mapStateToProps = (state: AppState, props: any): WidgetPaneReduxState => {
const mapStateToProps = (state: AppState, props: any): WidgetCardsPaneReduxState => {
return {
widgets: state.ui.widgetPane.widgets
cards: state.ui.widgetCardsPane.cards
}
}
@ -28,4 +27,4 @@ const mapDispatchToProps = (dispatch: any) => {
export default connect(
mapStateToProps,
mapDispatchToProps
)(WidgetPane)
)(WidgetCardsPane)

View File

@ -1,7 +1,7 @@
import React, { Component } from "react"
import styled from "styled-components"
import Canvas from "./Canvas"
import WidgetPane from "./WidgetPane"
import WidgetCardsPane from "./WidgetCardsPane"
import EditorHeader from "./EditorHeader"
import { CALCULATOR } from "@blueprintjs/icons/lib/esm/generated/iconContents";
@ -30,7 +30,7 @@ class Editor extends Component {
overflow: "hidden",
padding: "10px",
height: "calc(100vh - 60px)"}}>
<WidgetPane />
<WidgetCardsPane />
<ArtBoard>
<Canvas />
</ArtBoard>

View File

@ -3,7 +3,7 @@ import entityReducer from "./entityReducers"
import uiReducer from "./uiReducers"
import { CanvasReduxState } from "./uiReducers/canvasReducer"
import { CanvasWidgetsReduxState } from "./entityReducers/canvasWidgetsReducers"
import { WidgetPaneReduxState } from "./uiReducers/widgetPaneReducer"
import { WidgetCardsPaneReduxState } from "./uiReducers/widgetCardsPaneReducer"
import { EditorHeaderReduxState } from "./uiReducers/editorHeaderReducer"
const appReducer = combineReducers({
@ -16,7 +16,7 @@ export default appReducer
export interface AppState {
ui: {
canvas: CanvasReduxState
widgetPane: WidgetPaneReduxState
widgetCardsPane: WidgetCardsPaneReduxState
editorHeader: EditorHeaderReduxState
}
entities: {

View File

@ -1,7 +1,7 @@
import { combineReducers } from "redux"
import canvasReducer from "./canvasReducer"
import widgetPaneReducer from "./widgetPaneReducer"
import widgetCardsPaneReducer from "./widgetCardsPaneReducer"
import editorHeaderReducer from "./editorHeaderReducer"
const uiReducer = combineReducers({ canvas: canvasReducer, widgetPane: widgetPaneReducer, editorHeader: editorHeaderReducer })
const uiReducer = combineReducers({ canvas: canvasReducer, widgetCardsPane: widgetCardsPaneReducer, editorHeader: editorHeaderReducer })
export default uiReducer

View File

@ -0,0 +1,27 @@
import { createReducer } from "../../utils/PicassoUtils"
import {
ActionTypes,
ReduxAction,
LoadWidgetCardsPanePayload
} from "../../constants/ActionConstants"
import { IWidgetCardProps } from "../../widgets/BaseWidget";
import WidgetCardsPaneResponse from "../../mockResponses/WidgetCardsPaneResponse"
const initialState: WidgetCardsPaneReduxState = WidgetCardsPaneResponse
const widgetCardsPaneReducer = createReducer(initialState, {
[ActionTypes.SUCCESS_FETCHING_WIDGET_CARDS]: (
state: WidgetCardsPaneReduxState,
action: ReduxAction<LoadWidgetCardsPanePayload>
) => {
return { cards: action.payload.cards }
}
})
export interface WidgetCardsPaneReduxState {
cards: {
[id: string]: IWidgetCardProps[]
}
}
export default widgetCardsPaneReducer

View File

@ -1,25 +0,0 @@
import { createReducer } from "../../utils/PicassoUtils"
import {
ActionTypes,
ReduxAction,
LoadWidgetPanePayload
} from "../../constants/ActionConstants"
import { IWidgetProps } from "../../widgets/BaseWidget";
import WidgetPaneResponse from "../../mockResponses/WidgetPaneResponse"
const initialState: WidgetPaneReduxState = WidgetPaneResponse
const widgetPaneReducer = createReducer(initialState, {
// [ActionTypes.LOAD_CANVAS]: (
// state: WidgetPaneReduxState,
// action: ReduxAction<LoadWidgetPanePayload>
// ) => {
// return { widgets: action.payload.widgets }
// }
})
export interface WidgetPaneReduxState {
widgets: (IWidgetProps | any)[]
}
export default widgetPaneReducer

View File

@ -0,0 +1,17 @@
import CanvasWidgetsNormalizer from "../normalizers/CanvasWidgetsNormalizer"
import { ActionTypes, ReduxAction } from "../constants/ActionConstants"
import WidgetCardsPaneApi, { WidgetCardsPaneResponse, WidgetCardsPaneRequest } from "../api/WidgetCardsPaneApi"
import { call, put, takeLeading, all, takeEvery, takeLatest } from "redux-saga/effects"
export function* fetchWidgetCards(widgetCardsRequestAction: ReduxAction<WidgetCardsPaneRequest>) {
try {
const widgetCards: WidgetCardsPaneResponse = yield call(WidgetCardsPaneApi.fetchWidgetCards)
yield put({ type: ActionTypes.SUCCESS_FETCHING_WIDGET_CARDS, widgetCards})
} catch(err) {
yield put({ type: ActionTypes.ERROR_FETCHING_WIDGET_CARDS, err})
}
}
export function* fetchWidgetCardsSaga() {
yield takeLatest(ActionTypes.FETCH_WIDGET_CARDS, fetchWidgetCards)
}

View File

@ -1,6 +1,7 @@
import { all } from "redux-saga/effects"
import { watchFetchPage } from "../sagas/PageSagas"
import { fetchWidgetCardsSaga } from './WidgetCardsPaneSagas'
export function* rootSaga() {
yield all([watchFetchPage()])
yield all([watchFetchPage(), fetchWidgetCardsSaga()])
}

View File

@ -160,4 +160,12 @@ export interface IWidgetProps {
renderMode: RenderMode
}
export interface IWidgetCardProps {
widgetType: WidgetType
key?: string
label: string
icon: string
groups: string[]
}
export default BaseWidget