2023-12-01 19:19:15 +03:00

P8-Panels

"Панели" расширение к "ПАРУС 8 Онлайн"

Оглавление

Термины и сокращения
I. Назначение
II. Состав
III. Требования к разработчику
IV. Установка
V. Подключение панелей
VI. Разработка панелей

Термины и сокращения

Система - "ПАРУС 8 Предприятие"
БД - База Данных
СУБД - Система Управления Базами Данных
Расширение - программный комплекс, дополняющий функциональность той или иной программной системы. В контексте данного документа (если не указано иное) - описываемое расширение "Панели".
Фреймворк - программная платформа, определяющая структуру программной системы, программное обеспечение, облегчающее разработку и объединение разных компонентов большого программного проекта. В контексте данного документа (если не указано иное) - описываемое расширение "Панели".
Панель - представление данных и функций Системы, реализованное с применением описываемого фреймворка
SPA - Single Page Application - технология разработки WEB-приложений, предполагающая динамическую генерацию интерфейса внутри одного HTML-документа, отображаемого браузером
HTML - HyperText Markup Language — язык гипертекстовой разметки
CSS - Cascading Style Sheets - каскадные таблицы стилей
DOM - Document Object Model - объектная модель документа (в контексте данного документа - HTML)
JS - JavaScript — мультипарадигменный интерпретируемый язык программирования
JSX - JavaScript eXtension - расширение JavaScript, которое позволяет создавать деревья DOM с использованием синтаксиса, подобного XML
АРМ - Автоматизированное Рабочее Место

I. Назначение

Расширение представляет собой фреймворк, основной задачей которого является сокращение времени разработки нестандартных графических интерфейсов и панелей мониторинга, работающих в составе WEB-приложения "ПАРУС 8 Онлайн".

II. Состав

В расширение входят:

  • Библиотека расширения "P8-Panels-ParusOnlineExt.dll" для сервера приложений "ПАРУС 8 Онлайн" - обеспечивает низкоуровневое взаимодействие разрабатываемых панелей с Системой
  • Хранимые объекты сервера БД Системы, обеспечивающие обмен данными между панелями и учётными регистрами Системы
  • API для высокоуровневого взаимодействия с сервером БД Системы
  • API для взаимодействия разрабатываемых панелей с WEB-приложением "ПАРУС 8 Онлайн"
  • WEB-приложение "Парус 8 - Панели мониторинга", являющееся "точкой входа" для подключения реализуемых панелей, включающее в себя:
    • Подключенные и настроенные библиотеки "React", "React-Router", "MUI"
    • Настроенный транспайлер "Babel"
    • Настроенный сборщик WEB-приложений "WebPack"
    • Настроенный статический анализатор кода "ESLint"
    • Настройки среды разработки "Visual Studio Code"
    • Готовый контекст React-приложения
    • Компоненты для отображения единого бокового меню подключенных панелей, галереи подключенных панелей, интеграции в рабочий стол WEB-приложения "ПАРУС 8 Онлайн"
    • Готовые панели мониторинга для ряда прикланых приложений Системы

III. Требования к разработчику

Для успешной разработки собственных панелей, с применением описываемого фреймворка потребуются знания следующих технологий:

  • HTML, CSS, JS, JSX
  • Разработка SPA WEB-приложений
  • Знакомство с основами работы перечисленных выше библиотек и системных средств (в первую очередь "React")
  • Знание архитектуры Системы, принципов работы и организации её серверной части

На видеохостинге YouTube можно ознакомиться с уроками и обучающими курсами по большинству из перечисленных технологий. Например, с этими.

IV. Установка

  1. Установите сервер приложений "ПАРУС 8 Онлайн" согласно документации (см. "Парус-Онлайн 2. Часть 1. Установка ГГГГ.ММ.docx").
  2. Разместите на диске сервера приложений библиотеку расширения "P8-Panels-ParusOnlineExt", для этого скопируйте содержимое папки "bin" из репозитория расширения "P8-Panels-ParusOnlineExt", например, в каталог "C:\p8web20\Ext\P8-Panels-ParusOnlineExt".
  3. Подключите библиотеку расширения к серверу приложений "ПАРУС 8 Онлайн". Для этого добавьте ссылку на библиотеку в файл "Config\extensions.config" сервера приложений:
