feat: disabling the toast messages on view mode without debug flag (#23768)

## Description
When the application is in published mode, this Pr offers the ability to
disable the error toast. Only the toasts that the user initiated are
displayed; all others are disabled and messages are logged in the
console.
When the view mode url has `debug=true` as one of the query params, then
all the error toasts are visible.

#### PR fixes following issue(s)
Fixes #23605
Fixes #23603 

#### Media
> A video or a GIF is preferred. when using Loom, don’t embed because it
looks like it’s a GIF. instead, just link to the video
>
>
#### Type of change
> Please delete options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- Chore (housekeeping or task changes that don't impact user perception)
- This change requires a documentation update
>
>
>
## Testing
>
#### How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Also
list any relevant details for your test configuration.
> Delete anything that is not relevant
- [x] Manual
- [ ] Jest
- [ ] Cypress
>
>
#### Test Plan
> Add Testsmith test cases links that relate to this PR
>
>
#### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
>
>
>
## Checklist:
#### Dev activity
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag


#### QA activity:
- [ ] [Speedbreak
features](https://github.com/appsmithorg/TestSmith/wiki/Test-plan-implementation#speedbreaker-features-to-consider-for-every-change)
have been covered
- [ ] Test plan covers all impacted features and [areas of
interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans/_edit#areas-of-interest)
- [ ] Test plan has been peer reviewed by project stakeholders and other
QA members
- [x] Manually tested functionality on DP
- [ ] We had an implementation alignment call with stakeholders post QA
Round 2
- [ ] Cypress test cases have been added and approved by SDET/manual QA
- [ ] Added `Test Plan Approved` label after Cypress tests were reviewed
- [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
This commit is contained in:
Aman Agarwal 2023-06-09 19:28:45 +05:30 committed by GitHub
parent c4b9e272db
commit e558a2ecc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 468 additions and 47 deletions

View File

@ -30,7 +30,7 @@ describe("Test Create Api and Bind to Button widget", function () {
cy.updateCodeInput($el, "{{Api1.run()}}"); cy.updateCodeInput($el, "{{Api1.run()}}");
}); });
cy.PublishtheApp(); _.deployMode.DeployApp();
cy.wait(3000); cy.wait(3000);
cy.get("span:contains('Submit')").closest("div").click(); cy.get("span:contains('Submit')").closest("div").click();
@ -54,7 +54,7 @@ describe("Test Create Api and Bind to Button widget", function () {
cy.updateCodeInput($el, "{{Api1.run(() => {}, () => {})}}"); cy.updateCodeInput($el, "{{Api1.run(() => {}, () => {})}}");
}); });
cy.PublishtheApp(); _.deployMode.DeployApp();
cy.wait(3000); cy.wait(3000);
cy.get("span:contains('Submit')").closest("div").click(); cy.get("span:contains('Submit')").closest("div").click();

View File

@ -0,0 +1,104 @@
import * as _ from "../../../../support/Objects/ObjectsCore";
const SHOW_ALERT_WORKING_BUTTON = "Show alert working";
const SHOW_ALERT_MSG = "Hello World!";
const SHOW_ALERT_NOT_WORKING_BUTTON = "Show alert not working";
const SHOW_ALERT_NOT_WORKING_MSG = "Correct_input2 is not defined";
const RUN_JS_OBJECT_BUTTON = "RUN JSOBJECT";
const RUN_JS_OBJECT_MSG = "Incorrect_users failed to execute";
const PAGE_LOAD_MSG = `The action "Incorrect_users" has failed.`;
describe("Published mode toggle toast with debug flag in the url", function () {
before(() => {
cy.fixture("publishedModeToastToggleDsl").then((val) => {
_.agHelper.AddDsl(val);
});
});
it("1. Should not show any application related toasts", function () {
cy.fixture("datasources").then((datasourceFormData) => {
_.apiPage.CreateAndFillApi(
datasourceFormData["mockApiUrl"],
"Correct_users",
);
_.apiPage.ToggleOnPageLoadRun(true);
_.apiPage.CreateAndFillApi(
datasourceFormData["mockApiUrl"].replace("mock-api", "mock-api2err"),
"Incorrect_users",
);
_.apiPage.ToggleOnPageLoadRun(true);
_.jsEditor.CreateJSObject(
`export default {
async myFun1 () {
const res = await Correct_users.run();
showAlert("Hello info", "info");
showAlert("Hello error", "error");
showAlert("Hello warning", "warning");
showAlert("Hello success", "success");
await Incorrect_users.run();
return res;
}
}`,
{
paste: true,
completeReplace: true,
toRun: false,
shouldCreateNewJSObj: true,
},
);
_.deployMode.DeployApp(undefined, true, false);
_.agHelper.AssertElementAbsence(_.locators._toastMsg);
_.agHelper.ClickButton(SHOW_ALERT_WORKING_BUTTON);
_.agHelper.AssertContains(SHOW_ALERT_MSG, "exist", _.locators._toastMsg);
_.agHelper.ClickButton(SHOW_ALERT_NOT_WORKING_BUTTON);
_.agHelper.AssertContains(
SHOW_ALERT_NOT_WORKING_MSG,
"not.exist",
_.locators._toastMsg,
);
_.agHelper.ClickButton(RUN_JS_OBJECT_BUTTON);
_.agHelper.AssertContains("Hello success", "exist", _.locators._toastMsg);
_.agHelper.AssertContains(
RUN_JS_OBJECT_MSG,
"not.exist",
_.locators._toastMsg,
);
});
});
it("2. Should show all application related toasts with debug flag true in url", function () {
cy.url().then((url) => {
cy.visit({
url,
qs: {
debug: "true",
},
});
_.agHelper.GetNAssertContains(_.locators._toastMsg, PAGE_LOAD_MSG);
_.agHelper.ClickButton(SHOW_ALERT_WORKING_BUTTON);
_.agHelper.AssertContains(SHOW_ALERT_MSG, "exist", _.locators._toastMsg);
_.agHelper.Sleep(2000);
_.agHelper.ClickButton(SHOW_ALERT_NOT_WORKING_BUTTON);
_.agHelper.AssertContains(
SHOW_ALERT_NOT_WORKING_MSG,
"exist",
_.locators._toastMsg,
);
_.agHelper.ClickButton(RUN_JS_OBJECT_BUTTON);
_.agHelper.AssertContains("Hello success", "exist", _.locators._toastMsg);
_.agHelper.AssertContains(
RUN_JS_OBJECT_MSG,
"exist",
_.locators._toastMsg,
);
});
});
});

View File

@ -0,0 +1,277 @@
{
"id": "64746c35c8cae423b46bf2b0",
"userPermissions": [],
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 4896,
"snapColumns": 64,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0,
"bottomRow": 380,
"containerStyle": "none",
"snapRows": 124,
"parentRowSpace": 1,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 79,
"minHeight": 1292,
"dynamicTriggerPathList": [],
"parentColumnSpace": 1,
"dynamicBindingPathList": [],
"leftColumn": 0,
"children": [
{
"boxShadow": "none",
"iconSVG": "/static/media/icon.d0ce957b6c4640f8a7418ce846ee200e.svg",
"topRow": 0,
"labelWidth": 5,
"type": "INPUT_WIDGET_V2",
"animateLoading": true,
"resetOnSubmit": true,
"leftColumn": 0,
"dynamicBindingPathList": [
{
"key": "accentColor"
},
{
"key": "borderRadius"
}
],
"labelStyle": "",
"inputType": "TEXT",
"isDisabled": false,
"isRequired": false,
"dynamicHeight": "FIXED",
"accentColor": "{{appsmith.theme.colors.primaryColor}}",
"showStepArrows": false,
"isVisible": true,
"version": 2,
"isLoading": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"mobileBottomRow": 39,
"widgetName": "Correct_input",
"displayName": "Input",
"searchTags": [
"form",
"text input",
"number",
"textarea"
],
"bottomRow": 4,
"parentRowSpace": 10,
"autoFocus": false,
"hideCard": false,
"mobileRightColumn": 21,
"parentColumnSpace": 12.578125,
"dynamicTriggerPathList": [],
"labelPosition": "Top",
"key": "zssusa8tjd",
"labelTextSize": "0.875rem",
"isDeprecated": false,
"rightColumn": 37,
"widgetId": "9vv4sm9msa",
"minWidth": 450,
"label": "",
"parentId": "0",
"labelAlignment": "left",
"renderMode": "CANVAS",
"mobileTopRow": 32,
"responsiveBehavior": "fill",
"mobileLeftColumn": 1,
"maxDynamicHeight": 9000,
"iconAlign": "left",
"defaultText": "Hello World!",
"minDynamicHeight": 4
},
{
"resetFormOnClick": false,
"boxShadow": "none",
"mobileBottomRow": 36,
"widgetName": "Button1",
"onClick": "{{showAlert(Correct_input.text, 'success');}}",
"buttonColor": "{{appsmith.theme.colors.primaryColor}}",
"displayName": "Button",
"iconSVG": "/static/media/icon.7beb9123fb53027d9d6b778cdfe4caed.svg",
"searchTags": [
"click",
"submit"
],
"topRow": 6,
"bottomRow": 10,
"parentRowSpace": 10,
"type": "BUTTON_WIDGET",
"hideCard": false,
"mobileRightColumn": 38,
"animateLoading": true,
"parentColumnSpace": 12.578125,
"dynamicTriggerPathList": [
{
"key": "onClick"
}
],
"leftColumn": 0,
"dynamicBindingPathList": [
{
"key": "buttonColor"
},
{
"key": "borderRadius"
}
],
"text": "Show alert working",
"isDisabled": false,
"key": "sco9w67akk",
"isDeprecated": false,
"rightColumn": 16,
"isDefaultClickDisabled": true,
"widgetId": "cqagzdpjej",
"minWidth": 120,
"isVisible": true,
"recaptchaType": "V3",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"mobileTopRow": 32,
"responsiveBehavior": "hug",
"disabledWhenInvalid": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"mobileLeftColumn": 22,
"buttonVariant": "PRIMARY",
"placement": "CENTER"
},
{
"resetFormOnClick": false,
"boxShadow": "none",
"mobileBottomRow": 42,
"widgetName": "Button2",
"onClick": "{{showAlert(Correct_input2.text, '');}}",
"buttonColor": "#b91c1c",
"displayName": "Button",
"iconSVG": "/static/media/icon.7beb9123fb53027d9d6b778cdfe4caed.svg",
"searchTags": [
"click",
"submit"
],
"topRow": 6,
"bottomRow": 10,
"parentRowSpace": 10,
"type": "BUTTON_WIDGET",
"hideCard": false,
"mobileRightColumn": 38,
"animateLoading": true,
"parentColumnSpace": 12.578125,
"dynamicTriggerPathList": [
{
"key": "onClick"
}
],
"leftColumn": 21,
"dynamicBindingPathList": [
{
"key": "borderRadius"
}
],
"text": "Show alert not working",
"isDisabled": false,
"key": "sco9w67akk",
"isDeprecated": false,
"rightColumn": 37,
"isDefaultClickDisabled": true,
"widgetId": "s7lvatrsrg",
"minWidth": 120,
"isVisible": true,
"recaptchaType": "V3",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"mobileTopRow": 38,
"responsiveBehavior": "hug",
"disabledWhenInvalid": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"mobileLeftColumn": 22,
"buttonVariant": "PRIMARY",
"placement": "CENTER"
},
{
"resetFormOnClick": false,
"boxShadow": "none",
"mobileBottomRow": 27,
"widgetName": "Button3",
"onClick": "{{JSObject1.myFun1();}}",
"buttonColor": "#52525b",
"displayName": "Button",
"iconSVG": "/static/media/icon.7beb9123fb53027d9d6b778cdfe4caed.svg",
"searchTags": [
"click",
"submit"
],
"topRow": 0,
"bottomRow": 4,
"parentRowSpace": 10,
"type": "BUTTON_WIDGET",
"hideCard": false,
"mobileRightColumn": 60,
"animateLoading": true,
"parentColumnSpace": 12.578125,
"dynamicTriggerPathList": [
{
"key": "onClick"
}
],
"leftColumn": 44,
"dynamicBindingPathList": [
{
"key": "borderRadius"
}
],
"text": "RUN JSOBJECT",
"isDisabled": false,
"key": "sco9w67akk",
"isDeprecated": false,
"rightColumn": 60,
"isDefaultClickDisabled": true,
"widgetId": "fia0l15iti",
"minWidth": 120,
"isVisible": true,
"recaptchaType": "V3",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"mobileTopRow": 23,
"responsiveBehavior": "hug",
"disabledWhenInvalid": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"mobileLeftColumn": 44,
"buttonVariant": "PRIMARY",
"placement": "CENTER"
}
]
},
"layoutOnLoadActions": [
[
{
"id": "64746c35c8cae423b46bf2b3",
"name": "Incorrect_users",
"confirmBeforeExecute": false,
"pluginType": "API",
"jsonPathKeys": [],
"timeoutInMillisecond": 10000
},
{
"id": "64746c35c8cae423b46bf2b2",
"name": "Correct_users",
"confirmBeforeExecute": false,
"pluginType": "API",
"jsonPathKeys": [],
"timeoutInMillisecond": 10000
}
]
],
"layoutOnLoadActionErrors": [],
"new": false
}

