added axios type script
added api calls from a mock server added redux saga
This commit is contained in:
parent
4e2b003a5d
commit
d83f3d9308
|
|
@ -7,6 +7,7 @@
|
|||
"@blueprintjs/datetime": "^3.6.0",
|
||||
"@blueprintjs/icons": "^3.5.0",
|
||||
"@blueprintjs/table": "^3.4.0",
|
||||
"@types/axios": "^0.14.0",
|
||||
"@types/jest": "^23.3.13",
|
||||
"@types/lodash": "^4.14.120",
|
||||
"@types/moment-timezone": "^0.5.10",
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
import { IContainerWidgetProps } from "../widgets/ContainerWidget"
|
||||
import CanvasWidgetsNormalizer, { widgetSchema } from "../normalizers/CanvasWidgetsNormalizer"
|
||||
import { LoadCanvasPayload, ActionTypes, ReduxAction } from "../constants/ActionConstants"
|
||||
|
||||
export const loadCanvas = (canvasResponse: PageResponse): ReduxAction<LoadCanvasPayload> => {
|
||||
const normalizedResponse = CanvasWidgetsNormalizer.normalize(canvasResponse)
|
||||
return {
|
||||
type: ActionTypes.LOAD_CANVAS,
|
||||
payload: {
|
||||
pageWidgetId: normalizedResponse.result,
|
||||
widgets: normalizedResponse.entities.canvasWidgets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface PageResponse {
|
||||
pageWidget: IContainerWidgetProps<any>
|
||||
}
|
||||
62
app/client/src/api/Api.tsx
Normal file
62
app/client/src/api/Api.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import _ from "lodash"
|
||||
import {
|
||||
BASE_URL,
|
||||
REQUEST_TIMEOUT_MS,
|
||||
REQUEST_HEADERS
|
||||
} from "../constants/ApiConstants"
|
||||
|
||||
const axios = require("axios")
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: BASE_URL,
|
||||
timeout: REQUEST_TIMEOUT_MS,
|
||||
headers: REQUEST_HEADERS
|
||||
})
|
||||
|
||||
axiosInstance.interceptors.response.use(
|
||||
function(response: any) {
|
||||
// Do something with response data
|
||||
return response.data
|
||||
},
|
||||
function(error: any) {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
console.log(error.response.data)
|
||||
console.log(error.response.status)
|
||||
console.log(error.response.headers)
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.log(error.request)
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.log("Error", error.message)
|
||||
}
|
||||
console.log(error.config)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
class Api {
|
||||
static get(url: string, queryParams: any) {
|
||||
return axiosInstance.get(url + this.convertObjectToQueryParams(queryParams))
|
||||
}
|
||||
|
||||
static post(url: string, queryParams?: any, body?: any) {
|
||||
return axiosInstance.post(
|
||||
url + this.convertObjectToQueryParams(queryParams),
|
||||
body
|
||||
)
|
||||
}
|
||||
|
||||
static convertObjectToQueryParams(object: any): string {
|
||||
const paramArray: string[] = _.map(_.keys(object), key => {
|
||||
return encodeURIComponent(key) + "=" + encodeURIComponent(object[key])
|
||||
})
|
||||
return "?" + _.join(paramArray, "&")
|
||||
}
|
||||
}
|
||||
|
||||
export default Api
|
||||
12
app/client/src/api/ApiRequests.tsx
Normal file
12
app/client/src/api/ApiRequests.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { ContentType, DataType, EncodingType } from "../constants/ApiConstants";
|
||||
|
||||
export interface ApiHeaders {
|
||||
Accept: ContentType
|
||||
"Content-Type": ContentType
|
||||
dataType: DataType
|
||||
"Accept-Encoding": EncodingType
|
||||
}
|
||||
|
||||
export interface ApiRequest {
|
||||
|
||||
}
|
||||
9
app/client/src/api/ApiResponses.tsx
Normal file
9
app/client/src/api/ApiResponses.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
export type ApiErrorCodes = "INVALID_REQUEST" | "UNKNOWN"
|
||||
|
||||
export interface ResponseMeta {
|
||||
errorCode?: ApiErrorCodes
|
||||
}
|
||||
|
||||
export interface ApiResponse {
|
||||
responseMeta: ResponseMeta
|
||||
}
|
||||
21
app/client/src/api/PageApi.tsx
Normal file
21
app/client/src/api/PageApi.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import Api from "./Api"
|
||||
import { IContainerWidgetProps } from "../widgets/ContainerWidget"
|
||||
import { ApiResponse } from "./ApiResponses"
|
||||
|
||||
export interface PageRequest {
|
||||
pageId: string
|
||||
}
|
||||
|
||||
export interface PageResponse extends ApiResponse {
|
||||
pageWidget: IContainerWidgetProps<any>
|
||||
}
|
||||
|
||||
class PageApi extends Api {
|
||||
static url: string = "/page/"
|
||||
|
||||
static fetchPage(pageRequest: PageRequest): Promise<PageResponse> {
|
||||
return Api.get(PageApi.url + pageRequest.pageId, pageRequest)
|
||||
}
|
||||
}
|
||||
|
||||
export default PageApi
|
||||
|
|
@ -2,13 +2,15 @@ import ContainerWidget from "../widgets/ContainerWidget"
|
|||
import { IWidgetProps } from "../widgets/BaseWidget"
|
||||
|
||||
export type ActionType =
|
||||
| "LOAD_CANVAS"
|
||||
| "UPDATE_CANVAS"
|
||||
| "FETCH_CANVAS"
|
||||
| "CLEAR_CANVAS"
|
||||
| "DROP_WIDGET_CANVAS"
|
||||
| "REMOVE_WIDGET_CANVAS"
|
||||
| "LOAD_WIDGET_PANE"
|
||||
export const ActionTypes: { [id: string]: ActionType } = {
|
||||
LOAD_CANVAS: "LOAD_CANVAS",
|
||||
UPDATE_CANVAS: "UPDATE_CANVAS",
|
||||
FETCH_CANVAS: "FETCH_CANVAS",
|
||||
CLEAR_CANVAS: "CLEAR_CANVAS",
|
||||
DROP_WIDGET_CANVAS: "DROP_WIDGET_CANVAS",
|
||||
REMOVE_WIDGET_CANVAS: "REMOVE_WIDGET_CANVAS",
|
||||
|
|
|
|||
16
app/client/src/constants/ApiConstants.tsx
Normal file
16
app/client/src/constants/ApiConstants.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { ApiHeaders } from "../api/ApiRequests";
|
||||
|
||||
export type DataType = "json" | "xml"
|
||||
export type ContentType = "application/json" | "application/x-www-form-urlencoded"
|
||||
export type EncodingType = "gzip"
|
||||
|
||||
export const PROD_BASE_URL = "https://mobtools.com/api/"
|
||||
export const STAGE_BASE_URL = "https://14157cb0-190f-4082-a791-886a8df05930.mock.pstmn.io"
|
||||
export const BASE_URL = STAGE_BASE_URL
|
||||
export const REQUEST_TIMEOUT_MS = 2000
|
||||
export const REQUEST_HEADERS: ApiHeaders = {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
dataType: "json",
|
||||
"Accept-Encoding": "gzip"
|
||||
}
|
||||
|
|
@ -7,13 +7,20 @@ import Editor from "./pages/Editor";
|
|||
import PageNotFound from "./pages/PageNotFound";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
import { BrowserRouter, Route, Switch } from "react-router-dom";
|
||||
import { createStore } from "redux";
|
||||
import { createStore, applyMiddleware } from "redux";
|
||||
import appReducer from "./reducers";
|
||||
import WidgetBuilderRegistry from "./utils/WidgetRegistry";
|
||||
import { ThemeProvider, theme } from "./constants/DefaultTheme";
|
||||
import createSagaMiddleware from 'redux-saga'
|
||||
import { rootSaga } from "./sagas"
|
||||
import { ActionType } from "./constants/ActionConstants";
|
||||
|
||||
WidgetBuilderRegistry.registerWidgetBuilders();
|
||||
const store = createStore(appReducer);
|
||||
const sagaMiddleware = createSagaMiddleware()
|
||||
const store = createStore(appReducer, applyMiddleware(sagaMiddleware));
|
||||
sagaMiddleware.run(rootSaga)
|
||||
export const action = (type: ActionType) => store.dispatch({type})
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<ThemeProvider theme={theme}>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const WidgetPaneResponse: WidgetPaneReduxState = {
|
|||
text: "Lorem Ipsum",
|
||||
renderMode: RenderModes.COMPONENT_PANE,
|
||||
bottomRow: 50,
|
||||
widgetId: "1",
|
||||
rightColumn: 200
|
||||
},
|
||||
{
|
||||
|
|
@ -15,6 +16,7 @@ const WidgetPaneResponse: WidgetPaneReduxState = {
|
|||
text: "Lorem Ipsum",
|
||||
renderMode: RenderModes.COMPONENT_PANE,
|
||||
bottomRow: 50,
|
||||
widgetId: "2",
|
||||
rightColumn: 200
|
||||
},
|
||||
{
|
||||
|
|
@ -22,6 +24,7 @@ const WidgetPaneResponse: WidgetPaneReduxState = {
|
|||
renderMode: RenderModes.COMPONENT_PANE,
|
||||
backgroundColor: "#434343",
|
||||
bottomRow: 50,
|
||||
widgetId: "3",
|
||||
rightColumn: 200
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { normalize, schema, denormalize } from 'normalizr';
|
||||
import { PageResponse } from '../actions/CanvasActions';
|
||||
import { PageResponse } from '../api/PageApi';
|
||||
import { IContainerWidgetProps } from '../widgets/ContainerWidget';
|
||||
|
||||
export const widgetSchema = new schema.Entity('canvasWidgets', { }, { idAttribute: "widgetId" }, );
|
||||
|
|
|
|||
|
|
@ -2,16 +2,15 @@ import React, { Component } from "react"
|
|||
import { connect } from "react-redux"
|
||||
import { AppState } from "../../reducers"
|
||||
import WidgetFactory from "../../utils/WidgetFactory"
|
||||
import { loadCanvas } from "../../actions/CanvasActions";
|
||||
import CanvasResponse from "../../mockResponses/CanvasResponse";
|
||||
import { denormalize } from "normalizr";
|
||||
import CanvasWidgetsNormalizer, { widgetSchema } from "../../normalizers/CanvasWidgetsNormalizer";
|
||||
import { IContainerWidgetProps } from "../../widgets/ContainerWidget";
|
||||
import { action } from "../../index"
|
||||
import { ActionTypes } from "../../constants/ActionConstants";
|
||||
|
||||
class Canvas extends Component<{ pageWidget: IContainerWidgetProps<any>, loadCanvas: Function }> {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.loadCanvas()
|
||||
action(ActionTypes.FETCH_CANVAS)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -35,9 +34,6 @@ const mapStateToProps = (state: AppState, props: any) => {
|
|||
|
||||
const mapDispatchToProps = (dispatch: any) => {
|
||||
return {
|
||||
loadCanvas: () => {
|
||||
dispatch(loadCanvas({ pageWidget: CanvasResponse }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const initialState: CanvasWidgetsReduxState = {
|
|||
}
|
||||
|
||||
const canvasWidgetsReducer = createReducer(initialState, {
|
||||
[ActionTypes.LOAD_CANVAS]: (
|
||||
[ActionTypes.UPDATE_CANVAS]: (
|
||||
state: CanvasWidgetsReduxState,
|
||||
action: ReduxAction<LoadCanvasPayload>
|
||||
) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const initialState: CanvasReduxState = {
|
|||
}
|
||||
|
||||
const canvasReducer = createReducer(initialState, {
|
||||
[ActionTypes.LOAD_CANVAS]: (
|
||||
[ActionTypes.UPDATE_CANVAS]: (
|
||||
state: CanvasReduxState,
|
||||
action: ReduxAction<LoadCanvasPayload>
|
||||
) => {
|
||||
|
|
|
|||
27
app/client/src/sagas/CanvasSagas.tsx
Normal file
27
app/client/src/sagas/CanvasSagas.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import CanvasWidgetsNormalizer, {
|
||||
} from "../normalizers/CanvasWidgetsNormalizer"
|
||||
import {
|
||||
ActionTypes,
|
||||
} from "../constants/ActionConstants"
|
||||
import PageApi, { PageResponse } from "../api/PageApi"
|
||||
import { call, put, takeLeading, all, takeEvery } from "redux-saga/effects"
|
||||
|
||||
export function* fetchCanvas() {
|
||||
const pageResponse: PageResponse = yield call(PageApi.fetchPage, {
|
||||
pageId: "123"
|
||||
})
|
||||
const normalizedResponse = CanvasWidgetsNormalizer.normalize(pageResponse)
|
||||
const payload = {
|
||||
pageWidgetId: normalizedResponse.result,
|
||||
widgets: normalizedResponse.entities.canvasWidgets
|
||||
}
|
||||
yield put({ type: ActionTypes.UPDATE_CANVAS, payload })
|
||||
}
|
||||
|
||||
export function* watchFetchCanvas() {
|
||||
yield takeEvery(ActionTypes.FETCH_CANVAS, fetchCanvas)
|
||||
}
|
||||
|
||||
export function* canvasSagas() {
|
||||
yield all([fetchCanvas(), watchFetchCanvas()])
|
||||
}
|
||||
6
app/client/src/sagas/index.tsx
Normal file
6
app/client/src/sagas/index.tsx
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { all } from "redux-saga/effects"
|
||||
import { canvasSagas } from "../sagas/CanvasSagas"
|
||||
|
||||
export function* rootSaga() {
|
||||
yield all([canvasSagas()])
|
||||
}
|
||||
|
|
@ -914,6 +914,12 @@
|
|||
"@svgr/core" "^2.4.1"
|
||||
loader-utils "^1.1.0"
|
||||
|
||||
"@types/axios@^0.14.0":
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46"
|
||||
dependencies:
|
||||
axios "*"
|
||||
|
||||
"@types/dom4@^2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/dom4/-/dom4-2.0.1.tgz#506d5781b9bcab81bd9a878b198aec7dee2a6033"
|
||||
|
|
@ -1458,7 +1464,7 @@ aws4@^1.8.0:
|
|||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
|
||||
|
||||
axios@^0.18.0:
|
||||
axios@*, axios@^0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
|
||||
dependencies:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user