WEB APP: ApplicationContext отвязан от использования глобальных объектов

This commit is contained in:
Mikhail Chechnev 2023-09-25 14:12:22 +03:00
parent 8592c870d8
commit ea90de6240
5 changed files with 30 additions and 28 deletions

View File

@ -45,13 +45,13 @@ export const INPUTS = {
}; };
//Типовые сообщения об ошибках //Типовые сообщения об ошибках
export const ERROR = { export const ERRORS = {
UNDER_CONSTRUCTION: "Панель в разработке", UNDER_CONSTRUCTION: "Панель в разработке",
P8O_API_UNAVAILABLE: '"ПАРУС 8 Онлайн" недоступен', P8O_API_UNAVAILABLE: '"ПАРУС 8 Онлайн" недоступен',
DEFAULT: "Неожиданная ошибка" DEFAULT: "Неожиданная ошибка"
}; };
//Типовые сообщения для ошибок HTTP //Типовые сообщения для ошибок HTTP
export const ERROR_HTTP = { export const ERRORS_HTTP = {
404: "Адрес не найден" 404: "Адрес не найден"
}; };

View File

@ -15,7 +15,7 @@ import { NavigationContext, NavigationCtx, getRootLocation } from "./context/nav
import { P8PAppErrorPage } from "./components/p8p_app_error_page"; //Страница с ошибкой import { P8PAppErrorPage } from "./components/p8p_app_error_page"; //Страница с ошибкой
import { P8PAppWorkspace } from "./components/p8p_app_workspace"; //Рабочее пространство панели import { P8PAppWorkspace } from "./components/p8p_app_workspace"; //Рабочее пространство панели
import { P8PPanelsMenuGrid, PANEL_SHAPE } from "./components/p8p_panels_menu"; //Меню панелей import { P8PPanelsMenuGrid, PANEL_SHAPE } from "./components/p8p_panels_menu"; //Меню панелей
import { TITLES, BUTTONS, ERROR, ERROR_HTTP } from "../app.text"; //Текстовые ресурсы и константы import { TITLES, BUTTONS, ERRORS, ERRORS_HTTP } from "../app.text"; //Текстовые ресурсы и константы
//-------------------------- //--------------------------
//Вспомогательные компоненты //Вспомогательные компоненты
@ -35,7 +35,7 @@ const RouterError = ({ homePath }) => {
//Генерация содержимого //Генерация содержимого
return ( return (
<P8PAppErrorPage <P8PAppErrorPage
errorMessage={ERROR_HTTP[routeError.status] ? ERROR_HTTP[routeError.status] : ERROR.DEFAULT} errorMessage={ERRORS_HTTP[routeError.status] ? ERRORS_HTTP[routeError.status] : ERRORS.DEFAULT}
onNavigate={handleNavigate} onNavigate={handleNavigate}
navigateCaption={BUTTONS.NAVIGATE_HOME} navigateCaption={BUTTONS.NAVIGATE_HOME}
/> />

View File

@ -9,11 +9,9 @@
import React, { useReducer, createContext, useEffect, useContext, useCallback } from "react"; //ReactJS import React, { useReducer, createContext, useEffect, useContext, useCallback } from "react"; //ReactJS
import PropTypes from "prop-types"; //Контроль свойств компонента import PropTypes from "prop-types"; //Контроль свойств компонента
import { getDisplaySize } from "../core/utils"; //Вспомогательные функции
import { APP_AT, INITIAL_STATE, applicationReducer } from "./application_reducer"; //Редьюсер состояния import { APP_AT, INITIAL_STATE, applicationReducer } from "./application_reducer"; //Редьюсер состояния
import { MessagingСtx } from "./messaging"; //Контекст отображения сообщений import { MessagingСtx } from "./messaging"; //Контекст отображения сообщений
import { BackEndСtx } from "./backend"; //Контекст взаимодействия с сервером import { BackEndСtx } from "./backend"; //Контекст взаимодействия с сервером
import { ERROR } from "../../app.text"; //Текстовые ресурсы и константы
//--------- //---------
//Константы //Константы
@ -22,9 +20,10 @@ import { ERROR } from "../../app.text"; //Текстовые ресурсы и
//Клиентский API "ПАРУС 8 Онлайн" //Клиентский API "ПАРУС 8 Онлайн"
const P8O_API = window.parent?.parus?.clientApi; const P8O_API = window.parent?.parus?.clientApi;
//-------------------------------- //Структура объекта с описанием ошибок
//Вспомогательные классы и функции const APPLICATION_CONTEXT_ERRORS_SHAPE = PropTypes.shape({
//-------------------------------- P8O_API_UNAVAILABLE: PropTypes.string.isRequired
});
//---------------- //----------------
//Интерфейс модуля //Интерфейс модуля
@ -34,7 +33,7 @@ const P8O_API = window.parent?.parus?.clientApi;
export const ApplicationСtx = createContext(); export const ApplicationСtx = createContext();
//Провайдер контекста приложения //Провайдер контекста приложения
export const ApplicationContext = ({ guidGenerator, children }) => { export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, children }) => {
//Подключим редьюсер состояния //Подключим редьюсер состояния
const [state, dispatch] = useReducer(applicationReducer, INITIAL_STATE); const [state, dispatch] = useReducer(applicationReducer, INITIAL_STATE);
@ -63,18 +62,18 @@ export const ApplicationContext = ({ guidGenerator, children }) => {
const _id = id || guidGenerator(); const _id = id || guidGenerator();
P8O_API.ui.openTab({ id: _id, url, caption, onClose: () => (onClose ? onClose(_id) : null) }); P8O_API.ui.openTab({ id: _id, url, caption, onClose: () => (onClose ? onClose(_id) : null) });
return _id; return _id;
} else showMsgErr(ERROR.P8O_API_UNAVAILABLE); } else showMsgErr(errors.P8O_API_UNAVAILABLE);
}, },
[showMsgErr, guidGenerator] [showMsgErr, guidGenerator, errors.P8O_API_UNAVAILABLE]
); );
//Отображение раздела "ПАРУС 8 Онлайн" //Отображение раздела "ПАРУС 8 Онлайн"
const pOnlineShowUnit = useCallback( const pOnlineShowUnit = useCallback(
({ unitCode, showMethod = "main", inputParameters }) => { ({ unitCode, showMethod = "main", inputParameters }) => {
if (P8O_API) P8O_API.fn.openDocumentModal({ unitcode: unitCode, method: showMethod, inputParameters }); if (P8O_API) P8O_API.fn.openDocumentModal({ unitcode: unitCode, method: showMethod, inputParameters });
else showMsgErr(ERROR.P8O_API_UNAVAILABLE); else showMsgErr(errors.P8O_API_UNAVAILABLE);
}, },
[showMsgErr] [showMsgErr, errors.P8O_API_UNAVAILABLE]
); );
//Отображение документа "ПАРУС 8 Онлайн" //Отображение документа "ПАРУС 8 Онлайн"
@ -82,9 +81,9 @@ export const ApplicationContext = ({ guidGenerator, children }) => {
({ unitCode, document, showMethod = "main", inRnParameter = "in_RN" }) => { ({ unitCode, document, showMethod = "main", inRnParameter = "in_RN" }) => {
if (P8O_API) if (P8O_API)
P8O_API.fn.openDocumentModal({ unitcode: unitCode, method: showMethod, inputParameters: [{ name: inRnParameter, value: document }] }); P8O_API.fn.openDocumentModal({ unitcode: unitCode, method: showMethod, inputParameters: [{ name: inRnParameter, value: document }] });
else showMsgErr(ERROR.P8O_API_UNAVAILABLE); else showMsgErr(errors.P8O_API_UNAVAILABLE);
}, },
[showMsgErr] [showMsgErr, errors.P8O_API_UNAVAILABLE]
); );
//Отображение словаря "ПАРУС 8 Онлайн" //Отображение словаря "ПАРУС 8 Онлайн"
@ -92,27 +91,27 @@ export const ApplicationContext = ({ guidGenerator, children }) => {
({ unitCode, showMethod = "main", inputParameters, callBack }) => { ({ unitCode, showMethod = "main", inputParameters, callBack }) => {
if (P8O_API) if (P8O_API)
P8O_API.fn.openDictionary({ unitcode: unitCode, method: showMethod, inputParameters }, res => (callBack ? callBack(res) : null)); P8O_API.fn.openDictionary({ unitcode: unitCode, method: showMethod, inputParameters }, res => (callBack ? callBack(res) : null));
else showMsgErr(ERROR.P8O_API_UNAVAILABLE); else showMsgErr(errors.P8O_API_UNAVAILABLE);
}, },
[showMsgErr] [showMsgErr, errors.P8O_API_UNAVAILABLE]
); );
//Исполнение пользовательской процедуры "ПАРУС 8 Онлайн" //Исполнение пользовательской процедуры "ПАРУС 8 Онлайн"
const pOnlineUserProcedure = useCallback( const pOnlineUserProcedure = useCallback(
({ code, inputParameters, callBack }) => { ({ code, inputParameters, callBack }) => {
if (P8O_API) P8O_API.fn.performUserProcedureSync({ code, inputParameters }, res => (callBack ? callBack(res) : null)); if (P8O_API) P8O_API.fn.performUserProcedureSync({ code, inputParameters }, res => (callBack ? callBack(res) : null));
else showMsgErr(ERROR.P8O_API_UNAVAILABLE); else showMsgErr(errors.P8O_API_UNAVAILABLE);
}, },
[showMsgErr] [showMsgErr, errors.P8O_API_UNAVAILABLE]
); );
//Исполнение пользовательского отчёта "ПАРУС 8 Онлайн" //Исполнение пользовательского отчёта "ПАРУС 8 Онлайн"
const pOnlineUserReport = useCallback( const pOnlineUserReport = useCallback(
({ code, inputParameters }) => { ({ code, inputParameters }) => {
if (P8O_API) P8O_API.fn.performUserReport({ code, inputParameters }); if (P8O_API) P8O_API.fn.performUserReport({ code, inputParameters });
else showMsgErr(ERROR.P8O_API_UNAVAILABLE); else showMsgErr(errors.P8O_API_UNAVAILABLE);
}, },
[showMsgErr] [showMsgErr, errors.P8O_API_UNAVAILABLE]
); );
//Инициализация приложения //Инициализация приложения
@ -130,12 +129,12 @@ export const ApplicationContext = ({ guidGenerator, children }) => {
if (!state.initialized) { if (!state.initialized) {
//Слушаем изменение размеров окна //Слушаем изменение размеров окна
window.addEventListener("resize", () => { window.addEventListener("resize", () => {
setDisplaySize(getDisplaySize()); if (displaySizeGetter) setDisplaySize(displaySizeGetter());
}); });
//Инициализируем приложение //Инициализируем приложение
initApp(); initApp();
} }
}, [state.initialized, initApp]); }, [state.initialized, initApp, displaySizeGetter]);
//Вернём компонент провайдера //Вернём компонент провайдера
return ( return (
@ -158,6 +157,8 @@ export const ApplicationContext = ({ guidGenerator, children }) => {
//Контроль свойств - Провайдер контекста приложения //Контроль свойств - Провайдер контекста приложения
ApplicationContext.propTypes = { ApplicationContext.propTypes = {
errors: APPLICATION_CONTEXT_ERRORS_SHAPE.isRequired,
displaySizeGetter: PropTypes.func,
guidGenerator: PropTypes.func.isRequired, guidGenerator: PropTypes.func.isRequired,
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]) children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
}; };

View File

@ -10,7 +10,7 @@
import React, { useContext } from "react"; //Классы React import React, { useContext } from "react"; //Классы React
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
import { P8PAppErrorPage } from "../../components/p8p_app_error_page"; //Страница с ошибкой import { P8PAppErrorPage } from "../../components/p8p_app_error_page"; //Страница с ошибкой
import { BUTTONS, ERROR } from "../../../app.text"; //Текстовые ресурсы и константы import { BUTTONS, ERRORS } from "../../../app.text"; //Текстовые ресурсы и константы
//----------- //-----------
//Тело модуля //Тело модуля
@ -22,7 +22,7 @@ const Dummy = () => {
const { navigateBack } = useContext(NavigationCtx); const { navigateBack } = useContext(NavigationCtx);
//Генерация содержимого //Генерация содержимого
return <P8PAppErrorPage errorMessage={ERROR.UNDER_CONSTRUCTION} onNavigate={() => navigateBack()} navigateCaption={BUTTONS.NAVIGATE_BACK} />; return <P8PAppErrorPage errorMessage={ERRORS.UNDER_CONSTRUCTION} onNavigate={() => navigateBack()} navigateCaption={BUTTONS.NAVIGATE_BACK} />;
}; };
//---------------- //----------------