View File

@ -28,6 +28,7 @@ export class DeployMode {
public DeployApp( public DeployApp(
eleToCheckInDeployPage: string = this.locator._backToEditor, eleToCheckInDeployPage: string = this.locator._backToEditor,
toCheckFailureToast = true, toCheckFailureToast = true,
addDebugFlag = true,
) { ) {
//cy.intercept("POST", "/api/v1/applications/publish/*").as("publishAppli"); //cy.intercept("POST", "/api/v1/applications/publish/*").as("publishAppli");
// Wait before publish // Wait before publish
@ -36,7 +37,12 @@ export class DeployMode {
// Stubbing window.open to open in the same tab // Stubbing window.open to open in the same tab
cy.window().then((window) => { cy.window().then((window) => {
cy.stub(window, "open").callsFake((url) => { cy.stub(window, "open").callsFake((url) => {
window.location.href = Cypress.config().baseUrl + url.substring(1); const updatedUrl = `${Cypress.config().baseUrl + url.substring(1)}`;
window.location.href = `${updatedUrl}${
addDebugFlag
? (updatedUrl.indexOf("?") > -1 ? "&" : "?") + "debug=true"
: ""
}`;
}); });
}); });
cy.get(this.locator._publishButton).click(); cy.get(this.locator._publishButton).click();

View File

@ -1,4 +1,4 @@
import { spawn } from "redux-saga/effects"; import { call, spawn } from "redux-saga/effects";
import { import {
logActionExecutionError, logActionExecutionError,
TriggerFailureError, TriggerFailureError,
@ -35,6 +35,6 @@ export function* executePostMessage(
} }
} }
} catch (error) { } catch (error) {
logActionExecutionError((error as Error).message, true); yield call(logActionExecutionError, (error as Error).message, true);
} }
} }