<?xml version="1.0"?>
<parus.extensions enabled="true" resolveKind="Static" viewsMode="Shared" rootPath="c:\p8web20\Ext\">
	<extensions>
		<extension assembly="P8PanelsParusOnlineExt" path="P8-Panels-ParusOnlineExt\bin\P8-Panels-ParusOnlineExt.dll"/>
	</extensions>
</parus.extensions>

Где:

  • rootPath="c:\p8web20\Ext\" - атрибут, указывающий на корневой каталог хранения расширений для сервера приложений "ПАРУС 8 Онлайн"
  • path="P8-Panels-ParusOnlineExt\bin\P8-Panels-ParusOnlineExt.dll" - атрибут, указывающий на каталог размещения библиотеки расширения "Панели" относительного коревого rootPath
  1. Установите в файле конфигурации "PrecompiledApp.config" сервера приложений атрибут updatable в true:
<precompiledApp version="2" updatable="true"/>
  1. Разместите WEB-приложение "Парус 8 - Панели мониторинга" на сервере приложений "ПАРУС 8 Онлайн". Для этого в каталоге "Modules" сервера приложений создайте подкаталог "P8-Panels" и проведите клонирование репозитория "P8-Panels" в него:
git clone https://github.com/CITKParus/P8-Panels.git
  1. Проведите компиляцию хранимых объектов БД из каталога "db" клонированного репозитория (компиляцию проводить под пользователем-владельцем схемы серверной части Системы, с последующей перекомпиляцией зависимых инвалидных объектов), затем исполните скрипт "grants.sql", размещённый в этом же каталоге.

  2. Перезапустите сервер приложений "ПАРУС 8 Онлайн"

V. Подключение панелей

Файл "p8panels.config", располагаемый в каталоге "Config" сервера приложений "ПАРУС 8 Онлайн", определяет какие панели подключены к WEB-приложению, порядок формирования пунктов главного меню "ПАРУС 8 Онлайн" для доступа к подключенным панелям, состав галереи панелей и бокового меню навигации WEB-приложения "Парус 8 - Панели мониторинга", работающего в контексте "ПАРУС 8 Онлайн".

Главное меню, галерея панелей и боковое меню панелей

В корневом каталоге репозитория "P8-Panels" расположен файл "p8panels.config", содержащий конфигурацию поставляемых с расширением типовых панелей.

Данный файл конфигурации необходимо разместить локально, в каталоге "Config" сервера приложений "ПАРУС 8 Онлайн". Например, если сервер приложений установлен в "c:\p8web20\WebClient", то путь к "p8panels.config" должен быть "c:\p8web20\WebClient\Config\p8panels.config".

Рассмотрим формат файла конфигурации панелей на примере. Ниже приведён фрагмет "p8panels.config" из поставки расширения.

<CITK.P8Panels>
    <MenuItems>
	    <App name="ProjectPlanning">
            <MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
            <MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelsRoot" caption="Панели мониторинга" url="Modules/p8-panels/"/>
            <MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
            <MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelFin" caption="Экономика проектов" panelName="PrjFin"/>
            ...
        </App>
    </MenuItems>
    <Panels urlBase="Modules/p8-panels/#/">
        <Panel
                name="PrjFin"
                group="Планирование и учёт в проектах"
                caption="Экономика проектов"
                desc="Мониторинг калькуляции проекта, графиков финансирования, договоров с поставщиками материалов и ПКИ"
                url="prj_fin"
                path="prj_fin"
                icon="bar_chart"
                showInPanelsList="true"
                preview="./img/prj_fin.png"/>
        ...
    </Panels>
</CITK.P8Panels>

Настройки хранятся в формате XML. Корневым тэгом документа должен быть CITK.P8Panels. Дочерними для него могут быть две ветки конфигурации:

  • MenuItems - настройка пунктов главного меню WEB-приложения "ПАРУС 8 Online"
  • Panels - общий список панелей, подключаемых к приложению (не все панели обязательно выводить в виде пунктов меню)

