WIP: integrate with fetch pages and save pages APIs

This commit is contained in:
Abhinav Jha 2019-09-18 16:18:56 +05:30
parent 3317bed1d9
commit 673cd75a3f
16 changed files with 221 additions and 137 deletions

View File

@ -1,4 +1,5 @@
import { FetchPageRequest } from "../api/PageApi"; import { FetchPageRequest } from "../api/PageApi";
import { ResponseMeta } from "../api/ApiResponses";
import { RenderMode } from "../constants/WidgetConstants"; import { RenderMode } from "../constants/WidgetConstants";
import { import {
WidgetProps, WidgetProps,
@ -13,6 +14,7 @@ import {
SavePageErrorPayload, SavePageErrorPayload,
SavePageSuccessPayload, SavePageSuccessPayload,
} from "../constants/ReduxActionConstants"; } from "../constants/ReduxActionConstants";
import { ContainerWidgetProps } from "../widgets/ContainerWidget";
export const fetchPage = ( export const fetchPage = (
pageId: string, pageId: string,
@ -27,6 +29,13 @@ export const fetchPage = (
}; };
}; };
export const fetchPageError = (payload: ResponseMeta) => {
console.log("FETCH PAGE ERROR", payload);
return {
type: ReduxActionTypes.FETCH_PAGE_ERROR,
};
};
export const addWidget = ( export const addWidget = (
pageId: string, pageId: string,
widget: WidgetProps, widget: WidgetProps,
@ -62,10 +71,14 @@ export const loadCanvasWidgets = (
}; };
}; };
export const savePage = (payload: SavePagePayload) => { export const savePage = (
pageId: string,
layoutId: string,
dsl: ContainerWidgetProps<WidgetProps>,
): ReduxAction<SavePagePayload> => {
return { return {
type: ReduxActionTypes.SAVE_PAGE_INIT, type: ReduxActionTypes.SAVE_PAGE_INIT,
payload, payload: { pageId, layoutId, dsl },
}; };
}; };

View File