View File

@ -1,8 +1,10 @@
import AppsmithConsole from "utils/AppsmithConsole"; import AppsmithConsole from "utils/AppsmithConsole";
import { ActionValidationError } from "sagas/ActionExecution/errorUtils"; import { ActionValidationError } from "sagas/ActionExecution/errorUtils";
import { getType, Types } from "utils/TypeHelpers"; import { getType, Types } from "utils/TypeHelpers";
import { toast } from "design-system"; import type { ToastKind } from "design-system";
import type { TShowAlertDescription } from "workers/Evaluation/fns/showAlert"; import type { TShowAlertDescription } from "workers/Evaluation/fns/showAlert";
import { call } from "redux-saga/effects";
import showToast from "sagas/ToastSagas";
export default function* showAlertSaga(action: TShowAlertDescription) { export default function* showAlertSaga(action: TShowAlertDescription) {
const { payload } = action; const { payload } = action;
@ -14,24 +16,15 @@ export default function* showAlertSaga(action: TShowAlertDescription) {
getType(payload.message), getType(payload.message),
); );
} }
let kind: "success" | "info" | "warning" | "error" | undefined = undefined; // This is the toast that is rendered which is user generated by using `showAlert` platform function. This is forceDisplayed no matter the conditions.
switch (payload.style) { yield call(
case "info": showToast,
kind = "info"; payload.message,
break; {
case "success": kind: payload.style as ToastKind,
kind = "success"; },
break; { forceDisplay: true },
case "warning": );
kind = "warning";
break;
case "error":
kind = "error";
break;
}
toast.show(payload.message, {
kind: kind,
});
AppsmithConsole.info({ AppsmithConsole.info({
text: payload.style text: payload.style
? `showAlert('${payload.message}', '${payload.style}') was triggered` ? `showAlert('${payload.message}', '${payload.style}') was triggered`

View File

@ -8,7 +8,6 @@ import type { Types } from "utils/TypeHelpers";
import type { ActionTriggerKeys } from "@appsmith/workers/Evaluation/fns/index"; import type { ActionTriggerKeys } from "@appsmith/workers/Evaluation/fns/index";
import { getActionTriggerFunctionNames } from "@appsmith/workers/Evaluation/fns/index"; import { getActionTriggerFunctionNames } from "@appsmith/workers/Evaluation/fns/index";
import { getAppsmithConfigs } from "@appsmith/configs"; import { getAppsmithConfigs } from "@appsmith/configs";
import { toast } from "design-system";
import { getAppMode } from "@appsmith/selectors/applicationSelectors"; import { getAppMode } from "@appsmith/selectors/applicationSelectors";
import AnalyticsUtil from "../../utils/AnalyticsUtil"; import AnalyticsUtil from "../../utils/AnalyticsUtil";
import { import {
@ -17,6 +16,8 @@ import {
} from "../../actions/debuggerActions"; } from "../../actions/debuggerActions";
import { DEBUGGER_TAB_KEYS } from "../../components/editorComponents/Debugger/helpers"; import { DEBUGGER_TAB_KEYS } from "../../components/editorComponents/Debugger/helpers";
import store from "store"; import store from "store";
import showToast from "sagas/ToastSagas";
import { call } from "redux-saga/effects";
const APPSMITH_CONFIGS = getAppsmithConfigs(); const APPSMITH_CONFIGS = getAppsmithConfigs();
@ -62,10 +63,10 @@ export class ActionValidationError extends TriggerFailureError {
} }
} }
export const logActionExecutionError = ( export function* logActionExecutionError(
errorMessage: string, errorMessage: string,
isExecuteJSFunc = true, isExecuteJSFunc = true,
) => { ) {
//Commenting as per decision taken for the error hanlding epic to not show the trigger errors in the debugger. //Commenting as per decision taken for the error hanlding epic to not show the trigger errors in the debugger.
// if (triggerPropertyName) { // if (triggerPropertyName) {
// AppsmithConsole.addErrors([ // AppsmithConsole.addErrors([
@ -102,8 +103,9 @@ export const logActionExecutionError = (
store.dispatch(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.ERROR_TAB)); store.dispatch(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.ERROR_TAB));
} }
isExecuteJSFunc && if (isExecuteJSFunc)
toast.show(errorMessage, { // This is the toast that is rendered when any unhandled error occurs in JS object.
yield call(showToast, errorMessage, {
kind: "error", kind: "error",
action: { action: {
text: "debug", text: "debug",
@ -111,7 +113,7 @@ export const logActionExecutionError = (
className: "t--toast-debug-button", className: "t--toast-debug-button",
}, },
}); });
}; }
/* /*
* Thrown when action execution fails for some reason * Thrown when action execution fails for some reason

View File

@ -5,6 +5,8 @@ import {
getUserLocation, getUserLocation,
} from "./geolocationSaga"; } from "./geolocationSaga";
import { setUserCurrentGeoLocation } from "actions/browserRequestActions"; import { setUserCurrentGeoLocation } from "actions/browserRequestActions";
import { logActionExecutionError } from "./errorUtils";
const mockFn = jest.fn(); const mockFn = jest.fn();
jest.mock("./errorUtils.ts", () => ({ jest.mock("./errorUtils.ts", () => ({
@ -79,8 +81,14 @@ describe("getCurrentLocationSaga", () => {
}; };
const iter = getCurrentLocationSaga(trigger); const iter = getCurrentLocationSaga(trigger);
expect(iter.next().value).toEqual(call(getUserLocation, payload.options)); expect(iter.next().value).toEqual(call(getUserLocation, payload.options));
iter.next();
expect(mockFn).toBeCalled(); expect(iter.next().value).toEqual(
call(
logActionExecutionError,
"Cannot read properties of undefined (reading 'coords')",
true,
),
);
expect(iter.next().done).toBe(true); expect(iter.next().done).toBe(true);
}); });
}); });

View File

@ -102,7 +102,7 @@ function* errorCallbackHandler(triggerMeta: TriggerMeta, listenerId?: string) {
{ error: sanitizeGeolocationError(error) }, { error: sanitizeGeolocationError(error) },
listenerId, listenerId,
); );
logActionExecutionError(error.message, true); yield call(logActionExecutionError, error.message, true);
} }
} }
@ -117,7 +117,7 @@ export function* getCurrentLocationSaga(action: TGetGeoLocationDescription) {
yield put(setUserCurrentGeoLocation(currentLocation)); yield put(setUserCurrentGeoLocation(currentLocation));
return currentLocation; return currentLocation;
} catch (error) { } catch (error) {
logActionExecutionError((error as Error).message, true); yield call(logActionExecutionError, (error as Error).message, true);
if (error instanceof GeolocationPositionError) { if (error instanceof GeolocationPositionError) {
const sanitizedError = sanitizeGeolocationError(error); const sanitizedError = sanitizeGeolocationError(error);
throw new GeoLocationError(sanitizedError.message, [sanitizedError]); throw new GeoLocationError(sanitizedError.message, [sanitizedError]);
@ -135,7 +135,8 @@ export function* watchCurrentLocation(
if (watchId) { if (watchId) {
// When a watch is already active, we will not start a new watch. // When a watch is already active, we will not start a new watch.
// at a given point in time, only one watch is active // at a given point in time, only one watch is active
logActionExecutionError( yield call(
logActionExecutionError,
"A watchLocation is already active. Clear it before before starting a new one", "A watchLocation is already active. Clear it before before starting a new one",
true, true,
); );
@ -165,7 +166,7 @@ export function* watchCurrentLocation(
export function* stopWatchCurrentLocation() { export function* stopWatchCurrentLocation() {
if (watchId === undefined) { if (watchId === undefined) {
logActionExecutionError("No location watch active", true); yield call(logActionExecutionError, "No location watch active", true);
return; return;
} }
navigator.geolocation.clearWatch(watchId); navigator.geolocation.clearWatch(watchId);

View File

@ -32,7 +32,7 @@ import * as Sentry from "@sentry/react";
import { axiosConnectionAbortedCode } from "@appsmith/api/ApiUtils"; import { axiosConnectionAbortedCode } from "@appsmith/api/ApiUtils";
import { getLoginUrl } from "@appsmith/utils/adminSettingsHelpers"; import { getLoginUrl } from "@appsmith/utils/adminSettingsHelpers";
import type { PluginErrorDetails } from "api/ActionAPI"; import type { PluginErrorDetails } from "api/ActionAPI";
import { toast } from "design-system"; import showToast from "sagas/ToastSagas";
/** /**
* making with error message with action name * making with error message with action name
@ -224,7 +224,8 @@ export function* errorSaga(errorAction: ReduxAction<ErrorActionPayload>) {
break; break;
} }
case ErrorEffectTypes.SHOW_ALERT: { case ErrorEffectTypes.SHOW_ALERT: {
showAlertAboutError(message); // This is the toast that is rendered when any page load API fails.
yield call(showToast, message, { kind: "error" });
break; break;
} }
case ErrorEffectTypes.SAFE_CRASH: { case ErrorEffectTypes.SAFE_CRASH: {
@ -252,10 +253,6 @@ function logErrorSaga(action: ReduxAction<{ error: ErrorPayloadType }>) {
if (action.payload) log.error(action.payload.error); if (action.payload) log.error(action.payload.error);
} }
function showAlertAboutError(message: string) {
toast.show(message, { kind: "error" });
}
/** /**
* this saga do some logic before actually setting safeCrash to true * this saga do some logic before actually setting safeCrash to true
*/ */