MenuItems состоит из элементов App, каждый из которых определяет для какого из приложений Системы описываются пункты меню. MenuItems может содержать несколько элементов App. Каждый элемент App должен иметь обязательный атрибут name, определяющий код приложения Системы (см. колонку APPCODE в таблице APPLIST), в которое будут добавлены пункты меню. Дочерними для элемента App являются элементы MenuItem, каждый из которых описывает создаваемый расширением пункт меню. App может содержать несколько MenuItem. Каждый из MenuItem может иметь следующие атрибуты:

  • parent - обязательный, содержит GUID родительского пункта меню, к которому будет добавлен описываемый дочерний пункт (см. P_MENUS_CREATE_*_MENU, где * - код приложения Системы)
  • separator - необязательный, принимает значения "true" или "false", если "true" - создаваемый пункт меню будет разделителем, остальные атрибуты, описанные ниже будут проигнорированы
  • name - необязательный для separator="true", в прочих случаях - обязательный, уникальное имя пункта меню
  • caption - необязательный для separator="true", в прочих случаях - обязательный, видимый текст пункта меню
  • panelName - необязательный для separator="true" или если указан атрибут url, в прочих случаях - обязательный, определяет код панели, открываемой при выборе данного пункта меню конечным пользователем (коды панелей объявляются в секции Panels данного файла конфигурации, описана ниже)
  • url - необязательный для separator="true" или если указан атрибут panelName, в прочих случаях - обязательный, определяет URL, который будет открыт в отдельной закладке "ПАРУС 8 Онлайн" при выборе данного пункта меню конечным пользователем (в приведённом примере, для пункта меню "ShowPrjPanelsRoot" открывает домашнюю страницу WEB-приложения "Парус 8 - Панели мониторинга", отображающую галерею доступных панелей, см. ниже описание атрибута urlBase элемента Panels)

Panels - содержит список элементов Panel, описывающих подключенные панели. Элемент Panels имеет атрибут urlBase, определяющий корневой URL WEB-приложения "Парус 8 - Панели мониторинга", относительно него формируются URL панелей. Значение urlBase определяется физическим расположением WEB-приложения "Парус 8 - Панели мониторинга" на диске сервера приложений (см. пункт 5 в главе "IV. Установка"). В данном примеры, файлы WEB-приложения распологаются в каталоге "Modules/p8-panels" сервера приложений. Каждый из элементов Panel, дочерних для Panels, описывает одну панель и имеет следующие атрибуты:

  • name - обязательный, строка, указывается латиницей, определяет уникальное имя панели
  • group - необязательный, строка, указывается кириллицей, определяет имя группы, в которую входит панель (применяется при формировании галереи панелей, главного меню панелей и ссылок на рабочем столе)
  • caption - обязательный, строка, видимое наименование панели (применяется в галереи панелей, главном меню панелей, ссылках на рабочем столе, заголовках закладок)
  • desc - необязательный, строка,
  • url - обязательный, строка, указывается латиницей, относительй URL панели (по адресу Panel.urlBase + Panel.Panels.url сервер приложений "ПАРУС 8 Онлайн" будет выдавать HTML-страницу панели), для простоты навигации может повторять значение атрибута path
  • path - обязательный, строка, путь к исходному коду панели в структуре каталогов WEB-приложения "Парус 8 - Панели мониторинга" (панели должны размещаться в "app/panels", в данном атрибуте указыватся только имя каталога, созданного для панели в "app/panels")
  • icon - обязательный, строка, код иконки панели из символов шрифта Google Material Icons (применяется при формировании галереи панелей, главного меню панелей и ссылок на рабочем столе)
  • showInPanelsList - обязательный, принимает значения "true" или "false", определяет отображение ссылки на панель в галереи панелей, главном меню панелей, виджете рабочего стола
  • preview - полный путь и имя файла из каталога "img" WEB-приложения "Парус 8 - Панели мониторинга" (в каталог могут быть добавлены пользовательские изображения), служит в качестве изображения панели в галерее панелей