@ -12,6 +12,12 @@ const axiosInstance = axios.create({
baseURL: BASE_URL, baseURL: BASE_URL,
timeout: REQUEST_TIMEOUT_MS, timeout: REQUEST_TIMEOUT_MS,
headers: REQUEST_HEADERS, headers: REQUEST_HEADERS,
withCredentials: true,
//TODO(abhinav): remove this.
auth: {
username: "api_user",
password: "8uA@;&mB:cnvN~{#",
},
}); });
axiosInstance.interceptors.response.use( axiosInstance.interceptors.response.use(
@ -54,6 +60,13 @@ class Api {
); );
} }
static put(url: string, queryParams?: any, body?: any) {
return axiosInstance.put(
url + this.convertObjectToQueryParams(queryParams),
body,
);
}
static convertObjectToQueryParams(object: any): string { static convertObjectToQueryParams(object: any): string {
if (!_.isNil(object)) { if (!_.isNil(object)) {
const paramArray: string[] = _.map(_.keys(object), key => { const paramArray: string[] = _.map(_.keys(object), key => {

View File

@ -1,9 +1,10 @@
import { ContentType, DataType } from "../constants/ApiConstants"; import { ContentType, DataType } from "../constants/ApiConstants";
export interface APIHeaders { export interface APIHeaders {
Accept: ContentType; Accept?: ContentType;
"Content-Type": ContentType; "Content-Type"?: ContentType;
dataType: DataType; dataType?: DataType;
Origin?: string;
} }
export interface APIRequest { export interface APIRequest {

View File

@ -1,10 +1,26 @@
export type APIResponseCode = "SUCCESS" | "UNKNOWN"; export type APIResponseError = {
code: number;
message: string;
};
export interface ResponseMeta { export type ResponseMeta = {
responseCode: APIResponseCode; status: number;
message?: string; success: boolean;
} error?: APIResponseError;
};
export interface ApiResponse { export type ApiResponse = {
responseMeta: ResponseMeta; responseMeta: ResponseMeta;
} data: any;
};
// NO_RESOURCE_FOUND, 1000, "Unable to find {0} with id {1}"
// INVALID_PARAMTER, 4000, "Invalid parameter {0} provided in the input"
// PLUGIN_NOT_INSTALLED, 4001, "Plugin {0} not installed"
// MISSING_PLUGIN_ID, 4002, "Missing plugin id. Please input correct plugin id"
// MISSING_RESOURCE_ID, 4003, "Missing resource id. Please input correct resource id"
// MISSING_PAGE_ID, 4004, "Missing page id. Pleaes input correct page id"
// PAGE_DOES_NOT_EXIST_IN_ORG, 4006, "Page {0} does not belong to the current user {1} organization."
// UNAUTHORIZED_DOMAIN, 4001, "Invalid email domain provided. Please sign in with a valid work email ID"
// INTERNAL_SERVER_ERROR, 5000, "Internal server error while processing request"
// REPOSITORY_SAVE_FAILED, 5001, "Repository save failed."

View File

@ -11,31 +11,50 @@ export interface FetchPageRequest {
} }
export interface SavePageRequest { export interface SavePageRequest {
pageWidget: ContainerWidgetProps<WidgetProps>; dsl: ContainerWidgetProps<WidgetProps>;
layoutId: string;
pageId: string;
} }
export interface PageLayout { export interface PageLayout {
id: string;
dsl: ContainerWidgetProps<any>; dsl: ContainerWidgetProps<any>;
actions: PageAction[]; actions?: PageAction[];
} }
export interface FetchPageResponse extends ApiResponse { export type FetchPageResponse = ApiResponse & {
layout: PageLayout; data: {
} id: string;
name: string;
applicationId: string;
layouts: Array<PageLayout>;
};
};
export interface SavePageResponse { export interface SavePageResponse {
pageId: string; pageId: string;
} }
class PageApi extends Api { class PageApi extends Api {
static url = "/page"; static url = "/pages";
static getLayoutUpdateURL = (pageId: string, layoutId: string) => {
return `/layouts/${layoutId}/pages/${pageId}`;
};
static fetchPage(pageRequest: FetchPageRequest): Promise<FetchPageResponse> { static fetchPage(pageRequest: FetchPageRequest): Promise<FetchPageResponse> {
return Api.get(PageApi.url + "/" + pageRequest.pageId, pageRequest); return Api.get(PageApi.url + "/" + pageRequest.pageId);
} }
static savePage(savePageRequest: SavePageRequest): Promise<SavePageResponse> { static savePage(savePageRequest: SavePageRequest): Promise<SavePageResponse> {
return Api.post(PageApi.url, undefined, savePageRequest); const body = { dsl: savePageRequest.dsl };
return Api.put(
PageApi.getLayoutUpdateURL(
savePageRequest.pageId,
savePageRequest.layoutId,
),
undefined,
body,
);
} }
} }

View File

@ -1,75 +1,75 @@
import { AlertType, MessageIntent } from "../widgets/AlertWidget"; import { AlertType, MessageIntent } from "../widgets/AlertWidget";
export type EventType = export type EventType =
| "ON_CLICK" | "ON_CLICK"
| "ON_HOVER" | "ON_HOVER"
| "ON_TOGGLE" | "ON_TOGGLE"
| "ON_LOAD" | "ON_LOAD"
| "ON_TEXT_CHANGE" | "ON_TEXT_CHANGE"
| "ON_SUBMIT" | "ON_SUBMIT"
| "ON_CHECK_CHANGE" | "ON_CHECK_CHANGE"
| "ON_SELECT" | "ON_SELECT"
| "ON_DATE_SELECTED" | "ON_DATE_SELECTED"
| "ON_DATE_RANGE_SELECTED" | "ON_DATE_RANGE_SELECTED";
export type ActionType = export type ActionType =
| "API" | "API"
| "QUERY" | "QUERY"
| "NAVIGATION" | "NAVIGATION"
| "ALERT" | "ALERT"
| "JS_FUNCTION" | "JS_FUNCTION"
| "SET_VALUE" | "SET_VALUE"
| "DOWNLOAD" | "DOWNLOAD";
export interface ActionPayload { export interface ActionPayload {
actionType: ActionType actionType: ActionType;
contextParams: Record<string, string> contextParams: Record<string, string>;
} }
export interface APIActionPayload extends ActionPayload { export interface APIActionPayload extends ActionPayload {
apiId: string apiId: string;
} }
export interface QueryActionPayload extends ActionPayload { export interface QueryActionPayload extends ActionPayload {
queryId: string queryId: string;
} }
export type NavigationType = "NEW_TAB" | "INLINE" export type NavigationType = "NEW_TAB" | "INLINE";
export interface NavigateActionPayload extends ActionPayload { export interface NavigateActionPayload extends ActionPayload {
pageUrl: string pageUrl: string;
navigationType: NavigationType navigationType: NavigationType;
} }
export interface ShowAlertActionPayload extends ActionPayload { export interface ShowAlertActionPayload extends ActionPayload {
header: string header: string;
message: string message: string;
alertType: AlertType alertType: AlertType;
intent: MessageIntent intent: MessageIntent;
} }
export interface SetValueActionPayload extends ActionPayload { export interface SetValueActionPayload extends ActionPayload {
header: string header: string;
message: string message: string;
alertType: AlertType alertType: AlertType;
intent: MessageIntent intent: MessageIntent;
} }
export interface ExecuteJSActionPayload extends ActionPayload { export interface ExecuteJSActionPayload extends ActionPayload {
jsFunctionId: string jsFunctionId: string;
} }
export type DownloadFiletype = "CSV" | "XLS" | "JSON" | "TXT" export type DownloadFiletype = "CSV" | "XLS" | "JSON" | "TXT";
export interface DownloadDataActionPayload extends ActionPayload { export interface DownloadDataActionPayload extends ActionPayload {
data: JSON data: JSON;
fileName: string fileName: string;
fileType: DownloadFiletype fileType: DownloadFiletype;
} }
export interface PageAction { export interface PageAction {
actionId: string actionId: string;
actionType: ActionType actionType: ActionType;
actionName: string actionName: string;
dynamicBindings: string[] dynamicBindings: string[];
} }

View File

@ -9,14 +9,12 @@ export type EncodingType = "gzip";
export const PROD_BASE_URL = "https://mobtools.com/api/"; export const PROD_BASE_URL = "https://mobtools.com/api/";
export const MOCK_BASE_URL = export const MOCK_BASE_URL =
"https://f78ff9dd-2c08-45f1-9bf9-8c670a1bb696.mock.pstmn.io"; "https://f78ff9dd-2c08-45f1-9bf9-8c670a1bb696.mock.pstmn.io";
export const STAGE_BASE_URL = export const STAGE_BASE_URL = "https://appsmith-test.herokuapp.com/api/v1/";
"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 = 5000;
export const REQUEST_TIMEOUT_MS = 2000;
export const REQUEST_HEADERS: APIHeaders = { export const REQUEST_HEADERS: APIHeaders = {
Accept: "application/json", Accept: "application/json",
"Content-Type": "application/json", "Content-Type": "application/json",
dataType: "json",
}; };
export interface APIException { export interface APIException {

View File

@ -26,6 +26,7 @@ export const ReduxActionTypes = {
SAVE_PAGE_INIT: "SAVE_PAGE_INIT", SAVE_PAGE_INIT: "SAVE_PAGE_INIT",
SAVE_PAGE_SUCCESS: "SAVE_PAGE_SUCCESS", SAVE_PAGE_SUCCESS: "SAVE_PAGE_SUCCESS",
SAVE_PAGE_ERROR: "SAVE_PAGE_ERROR", SAVE_PAGE_ERROR: "SAVE_PAGE_ERROR",
FETCH_PAGE_ERROR: "FETCH_PAGE_ERROR",
}; };
export type ReduxActionType = (typeof ReduxActionTypes)[keyof typeof ReduxActionTypes]; export type ReduxActionType = (typeof ReduxActionTypes)[keyof typeof ReduxActionTypes];
@ -38,6 +39,7 @@ export interface ReduxAction<T> {
export interface LoadCanvasWidgetsPayload { export interface LoadCanvasWidgetsPayload {
pageWidgetId: string; pageWidgetId: string;
widgets: { [widgetId: string]: WidgetProps }; widgets: { [widgetId: string]: WidgetProps };
layoutId: string;
} }
export interface LoadWidgetConfigPayload { export interface LoadWidgetConfigPayload {

View File

@ -1,5 +1,5 @@
import { normalize, schema, denormalize } from "normalizr"; import { normalize, schema, denormalize } from "normalizr";
import { FetchPageResponse } from "../api/PageApi"; import { WidgetProps } from "../widgets/BaseWidget";
import { ContainerWidgetProps } from "../widgets/ContainerWidget"; import { ContainerWidgetProps } from "../widgets/ContainerWidget";
export const widgetSchema = new schema.Entity( export const widgetSchema = new schema.Entity(
@ -11,15 +11,15 @@ widgetSchema.define({ children: [widgetSchema] });
class CanvasWidgetsNormalizer { class CanvasWidgetsNormalizer {
static normalize( static normalize(
pageResponse: FetchPageResponse, dsl: ContainerWidgetProps<WidgetProps>,
): { entities: any; result: any } { ): { entities: any; result: any } {
return normalize(pageResponse.layout.dsl, widgetSchema); return normalize(dsl, widgetSchema);
} }
static denormalize( static denormalize(
pageWidgetId: string, pageWidgetId: string,
entities: any, entities: any,
): ContainerWidgetProps<any> { ): ContainerWidgetProps<WidgetProps> {
return denormalize(pageWidgetId, widgetSchema, entities); return denormalize(pageWidgetId, widgetSchema, entities);
} }
} }

View File

@ -13,7 +13,7 @@ import WidgetCardsPane from "./WidgetCardsPane";
import EditorHeader from "./EditorHeader"; import EditorHeader from "./EditorHeader";
import CanvasWidgetsNormalizer from "../../normalizers/CanvasWidgetsNormalizer"; import CanvasWidgetsNormalizer from "../../normalizers/CanvasWidgetsNormalizer";
import { ContainerWidgetProps } from "../../widgets/ContainerWidget"; import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
import { fetchPage, updateWidget } from "../../actions/pageActions"; import { fetchPage, updateWidget, savePage } from "../../actions/pageActions";
import { RenderModes } from "../../constants/WidgetConstants"; import { RenderModes } from "../../constants/WidgetConstants";
import EditorDragLayer from "./EditorDragLayer"; import EditorDragLayer from "./EditorDragLayer";
@ -51,12 +51,15 @@ type EditorProps = {
fetchCanvasWidgets: Function; fetchCanvasWidgets: Function;
cards: { [id: string]: WidgetCardProps[] } | any; cards: { [id: string]: WidgetCardProps[] } | any;
updateWidgetProperty: Function; updateWidgetProperty: Function;
savePageLayout: Function;
page: string; page: string;
currentPageId: string;
currentLayoutId: string;
}; };
class Editor extends Component<EditorProps> { class Editor extends Component<EditorProps> {
componentDidMount() { componentDidMount() {
this.props.fetchCanvasWidgets("1"); this.props.fetchCanvasWidgets(this.props.currentPageId);
} }
public render() { public render() {
@ -89,6 +92,8 @@ const mapStateToProps = (state: AppState): EditorReduxState => {
cards: state.ui.widgetCardsPane.cards, cards: state.ui.widgetCardsPane.cards,
layout, layout,
pageWidgetId: state.ui.editor.pageWidgetId, pageWidgetId: state.ui.editor.pageWidgetId,
currentPageId: state.ui.editor.currentPageId,
currentLayoutId: state.ui.editor.currentLayoutId,
}; };
}; };
@ -101,6 +106,11 @@ const mapDispatchToProps = (dispatch: any) => {
widgetProps: WidgetProps, widgetProps: WidgetProps,
payload: any, payload: any,
) => dispatch(updateWidget(propertyType, widgetProps, payload)), ) => dispatch(updateWidget(propertyType, widgetProps, payload)),
savePageLayout: (
pageId: string,
layoutId: string,
dsl: ContainerWidgetProps<WidgetProps>,
) => dispatch(savePage(pageId, layoutId, dsl)),
}; };
}; };

View File

@ -1,5 +0,0 @@
export default function snapToGrid(cellSize: number, x: number, y: number) {
const snappedX = Math.round(x / cellSize) * cellSize
const snappedY = Math.round(y / cellSize) * cellSize
return [snappedX, snappedY]
}

View File

@ -5,7 +5,6 @@ import {
ReduxAction, ReduxAction,
} from "../../constants/ReduxActionConstants"; } from "../../constants/ReduxActionConstants";
import { WidgetProps } from "../../widgets/BaseWidget"; import { WidgetProps } from "../../widgets/BaseWidget";
import CanvasWidgetsNormalizer from "../../normalizers/CanvasWidgetsNormalizer";
const initialState: CanvasWidgetsReduxState = {}; const initialState: CanvasWidgetsReduxState = {};
@ -24,18 +23,20 @@ const canvasWidgetsReducer = createReducer(initialState, {
state: CanvasWidgetsReduxState, state: CanvasWidgetsReduxState,
action: ReduxAction<{ pageId: string; widget: WidgetProps }>, action: ReduxAction<{ pageId: string; widget: WidgetProps }>,
) => { ) => {
const widget = action.payload.widget; // const widget = action.payload.widget;
const widgetTree = CanvasWidgetsNormalizer.denormalize("0", { // const widgetTree = CanvasWidgetsNormalizer.denormalize("0", {
canvasWidgets: state, // canvasWidgets: state,
}); // });
const children = widgetTree.children || []; // const children = widgetTree.children || [];
children.push(widget); // children.push(widget);
widgetTree.children = children; // widgetTree.children = children;
const newState = CanvasWidgetsNormalizer.normalize({ // const newState = CanvasWidgetsNormalizer.normalize({
responseMeta: { responseCode: "SUCCESS" }, // responseMeta: { responseCode: "SUCCESS" },
layout: { dsl: widgetTree, actions: [] }, // layout: { dsl: widgetTree, actions: [] },
}).entities; // }).entities;
return newState.canvasWidgets; // return newState.canvasWidgets;
console.log(action.payload.widget);
return state;
}, },
}); });

View File

@ -10,6 +10,8 @@ import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
const initialState: EditorReduxState = { const initialState: EditorReduxState = {
pageWidgetId: "0", pageWidgetId: "0",
currentPageId: "5d807e76795dc6000482bc76",
currentLayoutId: "5d807e76795dc6000482bc75",
}; };
const editorReducer = createReducer(initialState, { const editorReducer = createReducer(initialState, {
@ -36,6 +38,8 @@ export interface EditorReduxState {
[id: string]: WidgetCardProps[]; [id: string]: WidgetCardProps[];
}; };
pageWidgetId: string; pageWidgetId: string;
currentPageId: string;
currentLayoutId: string;
} }
export default editorReducer; export default editorReducer;

View File

@ -15,6 +15,7 @@ import ActionAPI, { ActionCreatedResponse } from "../api/ActionAPI";
import { AppState } from "../reducers"; import { AppState } from "../reducers";
import { JSONPath } from "jsonpath-plus"; import { JSONPath } from "jsonpath-plus";
import _ from "lodash"; import _ from "lodash";
import { extractCurrentDSL } from "./utils";
const getDataTree = (state: AppState) => { const getDataTree = (state: AppState) => {
return state.entities; return state.entities;
@ -82,7 +83,7 @@ export function* executeAction(
); );
if (pageRequest.renderMode === RenderModes.CANVAS) { if (pageRequest.renderMode === RenderModes.CANVAS) {
const normalizedResponse = CanvasWidgetsNormalizer.normalize( const normalizedResponse = CanvasWidgetsNormalizer.normalize(
pageResponse, extractCurrentDSL(pageResponse),
); );
const payload = { const payload = {
pageWidgetId: normalizedResponse.result, pageWidgetId: normalizedResponse.result,

View File

@ -8,6 +8,7 @@ import {
loadCanvasWidgets, loadCanvasWidgets,
savePageError, savePageError,
savePageSuccess, savePageSuccess,
fetchPageError,
} from "../actions/pageActions"; } from "../actions/pageActions";
import PageApi, { import PageApi, {
FetchPageResponse, FetchPageResponse,
@ -16,64 +17,62 @@ import PageApi, {
SavePageRequest, SavePageRequest,
} from "../api/PageApi"; } from "../api/PageApi";
import { call, put, takeLatest, all } from "redux-saga/effects"; import { call, put, takeLatest, all } from "redux-saga/effects";
import { RenderModes } from "../constants/WidgetConstants"; import { extractCurrentDSL } from "./utils";
export function* fetchPage(pageRequestAction: ReduxAction<FetchPageRequest>) { export function* fetchPage(pageRequestAction: ReduxAction<FetchPageRequest>) {
const pageRequest = pageRequestAction.payload; const pageRequest = pageRequestAction.payload;
try { try {
// const pageResponse: PageResponse = yield call( const fetchPageResponse: FetchPageResponse = yield call(
// PageApi.fetchPage, PageApi.fetchPage,
// pageRequest, pageRequest,
// ); );
if (pageRequest.renderMode === RenderModes.CANVAS) { if (fetchPageResponse.responseMeta.success) {
const pageResponse = JSON.parse(`{
"responseMeta": {},
"layout": {
"dsl": {
"widgetId": "0",
"type": "CONTAINER_WIDGET",
"snapColumns": 16,
"snapRows": 100,
"topRow": 0,
"bottomRow": 2000,
"leftColumn": 0,
"rightColumn": 1000,
"parentColumnSpace": 1,
"parentRowSpace": 1,
"backgroundColor": "#ffffff",
"renderMode": "CANVAS",
"children": [
{
"widgetId": "1",
"type": "CONTAINER_WIDGET",
"snapColumns": 10,
"snapRows": 10,
"topRow": 1,
"bottomRow": 20,
"leftColumn": 1,
"rightColumn": 16,
"backgroundColor": "#000000",
"renderMode": "CANVAS",
"children": []
}
]
}
}
}`);
const normalizedResponse = CanvasWidgetsNormalizer.normalize( const normalizedResponse = CanvasWidgetsNormalizer.normalize(
pageResponse, extractCurrentDSL(fetchPageResponse),
); );
const canvasWidgetsPayload: LoadCanvasWidgetsPayload = { const canvasWidgetsPayload: LoadCanvasWidgetsPayload = {
pageWidgetId: normalizedResponse.result, pageWidgetId: normalizedResponse.result,
widgets: normalizedResponse.entities.canvasWidgets, widgets: normalizedResponse.entities.canvasWidgets,
layoutId: fetchPageResponse.data.layouts[0].id,
}; };
yield put(loadCanvasWidgets(canvasWidgetsPayload)); yield put(loadCanvasWidgets(canvasWidgetsPayload));
yield put({ yield put({
type: ReduxActionTypes.LOAD_CANVAS_ACTIONS, type: ReduxActionTypes.LOAD_CANVAS_ACTIONS,
payload: pageResponse.layout.actions, payload: fetchPageResponse.data.layouts[0].actions, // TODO: Refactor
}); });
} else {
yield put(fetchPageError(fetchPageResponse.responseMeta));
} }
// const fetchPageResponse = JSON.parse(`{
// "responseMeta": {
// "success": true,
// "code": 200
// },
// "data": {
// "id": "5d807e76795dc6000482bc76",
// "applicationId": "5d807e45795dc6000482bc74",
// "layouts": [
// {
// "id": "5d807e76795dc6000482bc75",
// "dsl": {
// "widgetId": "0",
// "type": "CONTAINER_WIDGET",
// "snapColumns": 16,
// "snapRows": 100,
// "topRow": 0,
// "bottomRow": 2000,
// "leftColumn": 0,
// "rightColumn": 1000,
// "parentColumnSpace": 1,
// "parentRowSpace": 1,
// "backgroundColor": "#ffffff",
// "renderMode": "CANVAS",
// "children": []
// }
// }
// ]
// }
// }`);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
//TODO(abhinav): REFACTOR THIS //TODO(abhinav): REFACTOR THIS
@ -82,7 +81,6 @@ export function* fetchPage(pageRequestAction: ReduxAction<FetchPageRequest>) {
export function* savePage(savePageAction: ReduxAction<SavePageRequest>) { export function* savePage(savePageAction: ReduxAction<SavePageRequest>) {
const savePageRequest = savePageAction.payload; const savePageRequest = savePageAction.payload;
try { try {
const savePageResponse: SavePageResponse = yield call( const savePageResponse: SavePageResponse = yield call(
PageApi.savePage, PageApi.savePage,

View File

@ -0,0 +1,13 @@
import { FetchPageResponse } from "../api/PageApi";
import { ContainerWidgetProps } from "../widgets/ContainerWidget";
import { WidgetProps } from "../widgets/BaseWidget";
export const extractCurrentDSL = (
fetchPageResponse: FetchPageResponse,
): ContainerWidgetProps<WidgetProps> => {
return fetchPageResponse.data.layouts[0].dsl;
};
export default {
extractCurrentDSL,
};