View File

@ -23,7 +23,7 @@ import type { EvalError, EvaluationError } from "utils/DynamicBindingUtils";
import { EvalErrorTypes, getEvalErrorPath } from "utils/DynamicBindingUtils"; import { EvalErrorTypes, getEvalErrorPath } from "utils/DynamicBindingUtils";
import { find, get, some } from "lodash"; import { find, get, some } from "lodash";
import LOG_TYPE from "entities/AppsmithConsole/logtype"; import LOG_TYPE from "entities/AppsmithConsole/logtype";
import { put, select } from "redux-saga/effects"; import { call, put, select } from "redux-saga/effects";
import type { AnyReduxAction } from "@appsmith/constants/ReduxActionConstants"; import type { AnyReduxAction } from "@appsmith/constants/ReduxActionConstants";
import AppsmithConsole from "utils/AppsmithConsole"; import AppsmithConsole from "utils/AppsmithConsole";
import * as Sentry from "@sentry/react"; import * as Sentry from "@sentry/react";
@ -324,7 +324,7 @@ export function* dynamicTriggerErrorHandler(errors: any[]) {
for (const error of errors) { for (const error of errors) {
const errorMessage = const errorMessage =
error.errorMessage.message.message || error.errorMessage.message; error.errorMessage.message.message || error.errorMessage.message;
logActionExecutionError(errorMessage, true); yield call(logActionExecutionError, errorMessage, true);
} }
} }
} }