На рисунках ниже проиллюстрировано применение атрибутов элемента Panel.

Применение атрибутов панели Размещение панели

Подключение разработанных пользователем панелей осуществляется путём добавления элементов Panels в файл конфигурации (при необходимости и элементов App\MenuItems, если предполагается открытие панели через главное меню WEB-приложения "ПАРУС 8 Онлайн").

Изменения файла конфигурации в части элементов MenuItems требуют перезапуска сервера приложений "ПАРУС 8 Онлайн" и завершения/начала сеансов конечных пользователей.

Будьте внимательны при обновлении: если в локальном файле "p8panels.config" содержится конфигурация пользовательских панелей, то его нельзя заменять копированием дистрибутивной версии файла при обновлении - будут утеряны сделанные настройки. В этом случае файл следует модифицировать экспертным путём, добавив в локальный "p8panels.config" изменения из дистрибутивного вручную.

VI. Разработка панелей

Внимание: данное руководство не является обучающим курсом по WEB-разработке как таковой. Изложенные ниже сведения о порядке реализации пользовательских панелей, даны с учётом приведённых ранее требований к разработчику.

Общие сведения

Расширение "Панели" позволяет подключать нестандартные интерфейсы разрабатываемые на местах, без привлечения вендора. Это могут быть не только панели мониторинга, но и формы ввода данных, различные АРМ, выполняющие бизнес-функции в Системе.

С точки зрения клиенсткой части, Панели представляют собой функциональные компоненты React, автоматически (благодаря описанному выше файлу конфигурации) встраиваемые в систему маршрутизации WEB-приложения "Парус 8 - Панели мониторинга" (далее "приложения" или "WEB-приложения", если контекст явно не указывает на иное). Каждая панель состоит из:

  • Набора JS-объектов и функций, управляющих состоянием панели
  • Функций для обмена данными с сервером БД Системы и выполнения бизнес-процедур в ней
  • JSX разметки, отражающей смену состояния панели

Такая структура исходного кода панели продиктована архитектурными требованиями к функциональным React-компонентам. Каждая панель (и все необходимые для её функционирования JS-модули и вспомогательный файлы) размещается в отдельном каталоге (см. выше - "app/panels", здесь и далее каталоги указаны относительно корневого каталога размещения приложения, если явно не указано иное) WEB-приложения "Парус 8 - Панели мониторинга".

Каждая панель должна иметь в составе "index.js" - точку входа по умолчанию. "index.js" должен экспортировать фунциональный React-компонент панели с имененем RootClass (см. для примера "app/panels/prj_fin/index.js").

После добавления новых панелей в состав приложения необходима его "пересборка". Для этого предусмотрены преднастроенные скрипты dev и build. Скрипты размещены в секции scripts файла зависимостей package.json WEB-приложения. Исполнение скриптов сборки выполняется через пакетный менеджер npm из корневого каталога приложения:

REM Запуск скрипта для отладочной сборки
c:\inetpub\p8web20\WebClient\Modules\P8-Panels>npm run dev

REM Запуск скрипта финальной сборки
c:\inetpub\p8web20\WebClient\Modules\P8-Panels>npm run build

Скрипт финальной сборки формирует обновлённое WEB-приложение в каталоге "dist" и завершает работу. Скрипт отладочной сборки обновляет WEB-приложение в каталоге "dist" и остаётся в активном режиме, "слушая" измнения файлов исходного кода приложения и автоматически обновляя "dist", если таковые изменения будут зафиксированы. Это позволяет отлаживать панели не выполняя пересборку вручную.

После пересборки обновлённые/новые панели доступны конечному пользователю для эксплуатации через WEB-приложение "ПАРУС 8 Онлайн".

Серверная часть любой из панелей - набор хранимых процедур/функций/пакетов БД Системы. Состав объектов, их алгоритмы, входные параметры и выходные данные зависят от специфики панели и специально не регламентируются. Необходимо понимать, что с помощью специального API из клиентской JS-функции панели можно обращаться к хранимым объектам БД - исполнять их, передавать значения входных параметров (например, считанные из форм ввода, размещённых на панели), получать и отображать на панели значения выходных параметров исполненного серверного объекта (в виде таблиц, карточек, графиков и прочими способами, отвечающими функциональным требованиям реализуемой панели).

