/* Парус 8 - Панели мониторинга Ядро: Вспомогательные функции */ //--------------------- //Подключение библиотек //--------------------- import { XMLParser, XMLBuilder } from "fast-xml-parser"; //Конвертация XML в JSON и JSON в XML import dayjs from "dayjs"; //Работа с датами //--------- //Константы //--------- //Коды типовых размеров экранов const DISPLAY_SIZE_CODE = { XS: "XS", //eXtra Small - супер маленький экран SM: "SM", //Small - маленький экран MD: "MD", //Middle - средний экран LG: "LG" //Large - большой экран }; //Типовые размеры экранов const DISPLAY_SIZE = { [DISPLAY_SIZE_CODE.XS]: { WIDTH_FROM: 0, WIDTH_TO: 767 }, //eXtra Small - супер маленький экран < 768px [DISPLAY_SIZE_CODE.SM]: { WIDTH_FROM: 768, WIDTH_TO: 991 }, //Small - маленький экран >= 768px [DISPLAY_SIZE_CODE.MD]: { WIDTH_FROM: 992, WIDTH_TO: 1199 }, //Middle - средний экран >= 992px [DISPLAY_SIZE_CODE.LG]: { WIDTH_FROM: 1200, WIDTH_TO: 1000000 } //Large - большой экран >= 1200px }; //Типовые пути конвертации в массив (при переводе XML -> JSON) const XML_ALWAYS_ARRAY_PATHS = [ "XRESPOND.XPAYLOAD.XOUT_ARGUMENTS", "XRESPOND.XPAYLOAD.XDATA_GRID.rows", "XRESPOND.XPAYLOAD.XDATA_GRID.columnsDef", "XRESPOND.XPAYLOAD.XDATA_GRID.columnsDef.values", "XRESPOND.XPAYLOAD.XDATA_GRID.groups", "XRESPOND.XPAYLOAD.XGANTT.taskAttributes", "XRESPOND.XPAYLOAD.XGANTT.taskColors", "XRESPOND.XPAYLOAD.XGANTT.tasks", "XRESPOND.XPAYLOAD.XGANTT.tasks.dependencies", "XRESPOND.XPAYLOAD.XCHART.labels", "XRESPOND.XPAYLOAD.XCHART.datasets", "XRESPOND.XPAYLOAD.XCHART.datasets.data", "XRESPOND.XPAYLOAD.XCHART.datasets.items", "XRESPOND.XPAYLOAD.XCYCLOGRAM.taskAttributes", "XRESPOND.XPAYLOAD.XCYCLOGRAM.columns", "XRESPOND.XPAYLOAD.XCYCLOGRAM.groups", "XRESPOND.XPAYLOAD.XCYCLOGRAM.tasks" ]; //Типовые шаблоны конвертации в массив (при переводе XML -> JSON) const XML_ALWAYS_ARRAY_PATH_PATTERNS = [ /(.*)XDATA_GRID.rows$/, /(.*)XDATA_GRID.columnsDef$/, /(.*)XDATA_GRID.columnsDef.values$/, /(.*)XDATA_GRID.groups$/, /(.*)XGANTT.taskAttributes$/, /(.*)XGANTT.taskColors$/, /(.*)XGANTT.tasks$/, /(.*)XGANTT.tasks.dependencies$/, /(.*)XCHART.labels$/, /(.*)XCHART.datasets$/, /(.*)XCHART.datasets.data$/, /(.*)XCHART.datasets.items$/, /(.*)XCYCLOGRAM.taskAttributes$/, /(.*)XCYCLOGRAM.columns$/, /(.*)XCYCLOGRAM.groups$/, /(.*)XCYCLOGRAM.tasks$/ ]; //Типовой постфикс тега для массива (при переводе XML -> JSON) const XML_ALWAYS_ARRAY_POSTFIX = "__SYSTEM__ARRAY__"; //Типовые шаблоны конвертации значения атрибута в строку (при переводе XML -> JSON) const XML_ATTR_ALWAYS_STR_PATH_PATTERNS = [ /(.*)XDATA_GRID.columnsDef.name$/, /(.*)XDATA_GRID.columnsDef.caption$/, /(.*)XDATA_GRID.columnsDef.parent$/, /(.*)XDATA_GRID.groups.name$/, /(.*)XDATA_GRID.groups.caption$/, /(.*)XCYCLOGRAM.columns.name$/, /(.*)XCYCLOGRAM.groups.name$/ ]; //----------- //Тело модуля //----------- //Проверка существования значения const hasValue = value => typeof value !== "undefined" && value !== null && value !== ""; //Проверка типа устройства const getDisplaySize = () => { let res = DISPLAY_SIZE_CODE.MD; Object.keys(DISPLAY_SIZE).map(dspl => { if (window.innerWidth >= DISPLAY_SIZE[dspl].WIDTH_FROM && window.innerWidth <= DISPLAY_SIZE[dspl].WIDTH_TO) res = dspl; }); return res; }; //Глубокое копирование объекта const deepCopyObject = obj => (structuredClone ? structuredClone(obj) : JSON.parse(JSON.stringify(obj))); //Конвертация объекта в Base64 XML const object2Base64XML = (obj, builderOptions) => { const builder = new XMLBuilder(builderOptions); return btoa(unescape(encodeURIComponent(builder.build(obj)))); }; //Конвертация XML в JSON const xml2JSON = ({ xmlDoc, isArray, transformTagName, tagValueProcessor, attributeValueProcessor, useDefaultPatterns = true }) => { return new Promise((resolve, reject) => { try { let opts = { ignoreDeclaration: true, ignoreAttributes: false, parseAttributeValue: true, attributeNamePrefix: "" }; if (useDefaultPatterns) { opts.isArray = (name, jPath, isLeafNode, isAttribute) => XML_ALWAYS_ARRAY_PATHS.indexOf(jPath) !== -1 || XML_ALWAYS_ARRAY_PATH_PATTERNS.some(pattern => pattern.test(jPath)) || jPath.endsWith(XML_ALWAYS_ARRAY_POSTFIX) || (isArray ? isArray(name, jPath, isLeafNode, isAttribute) : undefined); opts.attributeValueProcessor = (name, val, jPath) => XML_ATTR_ALWAYS_STR_PATH_PATTERNS.some(pattern => pattern.test(`${jPath}.${name}`)) ? undefined : attributeValueProcessor ? attributeValueProcessor(name, val, jPath) : val; } else { if (isArray) opts.isArray = isArray; if (attributeValueProcessor) opts.attributeValueProcessor = attributeValueProcessor; } if (transformTagName) opts.transformTagName = transformTagName; if (tagValueProcessor) opts.tagValueProcessor = tagValueProcessor; const parser = new XMLParser(opts); resolve(parser.parse(xmlDoc)); } catch (e) { reject(e); } }); }; //Форматирование даты в формат РФ const formatDateRF = value => (value ? dayjs(value).format("DD.MM.YYYY") : null); //Форматирование даты и времени в формат РФ const formatDateTimeRF = value => (value ? dayjs(value).format("DD.MM.YYYY HH:mm:ss") : null); //Форматирование даты в формат JSON (только дата, без времени) const formatDateJSONDateOnly = value => (value ? dayjs(value).format("YYYY-MM-DD") : 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 = () => "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) ); //---------------- //Интерфейс модуля //---------------- export { hasValue, getDisplaySize, deepCopyObject, object2Base64XML, xml2JSON, formatDateRF, formatDateTimeRF, formatDateJSONDateOnly, formatNumberRFCurrency, formatErrorMessage, genGUID };