View File

@ -0,0 +1,35 @@
import type { ToastProps } from "design-system";
import { toast } from "design-system";
import { APP_MODE } from "entities/App";
import { select } from "redux-saga/effects";
import { getAppMode } from "selectors/entitiesSelector";
import log from "loglevel";
type ExtraOptions = {
// This enables showing of toast no matter the conditions
forceDisplay?: boolean;
};
/**
* Shows toast
* @param message
* @param [options] These are toast props that toast from design-sytem(react-toastify) library takes
* @param [extraOtions] These additional options enable the addition of additional requirements, based on which the toast will only then be produced. (for future extensibility as well)
* @returns
*/
export default function* showToast(
message: string,
options?: ToastProps,
extraOtions?: ExtraOptions,
) {
const appMode: APP_MODE | undefined = yield select(getAppMode);
const urlObject = new URL(window?.location?.href);
const debugFlag = urlObject?.searchParams?.get("debug");
const debug = debugFlag === "true" || debugFlag;
if (appMode === APP_MODE.PUBLISHED && !debug && !extraOtions?.forceDisplay) {
log.error(message);
return;
}
toast.show(message, options);
}

View File

@ -129,9 +129,7 @@ function* executeInIntervals(
source: triggerMeta.source, source: triggerMeta.source,
}); });
} catch (e) { } catch (e) {
logActionExecutionError( yield call(logActionExecutionError, e.message);
e.message,
);
} }
yield delay(interval); yield delay(interval);
} }