API для взаимодействия с сервером "ПАРУС 8 Предприятие"

Для исполнения хранимых процедур/функций БД Системы в составе расширения предусмотрен специальный API. Его подключение к компоненте панели осуществляется через контекст BackEndСtx ("app/context/backend.js").

В состав API входят:

  • SERV_DATA_TYPE_STR - константа для типа данных "строка", при описании параметров исполняемых хранимых объектов
  • SERV_DATA_TYPE_NUMB - константа для типа данных "число", при описании параметров исполняемых хранимых объектов
  • SERV_DATA_TYPE_DATE - константа для типа данных "дата", при описании параметров исполняемых хранимых объектов
  • SERV_DATA_TYPE_CLOB - константа для типа данных "текст", при описании параметров исполняемых хранимых объектов
  • isRespErr - проверка результата исполнения серверного объекта на наличие ошибок
  • getRespErrMessage - получение ошибки исполнения серверного объекта
  • getRespPayload - получение выходных значений, полученных после успешного исполнения
  • executeStored - асинхронное исполнение хранимой процедуры/функции БД Системы
  • getConfig - асинхронное считывание параметров конфигурации, определённых в "p8panels.config" (возвращает их JSON-представление)

При формировании ответов, функции, получающие данные с сервера, возвращают типовые значения:

//Типовой успех
{
    SSTATUS: "OK",
    XPAYLOAD: Object
}

//Типовая ошибка
{
    SSTATUS: "ERR",
    SMESSAGE: String
}

Где:

  • SSTATUS - строка, состояние исполнения ("OK" - успех или "ERR" - ошибка)
  • XPAYLOAD - объект, полезная нагрузка, данные полученные от серверного объекта (отсутствует, если SSTATUS = "ERR")
  • SMESSAGE - строка, текст сообщения об ошибке (отсутствует, если SSTATUS = "OK")

boolean isRespErr(Object)

Входные параметры: обязательный, объект, результат вызова executeStored

Результат: true - если полученный на вход результат исполнения executeStored содержит ошибку, false - в остальных случаях

String getRespErrMessage(Object)

Входные параметры: обязательный, объект, результат вызова executeStored

Результат: текст сообщения об ошибке - если полученный на вход результат исполнения executeStored содержит ошибку, пустая строка ("") - в остальных случаях

Object getRespPayload(Object)

Входные параметры: обязательный, объект, результат вызова executeStored (вызов должен осуществляться с параметром fullResponse = true)

Результат: объект с данными, размещёнными в XPAYLOAD ответа сервера - если полученный на вход результат исполнения executeStored содержит полезную нагрузку, null - в остальных случаях

async Object executeStored(Object)

Входные параметры:

{
    stored,
    args,
    respArg,
    isArray,
    tagValueProcessor,
    attributeValueProcessor,
    loader = true,
    loaderMessage = "",
    throwError = true,
    showErrorMessage = true,
    fullResponse = false,
    spreadOutArguments = true
}

