Merge branch 'release' into feature/telemetry
This commit is contained in:
commit
946b3ba25f
|
|
@ -1,41 +1,41 @@
|
|||
const queryLocators = require("../../../locators/QueryEditor.json");
|
||||
const queryEditor = require("../../../locators/QueryEditor.json");
|
||||
// const queryLocators = require("../../../locators/QueryEditor.json");
|
||||
// const queryEditor = require("../../../locators/QueryEditor.json");
|
||||
|
||||
let datasourceName;
|
||||
// let datasourceName;
|
||||
|
||||
describe("Add widget", function() {
|
||||
beforeEach(() => {
|
||||
cy.createPostgresDatasource();
|
||||
cy.get("@createDatasource").then(httpResponse => {
|
||||
datasourceName = httpResponse.response.body.data.name;
|
||||
});
|
||||
});
|
||||
// describe("Add widget", function() {
|
||||
// beforeEach(() => {
|
||||
// cy.createPostgresDatasource();
|
||||
// cy.get("@createDatasource").then(httpResponse => {
|
||||
// datasourceName = httpResponse.response.body.data.name;
|
||||
// });
|
||||
// });
|
||||
|
||||
it("Add widget", () => {
|
||||
cy.NavigateToQueryEditor();
|
||||
cy.contains(".t--datasource-name", datasourceName)
|
||||
.find(queryLocators.createQuery)
|
||||
.click();
|
||||
// it("Add widget", () => {
|
||||
// cy.NavigateToQueryEditor();
|
||||
// cy.contains(".t--datasource-name", datasourceName)
|
||||
// .find(queryLocators.createQuery)
|
||||
// .click();
|
||||
|
||||
cy.get(queryLocators.templateMenu).click();
|
||||
cy.get(".CodeMirror textarea")
|
||||
.first()
|
||||
.focus()
|
||||
.type("select * from configs");
|
||||
cy.wait(500);
|
||||
cy.get(queryEditor.runQuery).click();
|
||||
cy.wait("@postExecute").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
cy.get(".t--add-widget").click();
|
||||
cy.SearchEntityandOpen("Table1");
|
||||
cy.isSelectRow(1);
|
||||
cy.readTabledataPublish("1", "0").then(tabData => {
|
||||
const tabValue = tabData;
|
||||
expect(tabValue).to.be.equal("5");
|
||||
cy.log("the value is " + tabValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
// cy.get(queryLocators.templateMenu).click();
|
||||
// cy.get(".CodeMirror textarea")
|
||||
// .first()
|
||||
// .focus()
|
||||
// .type("select * from configs");
|
||||
// cy.wait(500);
|
||||
// cy.get(queryEditor.runQuery).click();
|
||||
// cy.wait("@postExecute").should(
|
||||
// "have.nested.property",
|
||||
// "response.body.responseMeta.status",
|
||||
// 200,
|
||||
// );
|
||||
// cy.get(".t--add-widget").click();
|
||||
// cy.SearchEntityandOpen("Table1");
|
||||
// cy.isSelectRow(1);
|
||||
// cy.readTabledataPublish("1", "0").then(tabData => {
|
||||
// const tabValue = tabData;
|
||||
// expect(tabValue).to.be.equal("5");
|
||||
// cy.log("the value is " + tabValue);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { EditorModes } from "../components/editorComponents/CodeEditor/EditorConfig";
|
||||
import { APP_MODE } from "../reducers/entityReducers/appReducer";
|
||||
import { UpdateApplicationPayload } from "api/ApplicationApi";
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
ReduxActionTypes,
|
||||
ReduxAction,
|
||||
InitializeEditorPayload,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
|
||||
export const initEditor = (
|
||||
|
|
@ -14,3 +15,17 @@ export const initEditor = (
|
|||
pageId,
|
||||
},
|
||||
});
|
||||
|
||||
export const initEditorError = (): ReduxAction<{ show: false }> => ({
|
||||
type: ReduxActionErrorTypes.INITIALIZE_EDITOR_ERROR,
|
||||
payload: {
|
||||
show: false,
|
||||
},
|
||||
});
|
||||
|
||||
export const initViewerError = (): ReduxAction<{ show: false }> => ({
|
||||
type: ReduxActionErrorTypes.INITIALIZE_PAGE_VIEWER_ERROR,
|
||||
payload: {
|
||||
show: false,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,13 +4,10 @@ import {
|
|||
API_REQUEST_HEADERS,
|
||||
} from "constants/ApiConstants";
|
||||
import { ActionApiResponse } from "./ActionAPI";
|
||||
import {
|
||||
AUTH_LOGIN_URL,
|
||||
PAGE_NOT_FOUND_URL,
|
||||
SERVER_ERROR_URL,
|
||||
} from "constants/routes";
|
||||
import { AUTH_LOGIN_URL, PAGE_NOT_FOUND_URL } from "constants/routes";
|
||||
import history from "utils/history";
|
||||
import { convertObjectToQueryParams } from "utils/AppsmithUtils";
|
||||
import { SERVER_API_TIMEOUT_ERROR } from "../constants/messages";
|
||||
|
||||
//TODO(abhinav): Refactor this to make more composable.
|
||||
export const apiRequestConfig = {
|
||||
|
|
@ -22,8 +19,10 @@ export const apiRequestConfig = {
|
|||
|
||||
const axiosInstance: AxiosInstance = axios.create();
|
||||
|
||||
export const axiosConnectionAbortedCode = "ECONNABORTED";
|
||||
const executeActionRegex = /actions\/execute/;
|
||||
const currentUserRegex = /\/me$/;
|
||||
const timeoutErrorRegex = /timeout of (\d+)ms exceeded/;
|
||||
|
||||
axiosInstance.interceptors.request.use((config: any) => {
|
||||
return { ...config, timer: performance.now() };
|
||||
});
|
||||
|
|
@ -50,20 +49,25 @@ axiosInstance.interceptors.response.use(
|
|||
return response.data;
|
||||
},
|
||||
function(error: any) {
|
||||
// Return if the call was cancelled via cancel token
|
||||
if (axios.isCancel(error)) {
|
||||
return;
|
||||
}
|
||||
if (error.code === "ECONNABORTED") {
|
||||
if (error.config && error.config.url.match(currentUserRegex)) {
|
||||
history.replace({ pathname: SERVER_ERROR_URL });
|
||||
}
|
||||
return Promise.reject({
|
||||
message: "Please check your internet connection",
|
||||
});
|
||||
}
|
||||
// Return modified response if action execution failed
|
||||
if (error.config && error.config.url.match(executeActionRegex)) {
|
||||
return makeExecuteActionResponse(error.response);
|
||||
}
|
||||
// Return error if any timeout happened in other api calls
|
||||
if (
|
||||
error.code === axiosConnectionAbortedCode &&
|
||||
error.message &&
|
||||
error.message.match(timeoutErrorRegex)
|
||||
) {
|
||||
return Promise.reject({
|
||||
...error,
|
||||
message: SERVER_API_TIMEOUT_ERROR,
|
||||
});
|
||||
}
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
|
|
|
|||
BIN
app/client/src/assets/images/timeout-image.png
Normal file
BIN
app/client/src/assets/images/timeout-image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
|
|
@ -292,8 +292,10 @@ class CodeEditor extends Component<Props, State> {
|
|||
("dataTreePath" in this.props && !!this.props.dataTreePath));
|
||||
|
||||
const showBindingPrompt =
|
||||
(!this.props.input.value?.includes("{{") || !this.props.input.value) &&
|
||||
showEvaluatedValue;
|
||||
showEvaluatedValue &&
|
||||
(!_.isString(this.props.input.value) ||
|
||||
!this.props.input.value?.includes("{{") ||
|
||||
!this.props.input.value);
|
||||
|
||||
return (
|
||||
<DynamicAutocompleteInputWrapper
|
||||
|
|
|
|||
|
|
@ -8,3 +8,20 @@ const APP_STORE_NAMESPACE = "APPSMITH_LOCAL_STORE";
|
|||
|
||||
export const getAppStoreName = (appId: string) =>
|
||||
`${APP_STORE_NAMESPACE}-${appId}`;
|
||||
|
||||
export const getAppStore = (appId: string) => {
|
||||
const appStoreName = getAppStoreName(appId);
|
||||
let storeString = "{}";
|
||||
// Check if localStorage exists
|
||||
if (localStorage) {
|
||||
const appStore = localStorage.getItem(appStoreName);
|
||||
if (appStore) storeString = appStore;
|
||||
}
|
||||
let store;
|
||||
try {
|
||||
store = JSON.parse(storeString);
|
||||
} catch (e) {
|
||||
store = {};
|
||||
}
|
||||
return store;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTy
|
|||
|
||||
export const ReduxActionErrorTypes: { [key: string]: string } = {
|
||||
INITIALIZE_EDITOR_ERROR: "INITIALIZE_EDITOR_ERROR",
|
||||
INITIALIZE_PAGE_VIEWER_ERROR: "INITIALIZE_PAGE_VIEWER_ERROR",
|
||||
API_ERROR: "API_ERROR",
|
||||
WIDGET_DELETE_ERROR: "WIDGET_DELETE_ERROR",
|
||||
UPDATE_APPLICATION_ERROR: "UPDATE_APPLICATION_ERROR",
|
||||
|
|
|
|||
|
|
@ -168,3 +168,6 @@ export const GOOGLE_RECAPTCHA_KEY_ERROR =
|
|||
"Google Re-Captcha Token Generation failed! Please check the Re-captcha Site Key.";
|
||||
export const GOOGLE_RECAPTCHA_DOMAIN_ERROR =
|
||||
"Google Re-Captcha Token Generation failed! Please check the allowed domains.";
|
||||
|
||||
export const SERVER_API_TIMEOUT_ERROR =
|
||||
"Appsmith server is taking too long to respond. Please try again after some time";
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ import {
|
|||
getApplicationViewerPageURL,
|
||||
} from "constants/routes";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { getIsInitialized } from "selectors/appViewSelectors";
|
||||
import {
|
||||
getIsInitialized,
|
||||
getIsInitializeError,
|
||||
} from "selectors/appViewSelectors";
|
||||
import { executeAction } from "actions/widgetActions";
|
||||
import { ExecuteActionPayload } from "constants/ActionConstants";
|
||||
import { updateWidgetPropertyRequest } from "actions/controlActions";
|
||||
|
|
@ -23,6 +26,8 @@ import {
|
|||
} from "actions/metaActions";
|
||||
import { editorInitializer } from "utils/EditorUtils";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import log from "loglevel";
|
||||
import ServerTimeout from "../common/ServerTimeout";
|
||||
const SentryRoute = Sentry.withSentryRouting(Route);
|
||||
|
||||
const AppViewerBody = styled.section`
|
||||
|
|
@ -36,6 +41,7 @@ const AppViewerBody = styled.section`
|
|||
export type AppViewerProps = {
|
||||
initializeAppViewer: (applicationId: string, pageId?: string) => void;
|
||||
isInitialized: boolean;
|
||||
isInitializeError: boolean;
|
||||
executeAction: (actionPayload: ExecuteActionPayload) => void;
|
||||
updateWidgetProperty: (
|
||||
widgetId: string,
|
||||
|
|
@ -62,7 +68,7 @@ class AppViewer extends Component<
|
|||
this.setState({ registered: true });
|
||||
});
|
||||
const { applicationId, pageId } = this.props.match.params;
|
||||
console.log({ applicationId, pageId });
|
||||
log.debug({ applicationId, pageId });
|
||||
if (applicationId) {
|
||||
this.props.initializeAppViewer(applicationId, pageId);
|
||||
}
|
||||
|
|
@ -73,7 +79,10 @@ class AppViewer extends Component<
|
|||
};
|
||||
|
||||
public render() {
|
||||
const { isInitialized } = this.props;
|
||||
const { isInitialized, isInitializeError } = this.props;
|
||||
if (isInitializeError) {
|
||||
return <ServerTimeout />;
|
||||
}
|
||||
return (
|
||||
<EditorContext.Provider
|
||||
value={{
|
||||
|
|
@ -100,6 +109,7 @@ class AppViewer extends Component<
|
|||
|
||||
const mapStateToProps = (state: AppState) => ({
|
||||
isInitialized: getIsInitialized(state),
|
||||
isInitializeError: getIsInitializeError(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => ({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter, RouteComponentProps } from "react-router-dom";
|
||||
import { RouteComponentProps, withRouter } from "react-router-dom";
|
||||
import {
|
||||
BuilderRouteParams,
|
||||
getApplicationViewerPageURL,
|
||||
|
|
@ -13,15 +13,16 @@ import TouchBackend from "react-dnd-touch-backend";
|
|||
import {
|
||||
getCurrentApplicationId,
|
||||
getCurrentPageId,
|
||||
getPublishingError,
|
||||
getIsEditorLoading,
|
||||
getIsEditorInitialized,
|
||||
getIsEditorInitializeError,
|
||||
getIsEditorLoading,
|
||||
getIsPublishingApplication,
|
||||
getPublishingError,
|
||||
} from "selectors/editorSelectors";
|
||||
import {
|
||||
Dialog,
|
||||
Classes,
|
||||
AnchorButton,
|
||||
Classes,
|
||||
Dialog,
|
||||
Hotkey,
|
||||
Hotkeys,
|
||||
Spinner,
|
||||
|
|
@ -40,11 +41,12 @@ import ConfirmRunModal from "pages/Editor/ConfirmRunModal";
|
|||
import * as Sentry from "@sentry/react";
|
||||
import {
|
||||
copyWidget,
|
||||
pasteWidget,
|
||||
deleteSelectedWidget,
|
||||
cutWidget,
|
||||
deleteSelectedWidget,
|
||||
pasteWidget,
|
||||
} from "actions/widgetActions";
|
||||
import { isMac } from "utils/helpers";
|
||||
import ServerTimeout from "../common/ServerTimeout";
|
||||
|
||||
type EditorProps = {
|
||||
currentApplicationId?: string;
|
||||
|
|
@ -53,6 +55,7 @@ type EditorProps = {
|
|||
isPublishing: boolean;
|
||||
isEditorLoading: boolean;
|
||||
isEditorInitialized: boolean;
|
||||
isEditorInitializeError: boolean;
|
||||
errorPublishing: boolean;
|
||||
copySelectedWidget: () => void;
|
||||
pasteCopiedWidget: () => void;
|
||||
|
|
@ -189,6 +192,8 @@ class Editor extends Component<Props> {
|
|||
nextProps.isPublishing !== this.props.isPublishing ||
|
||||
nextProps.isEditorLoading !== this.props.isEditorLoading ||
|
||||
nextProps.errorPublishing !== this.props.errorPublishing ||
|
||||
nextProps.isEditorInitializeError !==
|
||||
this.props.isEditorInitializeError ||
|
||||
nextState.isDialogOpen !== this.state.isDialogOpen ||
|
||||
nextState.registered !== this.state.registered
|
||||
);
|
||||
|
|
@ -200,6 +205,9 @@ class Editor extends Component<Props> {
|
|||
});
|
||||
};
|
||||
public render() {
|
||||
if (this.props.isEditorInitializeError) {
|
||||
return <ServerTimeout />;
|
||||
}
|
||||
if (!this.props.isEditorInitialized || !this.state.registered) {
|
||||
return (
|
||||
<CenteredWrapper style={{ height: "calc(100vh - 48px)" }}>
|
||||
|
|
@ -260,6 +268,7 @@ const mapStateToProps = (state: AppState) => ({
|
|||
isPublishing: getIsPublishingApplication(state),
|
||||
isEditorLoading: getIsEditorLoading(state),
|
||||
isEditorInitialized: getIsEditorInitialized(state),
|
||||
isEditorInitializeError: getIsEditorInitializeError(state),
|
||||
user: getCurrentUser(state),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import { RouterProps } from "react-router";
|
||||
import { RouteComponentProps, withRouter } from "react-router";
|
||||
import styled from "styled-components";
|
||||
import Button from "components/editorComponents/Button";
|
||||
import PageUnavailableImage from "assets/images/404-image.png";
|
||||
|
|
@ -20,7 +20,7 @@ const Wrapper = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
class PageNotFound extends React.PureComponent<RouterProps> {
|
||||
class PageNotFound extends React.PureComponent<RouteComponentProps> {
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
|
|
@ -54,4 +54,4 @@ class PageNotFound extends React.PureComponent<RouterProps> {
|
|||
}
|
||||
}
|
||||
|
||||
export default PageNotFound;
|
||||
export default withRouter(PageNotFound);
|
||||
|
|
|
|||
56
app/client/src/pages/common/ServerTimeout.tsx
Normal file
56
app/client/src/pages/common/ServerTimeout.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import AppTimeoutImage from "assets/images/timeout-image.png";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
height: calc(100vh - ${props => props.theme.headerHeight});
|
||||
.bold-text {
|
||||
font-weight: ${props => props.theme.fontWeights[3]};
|
||||
font-size: 24px;
|
||||
}
|
||||
.page-unavailable-img {
|
||||
width: 35%;
|
||||
}
|
||||
.button-position {
|
||||
margin: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
const RetryButton = styled.button`
|
||||
background-color: #f3672a;
|
||||
color: white;
|
||||
height: 40px;
|
||||
width: 300px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 17px;
|
||||
`;
|
||||
|
||||
const ServerTimeout = () => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<img
|
||||
src={AppTimeoutImage}
|
||||
alt="Page Unavailable"
|
||||
className="page-unavailable-img"
|
||||
/>
|
||||
<div>
|
||||
<p className="bold-text">
|
||||
Appsmith server is taking too long to respond
|
||||
</p>
|
||||
<p>Please retry after some time</p>
|
||||
<RetryButton onClick={() => window.location.reload()}>
|
||||
{"Retry"}
|
||||
</RetryButton>
|
||||
</div>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerTimeout;
|
||||
|
|
@ -5,12 +5,14 @@ import {
|
|||
ReduxAction,
|
||||
ReduxActionTypes,
|
||||
PageListPayload,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { FetchPublishedPageSuccessPayload } from "actions/pageActions";
|
||||
|
||||
const initialState: AppViewReduxState = {
|
||||
isFetchingPage: false,
|
||||
initialized: false,
|
||||
initializeError: false,
|
||||
pages: [],
|
||||
pageWidgetId: "0",
|
||||
};
|
||||
|
|
@ -24,6 +26,11 @@ const appViewReducer = createReducer(initialState, {
|
|||
) => {
|
||||
return { ...state, initialized: true };
|
||||
},
|
||||
[ReduxActionErrorTypes.INITIALIZE_PAGE_VIEWER_ERROR]: (
|
||||
state: AppViewReduxState,
|
||||
) => {
|
||||
return { ...state, initializeError: true };
|
||||
},
|
||||
[ReduxActionTypes.FETCH_PUBLISHED_PAGE_INIT]: (state: AppViewReduxState) => {
|
||||
return { ...state, dsl: undefined, isFetchingPage: true };
|
||||
},
|
||||
|
|
@ -45,6 +52,7 @@ const appViewReducer = createReducer(initialState, {
|
|||
|
||||
export interface AppViewReduxState {
|
||||
initialized: boolean;
|
||||
initializeError: boolean;
|
||||
dsl?: ContainerWidgetProps<WidgetProps>;
|
||||
isFetchingPage: boolean;
|
||||
currentLayoutId?: string;
|
||||
|
|
|
|||
|
|
@ -5,12 +5,11 @@ import {
|
|||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
import moment from "moment";
|
||||
|
||||
const initialState: EditorReduxState = {
|
||||
initialized: false,
|
||||
initializationError: false,
|
||||
loadingStates: {
|
||||
publishing: false,
|
||||
publishingError: false,
|
||||
|
|
@ -68,11 +67,8 @@ const editorReducer = createReducer(initialState, {
|
|||
) => {
|
||||
return {
|
||||
...state,
|
||||
loadingStates: {
|
||||
...state.loadingStates,
|
||||
loading: false,
|
||||
loadingError: true,
|
||||
},
|
||||
initializationError: true,
|
||||
initialized: false,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.PUBLISH_APPLICATION_INIT]: (state: EditorReduxState) => {
|
||||
|
|
@ -178,7 +174,7 @@ const editorReducer = createReducer(initialState, {
|
|||
|
||||
export interface EditorReduxState {
|
||||
initialized: boolean;
|
||||
dsl?: ContainerWidgetProps<WidgetProps>;
|
||||
initializationError: boolean;
|
||||
pageWidgetId?: string;
|
||||
currentLayoutId?: string;
|
||||
currentPageName?: string;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { put, takeLatest, call } from "redux-saga/effects";
|
|||
import { ERROR_401, ERROR_500, ERROR_0 } from "constants/messages";
|
||||
import { ToastType } from "react-toastify";
|
||||
import log from "loglevel";
|
||||
import { axiosConnectionAbortedCode } from "../api/Api";
|
||||
|
||||
export function* callAPI(apiCall: any, requestPayload: any) {
|
||||
try {
|
||||
|
|
@ -60,7 +61,7 @@ export function getResponseErrorMessage(response: ApiResponse) {
|
|||
: undefined;
|
||||
}
|
||||
|
||||
type ErrorPayloadType = { code?: number; message?: string };
|
||||
type ErrorPayloadType = { code?: number | string; message?: string };
|
||||
let ActionErrorDisplayMap: {
|
||||
[key: string]: (error: ErrorPayloadType) => string;
|
||||
} = {};
|
||||
|
|
@ -92,6 +93,7 @@ export function* errorSaga(
|
|||
type,
|
||||
payload: { error, show = true },
|
||||
} = errorAction;
|
||||
|
||||
const message =
|
||||
error && error.message ? error.message : ActionErrorDisplayMap[type](error);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import { all, call, put, select, take, takeLatest } from "redux-saga/effects";
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
put,
|
||||
select,
|
||||
take,
|
||||
takeLatest,
|
||||
race,
|
||||
} from "redux-saga/effects";
|
||||
import {
|
||||
InitializeEditorPayload,
|
||||
Page,
|
||||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionTypes,
|
||||
|
|
@ -21,126 +28,86 @@ import { fetchActions, fetchActionsForView } from "actions/actionActions";
|
|||
import { fetchApplication } from "actions/applicationActions";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { getCurrentApplication } from "selectors/applicationSelectors";
|
||||
import { AppState } from "reducers";
|
||||
import PageApi, { FetchPageResponse } from "api/PageApi";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
import { extractCurrentDSL } from "utils/WidgetPropsUtils";
|
||||
import { APP_MODE } from "reducers/entityReducers/appReducer";
|
||||
import { getAppStoreName } from "constants/AppConstants";
|
||||
import { getAppStore } from "constants/AppConstants";
|
||||
import { getDefaultPageId } from "./selectors";
|
||||
|
||||
const getAppStore = (appId: string) => {
|
||||
const appStoreName = getAppStoreName(appId);
|
||||
const storeString = localStorage.getItem(appStoreName) || "{}";
|
||||
let store;
|
||||
try {
|
||||
store = JSON.parse(storeString);
|
||||
} catch (e) {
|
||||
store = {};
|
||||
}
|
||||
return store;
|
||||
};
|
||||
import { populatePageDSLsSaga } from "./PageSagas";
|
||||
import { initEditorError, initViewerError } from "../actions/initActions";
|
||||
|
||||
function* initializeEditorSaga(
|
||||
initializeEditorAction: ReduxAction<InitializeEditorPayload>,
|
||||
) {
|
||||
const { applicationId, pageId } = initializeEditorAction.payload;
|
||||
// Step 1: Set App Mode. Start getting all the data needed
|
||||
yield put(setAppMode(APP_MODE.EDIT));
|
||||
yield put({ type: ReduxActionTypes.START_EVALUATION });
|
||||
yield all([
|
||||
put(fetchPageList(applicationId, APP_MODE.EDIT)),
|
||||
put(fetchEditorConfigs()),
|
||||
put(fetchActions(applicationId)),
|
||||
put(fetchPage(pageId)),
|
||||
put(fetchApplication(applicationId, APP_MODE.EDIT)),
|
||||
]);
|
||||
// Step 2: Wait for all data to be in the state
|
||||
yield all([
|
||||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_PAGE_SUCCESS),
|
||||
take(ReduxActionTypes.SWITCH_CURRENT_PAGE_ID),
|
||||
take(ReduxActionTypes.FETCH_ACTIONS_SUCCESS),
|
||||
]);
|
||||
|
||||
// Step 3: Call all the APIs which needs Organization Id from PageList API response.
|
||||
yield all([put(fetchPlugins()), put(fetchDatasources())]);
|
||||
|
||||
// Step 4: Wait for all data to be in the state
|
||||
yield all([
|
||||
take(ReduxActionTypes.FETCH_PLUGINS_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_DATASOURCES_SUCCESS),
|
||||
]);
|
||||
|
||||
// Step 5: Set app store
|
||||
yield put(updateAppStore(getAppStore(applicationId)));
|
||||
|
||||
const currentApplication = yield select(getCurrentApplication);
|
||||
|
||||
const appName = currentApplication ? currentApplication.name : "";
|
||||
const appId = currentApplication ? currentApplication.id : "";
|
||||
|
||||
AnalyticsUtil.logEvent("EDITOR_OPEN", {
|
||||
appId: appId,
|
||||
appName: appName,
|
||||
});
|
||||
|
||||
// Step 6: Notify UI that the editor is ready to go
|
||||
yield put({
|
||||
type: ReduxActionTypes.INITIALIZE_EDITOR_SUCCESS,
|
||||
});
|
||||
yield call(populatePageDSLsSaga);
|
||||
}
|
||||
|
||||
function* fetchPageDSLSaga(pageId: string) {
|
||||
try {
|
||||
const fetchPageResponse: FetchPageResponse = yield call(PageApi.fetchPage, {
|
||||
id: pageId,
|
||||
yield put(setAppMode(APP_MODE.EDIT));
|
||||
yield put({ type: ReduxActionTypes.START_EVALUATION });
|
||||
yield all([
|
||||
put(fetchPageList(applicationId, APP_MODE.EDIT)),
|
||||
put(fetchEditorConfigs()),
|
||||
put(fetchActions(applicationId)),
|
||||
put(fetchPage(pageId)),
|
||||
put(fetchApplication(applicationId, APP_MODE.EDIT)),
|
||||
]);
|
||||
|
||||
const resultOfPrimaryCalls = yield race({
|
||||
success: all([
|
||||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_PAGE_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_APPLICATION_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_ACTIONS_SUCCESS),
|
||||
]),
|
||||
failure: take([
|
||||
ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_PAGE_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_APPLICATION_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
|
||||
]),
|
||||
});
|
||||
const isValidResponse = yield validateResponse(fetchPageResponse);
|
||||
if (isValidResponse) {
|
||||
return {
|
||||
pageId: pageId,
|
||||
dsl: extractCurrentDSL(fetchPageResponse),
|
||||
};
|
||||
|
||||
if (resultOfPrimaryCalls.failure) {
|
||||
yield put(initEditorError());
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_PAGE_DSL_ERROR,
|
||||
payload: {
|
||||
pageId: pageId,
|
||||
error,
|
||||
show: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* populatePageDSLsSaga() {
|
||||
try {
|
||||
yield put({
|
||||
type: ReduxActionTypes.POPULATE_PAGEDSLS_INIT,
|
||||
yield all([put(fetchPlugins()), put(fetchDatasources())]);
|
||||
|
||||
const resultOfSecondaryCalls = yield race({
|
||||
success: all([
|
||||
take(ReduxActionTypes.FETCH_PLUGINS_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_DATASOURCES_SUCCESS),
|
||||
]),
|
||||
failure: take([
|
||||
ReduxActionErrorTypes.FETCH_PLUGINS_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_DATASOURCES_ERROR,
|
||||
]),
|
||||
});
|
||||
const pageIds: string[] = yield select((state: AppState) =>
|
||||
state.entities.pageList.pages.map((page: Page) => page.pageId),
|
||||
);
|
||||
const pageDSLs = yield all(
|
||||
pageIds.map((pageId: string) => {
|
||||
return call(fetchPageDSLSaga, pageId);
|
||||
}),
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_PAGE_DSLS_SUCCESS,
|
||||
payload: pageDSLs,
|
||||
|
||||
if (resultOfSecondaryCalls.failure) {
|
||||
yield put(initEditorError());
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(updateAppStore(getAppStore(applicationId)));
|
||||
|
||||
const currentApplication = yield select(getCurrentApplication);
|
||||
|
||||
const appName = currentApplication ? currentApplication.name : "";
|
||||
const appId = currentApplication ? currentApplication.id : "";
|
||||
|
||||
AnalyticsUtil.logEvent("EDITOR_OPEN", {
|
||||
appId: appId,
|
||||
appName: appName,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.POPULATE_PAGEDSLS_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
type: ReduxActionTypes.INITIALIZE_EDITOR_SUCCESS,
|
||||
});
|
||||
} catch (e) {
|
||||
yield put(initEditorError());
|
||||
return;
|
||||
}
|
||||
|
||||
yield call(populatePageDSLsSaga);
|
||||
}
|
||||
|
||||
export function* initializeAppViewerSaga(
|
||||
|
|
@ -156,11 +123,23 @@ export function* initializeAppViewerSaga(
|
|||
put(fetchApplication(applicationId, APP_MODE.PUBLISHED)),
|
||||
]);
|
||||
|
||||
yield all([
|
||||
take(ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_APPLICATION_SUCCESS),
|
||||
]);
|
||||
const resultOfPrimaryCalls = yield race({
|
||||
success: all([
|
||||
take(ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_APPLICATION_SUCCESS),
|
||||
]),
|
||||
failure: take([
|
||||
ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_APPLICATION_ERROR,
|
||||
]),
|
||||
});
|
||||
|
||||
if (resultOfPrimaryCalls.failure) {
|
||||
yield put(initViewerError());
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(updateAppStore(getAppStore(applicationId)));
|
||||
const defaultPageId = yield select(getDefaultPageId);
|
||||
|
|
@ -168,7 +147,15 @@ export function* initializeAppViewerSaga(
|
|||
|
||||
if (toLoadPageId) {
|
||||
yield put(fetchPublishedPage(toLoadPageId, true));
|
||||
yield take(ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS);
|
||||
|
||||
const resultOfFetchPage = yield race({
|
||||
success: take(ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS),
|
||||
failure: take(ReduxActionErrorTypes.FETCH_PUBLISHED_PAGE_ERROR),
|
||||
});
|
||||
if (resultOfFetchPage.failure) {
|
||||
yield put(initViewerError());
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(setAppMode(APP_MODE.PUBLISHED));
|
||||
yield put(updateAppStore(getAppStore(applicationId)));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import CanvasWidgetsNormalizer from "normalizers/CanvasWidgetsNormalizer";
|
||||
import { AppState } from "reducers";
|
||||
import {
|
||||
Page,
|
||||
PageListPayload,
|
||||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
|
|
@ -43,7 +44,6 @@ import {
|
|||
select,
|
||||
takeLatest,
|
||||
takeLeading,
|
||||
take,
|
||||
} from "redux-saga/effects";
|
||||
import history from "utils/history";
|
||||
import { BUILDER_PAGE_URL } from "constants/routes";
|
||||
|
|
@ -117,6 +117,16 @@ export function* fetchPageListSaga(
|
|||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_LIST_API,
|
||||
);
|
||||
} else {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_LIST_API,
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR,
|
||||
payload: {
|
||||
error: response.responseMeta.error,
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
|
|
@ -608,6 +618,57 @@ export function* setDataUrl() {
|
|||
yield put(setUrlData(urlData));
|
||||
}
|
||||
|
||||
function* fetchPageDSLSaga(pageId: string) {
|
||||
try {
|
||||
const fetchPageResponse: FetchPageResponse = yield call(PageApi.fetchPage, {
|
||||
id: pageId,
|
||||
});
|
||||
const isValidResponse = yield validateResponse(fetchPageResponse);
|
||||
if (isValidResponse) {
|
||||
return {
|
||||
pageId: pageId,
|
||||
dsl: extractCurrentDSL(fetchPageResponse),
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_PAGE_DSL_ERROR,
|
||||
payload: {
|
||||
pageId: pageId,
|
||||
error,
|
||||
show: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* populatePageDSLsSaga() {
|
||||
try {
|
||||
yield put({
|
||||
type: ReduxActionTypes.POPULATE_PAGEDSLS_INIT,
|
||||
});
|
||||
const pageIds: string[] = yield select((state: AppState) =>
|
||||
state.entities.pageList.pages.map((page: Page) => page.pageId),
|
||||
);
|
||||
const pageDSLs = yield all(
|
||||
pageIds.map((pageId: string) => {
|
||||
return call(fetchPageDSLSaga, pageId);
|
||||
}),
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_PAGE_DSLS_SUCCESS,
|
||||
payload: pageDSLs,
|
||||
});
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.POPULATE_PAGEDSLS_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default function* pageSagas() {
|
||||
yield all([
|
||||
takeLatest(ReduxActionTypes.FETCH_PAGE_INIT, fetchPageSaga),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,11 @@ export const getIsInitialized = createSelector(
|
|||
(view: AppViewReduxState) => view.initialized,
|
||||
);
|
||||
|
||||
export const getIsInitializeError = createSelector(
|
||||
getAppViewState,
|
||||
(view: AppViewReduxState) => view.initializeError,
|
||||
);
|
||||
|
||||
export const getCurrentDSLPageId = createSelector(
|
||||
getPageListState,
|
||||
(pageList: PageListReduxState) => pageList.currentPageId,
|
||||
|
|
|
|||
|
|
@ -20,14 +20,12 @@ import { getDataTree } from "selectors/dataTreeSelectors";
|
|||
import _ from "lodash";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
import { DataTreeWidget, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||
import { getActions, getWidgetsMeta } from "sagas/selectors";
|
||||
import { getActions } from "sagas/selectors";
|
||||
|
||||
import * as log from "loglevel";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
import { getCanvasWidgets } from "./entitiesSelector";
|
||||
import { MetaState } from "../reducers/entityReducers/metaReducer";
|
||||
import { WidgetTypes } from "../constants/WidgetConstants";
|
||||
|
||||
const getWidgetConfigs = (state: AppState) => state.entities.widgetConfig;
|
||||
|
|
@ -45,6 +43,9 @@ const getWidgets = (state: AppState): CanvasWidgetsReduxState =>
|
|||
export const getIsEditorInitialized = (state: AppState) =>
|
||||
state.ui.editor.initialized;
|
||||
|
||||
export const getIsEditorInitializeError = (state: AppState): boolean =>
|
||||
state.ui.editor.initializationError;
|
||||
|
||||
export const getIsEditorLoading = (state: AppState) =>
|
||||
state.ui.editor.loadingStates.loading;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,74 +4,93 @@ import lombok.Getter;
|
|||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
enum AppsmithErrorAction {
|
||||
DEFAULT,
|
||||
LOG_EXTERNALLY
|
||||
}
|
||||
@Getter
|
||||
public enum AppsmithError {
|
||||
|
||||
INVALID_PARAMETER(400, 4000, "Please enter a valid parameter {0}."),
|
||||
PLUGIN_NOT_INSTALLED(400, 4001, "Plugin {0} not installed"),
|
||||
PLUGIN_ID_NOT_GIVEN(400, 4002, "Missing plugin id. Please enter one."),
|
||||
DATASOURCE_NOT_GIVEN(400, 4003, "Missing datasource. Add/enter/connect a datasource to create a valid action."),
|
||||
PAGE_ID_NOT_GIVEN(400, 4004, "Missing page id. Please enter one."),
|
||||
PAGE_DOESNT_BELONG_TO_USER_ORGANIZATION(400, 4006, "Page {0} does not belong to the current user {1} organization"),
|
||||
UNSUPPORTED_OPERATION(400, 4007, "Unsupported operation"),
|
||||
USER_DOESNT_BELONG_ANY_ORGANIZATION(400, 4009, "User {0} does not belong to any organization"),
|
||||
USER_DOESNT_BELONG_TO_ORGANIZATION(400, 4010, "User {0} does not belong to an organization with id {1}"),
|
||||
NO_CONFIGURATION_FOUND_IN_DATASOURCE(400, 4011, "No datasource configuration found. Please configure it and try again."),
|
||||
INVALID_ACTION(400, 4012, "Action {0} with id {1} is invalid: {2}"),
|
||||
INVALID_DATASOURCE(400, 4013, "Datasource is invalid. Please edit to make it valid. Details: {0}"),
|
||||
INVALID_ACTION_NAME(400, 4014, "Action name is invalid. Please input syntactically correct name"),
|
||||
INVALID_DATASOURCE_CONFIGURATION(400, 4015, "Datasource configuration is invalid"),
|
||||
NO_CONFIGURATION_FOUND_IN_ACTION(400, 4016, "No action configuration found. Please configure it and try again."),
|
||||
NAME_CLASH_NOT_ALLOWED_IN_REFACTOR(400, 4017, "The new name {1} already exists in the current page. Choose another name."),
|
||||
PAGE_DOESNT_BELONG_TO_APPLICATION(400, 4018, "Page {0} does not belong to the application {1}"),
|
||||
NO_DSL_FOUND_IN_PAGE(400, 4020, "The page {0} doesn't have a DSL. This is an unexpected state"),
|
||||
USER_ALREADY_EXISTS_IN_ORGANIZATION(400, 4021, "The user {0} has already been added to the organization with role {1}"),
|
||||
UNAUTHORIZED_DOMAIN(401, 4019, "Invalid email domain provided. Please sign in with a valid work email ID"),
|
||||
USER_NOT_SIGNED_IN(401, 4020, "User is not logged in. Please sign in with the registered email ID or sign up" ),
|
||||
INVALID_PASSWORD_RESET(400, 4020, "Unable to reset the password. Please initiate a request via 'forgot password' button to reset your password"),
|
||||
LOGIN_INTERNAL_ERROR(401, 4021, "Internal error while trying to login"),
|
||||
JSON_PROCESSING_ERROR(400, 4022, "Json processing error with error {0}"),
|
||||
INVALID_CREDENTIALS(200, 4023, "Invalid credentials provided. Did you input the credentials correctly?"),
|
||||
DUPLICATE_KEY(409, 4024, "Duplicate key error"),
|
||||
USER_ALREADY_EXISTS_SIGNUP(409, 4025, "There is already an account registered with this email {0}. Please sign in."),
|
||||
UNAUTHORIZED_ACCESS(403, 4025, "Unauthorized access"),
|
||||
ACTION_IS_NOT_AUTHORIZED(403, 4026, "Sorry. You do not have permissions to perform this action"),
|
||||
INVALID_DATASOURCE_NAME(400, 4026, "Invalid datasource name. Check again."),
|
||||
NO_RESOURCE_FOUND(404, 4027, "Unable to find {0} with id {1}"),
|
||||
USER_NOT_FOUND(404, 4027, "Unable to find user with email {0}"),
|
||||
ACL_NO_RESOURCE_FOUND(404, 4028, "Unable to find {0} with id {1}. Either the asset doesn't exist or you don't have required permissions"),
|
||||
GENERIC_BAD_REQUEST(400, 4028, "Bad Request: {0}"),
|
||||
VALIDATION_FAILURE(400, 4028, "Validation Failure(s): {0}"),
|
||||
INVALID_CURL_COMMAND(400, 4029, "Invalid cURL command, couldn't import."),
|
||||
INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request"),
|
||||
REPOSITORY_SAVE_FAILED(500, 5001, "Failed to save the repository. Try again."),
|
||||
PLUGIN_INSTALLATION_FAILED_DOWNLOAD_ERROR(500, 5002, "Plugin installation failed due to an error while downloading it. Check the jar location & try again."),
|
||||
PLUGIN_RUN_FAILED(500, 5003, "Plugin execution failed with error {0}"),
|
||||
PLUGIN_EXECUTION_TIMEOUT(504, 5040, "Plugin Execution exceeded the maximum allowed time. Please increase the timeout in your action settings or check your backend action endpoint"),
|
||||
PLUGIN_LOAD_FORM_JSON_FAIL(500, 5004, "Unable to load datasource form configuration. Details: {0}."),
|
||||
PLUGIN_LOAD_TEMPLATES_FAIL(500, 5005, "Unable to load datasource templates. Details: {0}."),
|
||||
MARKETPLACE_TIMEOUT(504, 5041, "Marketplace is responding too slowly. Please try again later"),
|
||||
DATASOURCE_HAS_ACTIONS(409, 4030, "Cannot delete datasource since it has {0} action(s) using it."),
|
||||
ORGANIZATION_ID_NOT_GIVEN(400, 4031, "Missing organization id. Please enter one."),
|
||||
INVALID_CURL_METHOD(400, 4032, "Invalid method in cURL command: {0}."),
|
||||
OAUTH_NOT_AVAILABLE(500, 5006, "Login with {0} is not supported."),
|
||||
MARKETPLACE_NOT_CONFIGURED(500, 5007, "Marketplace is not configured."),
|
||||
INVALID_PARAMETER(400, 4000, "Please enter a valid parameter {0}.", AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_NOT_INSTALLED(400, 4001, "Plugin {0} not installed", AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_ID_NOT_GIVEN(400, 4002, "Missing plugin id. Please enter one.", AppsmithErrorAction.DEFAULT),
|
||||
DATASOURCE_NOT_GIVEN(400, 4003, "Missing datasource. Add/enter/connect a datasource to create a valid action.", AppsmithErrorAction.DEFAULT),
|
||||
PAGE_ID_NOT_GIVEN(400, 4004, "Missing page id. Please enter one.", AppsmithErrorAction.DEFAULT),
|
||||
PAGE_DOESNT_BELONG_TO_USER_ORGANIZATION(400, 4006, "Page {0} does not belong to the current user {1} " +
|
||||
"organization", AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
UNSUPPORTED_OPERATION(400, 4007, "Unsupported operation", AppsmithErrorAction.DEFAULT),
|
||||
USER_DOESNT_BELONG_ANY_ORGANIZATION(400, 4009, "User {0} does not belong to any organization",
|
||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
USER_DOESNT_BELONG_TO_ORGANIZATION(400, 4010, "User {0} does not belong to an organization with id {1}",
|
||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
NO_CONFIGURATION_FOUND_IN_DATASOURCE(400, 4011, "No datasource configuration found. Please configure it and try again.", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_ACTION(400, 4012, "Action {0} with id {1} is invalid: {2}", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_DATASOURCE(400, 4013, "Datasource is invalid. Please edit to make it valid. Details: {0}", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_ACTION_NAME(400, 4014, "Action name is invalid. Please input syntactically correct name", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_DATASOURCE_CONFIGURATION(400, 4015, "Datasource configuration is invalid", AppsmithErrorAction.DEFAULT),
|
||||
NO_CONFIGURATION_FOUND_IN_ACTION(400, 4016, "No action configuration found. Please configure it and try again.", AppsmithErrorAction.DEFAULT),
|
||||
NAME_CLASH_NOT_ALLOWED_IN_REFACTOR(400, 4017, "The new name {1} already exists in the current page. Choose another name.", AppsmithErrorAction.DEFAULT),
|
||||
PAGE_DOESNT_BELONG_TO_APPLICATION(400, 4018, "Page {0} does not belong to the application {1}",
|
||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
NO_DSL_FOUND_IN_PAGE(400, 4020, "The page {0} doesn't have a DSL. This is an unexpected state", AppsmithErrorAction.DEFAULT),
|
||||
USER_ALREADY_EXISTS_IN_ORGANIZATION(400, 4021, "The user {0} has already been added to the organization with role {1}", AppsmithErrorAction.DEFAULT),
|
||||
UNAUTHORIZED_DOMAIN(401, 4019, "Invalid email domain provided. Please sign in with a valid work email ID", AppsmithErrorAction.DEFAULT),
|
||||
USER_NOT_SIGNED_IN(401, 4020, "User is not logged in. Please sign in with the registered email ID or sign up",
|
||||
AppsmithErrorAction.DEFAULT),
|
||||
INVALID_PASSWORD_RESET(400, 4020, "Unable to reset the password. Please initiate a request via 'forgot password' " +
|
||||
"button to reset your password", AppsmithErrorAction.DEFAULT),
|
||||
LOGIN_INTERNAL_ERROR(401, 4021, "Internal error while trying to login", AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
JSON_PROCESSING_ERROR(400, 4022, "Json processing error with error {0}", AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
INVALID_CREDENTIALS(200, 4023, "Invalid credentials provided. Did you input the credentials correctly?", AppsmithErrorAction.DEFAULT),
|
||||
DUPLICATE_KEY(409, 4024, "Duplicate key error", AppsmithErrorAction.DEFAULT),
|
||||
USER_ALREADY_EXISTS_SIGNUP(409, 4025, "There is already an account registered with this email {0}. Please sign in.", AppsmithErrorAction.DEFAULT),
|
||||
UNAUTHORIZED_ACCESS(403, 4025, "Unauthorized access", AppsmithErrorAction.DEFAULT),
|
||||
ACTION_IS_NOT_AUTHORIZED(403, 4026, "Sorry. You do not have permissions to perform this action", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_DATASOURCE_NAME(400, 4026, "Invalid datasource name. Check again.", AppsmithErrorAction.DEFAULT),
|
||||
NO_RESOURCE_FOUND(404, 4027, "Unable to find {0} with id {1}", AppsmithErrorAction.DEFAULT),
|
||||
USER_NOT_FOUND(404, 4027, "Unable to find user with email {0}", AppsmithErrorAction.DEFAULT),
|
||||
ACL_NO_RESOURCE_FOUND(404, 4028, "Unable to find {0} with id {1}. Either the asset doesn't exist or you don't have required permissions", AppsmithErrorAction.DEFAULT),
|
||||
GENERIC_BAD_REQUEST(400, 4028, "Bad Request: {0}", AppsmithErrorAction.DEFAULT),
|
||||
VALIDATION_FAILURE(400, 4028, "Validation Failure(s): {0}", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_CURL_COMMAND(400, 4029, "Invalid cURL command, couldn't import.", AppsmithErrorAction.DEFAULT),
|
||||
INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request", AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
REPOSITORY_SAVE_FAILED(500, 5001, "Failed to save the repository. Try again.", AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_INSTALLATION_FAILED_DOWNLOAD_ERROR(500, 5002, "Plugin installation failed due to an error while " +
|
||||
"downloading it. Check the jar location & try again.", AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
PLUGIN_RUN_FAILED(500, 5003, "Plugin execution failed with error {0}", AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_EXECUTION_TIMEOUT(504, 5040, "Plugin Execution exceeded the maximum allowed time. Please increase the timeout in your action settings or check your backend action endpoint", AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_LOAD_FORM_JSON_FAIL(500, 5004, "Unable to load datasource form configuration. Details: {0}.",
|
||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
PLUGIN_LOAD_TEMPLATES_FAIL(500, 5005, "Unable to load datasource templates. Details: {0}.",
|
||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
MARKETPLACE_TIMEOUT(504, 5041, "Marketplace is responding too slowly. Please try again later", AppsmithErrorAction.DEFAULT),
|
||||
DATASOURCE_HAS_ACTIONS(409, 4030, "Cannot delete datasource since it has {0} action(s) using it.", AppsmithErrorAction.DEFAULT),
|
||||
ORGANIZATION_ID_NOT_GIVEN(400, 4031, "Missing organization id. Please enter one.", AppsmithErrorAction.DEFAULT),
|
||||
INVALID_CURL_METHOD(400, 4032, "Invalid method in cURL command: {0}.", AppsmithErrorAction.DEFAULT),
|
||||
OAUTH_NOT_AVAILABLE(500, 5006, "Login with {0} is not supported.", AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
MARKETPLACE_NOT_CONFIGURED(500, 5007, "Marketplace is not configured.", AppsmithErrorAction.DEFAULT),
|
||||
;
|
||||
|
||||
|
||||
private final Integer httpErrorCode;
|
||||
private final Integer appErrorCode;
|
||||
private final String message;
|
||||
private final AppsmithErrorAction errorAction;
|
||||
|
||||
AppsmithError(Integer httpErrorCode, Integer appErrorCode, String message, Object... args) {
|
||||
AppsmithError(Integer httpErrorCode, Integer appErrorCode, String message, AppsmithErrorAction errorAction, Object... args) {
|
||||
this.httpErrorCode = httpErrorCode;
|
||||
this.appErrorCode = appErrorCode;
|
||||
MessageFormat fmt = new MessageFormat(message);
|
||||
this.message = fmt.format(args);
|
||||
this.errorAction = errorAction;
|
||||
}
|
||||
|
||||
public String getMessage(Object... args) {
|
||||
return new MessageFormat(this.message).format(args);
|
||||
}
|
||||
|
||||
public AppsmithErrorAction getErrorAction() {
|
||||
return this.errorAction;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,8 @@ public class AppsmithException extends Exception {
|
|||
return this.error == null ? -1 : this.error.getAppErrorCode();
|
||||
}
|
||||
|
||||
public AppsmithErrorAction getErrorAction() {
|
||||
return this.error.getErrorAction();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,16 @@ public class GlobalExceptionHandler {
|
|||
|
||||
private void doLog(Throwable error) {
|
||||
log.error("", error);
|
||||
if (rollbar != null) {
|
||||
rollbar.log(error);
|
||||
|
||||
if (error instanceof AppsmithException) {
|
||||
if (rollbar != null && ((AppsmithException)error).getErrorAction() == AppsmithErrorAction.LOG_EXTERNALLY) {
|
||||
rollbar.log(error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(rollbar != null) {
|
||||
rollbar.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user