forked from CITKParus/P8-Panels
ЦИТК-929 - Вывод сообщения об ошибке без стэка вызова
This commit is contained in:
parent
1e580f806d
commit
ef397b1818
@ -29,6 +29,8 @@ export const BUTTONS = {
|
|||||||
OK: "ОК", //Ок
|
OK: "ОК", //Ок
|
||||||
CANCEL: "Отмена", //Отмена
|
CANCEL: "Отмена", //Отмена
|
||||||
CLOSE: "Закрыть", //Сокрытие
|
CLOSE: "Закрыть", //Сокрытие
|
||||||
|
ERR_MORE: "Подробнее", //Отображение подробного текста ошибки
|
||||||
|
HIDE: "Скрыть", //Скрытие информации
|
||||||
CLEAR: "Очистить", //Очистка
|
CLEAR: "Очистить", //Очистка
|
||||||
ORDER_ASC: "По возрастанию", //Сортировка по возрастанию
|
ORDER_ASC: "По возрастанию", //Сортировка по возрастанию
|
||||||
ORDER_DESC: "По убыванию", //Сортировка по убыванию
|
ORDER_DESC: "По убыванию", //Сортировка по убыванию
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//Подключение библиотек
|
//Подключение библиотек
|
||||||
//---------------------
|
//---------------------
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
import React, { useState } from "react"; //Классы React
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
import Dialog from "@mui/material/Dialog"; //базовый класс диалога Material UI
|
import Dialog from "@mui/material/Dialog"; //базовый класс диалога Material UI
|
||||||
import DialogTitle from "@mui/material/DialogTitle"; //Заголовок диалога
|
import DialogTitle from "@mui/material/DialogTitle"; //Заголовок диалога
|
||||||
@ -66,7 +66,25 @@ const STYLES = {
|
|||||||
//-----------
|
//-----------
|
||||||
|
|
||||||
//Сообщение
|
//Сообщение
|
||||||
const P8PAppMessage = ({ variant, title, titleText, cancelBtn, onCancel, cancelBtnCaption, okBtn, onOk, okBtnCaption, open, text }) => {
|
const P8PAppMessage = ({
|
||||||
|
variant,
|
||||||
|
title,
|
||||||
|
titleText,
|
||||||
|
cancelBtn,
|
||||||
|
onCancel,
|
||||||
|
cancelBtnCaption,
|
||||||
|
okBtn,
|
||||||
|
onOk,
|
||||||
|
okBtnCaption,
|
||||||
|
open,
|
||||||
|
text,
|
||||||
|
fullErrorText,
|
||||||
|
showErrMoreCaption,
|
||||||
|
hideErrMoreCaption
|
||||||
|
}) => {
|
||||||
|
//Состояние подробной информации об ошибке
|
||||||
|
const [showFullErrorText, setShowFullErrorText] = useState(false);
|
||||||
|
|
||||||
//Подбор стиля и ресурсов
|
//Подбор стиля и ресурсов
|
||||||
let style = STYLES.INFO;
|
let style = STYLES.INFO;
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
@ -107,11 +125,21 @@ const P8PAppMessage = ({ variant, title, titleText, cancelBtn, onCancel, cancelB
|
|||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Кнопка Подробнее
|
||||||
|
let fullErrorTextBtn;
|
||||||
|
if (fullErrorText && variant === P8P_APP_MESSAGE_VARIANT.ERR)
|
||||||
|
fullErrorTextBtn = (
|
||||||
|
<Button onClick={() => setShowFullErrorText(!showFullErrorText)} color="warning" autoFocus>
|
||||||
|
{!showFullErrorText ? showErrMoreCaption : hideErrMoreCaption}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
//Все действия
|
//Все действия
|
||||||
let actionsPart;
|
let actionsPart;
|
||||||
if (cancelBtnPart || okBtnPart)
|
if (cancelBtnPart || okBtnPart)
|
||||||
actionsPart = (
|
actionsPart = (
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
{fullErrorTextBtn}
|
||||||
{okBtnPart}
|
{okBtnPart}
|
||||||
{cancelBtnPart}
|
{cancelBtnPart}
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
@ -128,7 +156,7 @@ const P8PAppMessage = ({ variant, title, titleText, cancelBtn, onCancel, cancelB
|
|||||||
{titlePart}
|
{titlePart}
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText id="message-dialog-description" style={style.bodyText}>
|
<DialogContentText id="message-dialog-description" style={style.bodyText}>
|
||||||
{text}
|
{!showFullErrorText ? text : fullErrorText}
|
||||||
</DialogContentText>
|
</DialogContentText>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
{actionsPart}
|
{actionsPart}
|
||||||
@ -148,7 +176,10 @@ P8PAppMessage.propTypes = {
|
|||||||
onOk: PropTypes.func,
|
onOk: PropTypes.func,
|
||||||
okBtnCaption: PropTypes.string,
|
okBtnCaption: PropTypes.string,
|
||||||
open: PropTypes.bool,
|
open: PropTypes.bool,
|
||||||
text: PropTypes.string
|
text: PropTypes.string,
|
||||||
|
fullErrorText: PropTypes.string,
|
||||||
|
showErrMoreCaption: PropTypes.string,
|
||||||
|
hideErrMoreCaption: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
//Встроенное сообщение
|
//Встроенное сообщение
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import React, { createContext, useContext, useCallback } from "react"; //ReactJS
|
import React, { createContext, useContext, useCallback } from "react"; //ReactJS
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
import { MessagingСtx } from "./messaging"; //Контекст сообщений
|
import { MessagingСtx } from "./messaging"; //Контекст сообщений
|
||||||
|
import { formatErrorMessage } from "../core/utils"; //Вспомогательные функции
|
||||||
|
|
||||||
//---------
|
//---------
|
||||||
//Константы
|
//Константы
|
||||||
@ -80,7 +81,12 @@ export const BackEndContext = ({ client, children }) => {
|
|||||||
if (fullResponse === true || isRespErr(result)) return result;
|
if (fullResponse === true || isRespErr(result)) return result;
|
||||||
else return result.XPAYLOAD;
|
else return result.XPAYLOAD;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (showErrorMessage) showMsgErr(e.message);
|
if (showErrorMessage) {
|
||||||
|
//Разбираем текст ошибки
|
||||||
|
let errMsg = formatErrorMessage(e.message);
|
||||||
|
//Отображаем ошибку
|
||||||
|
showMsgErr(errMsg.text, errMsg.fullErrorText);
|
||||||
|
}
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
if (loader !== false) hideLoader();
|
if (loader !== false) hideLoader();
|
||||||
|
@ -33,7 +33,9 @@ const MESSAGING_CONTEXT_TEXTS_SHAPE = PropTypes.shape({
|
|||||||
const MESSAGING_CONTEXT_BUTTONS_SHAPE = PropTypes.shape({
|
const MESSAGING_CONTEXT_BUTTONS_SHAPE = PropTypes.shape({
|
||||||
CLOSE: PropTypes.string.isRequired,
|
CLOSE: PropTypes.string.isRequired,
|
||||||
OK: PropTypes.string.isRequired,
|
OK: PropTypes.string.isRequired,
|
||||||
CANCEL: PropTypes.string.isRequired
|
CANCEL: PropTypes.string.isRequired,
|
||||||
|
ERR_MORE: PropTypes.string.isRequired,
|
||||||
|
HIDE: PropTypes.string.isRequired
|
||||||
});
|
});
|
||||||
|
|
||||||
//----------------
|
//----------------
|
||||||
@ -56,12 +58,13 @@ export const MessagingContext = ({ titles, texts, buttons, children }) => {
|
|||||||
|
|
||||||
//Отображение сообщения
|
//Отображение сообщения
|
||||||
const showMsg = useCallback(
|
const showMsg = useCallback(
|
||||||
(type, text, msgOnOk = null, msgOnCancel = null) => dispatch({ type: MSG_AT.SHOW_MSG, payload: { type, text, msgOnOk, msgOnCancel } }),
|
(type, text, fullErrorText = null, msgOnOk = null, msgOnCancel = null) =>
|
||||||
|
dispatch({ type: MSG_AT.SHOW_MSG, payload: { type, text, fullErrorText, msgOnOk, msgOnCancel } }),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
//Отображение сообщения - ошибка
|
//Отображение сообщения - ошибка
|
||||||
const showMsgErr = useCallback((text, msgOnOk = null) => showMsg(MSG_TYPE.ERR, text, msgOnOk), [showMsg]);
|
const showMsgErr = useCallback((text, fullErrorText = null, msgOnOk = null) => showMsg(MSG_TYPE.ERR, text, fullErrorText, msgOnOk), [showMsg]);
|
||||||
|
|
||||||
//Отображение сообщения - информация
|
//Отображение сообщения - информация
|
||||||
const showMsgInfo = useCallback((text, msgOnOk = null) => showMsg(MSG_TYPE.INFO, text, msgOnOk), [showMsg]);
|
const showMsgInfo = useCallback((text, msgOnOk = null) => showMsg(MSG_TYPE.INFO, text, msgOnOk), [showMsg]);
|
||||||
@ -126,6 +129,7 @@ export const MessagingContext = ({ titles, texts, buttons, children }) => {
|
|||||||
open={true}
|
open={true}
|
||||||
variant={state.msgType}
|
variant={state.msgType}
|
||||||
text={state.msgText}
|
text={state.msgText}
|
||||||
|
fullErrorText={state.msgFullErrorText}
|
||||||
title
|
title
|
||||||
titleText={state.msgType == MSG_TYPE.ERR ? titles.ERR : state.msgType == MSG_TYPE.WARN ? titles.WARN : titles.INFO}
|
titleText={state.msgType == MSG_TYPE.ERR ? titles.ERR : state.msgType == MSG_TYPE.WARN ? titles.WARN : titles.INFO}
|
||||||
okBtn={true}
|
okBtn={true}
|
||||||
@ -134,6 +138,8 @@ export const MessagingContext = ({ titles, texts, buttons, children }) => {
|
|||||||
cancelBtn={state.msgType == MSG_TYPE.WARN}
|
cancelBtn={state.msgType == MSG_TYPE.WARN}
|
||||||
onCancel={handleMessageCancelClick}
|
onCancel={handleMessageCancelClick}
|
||||||
cancelBtnCaption={buttons.CANCEL}
|
cancelBtnCaption={buttons.CANCEL}
|
||||||
|
showErrMoreCaption={buttons.ERR_MORE}
|
||||||
|
hideErrMoreCaption={buttons.HIDE}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{children}
|
{children}
|
||||||
|
@ -35,6 +35,7 @@ const INITIAL_STATE = {
|
|||||||
msg: false,
|
msg: false,
|
||||||
msgType: MSG_TYPE.ERR,
|
msgType: MSG_TYPE.ERR,
|
||||||
msgText: null,
|
msgText: null,
|
||||||
|
msgFullErrorText: null,
|
||||||
msgOnOk: null,
|
msgOnOk: null,
|
||||||
msgOnCancel: null
|
msgOnCancel: null
|
||||||
};
|
};
|
||||||
@ -59,6 +60,7 @@ const handlers = {
|
|||||||
msg: true,
|
msg: true,
|
||||||
msgType: payload.type || MSG_TYPE.APP_ERR,
|
msgType: payload.type || MSG_TYPE.APP_ERR,
|
||||||
msgText: payload.text,
|
msgText: payload.text,
|
||||||
|
msgFullErrorText: payload.fullErrorText,
|
||||||
msgOnOk: payload.msgOnOk,
|
msgOnOk: payload.msgOnOk,
|
||||||
msgOnCancel: payload.msgOnCancel
|
msgOnCancel: payload.msgOnCancel
|
||||||
}),
|
}),
|
||||||
|
@ -158,6 +158,34 @@ const formatDateJSONDateOnly = value => (value ? dayjs(value).format("YYYY-MM-DD
|
|||||||
//Форматирование числа в "Денежном" формате РФ
|
//Форматирование числа в "Денежном" формате РФ
|
||||||
const formatNumberRFCurrency = value => (hasValue(value) ? new Intl.NumberFormat("ru-RU", { minimumFractionDigits: 2 }).format(value) : null);
|
const formatNumberRFCurrency = value => (hasValue(value) ? new Intl.NumberFormat("ru-RU", { minimumFractionDigits: 2 }).format(value) : null);
|
||||||
|
|
||||||
|
//Форматирование текста ошибки
|
||||||
|
const formatErrorMessage = errorMsg => {
|
||||||
|
//Инициализируем текст заголовка ошибки
|
||||||
|
let text = "";
|
||||||
|
//Пробуем извлечь заголовок текста ошибки
|
||||||
|
try {
|
||||||
|
//Если это ошибка Oracle
|
||||||
|
if (errorMsg.match(/^ORA-/)) {
|
||||||
|
//Считываем первую строку с заголовочным текстом ошибки
|
||||||
|
text = errorMsg.match(/^.*(?=(\nORA-))/)[0];
|
||||||
|
//Убираем лишнюю информацию и пробелы
|
||||||
|
text = text.replace(/ORA-\d*:/g, "").trim();
|
||||||
|
}
|
||||||
|
//Если это ошибка PG
|
||||||
|
if (errorMsg.match(/^SQL Error/)) {
|
||||||
|
//Считываем первую строку с заголовочным текстом ошибки
|
||||||
|
text = errorMsg.match(/.*(?=(\n.*Where)|(.*Where))/)[0];
|
||||||
|
//Убираем лишнюю информацию и пробелы
|
||||||
|
text = text.replace(/SQL Error \[\d*\]: ERROR:/g, "").trim();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
//Если произошла ошибка - оставляем полный текст ошибки
|
||||||
|
text = errorMsg;
|
||||||
|
}
|
||||||
|
//Возвращаем результат
|
||||||
|
return { text: text || errorMsg, fullErrorText: text ? errorMsg : null };
|
||||||
|
};
|
||||||
|
|
||||||
//Формирование уникального идентификатора
|
//Формирование уникального идентификатора
|
||||||
const genGUID = () =>
|
const genGUID = () =>
|
||||||
"10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
|
"10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
|
||||||
@ -178,5 +206,6 @@ export {
|
|||||||
formatDateTimeRF,
|
formatDateTimeRF,
|
||||||
formatDateJSONDateOnly,
|
formatDateJSONDateOnly,
|
||||||
formatNumberRFCurrency,
|
formatNumberRFCurrency,
|
||||||
|
formatErrorMessage,
|
||||||
genGUID
|
genGUID
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user