stored - обязательный, строка, имя исполняемого хранимого объекта (для пакетных - "ПАКЕТ.ОБЪЕКТ")
args - необязательный, объект, описание параметров исполняемого хранимого объета вида: {"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}} (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, с CLOB-параметрами это не всегда может произойти корректно)
respArg - необязательный, строка, имя выходного параметра исполняемого объекта, значение которого необходимо вернуть как данные ответа (если не указан - возвращвется типовой ответ)
isArray, tagValueProcessor, attributeValueProcessor - необязательны, функции, позволяющие провести корректировку парсинга XML-ответа сервера в JSON (сигнатура и назначение функций описаны в документации к fast-xml-parser)
loader - необязательный, логический, признак отображения типового индикатора процесса
loaderMessage - необязательный, строка, текст индикатора процесса (при отсутствии будет использован типовой)
throwError - необязательный, логический, признак генерации исключения, если false - возвращает ошибку в типовом формате
showErrorMessage - необязательный, логический, признак отображения типового клиентского сообщение об ошибке, в случае её возникновения (только если throwError = true)
fullResponse - необязательный, логический, признак возврата полного типового ответа сервера, если false - возвращается только содержимое XPAYLOAD
spreadOutArguments - необязательный, логический, признак "разделения" значений выходных параметров исполняемого обхекта (игнорируется при наличии respArg), если true - XPAYLOAD будет содержать ответ в виде {"ВЫХОДНОЙ_ПАРАМЕТР1": "ЗНАЧЕНИЕ", "ВЫХОДНОЙ_ПАРАМЕТР2": "ЗНАЧЕНИЕ", ...}, если false - XPAYLOAD будет содержать ответ в виде {XOUT_ARGUMENTS: [{SNAME: "ВЫХОДНОЙ_ПАРАМЕТР1", VALUE: "ЗНАЧЕНИЕ"}, {SNAME: "ВЫХОДНОЙ_ПАРАМЕТР2", VALUE: "ЗНАЧЕНИЕ"}, ...]}

Результат: объект с данными, размещёнными в XPAYLOAD ответа сервера (если fullResponse = false) или полный типовой ответ (описан выше).

Пример:

import React, { useState, useContext } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером

//Функциональный компонент панели (или её части)
const MyPanel = () => {
    //Собственное состояние
    const [state, setState] = useState({ dataLoaded: false, data: [], filters: null, orders: null });

    //Подключение к контексту взаимодействия с сервером
    const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);

    //Загрузка данных проектов с сервера
    const loadProjects = async (agentName) => {
        //Исполняем процедуру
        const data = await executeStored({
            stored: "UDO_P_GET_MY_DATA",
            args: {
                CFILTERS: { VALUE: state.filters, SDATA_TYPE: SERV_DATA_TYPE_CLOB },
                CORDERS: { VALUE: state.orders, SDATA_TYPE: SERV_DATA_TYPE_CLOB },
                SAGENT: agentName
            },
            respArg: "COUT"
        });
        //Отражаем данные в состоянии
        setState(pv => ({ ...pv, data: [...data], dataLoaded: true }));
    }
};

async Object getConfig(Object)

Входные параметры:

{
    loader = true,
    loaderMessage = "",
    throwError = true,
    showErrorMessage = true
}

loader - необязательный, логический, признак отображения типового индикатора процесса
loaderMessage - необязательный, строка, текст индикатора процесса (при отсутствии будет использован типовой)
throwError - необязательный, логический, признак генерации исключения, если false - возвращает ошибку в типовом формате
showErrorMessage - необязательный, логический, признак отображения типового клиентского сообщения об ошибке, в случае её возникновения (только если throwError = true)

Результат: объект, типовой ответ, где XPAYLOAD объект вида (см. описание атрибутов выше, в описании "p8panels.config"):

{
    "MenuItems": {
        "App": [
            {
                "MenuItem": [
                    {
                        "parent": ...,
                        "name": ...,
                        "caption": ...,
                        "url": ...,
                        "separator": ...
                    },
                    ...
                ],
                "name": "Realiz"
            },
            ...
        ]
    },
    "Panels": {
        "Panel": [
            {
                "name": ...,
                "group": ...,
                "caption": ...,
                "desc": ...,
                "url": ...,
                "path": ...,
                "icon": ...,
                "showInPanelsList": ...,
                "preview": ...
            },
            ...
        ],
        "urlBase": ...
    }
}

API для взаимодействия с WEB-приложением "ПАРУС 8 Онлайн"

Компоненты пользовательского интерфейса

Типовые интерфейсные примитивы

Компоненты MUI
Сообщения "P8PAppMessage", "P8PAppInlineMessage"
Индикатор загрузки "P8PAppProgress"

Высокоуровневые компоненты

Таблица данных "P8PDataGrid"
Графики "P8PChart"
Диаграмма ганта "P8PGantt"
Description
Parus 8 Panels - Parus 8 Online data publication framework
Readme 48 MiB
Languages
sql 56.4%
JavaScript 43.3%
CSS 0.3%