View File

@ -12,7 +12,8 @@ import { MessagingContext } from "./context/messaging"; //Контекст со
import { BackEndContext } from "./context/backend"; //Контекст взаимодействия с сервером import { BackEndContext } from "./context/backend"; //Контекст взаимодействия с сервером
import { ApplicationContext } from "./context/application"; //Контекст приложения import { ApplicationContext } from "./context/application"; //Контекст приложения
import { App } from "./app"; //Приложение import { App } from "./app"; //Приложение
import { genGUID } from "./core/utils"; //Вспомогательные функции import { ERRORS } from "../app.text"; //Текстовые ресурсы и константы
import { getDisplaySize, genGUID } from "./core/utils"; //Вспомогательные функции
import client from "./core/client"; //Клиент для взаимодействия с сервером import client from "./core/client"; //Клиент для взаимодействия с сервером
//----------- //-----------
@ -24,7 +25,7 @@ const Root = () => {
return ( return (
<MessagingContext> <MessagingContext>
<BackEndContext client={client}> <BackEndContext client={client}>
<ApplicationContext guidGenerator={genGUID}> <ApplicationContext errors={ERRORS} displaySizeGetter={getDisplaySize} guidGenerator={genGUID}>
<App /> <App />
</ApplicationContext> </ApplicationContext>
</BackEndContext> </BackEndContext>