diff --git a/app/client/src/components/editorComponents/Debugger/index.tsx b/app/client/src/components/editorComponents/Debugger/index.tsx index 86d987f91418..4ca5397f701a 100644 --- a/app/client/src/components/editorComponents/Debugger/index.tsx +++ b/app/client/src/components/editorComponents/Debugger/index.tsx @@ -13,7 +13,7 @@ import { getTypographyByKey } from "constants/DefaultTheme"; import { Layers } from "constants/Layers"; import { stopEventPropagation } from "utils/AppsmithUtils"; -const Container = styled.div<{ errorCount: number }>` +const Container = styled.div<{ errorCount: number; warningCount: number }>` z-index: ${Layers.debugger}; background-color: ${(props) => props.theme.colors.debugger.floatingButton.background}; @@ -40,8 +40,10 @@ const Container = styled.div<{ errorCount: number }>` height: 16px; padding: ${(props) => props.theme.spaces[1]}px; background-color: ${(props) => - !!props.errorCount - ? props.theme.colors.debugger.floatingButton.errorCount + props.errorCount + props.warningCount > 0 + ? props.errorCount === 0 + ? props.theme.colors.debugger.floatingButton.warningCount + : props.theme.colors.debugger.floatingButton.errorCount : props.theme.colors.debugger.floatingButton.noErrorCount}; border-radius: 10px; position: absolute; @@ -55,9 +57,16 @@ const Container = styled.div<{ errorCount: number }>` function Debugger() { const dispatch = useDispatch(); - const errorCount = useSelector( - (state: AppState) => Object.keys(state.ui.debugger.errors).length, - ); + const messageCounters = useSelector((state) => { + const errorKeys = Object.keys(state.ui.debugger.errors); + const warnings = errorKeys.filter((key: string) => key.includes("warning")) + .length; + const errors = errorKeys.length - warnings; + return { errors, warnings }; + }); + + const totalMessageCount = messageCounters.errors + messageCounters.warnings; + const showDebugger = useSelector( (state: AppState) => state.ui.debugger.isOpen, ); @@ -74,14 +83,15 @@ function Debugger() { return ( -
{errorCount}
+
{totalMessageCount}
); - return ; + return ; } export default Debugger; diff --git a/app/client/src/constants/DefaultTheme.tsx b/app/client/src/constants/DefaultTheme.tsx index bda967fd82e7..91f6641f7cc3 100644 --- a/app/client/src/constants/DefaultTheme.tsx +++ b/app/client/src/constants/DefaultTheme.tsx @@ -1056,6 +1056,7 @@ type ColorType = { shadow: string; errorCount: string; noErrorCount: string; + warningCount: string; }; blankState: { shortcut: string; @@ -1706,6 +1707,7 @@ export const dark: ColorType = { shadow: "0px 12px 28px -6px rgba(0, 0, 0, 0.32)", errorCount: "#F22B2B", noErrorCount: "#03B365", + warningCount: "#DCAD00", }, inspectElement: { color: "#D4D4D4", @@ -2182,6 +2184,7 @@ export const light: ColorType = { shadow: "0px 12px 28px -6px rgba(0, 0, 0, 0.32)", errorCount: "#F22B2B", noErrorCount: "#03B365", + warningCount: "#DCAD00", }, inspectElement: { color: "#090707", diff --git a/app/client/src/entities/AppsmithConsole/logtype.ts b/app/client/src/entities/AppsmithConsole/logtype.ts index 8fd1658e13a6..1028dc5f6af5 100644 --- a/app/client/src/entities/AppsmithConsole/logtype.ts +++ b/app/client/src/entities/AppsmithConsole/logtype.ts @@ -5,6 +5,7 @@ enum LOG_TYPE { ACTION_EXECUTION_SUCCESS, ENTITY_DELETED, EVAL_ERROR, + EVAL_WARNING, ACTION_UPDATE, } diff --git a/app/client/src/sagas/PostEvaluationSagas.ts b/app/client/src/sagas/PostEvaluationSagas.ts index 47a7dd90a08e..56486975a022 100644 --- a/app/client/src/sagas/PostEvaluationSagas.ts +++ b/app/client/src/sagas/PostEvaluationSagas.ts @@ -1,4 +1,4 @@ -import { ENTITY_TYPE, Message } from "entities/AppsmithConsole"; +import { ENTITY_TYPE, Message, Severity } from "entities/AppsmithConsole"; import { DataTree } from "entities/DataTree/dataTreeFactory"; import { getEntityNameAndPropertyPath, @@ -72,80 +72,103 @@ function getLatestEvalPropertyErrors( entity, getEvalValuePath(evaluatedPath, false), ); - const evalErrors = allEvalErrors.filter( - (error) => error.errorType !== PropertyEvaluationErrorType.LINT, - ); + const evalErrors: EvaluationError[] = []; + const evalWarnings: EvaluationError[] = []; + + for (const err of allEvalErrors) { + if (err.severity === Severity.WARNING) { + evalWarnings.push(err); + } + if (err.severity === Severity.ERROR) { + evalErrors.push(err); + } + } + const idField = isWidget(entity) ? entity.widgetId : entity.actionId; const nameField = isWidget(entity) ? entity.widgetName : entity.name; const entityType = isWidget(entity) ? ENTITY_TYPE.WIDGET : ENTITY_TYPE.ACTION; - const debuggerKey = idField + "-" + propertyPath; + const debuggerKeys = [ + { + key: `${idField}-${propertyPath}`, + errors: evalErrors, + }, + { + key: `${idField}-${propertyPath}-warning`, + errors: evalWarnings, + isWarning: true, + }, + ]; // if dataTree has error but debugger does not -> add // if debugger has error and data tree has error -> update error // if debugger has error but data tree does not -> remove // if debugger or data tree does not have an error -> no change - if (evalErrors.length) { - // TODO Rank and set the most critical error - const error = evalErrors[0]; - const errorMessages = evalErrors.map((e) => ({ - message: e.errorMessage, - })); + for (const { errors, isWarning, key: debuggerKey } of debuggerKeys) { + if (errors.length) { + // TODO Rank and set the most critical error + const error = errors[0]; + const { errorType, severity } = error; + const errorMessages = errors.map((e) => ({ + message: e.errorMessage, + })); - if (!(debuggerKey in updatedDebuggerErrors)) { - store.dispatch( - logDebuggerErrorAnalytics({ - eventName: "DEBUGGER_NEW_ERROR", - entityId: idField, - entityName: nameField, - entityType, - propertyPath, - errorMessages, - }), - ); - } + if (!isWarning && !(debuggerKey in updatedDebuggerErrors)) { + store.dispatch( + logDebuggerErrorAnalytics({ + eventName: "DEBUGGER_NEW_ERROR", + entityId: idField, + entityName: nameField, + entityType, + propertyPath, + errorMessages, + }), + ); + } - const analyticsData = isWidget(entity) - ? { - widgetType: entity.type, - } - : {}; + const analyticsData = isWidget(entity) + ? { + widgetType: entity.type, + } + : {}; - // Add or update - updatedDebuggerErrors[debuggerKey] = { - logType: LOG_TYPE.EVAL_ERROR, - text: PropertyEvalErrorTypeDebugMessage[error.errorType]( - propertyPath, - ), - messages: errorMessages, - severity: error.severity, - timestamp: moment().format("hh:mm:ss"), - source: { - id: idField, - name: nameField, - type: entityType, - propertyPath: propertyPath, - }, - state: { - [propertyPath]: evaluatedValue, - }, - analytics: analyticsData, - }; - } else if (debuggerKey in updatedDebuggerErrors) { - store.dispatch( - logDebuggerErrorAnalytics({ - eventName: "DEBUGGER_RESOLVED_ERROR", - entityId: idField, - entityName: nameField, - entityType, - propertyPath: - updatedDebuggerErrors[debuggerKey].source?.propertyPath ?? "", - errorMessages: updatedDebuggerErrors[debuggerKey].messages ?? [], - }), - ); - // Remove - delete updatedDebuggerErrors[debuggerKey]; + // Add or update + updatedDebuggerErrors[debuggerKey] = { + logType: isWarning ? LOG_TYPE.EVAL_WARNING : LOG_TYPE.EVAL_ERROR, + text: PropertyEvalErrorTypeDebugMessage[errorType](propertyPath), + messages: errorMessages, + severity, + timestamp: moment().format("hh:mm:ss"), + source: { + id: idField, + name: nameField, + type: entityType, + propertyPath: propertyPath, + }, + state: { + [propertyPath]: evaluatedValue, + }, + analytics: analyticsData, + }; + } else if (debuggerKey in updatedDebuggerErrors) { + if (!isWarning) { + store.dispatch( + logDebuggerErrorAnalytics({ + eventName: "DEBUGGER_RESOLVED_ERROR", + entityId: idField, + entityName: nameField, + entityType, + propertyPath: + updatedDebuggerErrors[debuggerKey].source?.propertyPath ?? "", + errorMessages: + updatedDebuggerErrors[debuggerKey].messages ?? [], + }), + ); + } + // Remove + delete updatedDebuggerErrors[debuggerKey]; + } } } }