diff --git a/app/components/p8p_dialog.js b/app/components/p8p_dialog.js
index c453588..e0d265f 100644
--- a/app/components/p8p_dialog.js
+++ b/app/components/p8p_dialog.js
@@ -9,12 +9,16 @@
import React, { useEffect, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
+import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Box, Typography, IconButton, Icon } from "@mui/material"; //Интерфейсные компоненты
import { BUTTONS } from "../../app.text"; //Общие текстовые ресурсы
import { P8P_INPUT, P8PInput } from "./p8p_input"; //Поле ввода
-import { P8P_DIALOG_CONTENT_VARIANT } from "../theme/variants/p8p_dialog_content_variants"; //Варианты содержимого диалога
-import { P8P_BUTTON_VARIANT } from "../theme/variants/p8p_button_variants"; //Варианты кнопок
import { P8P_DIALOG_TITLE_VARIANT } from "../theme/variants/p8p_dialog_title_variants"; //Варианты заголовков диалога
+import { P8P_DIALOG_CONTENT_VARIANT } from "../theme/variants/p8p_dialog_content_variants"; //Варианты содержимого диалога
+import { P8P_DIALOG_ACTIONS_VARIANT } from "../theme/variants/p8p_dialog_actions_variants"; //Варианты действий диалога
+import { P8P_BUTTON_VARIANT } from "../theme/variants/p8p_button_variants"; //Варианты кнопок
+import { P8P_TYPOGRAPHY_VARIANT } from "../theme/p8p_typography"; //Варианты шрифтов
+import { P8P_ICON_BUTTON_VARIANT } from "../theme/variants/p8p_icon_button_variants"; //Варианты кнопок-иконок
+import { P8P_BOX_DIALOG_TITLE } from "../theme/styles/box"; //Стили контейнеров
//---------
//Константы
@@ -49,6 +53,8 @@ const P8PDialog = ({
inputs,
children,
okDisabled = false,
+ paddingDisabled = false,
+ actionsDisabled = false,
scrollContent = true,
onOk,
onCancel,
@@ -89,30 +95,47 @@ const P8PDialog = ({
//Формирование представления
return (
);
};
@@ -125,6 +148,8 @@ P8PDialog.propTypes = {
inputs: PropTypes.arrayOf(PropTypes.shape(P8P_INPUT)),
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
okDisabled: PropTypes.bool,
+ paddingDisabled: PropTypes.bool,
+ actionsDisabled: PropTypes.bool,
scrollContent: PropTypes.bool,
onOk: PropTypes.func,
onCancel: PropTypes.func,
diff --git a/app/components/p8p_header.js b/app/components/p8p_header.js
new file mode 100644
index 0000000..a075f9c
--- /dev/null
+++ b/app/components/p8p_header.js
@@ -0,0 +1,34 @@
+/*
+ Парус 8 - Панели мониторинга
+ Компонент: Заголовок
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box } from "@mui/material"; //Интерфейсные элементы
+import { P8P_BOX_HEADER } from "../theme/styles/box"; //Стили контейнеров
+
+//-----------
+//Тело модуля
+//-----------
+
+//Заголовок
+const P8PHeader = ({ children, isFixed }) => {
+ return {children};
+};
+
+//Контроль свойств - Заголовок
+P8PHeader.propTypes = {
+ children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),
+ isFixed: PropTypes.bool
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeader };
diff --git a/app/components/p8p_header/components/p8p_header_button_base.js b/app/components/p8p_header/components/p8p_header_button_base.js
new file mode 100644
index 0000000..5b64e57
--- /dev/null
+++ b/app/components/p8p_header/components/p8p_header_button_base.js
@@ -0,0 +1,79 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Базовая кнопка
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Icon, Typography, Stack, IconButton, Button } from "@mui/material"; //Интерфейсные элементы
+import { P8P_TYPOGRAPHY_VARIANT } from "../../../theme/p8p_typography"; //Варианты шрифтов
+import { P8P_TYPOGRAPHY_MAX_LINES } from "../../../theme/styles/typography"; //Стили текста
+import { P8P_STACK_HEADER_WITH_CLEAR } from "../../../theme/styles/stack"; // //Стили для групповой информации
+import { P8P_ICON_VARIANT } from "../../../theme/variants/p8p_icon_variants"; //Варианты иконок
+import { P8P_COMPONENT_SIZE } from "../../../theme/constants"; //Общие константы стилей
+import { P8P_BUTTON_VARIANT } from "../../../theme/variants/p8p_button_variants"; //Варианты кнопок
+import { P8PHeaderItem } from "./p8p_header_item"; //Элемент заголовка
+
+//-----------
+//Тело модуля
+//-----------
+
+//Базовая кнопка
+const P8PHeaderButtonBase = ({ icon, value, width, size = P8P_COMPONENT_SIZE.LARGE, iconSize, onClick, onClear, customButtonContent }) => {
+ console.log("rerender");
+ //При нажатии на кнопку
+ const handleClick = () => onClick && onClick();
+
+ //При необходимости очистки
+ const handleClear = () => onClear && onClear();
+
+ //Содержимое кнопки
+ const buttonConent = customButtonContent || (
+
+ {icon ? {icon} : null}
+ {value ? (
+
+ {value}
+
+ ) : null}
+
+ );
+
+ //Генерация содержимого
+ return (
+
+
+
+ {onClear ? (
+
+ cancel
+
+ ) : null}
+
+
+ );
+};
+
+//Контроль свойств - Базовая кнопка
+P8PHeaderButtonBase.propTypes = {
+ icon: PropTypes.string,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ iconSize: PropTypes.oneOf(Object.values(P8P_COMPONENT_SIZE)),
+ size: PropTypes.oneOf(Object.values(P8P_COMPONENT_SIZE)),
+ onClick: PropTypes.func.isRequired,
+ onClear: PropTypes.func,
+ customButtonContent: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)])
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderButtonBase };
diff --git a/app/components/p8p_header/components/p8p_header_filter_item.js b/app/components/p8p_header/components/p8p_header_filter_item.js
new file mode 100644
index 0000000..abea3b7
--- /dev/null
+++ b/app/components/p8p_header/components/p8p_header_filter_item.js
@@ -0,0 +1,78 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Элемент фильтра
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Icon, Stack, Typography, IconButton } from "@mui/material"; //Интерфейсные элементы
+import { P8P_TYPOGRAPHY_VARIANT } from "../../../theme/p8p_typography"; //Варианты шрифтов
+import { P8P_TYPOGRAPHY_MAX_LINES } from "../../../theme/styles/typography"; //Стили текста
+import { P8P_STACK_HEADER_FILTER, P8P_STACK_HEADER_FILTER_CONTAINER } from "../../../theme/styles/stack"; //Стили для групповой информации
+import { P8P_ICON_VARIANT } from "../../../theme/variants/p8p_icon_variants"; //Варианты иконок
+
+//-----------
+//Тело модуля
+//-----------
+
+//Элемент фильтра
+const P8PHeaderFilterItem = ({ filter, onClick, onDelete }) => {
+ //Признак возможности нажатия
+ const isClickable = onDelete || onClick ? true : false;
+
+ //При нажатии на содержимое
+ const handleFilterClick = () => onClick && onClick(filter);
+
+ //При удалении фильтра
+ const handleFilterDelete = () => onDelete && onDelete(filter);
+
+ //Генерация содержимого
+ return (
+
+ (onClick ? handleFilterClick : null)}>
+
+ {filter.caption}
+
+ {!React.isValidElement(filter.value) ? (
+
+ {filter.value}
+
+ ) : (
+ filter.value
+ )}
+
+ {onDelete ? (
+
+ cancel
+
+ ) : null}
+
+ );
+};
+
+//Контроль свойств - Элемент фильтра
+P8PHeaderFilterItem.propTypes = {
+ filter: PropTypes.object,
+ onClick: PropTypes.func,
+ onDelete: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderFilterItem };
diff --git a/app/components/p8p_header/components/p8p_header_item.js b/app/components/p8p_header/components/p8p_header_item.js
new file mode 100644
index 0000000..32d05c9
--- /dev/null
+++ b/app/components/p8p_header/components/p8p_header_item.js
@@ -0,0 +1,35 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Элемент заголовка
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box } from "@mui/material"; //Интерфейсные элементы
+import { P8P_BOX_HEADER_ITEM } from "../../../theme/styles/box"; //Стили контейнеров
+
+//-----------
+//Тело модуля
+//-----------
+
+//Элемент заголовка
+const P8PHeaderItem = ({ width, children }) => {
+ //Генерация содержимого
+ return {children};
+};
+
+//Контроль свойств - Элемент заголовка
+P8PHeaderItem.propTypes = {
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)])
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderItem };
diff --git a/app/components/p8p_header/p8p_header_button.js b/app/components/p8p_header/p8p_header_button.js
new file mode 100644
index 0000000..7b889f0
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_button.js
@@ -0,0 +1,39 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Кнопка
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { P8P_COMPONENT_SIZE } from "../../theme/constants"; //Общие константы стилей
+import { P8PHeaderButtonBase } from "./components/p8p_header_button_base"; //Базовая кнопка заголовка
+
+//-----------
+//Тело модуля
+//-----------
+
+//Кнопка
+const P8PHeaderButton = ({ icon, value, width, size = P8P_COMPONENT_SIZE.LARGE, iconSize, onClick }) => {
+ //Генерация содержимого
+ return ;
+};
+
+//Контроль свойств - Кнопка
+P8PHeaderButton.propTypes = {
+ icon: PropTypes.string,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ iconSize: PropTypes.oneOf(Object.values(P8P_COMPONENT_SIZE)),
+ size: PropTypes.oneOf(Object.values(P8P_COMPONENT_SIZE)),
+ onClick: PropTypes.func.isRequired
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderButton };
diff --git a/app/components/p8p_header/p8p_header_constants.js b/app/components/p8p_header/p8p_header_constants.js
new file mode 100644
index 0000000..33ef5b2
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_constants.js
@@ -0,0 +1,40 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Константы
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { STATE } from "../../../app.text"; //Текстовые ресурсы и константы
+
+//-----------
+//Тело модуля
+//-----------
+
+//Минимальная ширина при наличии элементов
+const P8P_HEADER_MIN_FILTER_WIDTH = 125;
+
+//Структура элемента описания фильтра
+const P8P_HEADER_FILTER_SHAPE = PropTypes.shape({
+ name: PropTypes.string,
+ caption: PropTypes.string.isRequired,
+ value: PropTypes.any,
+ width: PropTypes.string
+});
+
+//Состояния индикатора
+const P8P_HEADER_INDICATOR_STATE = {
+ UNDEFINED: STATE.UNDEFINED,
+ OK: STATE.OK,
+ WARN: STATE.WARN,
+ ERR: STATE.ERR
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8P_HEADER_MIN_FILTER_WIDTH, P8P_HEADER_FILTER_SHAPE, P8P_HEADER_INDICATOR_STATE };
diff --git a/app/components/p8p_header/p8p_header_date_picker.js b/app/components/p8p_header/p8p_header_date_picker.js
new file mode 100644
index 0000000..4d8d77a
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_date_picker.js
@@ -0,0 +1,112 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Выбор даты
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useRef } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import dayjs from "dayjs"; //Работа с датами
+import { TextField, Typography, Stack } from "@mui/material"; //Интерфейсные элементы
+import { P8P_TYPOGRAPHY_VARIANT } from "../../theme/p8p_typography"; //Варианты шрифтов
+import { P8P_TEXT_FIELD_VARIANT } from "../../theme/variants/p8p_text_field_variants"; //Варианты полей ввода
+import { P8P_TYPOGRAPHY_MAX_LINES } from "../../theme/styles/typography"; //Стили шрифтов
+import { formatDateRF, formatDateTimeRF } from "../../core/utils"; //Общие вспомогательные функции приложения
+import { P8P_COMPONENT_SIZE } from "../../theme/constants"; //Общие константы стилей
+import { P8PHeaderButtonBase } from "./components/p8p_header_button_base"; //Базовая кнопка заголовка
+
+//---------
+//Константы
+//---------
+
+//Типы даты
+const P8P_HEADER_DATE_PICKER_TYPE = {
+ DATE: "date",
+ DATETIME: "datetime-local",
+ MONTH: "month",
+ WEEK: "week",
+ TIME: "time"
+};
+
+//Форматирование значения даты
+const P8P_HEADER_DATE_PICKER_CONVERTER = {
+ [P8P_HEADER_DATE_PICKER_TYPE.DATE]: date => formatDateRF(date),
+ [P8P_HEADER_DATE_PICKER_TYPE.DATETIME]: date => formatDateTimeRF(date),
+ [P8P_HEADER_DATE_PICKER_TYPE.MONTH]: date => dayjs(date).locale("ru").format("MMMM YYYY"),
+ [P8P_HEADER_DATE_PICKER_TYPE.WEEK]: date => {
+ //Определяем неделю и год
+ const [year, week] = date.split("-W");
+ //Строковый формат
+ return `${week} неделя ${year}`;
+ },
+ [P8P_HEADER_DATE_PICKER_TYPE.TIME]: date => date
+};
+
+//-----------
+//Тело модуля
+//-----------
+
+//Выбор даты
+const P8PHeaderDatePicker = ({ value, placeholder, type = "date", width, onSelect, onClear }) => {
+ //Ссылка на поле ввода
+ const inputRef = useRef(null);
+
+ //При нажатии на кнопку выбора
+ const handleButtonClick = () => inputRef.current.showPicker();
+
+ //При смене значения
+ const onChange = e => onSelect && onSelect(e.target.value);
+
+ //Собственное представление кнопки
+ const buttonContent = (
+
+
+
+ {value ? P8P_HEADER_DATE_PICKER_CONVERTER[type](value) : placeholder}
+
+
+ );
+
+ //Генерация содержимого
+ return (
+
+ );
+};
+
+//Контроль свойств - Выбор даты
+P8PHeaderDatePicker.propTypes = {
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ placeholder: PropTypes.string.isRequired,
+ type: PropTypes.oneOf(Object.values(P8P_HEADER_DATE_PICKER_TYPE)),
+ width: PropTypes.string,
+ onSelect: PropTypes.func,
+ onClear: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderDatePicker, P8P_HEADER_DATE_PICKER_TYPE };
diff --git a/app/components/p8p_header/p8p_header_dictionary.js b/app/components/p8p_header/p8p_header_dictionary.js
new file mode 100644
index 0000000..ceba724
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_dictionary.js
@@ -0,0 +1,73 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Плавающая кнопка действия
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useContext } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { ApplicationCtx } from "../../context/application"; //Контекст приложения
+import { P8P_COMPONENT_SIZE } from "../../theme/constants"; //Общие константы стилей
+import { P8PHeaderButtonBase } from "./components/p8p_header_button_base"; //Общие константы стилей
+
+//---------
+//Константы
+//---------
+
+//Структура элемента входного параметра
+const P8P_HEADER_DICT_INPUT_PRMS = PropTypes.shape({
+ name: PropTypes.string.isRequired,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
+});
+
+//-----------
+//Тело модуля
+//-----------
+
+//Выбор значения из словаря
+const P8PHeaderDictionary = ({ value, placeholder, unitCode, showMethod = "main", inputParameters, width, onSelect, onClear }) => {
+ //Подключение к контексту приложения
+ const { pOnlineShowDictionary } = useContext(ApplicationCtx);
+
+ //При нажатии на кнопку
+ const handleButtonClick = () => {
+ pOnlineShowDictionary({
+ unitCode,
+ showMethod,
+ inputParameters,
+ callBack: res => res.success && onSelect && onSelect(res.outParameters)
+ });
+ };
+
+ //Формирование представления
+ return (
+
+ );
+};
+
+//Контроль свойств - Выбор значения из словаря
+P8PHeaderDictionary.propTypes = {
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ placeholder: PropTypes.string.isRequired,
+ unitCode: PropTypes.string.isRequired,
+ showMethod: PropTypes.string,
+ inputParameters: PropTypes.arrayOf(P8P_HEADER_DICT_INPUT_PRMS),
+ width: PropTypes.string,
+ onSelect: PropTypes.func,
+ onClear: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderDictionary };
diff --git a/app/components/p8p_header/p8p_header_field.js b/app/components/p8p_header/p8p_header_field.js
new file mode 100644
index 0000000..a69d55b
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_field.js
@@ -0,0 +1,82 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Поле ввода
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { TextField, InputAdornment, Icon, FormControl, IconButton } from "@mui/material"; //Интерфейсные элементы
+import { P8P_FORM_CONTROL_HEADER_FIELD } from "../../theme/styles/form_control"; //Стили контекста полей ввода
+import { P8P_TEXT_FIELD_VARIANT } from "../../theme/variants/p8p_text_field_variants"; //Варианты полей ввода
+import { P8PHeaderItem } from "./components/p8p_header_item"; //Элемент заголовка
+
+//---------
+//Константы
+//---------
+
+//Структура элемента доп. иконки поля ввода
+const P8P_HEADER_FIELD_ADORNMENT_SHAPE = PropTypes.shape({
+ icon: PropTypes.string.isRequired,
+ disabled: PropTypes.bool,
+ onClick: PropTypes.func
+});
+
+//-----------
+//Тело модуля
+//-----------
+
+//Поле ввода
+const P8PHeaderField = ({ value, placeholder, type = "text", endAdornments = [], width, onChange }) => {
+ //При смене значения
+ const handleChange = e => onChange && onChange(e.target.value);
+
+ //Генерация содержимого
+ return (
+
+
+ 0 ? (
+
+ {endAdornments.map((item, index) => (
+ item.onClick(e)} key={index} disabled={item.disabled}>
+ {item.icon}
+
+ ))}
+
+ ) : null
+ }}
+ />
+
+
+ );
+};
+
+//Контроль свойств - Поле ввода
+P8PHeaderField.propTypes = {
+ value: PropTypes.any,
+ placeholder: PropTypes.string.isRequired,
+ type: PropTypes.string,
+ endAdornments: PropTypes.arrayOf(P8P_HEADER_FIELD_ADORNMENT_SHAPE),
+ width: PropTypes.string,
+ onChange: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderField };
diff --git a/app/components/p8p_header/p8p_header_filter.js b/app/components/p8p_header/p8p_header_filter.js
new file mode 100644
index 0000000..88d3abf
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_filter.js
@@ -0,0 +1,125 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Фильтры
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box, Icon, Grid, IconButton, Popover, List, ListItem } from "@mui/material"; //Интерфейсные элементы
+import { P8P_GRID_VARIANT } from "../../theme/variants/p8p_grid_variants"; //Варианты сеток
+import { P8P_ICON_BUTTON_VARIANT } from "../../theme/variants/p8p_icon_button_variants"; //Варианты кнопок-иконок
+import { P8P_BOX_HEADER_FILTER, P8P_BOX_HEADER_FILTER_GRP } from "../../theme/styles/box"; //Стили контейнеров
+import { P8P_LIST_VARIANT } from "../../theme/variants/p8p_list_variants"; //Варианты списка
+import { P8P_LIST_ITEM_VARIANT } from "../../theme/variants/p8p_list_item_variants"; //Варианты элемента списка
+import { P8PHeaderFilterItem } from "./components/p8p_header_filter_item"; //Элемент фильтра заголовка
+import { useP8PHeaderFilter } from "./p8p_header_hooks"; //Вспомогательные хуки фильтра
+import { P8P_GRID_HEADER_FILTER_ITEM } from "../../theme/styles/grid"; //Стили адаптивного контейнера
+import { P8P_HEADER_FILTER_SHAPE } from "./p8p_header_constants"; //Константы заголовка
+
+//-----------
+//Тело модуля
+//-----------
+
+//Фильтры
+const P8PHeaderFilter = ({ filters, width, onClick, onDelete, showEmpty = true, maxDisplay = null }) => {
+ //Собственное состояние - состояние фильтра
+ const { gridRef, anchorEl, allowedFilters, visibleCount, isOverflowed, isLessMinWidth, handleFilterMoreOpen, handleFilterMoreClose } =
+ useP8PHeaderFilter({ filters, maxDisplay });
+
+ //Флаг отображения выпадающего списка
+ const open = Boolean(anchorEl);
+ //Флаг органичения отображения
+ const isLimited = maxDisplay > 0;
+ //Скрытые фильтры
+ const hiddenFilters = filters.slice(visibleCount);
+
+ //При удалении фильтра
+ const handleFilterDelete = filter => onDelete && onDelete({ filter });
+
+ //При нажатии на фильтр
+ const handleFilterClick = filter => onClick && onClick({ filter });
+
+ //Генерация содержимого
+ return (
+ <>
+ {showEmpty || allowedFilters.length > 0 ? (
+
+
+
+ {allowedFilters.map((filter, index) => (
+
+
+
+ ))}
+
+
+ {isOverflowed && (
+
+ tune
+
+ )}
+
+ ) : null}
+
+
+ {hiddenFilters.map((filter, index) => (
+
+
+
+ ))}
+
+
+ >
+ );
+};
+
+//Контроль свойств - Фильтры
+P8PHeaderFilter.propTypes = {
+ filters: PropTypes.arrayOf(P8P_HEADER_FILTER_SHAPE),
+ width: PropTypes.string,
+ onClick: PropTypes.func,
+ onDelete: PropTypes.func,
+ showEmpty: PropTypes.bool,
+ maxDisplay: PropTypes.number
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderFilter };
diff --git a/app/components/p8p_header/p8p_header_hooks.js b/app/components/p8p_header/p8p_header_hooks.js
new file mode 100644
index 0000000..0cfb305
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_hooks.js
@@ -0,0 +1,121 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Хуки для заголовка
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import { useState, useEffect, useCallback, useRef, useMemo } from "react"; //Классы React
+import { P8P_HEADER_MIN_FILTER_WIDTH } from "./p8p_header_constants"; //Константы заголовка
+
+//-----------
+//Тело модуля
+//-----------
+
+//Кастомный хук для определения информации об отображении
+const useP8PHeaderVisibleInfo = (containerRef, maxDisplay, totalFilters) => {
+ //Отображаемое количество
+ const [visibleCount, setVisibleCount] = useState(maxDisplay > 0 ? maxDisplay : 0);
+ //Признак переполненности
+ const [isOverflowed, setIsOverflowed] = useState(false);
+ //Признак уменьшения меньше минимального значения
+ const [isLessMinWidth, setIsLessMinWidth] = useState(false);
+
+ //Пересчет количество отображаемых
+ const recalcVisibleCount = useCallback(container => {
+ //Определяем дочерние элементы
+ const items = container.children;
+ //Определяем параметры контейнера
+ const containerRect = container.getBoundingClientRect();
+ //Если блок меньше минимального значения
+ if (containerRect.width < P8P_HEADER_MIN_FILTER_WIDTH && items.length > 0) {
+ //Информируем, что невозможно показать
+ setVisibleCount(0);
+ setIsOverflowed(true);
+ setIsLessMinWidth(true);
+ return;
+ }
+ //Обнуляем счетчик видимых
+ let visible = 0;
+ //Обходим дочерние элменты
+ for (let i = 0; i < items.length; i++) {
+ //Определяем параметры элемента
+ const itemRect = items[i].getBoundingClientRect();
+ //Проверяем, полностью ли элемент виден в контейнере
+ if (itemRect.bottom <= containerRect.bottom) {
+ visible++;
+ } else {
+ //Если один элемент скрыт, то и все последующие скрыты (при row-direction)
+ break;
+ }
+ }
+ //Устанавливаем отображаемых
+ setVisibleCount(visible);
+ setIsOverflowed(visible < items.length);
+ setIsLessMinWidth(false);
+ }, []);
+
+ //При открытии страницы
+ useEffect(() => {
+ //Определяем контейнер
+ const container = containerRef.current;
+ //Если контейнер не определен или установлено максимально отображение - не отслеживаем
+ if (!container || maxDisplay > 0) {
+ setIsOverflowed(maxDisplay < totalFilters);
+ return;
+ }
+ //Пересчет количество отображаемых
+ recalcVisibleCount(container);
+ //Определяем отслеживание
+ const observer = new ResizeObserver(() => {
+ //Пересчет количество отображаемых
+ recalcVisibleCount(container);
+ });
+ //Подключаем отслеживание
+ observer.observe(container);
+ //При закрытии компонента
+ return () => observer.disconnect();
+ }, [containerRef, maxDisplay, recalcVisibleCount, totalFilters]);
+ //Возвращаем данные
+ return { visibleCount, isOverflowed, isLessMinWidth };
+};
+
+//Хук состояния фильтра
+const useP8PHeaderFilter = ({ filters, maxDisplay }) => {
+ //Собственное состояние - контейнер элементов
+ const gridRef = useRef(null);
+
+ //Собственное состояние - элемент выпадающего списка
+ const [anchorEl, setAnchorEl] = useState(null);
+ //Собственное состояние - информация об отображении
+ const { visibleCount, isOverflowed, isLessMinWidth } = useP8PHeaderVisibleInfo(gridRef, maxDisplay, filters.length);
+
+ //Отображаемые фильтры
+ const allowedFilters = useMemo(() => {
+ if (Array.isArray(filters) && filters.length > 0) {
+ return filters.slice(0, maxDisplay || filters.length);
+ } else {
+ return [];
+ }
+ }, [filters, maxDisplay]);
+
+ //По нажатию на меню скрытых элементов
+ const handleFilterMoreOpen = event => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ //При закрытии меню скрытых элементов
+ const handleFilterMoreClose = () => {
+ setAnchorEl(null);
+ };
+
+ return { gridRef, anchorEl, allowedFilters, visibleCount, isOverflowed, isLessMinWidth, handleFilterMoreOpen, handleFilterMoreClose };
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { useP8PHeaderFilter };
diff --git a/app/components/p8p_header/p8p_header_indicator.js b/app/components/p8p_header/p8p_header_indicator.js
new file mode 100644
index 0000000..ba8cee2
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_indicator.js
@@ -0,0 +1,63 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Индикатор
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Stack, Typography } from "@mui/material"; //Интерфейсные элементы
+import { P8P_STACK_HEADER_INDICATOR } from "../../theme/styles/stack"; //Стили для групповой информации
+import { TEXTS } from "../../../app.text"; //Текстовые ресурсы и константы
+import { P8P_TYPOGRAPHY_VARIANT } from "../../theme/p8p_typography"; //Варианты шрифтов
+import { P8P_HEADER_INDICATOR_STATE } from "./p8p_header_constants"; //Константы заголовка
+import { P8P_TYPOGRAPY_HDR_INDICATOR } from "../../theme/styles/typography"; //Стили текста
+import { P8PHeaderItem } from "./components/p8p_header_item"; //Элемент заголовка
+
+//-----------
+//Тело модуля
+//-----------
+
+//Индикатор
+const P8PHeaderIndicator = ({ caption, value, state = P8P_HEADER_INDICATOR_STATE.UNDEFINED, disableCaptionColor = false, width, color, onClick }) => {
+ //При нажатии на текст
+ const handleClick = () => onClick && onClick({ caption, value });
+
+ //Генерация содержимого
+ return (
+
+
+
+ {caption}
+
+
+ {[undefined, null, ""].includes(value) ? TEXTS.NO_DATA_FOUND_SHORT : value}
+
+
+
+ );
+};
+
+//Контроль свойств - Индикатор
+P8PHeaderIndicator.propTypes = {
+ caption: PropTypes.string.isRequired,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ state: PropTypes.oneOf(Object.values(P8P_HEADER_INDICATOR_STATE)),
+ disableCaptionColor: PropTypes.bool,
+ width: PropTypes.string,
+ color: PropTypes.string,
+ onClick: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderIndicator };
diff --git a/app/components/p8p_header/p8p_header_selector.js b/app/components/p8p_header/p8p_header_selector.js
new file mode 100644
index 0000000..957b63b
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_selector.js
@@ -0,0 +1,103 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Выбор из выпадающего списка
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useMemo } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { FormControl, Select, MenuItem, Stack, Checkbox } from "@mui/material"; //Интерфейсные элементы
+import { P8P_SELECT_VARIANT } from "../../theme/variants/p8p_select_variants"; //Варианты полей выбора (Select)
+import { P8P_MENU_ITEM_VARIANT } from "../../theme/variants/p8p_menu_item_variants"; //Варианты элементов меню
+import { P8P_FORM_CONTROL_HEADER_SELECTOR } from "../../theme/styles/form_control"; //Стили контекста полей ввода
+import { P8PHeaderItem } from "./components/p8p_header_item"; //Элемент заголовка
+
+//---------
+//Константы
+//---------
+
+//Структура элемента выпадающего списка
+const P8P_HEADER_SELECTOR_OPTION = PropTypes.shape({
+ value: PropTypes.any.isRequired,
+ title: PropTypes.string.isRequired
+});
+
+//-----------
+//Тело модуля
+//-----------
+
+//Выбор из выпадающего списка
+const P8PHeaderSelector = ({ value, placeholder, options = [], multiple = false, width, onSelect }) => {
+ //При нажатии на текст
+ const handleChange = e => onSelect && onSelect(e.target.value);
+
+ //Отображаемое значение
+ const displayValue = useMemo(() => {
+ //Если это множественный выбор
+ if (multiple) {
+ //Нет значения
+ if (!value || value.length === 0) return placeholder;
+ //Собираем выбранные значения
+ return options
+ .filter(option => value.includes(option.value))
+ .map(option => option.title)
+ .join(", ");
+ } else {
+ //Нет значения
+ if (!value) return placeholder;
+ //Определяем отображаемое
+ const option = options.find(option => option.value === value);
+ return option ? option.title : placeholder;
+ }
+ }, [value, placeholder, options, multiple]);
+
+ //Генерация содержимого
+ return (
+
+
+
+
+
+ );
+};
+
+//Контроль свойств - Выбор из выпадающего списка
+P8PHeaderSelector.propTypes = {
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]),
+ placeholder: PropTypes.string.isRequired,
+ options: PropTypes.arrayOf(P8P_HEADER_SELECTOR_OPTION).isRequired,
+ multiple: PropTypes.bool,
+ width: PropTypes.string,
+ onSelect: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderSelector };
diff --git a/app/components/p8p_header/p8p_header_text.js b/app/components/p8p_header/p8p_header_text.js
new file mode 100644
index 0000000..8112b32
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_text.js
@@ -0,0 +1,63 @@
+/*
+ Парус 8 - Панели мониторинга - Заголовок
+ Компонент: Текст
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Typography, Stack } from "@mui/material"; //Интерфейсные элементы
+import { P8P_TYPOGRAPHY_VARIANT } from "../../theme/p8p_typography"; //Варианты шрифтов
+import { P8P_TYPOGRAPHY_MAX_LINES } from "../../theme/styles/typography"; //Стили текста
+import { P8P_STACK_HEADER_TEXT } from "../../theme/styles/stack"; //Стили продвинутого контейнера
+import { P8PHeaderItem } from "./components/p8p_header_item"; //Элемент заголовка
+
+//-----------
+//Тело модуля
+//-----------
+
+//Текст
+const P8PHeaderText = ({ title, subTitle, width, onClick, children }) => {
+ //При нажатии на текст
+ const handleClick = () => onClick && onClick({ title, subTitle });
+
+ //Определение максимального количества доступных строк
+ const maxLines = subTitle ? 1 : 2;
+
+ //Отображение по умолчанию
+ const defaultView = (
+
+
+ {title}
+
+ {subTitle ? (
+
+ {subTitle}
+
+ ) : null}
+
+ );
+
+ //Содержимое компонента
+ const content = children || defaultView;
+ //Генерация содержимого
+ return {content};
+};
+
+//Контроль свойств - Текст
+P8PHeaderText.propTypes = {
+ title: PropTypes.string,
+ subTitle: PropTypes.string,
+ width: PropTypes.string,
+ onClick: PropTypes.func,
+ children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PHeaderText };
diff --git a/app/components/p8p_header/p8p_header_utils.js b/app/components/p8p_header/p8p_header_utils.js
new file mode 100644
index 0000000..5d9231d
--- /dev/null
+++ b/app/components/p8p_header/p8p_header_utils.js
@@ -0,0 +1,200 @@
+import React, { useState } from "react";
+
+import { hasValue } from "../../core/utils";
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Stack, Chip, Typography, Box } from "@mui/material"; //Интерфейсные компоненты
+import { P8P_DATA_TYPES } from "../../core/data_types";
+import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper";
+import { P8P_BOX_HEADER_FILTER_CUSTOM } from "../../theme/styles/box";
+import { P8P_TYPOGRAPHY_VARIANT } from "../../theme/p8p_typography";
+import { P8P_TYPOGRAPHY_MAX_LINES } from "../../theme/styles/typography";
+import { P8P_STACK_HEADER_FILTER } from "../../theme/styles/stack";
+import { P8PTableColumnFilterDialog } from "../p8p_table/p8p_table_column_filter_dialog";
+
+const FilterComponent = ({ filter, columnDef, valueFromCaption, valueToCaption, valueFormatter, onFilterChanged }) => {
+ //Собственное состояние - фильтруемая колонка
+ const [filterColumn, setFilterColumn] = useState(null);
+ const isClickable = false;
+
+ //Значения фильтра фильтруемой колонки
+ const [filterColumnFrom, filterColumnTo] = filterColumn
+ ? (() => {
+ return filter ? [filter.from == null ? "" : filter.from, filter.to == null ? "" : filter.to] : ["", ""];
+ })()
+ : ["", ""];
+
+ //Отработка ввода значения фильтра колонки
+ const handleFilterOk = (columnName, from, to) => {
+ if (onFilterChanged) onFilterChanged({ columnName, from: from === "" ? null : from, to: to === "" ? null : to });
+ setFilterColumn(null);
+ };
+
+ //Отработка очистки значения фильтра колонки
+ const handleFilterClear = columnName => {
+ if (onFilterChanged) onFilterChanged({ columnName, from: null, to: null });
+ setFilterColumn(null);
+ };
+
+ //Отработка отмены ввода значения фильтра колонки
+ const handleFilterCancel = () => {
+ setFilterColumn(null);
+ };
+
+ return (
+ <>
+
+
+ {columnDef.name}
+
+ setFilterColumn(columnDef.name)}>
+
+ {hasValue(filter.from) && !columnDef.values && columnDef.dataType != P8P_DATA_TYPES.STR
+ ? `${valueFromCaption.toLowerCase()} `
+ : null}
+ {hasValue(filter.from) ? (valueFormatter ? valueFormatter({ value: filter.from, columnDef }) : filter.from) : null}
+ {hasValue(filter.to) && !columnDef.values && columnDef.dataType != P8P_DATA_TYPES.STR
+ ? ` ${valueToCaption.toLowerCase()} `
+ : null}
+ {hasValue(filter.to) ? (valueFormatter ? valueFormatter({ value: filter.to, columnDef }) : filter.to) : null}
+
+
+
+ {filterColumn ? (
+
+ ) : null}
+ >
+ );
+};
+
+//Контроль свойств - Текст
+FilterComponent.propTypes = {
+ filter: PropTypes.object,
+ columnDef: PropTypes.object,
+ valueFromCaption: PropTypes.string,
+ valueToCaption: PropTypes.string,
+ valueFormatter: PropTypes.func,
+ onFilterChanged: PropTypes.func
+};
+
+//Форматирование фильтра таблицы
+const formatFilterDataGrid = ({
+ filters,
+ columnsDef,
+ valueFromCaption = P8P_DATA_GRID_CONFIG_PROPS.valueFromCaption,
+ valueToCaption = P8P_DATA_GRID_CONFIG_PROPS.valueToCaption,
+ valueFormatter,
+ onClick,
+ onFilterChanged,
+ objectsCopier
+}) => {
+ //Форматируем фильтры под заголовок
+ const formattedFilters = filters.map(filter => {
+ //Определяем колонку
+ const columnDef = columnsDef.find(columnDef => columnDef.name == filter.name);
+ //Формирование содержимого фильтра
+ const buildFilterContent = () => {
+ //Инициализируем части
+ const parts = [];
+ //Если есть "Значение с"
+ if (hasValue(filter.from)) {
+ //Если необходимо добавить префикс
+ if (!columnDef.values && columnDef.dataType != P8P_DATA_TYPES.STR) {
+ parts.push(`${valueFromCaption.toLowerCase()} `);
+ }
+ //Добавляем "Значение с"
+ parts.push(valueFormatter ? valueFormatter({ value: filter.from, columnDef }) : filter.from);
+ }
+ //Если есть "Значение по"
+ if (hasValue(filter.to)) {
+ //Если необходимо добавить префикс
+ if (!columnDef.values && columnDef.dataType != P8P_DATA_TYPES.STR) {
+ parts.push(` ${valueToCaption.toLowerCase()} `);
+ }
+ //Добавляем "Значение по"
+ parts.push(valueFormatter ? valueFormatter({ value: filter.to, columnDef }) : filter.to);
+ }
+ //Возвращаем массив элементов
+ return parts;
+ };
+
+ //При изменении состояния фильтра
+ const handleFilterChanged = ({ columnName, from, to }) => {
+ let newFilters = objectsCopier(filters);
+ let curFilter = newFilters.find(f => f.name == columnName);
+ if (from == null && to == null && curFilter) newFilters.splice(newFilters.indexOf(curFilter), 1);
+ if ((from != null || to != null) && !curFilter) newFilters.push({ name: columnName, from, to });
+ if ((from != null || to != null) && curFilter) {
+ curFilter.from = from;
+ curFilter.to = to;
+ }
+ if (onFilterChanged) onFilterChanged({ filters: newFilters });
+ };
+ //Инициализируем содержмое значения
+ const content = buildFilterContent();
+ //Возвращаем результат
+ return {
+ caption: columnDef.caption,
+ // from: valueFormatter ? (
+ //
+ // {React.Children.toArray(content)}
+ //
+ // ) : (
+ // content.join("")
+ // ),
+ from: (
+
+ ),
+ customView: (
+
+ ),
+ onClick: () => onClick && onClick(columnDef.name)
+ };
+ });
+ return formattedFilters;
+};
+
+export const P8P_HEADER_FILTER_FORMAT = {
+ DATA_GRID: ({
+ filters,
+ columnsDef,
+ valueFromCaption = P8P_DATA_GRID_CONFIG_PROPS.valueFromCaption,
+ valueToCaption = P8P_DATA_GRID_CONFIG_PROPS.valueToCaption,
+ valueFormatter,
+ onClick,
+ onFilterChanged,
+ objectsCopier
+ }) => formatFilterDataGrid({ filters, columnsDef, valueFromCaption, valueToCaption, valueFormatter, onClick, onFilterChanged, objectsCopier })
+};
diff --git a/app/theme/constants.js b/app/theme/constants.js
new file mode 100644
index 0000000..87bc1de
--- /dev/null
+++ b/app/theme/constants.js
@@ -0,0 +1,15 @@
+/*
+ Парус 8 - Панели мониторинга
+ Общие константы стилей
+*/
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+//Размеры компонента
+export const P8P_COMPONENT_SIZE = {
+ SMALL: "small",
+ MEDIUM: "medium",
+ LARGE: "large"
+};
diff --git a/app/theme/p8p_components.js b/app/theme/p8p_components.js
index bb1d27a..59cecfc 100644
--- a/app/theme/p8p_components.js
+++ b/app/theme/p8p_components.js
@@ -18,10 +18,12 @@ import { P8P_ICON_OVERRIDES } from "./variants/p8p_icon_variants"; //Расши
import { P8P_ICON_BUTTON_OVERRIDES } from "./variants/p8p_icon_button_variants"; //Расширение IconButton
import { P8P_TEXT_FIELD_OVERRIDES } from "./variants/p8p_text_field_variants"; //Расширение TextField
import { P8P_LIST_OVERRIDES } from "./variants/p8p_list_variants"; //Расширение List
+import { P8P_LIST_ITEM_OVERRIDES } from "./variants/p8p_list_item_variants"; //Расширение ListItem
import { P8P_LIST_ITEM_TEXT_OVERRIDES } from "./variants/p8p_list_item_text_variants"; //Расширение ListItemText
import { P8P_DIALOG_TITLE_OVERRIDES } from "./variants/p8p_dialog_title_variants"; //Расширение DialogTitle
import { P8P_DIALOG_CONTENT_OVERRIDES } from "./variants/p8p_dialog_content_variants"; //Расширение DialogContent
import { P8P_DIALOG_CONTENT_TEXT_OVERRIDES } from "./variants/p8p_dialog_content_text_variants"; //Расширение DialogContentText
+import { P8P_DIALOG_ACTIONS_OVERRIDES } from "./variants/p8p_dialog_actions_variants"; //Расширение DialogActions
import { P8P_DRAWER_OVERRIDES } from "./variants/p8p_drawer_variants"; //Расширение Drawer
import { P8P_APP_BAR_OVERRIDES } from "./variants/p8p_app_bar_variants"; //Расширение AppBar
import { P8P_GRID_OVERRIDES } from "./variants/p8p_grid_variants"; //Расширение Grid
@@ -32,6 +34,7 @@ import { P8P_INPUT_OVERRIDES } from "./variants/p8p_input_variants"; //Расш
import { P8P_INPUT_LABEL_OVERRIDES } from "./variants/p8p_input_label_variants"; //Расширение InputLable
import { P8P_MENU_ITEM_OVERRIDES } from "./variants/p8p_menu_item_variants"; //Расширение MenuItem
import { P8P_AUTOCOMPLETE_OVERRIDES } from "./variants/p8p_autocomplete_variants"; //Расширение Autocomplete
+import { P8P_FAB_OVERRIDES } from "./variants/p8p_fab_variants"; //Расширение Fab
//----------------
//Интерфейс модуля
@@ -52,7 +55,9 @@ export const P8P_COMPONENTS = {
MuiDialogTitle: P8P_DIALOG_TITLE_OVERRIDES,
MuiDialogContent: P8P_DIALOG_CONTENT_OVERRIDES,
MuiDialogContentText: P8P_DIALOG_CONTENT_TEXT_OVERRIDES,
+ MuiDialogActions: P8P_DIALOG_ACTIONS_OVERRIDES,
MuiList: P8P_LIST_OVERRIDES,
+ MuiListItem: P8P_LIST_ITEM_OVERRIDES,
MuiListItemText: P8P_LIST_ITEM_TEXT_OVERRIDES,
MuiDrawer: P8P_DRAWER_OVERRIDES,
MuiAppBar: P8P_APP_BAR_OVERRIDES,
@@ -63,5 +68,6 @@ export const P8P_COMPONENTS = {
MuiInputLabel: P8P_INPUT_LABEL_OVERRIDES,
MuiInput: P8P_INPUT_OVERRIDES,
MuiMenuItem: P8P_MENU_ITEM_OVERRIDES,
- MuiAutocomplete: P8P_AUTOCOMPLETE_OVERRIDES
+ MuiAutocomplete: P8P_AUTOCOMPLETE_OVERRIDES,
+ MuiFab: P8P_FAB_OVERRIDES
};
diff --git a/app/theme/p8p_palette.js b/app/theme/p8p_palette.js
index d4fcb21..4994351 100644
--- a/app/theme/p8p_palette.js
+++ b/app/theme/p8p_palette.js
@@ -57,6 +57,11 @@ export const P8P_PALETTE = {
secondary: "#F8FAFD",
tableHeader: "#E6EAF3"
},
+ P8PScroll: {
+ track: "#EBEBEB",
+ thumb: "#b4b4b4",
+ hover: "#808080"
+ },
P8PAction: {
active: "#0000008a"
},
@@ -68,5 +73,12 @@ export const P8P_PALETTE = {
main: "#1976d2",
hover: "#c3e1ff"
},
+ P8PHeader: {
+ text: "#37474F",
+ textLink: "#0F71BD",
+ link: "#005EA6",
+ border: "#AFB9CB",
+ background: "#F5F7F7"
+ },
P8PPurple: "#5e35b1"
};
diff --git a/app/theme/p8p_typography.js b/app/theme/p8p_typography.js
index 5651507..18c73fb 100644
--- a/app/theme/p8p_typography.js
+++ b/app/theme/p8p_typography.js
@@ -176,6 +176,13 @@ export const P8P_TYPOGRAPHY = {
lineHeight: "140%",
letterSpacing: "0.1px"
},
+ P8PHeader: {
+ ...P8PFontMontserrat,
+ fontWeight: "600",
+ fontSize: "15px",
+ lineHeight: "140%",
+ letterSpacing: "-0.02em"
+ },
P8PDesktopGroup: {
fontFamily: "tahoma, arial, verdana, sans-serif!important",
fontSize: "13px !important",
@@ -212,6 +219,7 @@ export const P8P_TYPOGRAPHY_VARIANT = {
INPUT_LABEL: "P8PInputLabel",
BODY2_BOLD: "P8PBody2Bold",
TITLE: "P8PTitle",
+ HEADER: "P8PHeader",
DESKTOP_GROUP: "P8PDesktopGroup",
DESKTOP_CAPTION: "P8PDesktopCaption"
};
diff --git a/app/theme/styles/box.js b/app/theme/styles/box.js
index 5fa3a27..4a9b09d 100644
--- a/app/theme/styles/box.js
+++ b/app/theme/styles/box.js
@@ -7,7 +7,8 @@
//Подключение библиотек
//---------------------
-import { P8P_COMPONENT_WIDTH, P8P_COMPONENT_HEIGHT, P8P_SCROLL_AUTO } from "./common"; //Стили - общие
+import { hasValue } from "../../core/utils";
+import { P8P_SCROLL_AUTO } from "./common"; //Стили - общие
import { useTheme } from "@mui/material/styles"; //Хук темы приложения
//---------
@@ -41,21 +42,40 @@ export const P8P_BOX_CENTER_BETWEEN = {
//Контейнер плавающий, элементы по центру
export const P8P_BOX_CENTER = { display: "flex", alignItems: "center", justifyContent: "center" };
+//Контейнер с возможностью нажатия
+export const P8P_BOX_CLICKABLE = {
+ cursor: "pointer",
+ "&:hover": {
+ opacity: 0.8
+ }
+};
+
+//Контейнер для заголовка диалога
+export const P8P_BOX_DIALOG_TITLE = {
+ display: "grid",
+ gridTemplateColumns: "1fr auto 1fr",
+ alignItems: "center",
+ gap: "16px"
+};
+
//---------
//Стили приложения
//---------
//Контейнер рабочего пространства
export const P8P_BOX_APP_WORKSPACE = {
- ...P8P_COMPONENT_WIDTH({ width: "100vw" }),
- //width: "100vw",
- ...P8P_BOX_CENTER_BETWEEN
+ width: "100vw",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "space-between"
};
//Меню панелей - контейнер грида
export const P8P_BOX_PANELS_MENU_CONTAINER = {
- ...P8P_BOX_CENTER_START,
- ...P8P_COMPONENT_HEIGHT({ minHeight: "100vh" })
+ minHeight: "100vh",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start"
};
//---------
@@ -64,16 +84,16 @@ export const P8P_BOX_PANELS_MENU_CONTAINER = {
//Список настроек панели
export const P8P_BOX_SETTINGS_LIST = {
- ...P8P_COMPONENT_WIDTH({ width: "520px" }),
- ...P8P_COMPONENT_HEIGHT({ height: "500px" }),
- ...P8P_SCROLL_AUTO
+ ...P8P_SCROLL_AUTO,
+ width: "520px",
+ height: "500px"
};
//Список панелей настроек панелей
export const P8P_BOX_SETTINGS_PANELS = {
- ...P8P_COMPONENT_WIDTH({ width: "300px" }),
- ...P8P_COMPONENT_HEIGHT({ height: "500px" }),
- ...P8P_SCROLL_AUTO
+ ...P8P_SCROLL_AUTO,
+ width: "300px",
+ height: "500px"
};
//Контейнер настроек панелей
@@ -89,8 +109,7 @@ export const P8P_BOX_SETTINGS_CONTAINER = {
//Контейнер диаграмы Ганта
export const P8P_BOX_GANTT = ({ noData, zoomBarHeight, titleHeight }) => ({
- ...P8P_COMPONENT_HEIGHT({ height: `calc(100% - ${zoomBarHeight ? zoomBarHeight : "0px"} - ${titleHeight ? titleHeight : "0px"})` }),
- //height: `calc(100% - ${zoomBarHeight ? zoomBarHeight : "0px"} - ${titleHeight ? titleHeight : "0px"})`,
+ height: `calc(100% - ${zoomBarHeight ? zoomBarHeight : "0px"} - ${titleHeight ? titleHeight : "0px"})`,
display: noData ? "none" : ""
});
@@ -100,11 +119,10 @@ export const P8P_BOX_GANTT = ({ noData, zoomBarHeight, titleHeight }) => ({
//Контейнер циклограммы
export const P8P_BOX_CYCLOGRAM = ({ noData, zoomBarHeight, titleHeight }) => ({
+ height: `calc(100% - ${zoomBarHeight ? zoomBarHeight : "0px"} - ${titleHeight ? titleHeight : "0px"})`,
position: "relative",
overflow: "auto",
padding: "0px 8px",
- ...P8P_COMPONENT_HEIGHT({ height: `calc(100% - ${zoomBarHeight ? zoomBarHeight : "0px"} - ${titleHeight ? titleHeight : "0px"})` }),
- //height: `calc(100% - ${zoomBarHeight ? zoomBarHeight : "0px"} - ${titleHeight ? titleHeight : "0px"})`,
display: noData ? "none" : ""
});
@@ -124,9 +142,11 @@ export const P8P_BOX_CYCLOGRAM_GROUP = ({ height }) => {
const theme = useTheme();
//Возвращаем стиль
return {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
border: "1px solid",
backgroundColor: theme.palette.P8PCyclogram.group,
- ...P8P_BOX_CENTER,
height
};
};
@@ -150,3 +170,67 @@ export const P8P_BOX_CYCLOGRAM_TASK = ({ lineHeight, bgColor, textColor, highlig
}
};
};
+
+//---------
+//Стили заголовка
+//---------
+
+//Контейнер заголовка
+export const P8P_BOX_HEADER = ({ isFixed }) => ({
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "flex-start",
+ padding: "0px",
+ width: "100vw",
+ height: "64px",
+ background: "P8PHeader.background",
+ boxShadow: "0px 6px 6px rgba(182, 189, 201, 0.17), 0px 1px 3px rgba(182, 189, 201, 0.2)",
+ position: isFixed ? "fixed" : "relative",
+ overflow: "hidden"
+});
+
+//Контейнер элемента заголовка
+export const P8P_BOX_HEADER_ITEM = ({ width, minWidth, isClickable }) => ({
+ height: "100%",
+ width,
+ minWidth,
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ flexDirection: "column",
+ borderRight: "1px solid",
+ borderColor: "P8PHeader.border",
+ ...(!hasValue(width) ? { flex: 1 } : {}),
+ ...(isClickable ? { ...P8P_BOX_CLICKABLE } : {})
+});
+
+//Контейнер фильтров
+export const P8P_BOX_HEADER_FILTER = ({ width, isLimited, isLessMinWidth }) => ({
+ ...P8P_BOX_HEADER_ITEM({ width }),
+ minWidth: isLimited ? "max-content" : isLessMinWidth ? "73px" : null,
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ flexDirection: "row",
+ overflow: "hidden",
+ padding: "0px 16px"
+});
+
+//Контейнер списка фильтров
+export const P8P_BOX_HEADER_FILTER_GRP = {
+ minWidth: "0px",
+ height: "100%",
+ alignContent: "center",
+ flex: "1 1 0",
+ whiteSpace: "nowrap",
+ textOverflow: "ellipsis"
+};
+
+//Контейнер для кастомного фильтра
+export const P8P_BOX_HEADER_FILTER_CUSTOM = {
+ display: "-webkit-box",
+ overflow: "hidden",
+ WebkitBoxOrient: "vertical",
+ WebkitLineClamp: 1,
+ color: "P8PText.primary"
+};
diff --git a/app/theme/styles/common.js b/app/theme/styles/common.js
index 475aa84..f1b5b34 100644
--- a/app/theme/styles/common.js
+++ b/app/theme/styles/common.js
@@ -3,12 +3,6 @@
Вспомогательные стили - общие
*/
-//---------------------
-//Подключение библиотек
-//---------------------
-
-import { APP_STYLES } from "../../../app.styles"; //Типовые стили
-
//----------------
//Интерфейс модуля
//----------------
@@ -27,10 +21,10 @@ export const P8P_COMPONENT_HEIGHT = ({ height, minHeight, maxHeight }) => ({
...(maxHeight ? { maxHeight } : {})
});
-//Отображаемый скролл
-export const P8P_SCROLL_AUTO = {
- overflow: "auto",
- ...APP_STYLES.SCROLL
+//Полная ширина и высота
+export const P8P_COMPONENT_FULL_SIZE = {
+ height: "100%",
+ width: "100%"
};
//Отсутствие отступов
@@ -38,6 +32,12 @@ export const P8P_COMPONENT_ZERO_PADDING = {
padding: "0px"
};
+//Блок с возможностью нажатия
+export const P8P_COMPONENT_CLICKABLE_OPACITY = {
+ cursor: "pointer",
+ "&:hover": { backgroundColor: "inherit", opacity: "0.8" }
+};
+
//Стили
export const P8P_SCROLL = {
"&::-webkit-scrollbar": {
@@ -46,13 +46,19 @@ export const P8P_SCROLL = {
},
"&::-webkit-scrollbar-track": {
borderRadius: "8px",
- backgroundColor: "#EBEBEB"
+ backgroundColor: "P8PScroll.track"
},
"&::-webkit-scrollbar-thumb": {
borderRadius: "8px",
- backgroundColor: "#b4b4b4"
+ backgroundColor: "P8PScroll.thumb"
},
"&::-webkit-scrollbar-thumb:hover": {
- backgroundColor: "#808080"
+ backgroundColor: "P8PScroll.hover"
}
};
+
+//Отображаемый скролл
+export const P8P_SCROLL_AUTO = {
+ overflow: "auto",
+ ...P8P_SCROLL
+};
diff --git a/app/theme/styles/form_control.js b/app/theme/styles/form_control.js
new file mode 100644
index 0000000..c770b0f
--- /dev/null
+++ b/app/theme/styles/form_control.js
@@ -0,0 +1,30 @@
+/*
+ Парус 8 - Панели мониторинга
+ Вспомогательные стили FormControl
+*/
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+//---------
+//Стили заголовка
+//---------
+
+//Поле ввода заголовка
+export const P8P_FORM_CONTROL_HEADER_FIELD = {
+ height: "100%",
+ width: "100%",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ margin: "0px",
+ padding: "0px 16px"
+};
+
+//Поле выбора заголовка
+export const P8P_FORM_CONTROL_HEADER_SELECTOR = {
+ height: "100%",
+ width: "100%",
+ padding: "0px 8px"
+};
diff --git a/app/theme/styles/grid.js b/app/theme/styles/grid.js
new file mode 100644
index 0000000..47e88df
--- /dev/null
+++ b/app/theme/styles/grid.js
@@ -0,0 +1,19 @@
+/*
+ Парус 8 - Панели мониторинга
+ Вспомогательные стили Grid
+*/
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+//---------
+//Стили заголовка
+//---------
+
+//Элемент списка фильтров заголовка
+export const P8P_GRID_HEADER_FILTER_ITEM = ({ width, isLimited, isLessMinWidth }) => ({
+ width: width || "auto",
+ flexShrink: isLimited ? 0 : 1,
+ visibility: isLessMinWidth ? "hidden" : "visible"
+});
diff --git a/app/theme/styles/paper.js b/app/theme/styles/paper.js
index 223350c..b4a19bb 100644
--- a/app/theme/styles/paper.js
+++ b/app/theme/styles/paper.js
@@ -10,7 +10,6 @@
import { useTheme } from "@mui/material/styles"; //Хук темы приложения
import { STATE } from "../../../app.text"; //Типовые текстовые ресурсы и константы
import { P8P_COLOR_STATE, P8P_COLOR_STATE_BG } from "../colors/common"; //Дополнительные цвета - общие
-import { P8P_COMPONENT_WIDTH, P8P_COMPONENT_HEIGHT } from "./common"; //Стили - общие
//---------
//Константы
@@ -44,11 +43,9 @@ export const P8P_PAPER_INDICATOR = ({ state, color, backgroundColor, clickable }
const theme = useTheme();
//Возвращаем стиль
return {
+ height: "100%",
+ width: "100%",
padding: "10px",
- ...P8P_COMPONENT_WIDTH({ width: "100%" }),
- ...P8P_COMPONENT_HEIGHT({ height: "100%" }),
- //width: "100%",
- //height: "100%",
overflow: "hidden",
backgroundColor: backgroundColor || P8P_INDICATOR_BG_COLOR[state],
color: color || P8P_INDICATOR_COLOR[state],
diff --git a/app/theme/styles/stack.js b/app/theme/styles/stack.js
index 1fb2f8f..1845402 100644
--- a/app/theme/styles/stack.js
+++ b/app/theme/styles/stack.js
@@ -3,11 +3,7 @@
Вспомогательные стили Stack
*/
-//---------------------
-//Подключение библиотек
-//---------------------
-
-import { P8P_COMPONENT_WIDTH } from "./common"; //Стили - общие
+import { P8P_COMPONENT_CLICKABLE_OPACITY } from "./common";
//----------------
//Интерфейс модуля
@@ -15,8 +11,68 @@ import { P8P_COMPONENT_WIDTH } from "./common"; //Стили - общие
//Адаптивный с сокрытием
export const P8P_STACK_INLINE_HIDDEN = {
- ...P8P_COMPONENT_WIDTH({ width: "100%" }),
+ width: "100%",
containerType: "inline-size",
- //width: "100%",
overflow: "hidden"
};
+
+//---------
+//Стили заголовка
+//---------
+
+//Контейнер текста заголовка
+export const P8P_STACK_HEADER_TEXT = ({ isClickable }) => ({
+ height: "100%",
+ width: "100%",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ padding: "0px 8px",
+ color: isClickable ? "P8PHeader.textLink" : "P8PHeader.text",
+ ...(isClickable ? { ...P8P_COMPONENT_CLICKABLE_OPACITY } : {})
+});
+
+//Контейнер фильтра заголовка
+export const P8P_STACK_HEADER_FILTER = ({ isClickable = false }) => ({
+ width: "100%",
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "flex-start",
+ alignContent: "flex-start",
+ cursor: isClickable ? "pointer" : "default",
+ overflow: "hidden"
+});
+
+//Контейнер фильтра заголовка
+export const P8P_STACK_HEADER_FILTER_CONTAINER = ({ isClickable = false }) => ({
+ height: "100%",
+ width: "100%",
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "center",
+ gap: "4px",
+ paddingRight: "4px",
+ "&:hover": isClickable ? { opacity: 0.8 } : {}
+});
+
+//Контейнер кнопки с очисткой
+export const P8P_STACK_HEADER_WITH_CLEAR = {
+ height: "100%",
+ width: "100%",
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "center"
+};
+
+//Контейнер значений индикатора
+export const P8P_STACK_HEADER_INDICATOR = ({ isClickable }) => ({
+ height: "100%",
+ width: "100%",
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "start",
+ justifyContent: "center",
+ padding: "0px 8px",
+ overflow: "hidden",
+ ...(isClickable ? { ...P8P_COMPONENT_CLICKABLE_OPACITY } : {})
+});
diff --git a/app/theme/styles/typography.js b/app/theme/styles/typography.js
index 4ed4e9a..8ee50ed 100644
--- a/app/theme/styles/typography.js
+++ b/app/theme/styles/typography.js
@@ -7,7 +7,20 @@
//Подключение библиотек
//---------------------
-import { P8P_COMPONENT_WIDTH, P8P_COMPONENT_HEIGHT } from "./common"; //Стили - общие
+import { P8P_COLOR_STATE } from "../colors/common"; //Дополнительные цвета - общие
+import { STATE } from "../../../app.text"; //Типовые текстовые ресурсы и константы
+
+//---------
+//Константы
+//---------
+
+//Цвета текста индикатора заголовка
+const P8P_HEADER_INDICATOR_COLOR = {
+ [STATE.OK]: P8P_COLOR_STATE[STATE.OK],
+ [STATE.ERR]: P8P_COLOR_STATE[STATE.ERR],
+ [STATE.WARN]: P8P_COLOR_STATE[STATE.WARN],
+ DEFAULT: "P8PHeader.text"
+};
//----------------
//Интерфейс модуля
@@ -30,8 +43,25 @@ export const P8P_TYPOGRAPHY_DIALOG_TITLE = {
//Заголовок
export const P8P_TYPOGRAPHY_TITLE = {
- ...P8P_COMPONENT_HEIGHT({ height: "44px" })
- //height: "44px"
+ height: "44px"
+};
+
+//Максимальное количество строк
+export const P8P_TYPOGRAPHY_MAX_LINES = ({ maxLines }) => ({
+ width: "100%",
+ whiteSpace: "wrap",
+ display: "-webkit-box",
+ overflow: "hidden",
+ WebkitBoxOrient: "vertical",
+ WebkitLineClamp: maxLines
+});
+
+//Сокрытие лишнего текста
+export const P8P_TYPOGRAPHY_HIDDEN = {
+ textTransform: "none",
+ overflow: "hidden",
+ textOverflow: "ellipsis",
+ whiteSpace: "nowrap"
};
//---------
@@ -40,12 +70,11 @@ export const P8P_TYPOGRAPHY_TITLE = {
//Описание панели на рабочем столе
export const P8P_TYPOGRAPHY_PANEL_DESK = {
+ maxWidth: "140px",
display: "-webkit-box",
overflow: "hidden",
WebkitBoxOrient: "vertical",
- WebkitLineClamp: 2,
- ...P8P_COMPONENT_WIDTH({ maxWidth: "140px" })
- //maxWidth: "140px"
+ WebkitLineClamp: 2
};
//---------
@@ -72,9 +101,8 @@ export const P8P_TYPOGRAPHY_CG_GROUP = ({ maxWidth, maxHeight }) => ({
//Задача циклограммы
export const P8P_TYPOGRAPHY_CG_TASK = ({ maxHeight, availableLines }) => ({
+ width: "100%",
maxHeight,
- ...P8P_COMPONENT_WIDTH({ width: "100%" }),
- //width: "100%",
padding: "0px 5px",
overflowWrap: "break-word",
wordBreak: "break-all",
@@ -84,3 +112,17 @@ export const P8P_TYPOGRAPHY_CG_TASK = ({ maxHeight, availableLines }) => ({
WebkitBoxOrient: "vertical",
WebkitLineClamp: availableLines < 1 ? 1 : availableLines
});
+
+//---------
+//Стили заголовка
+//---------
+
+//Индикатор заголовка
+export const P8P_TYPOGRAPY_HDR_INDICATOR = ({ maxLines, state, isDefaultColor = false, color }) => ({
+ ...P8P_TYPOGRAPHY_MAX_LINES({ maxLines }),
+ color: isDefaultColor
+ ? P8P_HEADER_INDICATOR_COLOR.DEFAULT
+ : color
+ ? color
+ : P8P_HEADER_INDICATOR_COLOR[state] || P8P_HEADER_INDICATOR_COLOR.DEFAULT
+});
diff --git a/app/theme/utils.js b/app/theme/utils.js
index 25dbebe..b6d32bc 100644
--- a/app/theme/utils.js
+++ b/app/theme/utils.js
@@ -19,7 +19,7 @@ export const getButtonColorStyles = (color, theme, isOutlined = false) => {
//Возвращаем результат
return {
backgroundColor: !isOutlined ? colorObj.main : null,
- color: !isOutlined ? colorObj.contrastText || "#FFF" : colorObj.main,
+ color: !isOutlined ? colorObj.contrastText || theme.palette.P8PBackground.primary : colorObj.main,
...(isOutlined ? { border: `1px solid ${colorObj.main}` } : {}),
"&:hover": {
textDecoration: "none",
diff --git a/app/theme/variants/p8p_button_variants.js b/app/theme/variants/p8p_button_variants.js
index 809b471..fe28b49 100644
--- a/app/theme/variants/p8p_button_variants.js
+++ b/app/theme/variants/p8p_button_variants.js
@@ -7,24 +7,31 @@
//Подключение библиотек
//---------------------
+import { P8P_COMPONENT_SIZE } from "../constants"; //Общие константы стилей
import { getButtonColorStyles } from "../utils"; //Дополнительные функции стилизации
-import { P8P_COMPONENT_HEIGHT, P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
//---------
//Константы
//---------
+//Отступы кнопки заголовка
+const P8P_BUTTON_HDR_SIZE = {
+ [P8P_COMPONENT_SIZE.SMALL]: "0px 8px",
+ [P8P_COMPONENT_SIZE.MEDIUM]: "0px 16px",
+ [P8P_COMPONENT_SIZE.LARGE]: "0px 24px"
+};
+
//Размеры кнопок
const P8P_BUTTON_SIZE = {
- small: {
+ [P8P_COMPONENT_SIZE.SMALL]: {
fontSize: "13px",
padding: "4px 22px"
},
- medium: {
+ [P8P_COMPONENT_SIZE.MEDIUM]: {
fontSize: "14px",
padding: "6px 22px"
},
- large: {
+ [P8P_COMPONENT_SIZE.LARGE]: {
fontSize: "15px",
padding: "8px 22px"
},
@@ -66,16 +73,27 @@ export const P8P_BUTTONS = ({ theme, color, size }) => ({
border: "none"
},
P8PDesktopPanel: {
+ width: "150px",
+ height: "90px",
fontSize: "12px",
textTransform: "none",
- ...P8P_COMPONENT_WIDTH({ width: "150px" }),
- ...P8P_COMPONENT_HEIGHT({ width: "90px" }),
- // width: "150px",
- // height: "90px",
flexDirection: "column",
justifyContent: "flex-start",
color: theme.palette.P8PDesktop.main,
"&:hover": { backgroundColor: theme.palette.P8PDesktop.hover }
+ },
+ P8PHeader: {
+ height: "100%",
+ width: "100%",
+ borderRadius: "0px",
+ borderColor: theme.palette.P8PHeader.border,
+ boxShadow: "none",
+ textTransform: "none",
+ color: theme.palette.P8PHeader.link,
+ backgroundColor: "transparent",
+ padding: P8P_BUTTON_HDR_SIZE[size] || P8P_BUTTON_HDR_SIZE[P8P_COMPONENT_SIZE.LARGE],
+ overflow: "hidden",
+ "&:hover": { backgroundColor: "inherit", opacity: "0.8" }
}
});
@@ -85,7 +103,8 @@ export const P8P_BUTTON_VARIANT = {
SECONDARY: "P8PSecondary",
OUTLINED: "P8POutlined",
TEXT: "P8PText",
- DESKTOP_PANEL: "P8PDesktopPanel"
+ DESKTOP_PANEL: "P8PDesktopPanel",
+ HEADER: "P8PHeader"
};
//Кастомная стилистика компонента
diff --git a/app/theme/variants/p8p_card_variants.js b/app/theme/variants/p8p_card_variants.js
index a06aa23..6c9e083 100644
--- a/app/theme/variants/p8p_card_variants.js
+++ b/app/theme/variants/p8p_card_variants.js
@@ -3,12 +3,6 @@
Расширение стилистики Card
*/
-//---------------------
-//Подключение библиотек
-//---------------------
-
-import { P8P_COMPONENT_HEIGHT, P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
-
//----------------
//Интерфейс модуля
//----------------
@@ -17,10 +11,8 @@ import { P8P_COMPONENT_HEIGHT, P8P_COMPONENT_WIDTH } from "../styles/common"; //
export const P8P_CARDS = {
primary: {},
P8PPanelInfo: {
- ...P8P_COMPONENT_WIDTH({ maxWidth: 400 }),
- ...P8P_COMPONENT_HEIGHT({ height: "100%" }),
- //maxWidth: 400,
- //height: "100%",
+ maxWidth: "400px",
+ height: "100%",
flexDirection: "column",
display: "flex"
}
diff --git a/app/theme/variants/p8p_container_variants.js b/app/theme/variants/p8p_container_variants.js
index af17825..bf378d2 100644
--- a/app/theme/variants/p8p_container_variants.js
+++ b/app/theme/variants/p8p_container_variants.js
@@ -3,12 +3,6 @@
Расширение стилистики Container
*/
-//---------------------
-//Подключение библиотек
-//---------------------
-
-import { P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
-
//----------------
//Интерфейс модуля
//----------------
@@ -17,14 +11,12 @@ import { P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общи
export const P8P_CONTAINERS = {
primary: {},
P8PTableMoreButton: {
- ...P8P_COMPONENT_WIDTH({ width: "100%" }),
- //width: "100%",
+ width: "100%",
textAlign: "center",
padding: "5px"
},
P8PInlineMessage: {
- ...P8P_COMPONENT_WIDTH({ width: "100%" }),
- //width: "100%",
+ width: "100%",
textAlign: "center"
}
};
diff --git a/app/theme/variants/p8p_dialog_actions_variants.js b/app/theme/variants/p8p_dialog_actions_variants.js
new file mode 100644
index 0000000..38b08f5
--- /dev/null
+++ b/app/theme/variants/p8p_dialog_actions_variants.js
@@ -0,0 +1,31 @@
+/*
+ Парус 8 - Панели мониторинга
+ Расширение стилистики DialogActions
+*/
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+//Кастомные диалоги (действия)
+export const P8P_DIALOG_ACTIONS = {
+ primary: {},
+ P8PDialog: { padding: "8px 24px 16px 24px" }
+};
+
+//Наименование кастомных диалогов (действия)
+export const P8P_DIALOG_ACTIONS_VARIANT = {
+ DIALOG: "P8PDialog"
+};
+
+//Кастомная стилистика компонента
+export const P8P_DIALOG_ACTIONS_OVERRIDES = {
+ styleOverrides: {
+ root: ({ ownerState }) => {
+ //Определяем вариант
+ const variant = ownerState["variant"] || "primary";
+ //Возвращаем стили варианта
+ return P8P_DIALOG_ACTIONS[variant];
+ }
+ }
+};
diff --git a/app/theme/variants/p8p_dialog_content_variants.js b/app/theme/variants/p8p_dialog_content_variants.js
index 2e04b53..9cf6425 100644
--- a/app/theme/variants/p8p_dialog_content_variants.js
+++ b/app/theme/variants/p8p_dialog_content_variants.js
@@ -7,24 +7,39 @@
//Подключение библиотек
//---------------------
-import { APP_STYLES } from "../../../app.styles"; //Типовые стили
-import { P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
+import { P8P_SCROLL, P8P_SCROLL_AUTO } from "../styles/common"; //Стили - общие
+
+//---------
+//Константы
+//---------
+
+//Общие стили
+const defaultStyles = paddingDisabled => ({
+ ...(paddingDisabled ? { padding: "0px" } : {})
+});
//----------------
//Интерфейс модуля
//----------------
//Кастомные диалоги (содержимое)
-export const P8P_DIALOG_CONTENTS = theme => ({
+export const P8P_DIALOG_CONTENTS = (theme, paddingDisabled) => ({
primary: {},
- P8PPrimary: { overflow: "auto", ...APP_STYLES.SCROLL },
+ P8PPrimary: { ...theme.typography.P8PBody3, ...P8P_SCROLL_AUTO, ...defaultStyles(paddingDisabled) },
P8PTask: {
- ...P8P_COMPONENT_WIDTH({ minWidth: 400 }),
- //minWidth: 400,
- overflowX: "auto"
+ minWidth: "400px",
+ overflowX: "auto",
+ ...P8P_SCROLL,
+ ...defaultStyles(paddingDisabled)
},
- P8PHint: { ...theme.typography.P8PBody4, color: theme.palette.P8PText.primary },
- P8PHidden: { display: "flex", flexDirection: "column", overflow: "hidden" }
+ P8PHint: { ...theme.typography.P8PBody4, color: theme.palette.P8PText.primary, ...defaultStyles(paddingDisabled) },
+ P8PHidden: {
+ ...theme.typography.P8PBody3,
+ display: "flex",
+ flexDirection: "column",
+ overflow: "hidden",
+ ...defaultStyles(paddingDisabled)
+ }
});
//Наименование кастомных диалогов (содержимое)
@@ -41,8 +56,10 @@ export const P8P_DIALOG_CONTENT_OVERRIDES = {
root: ({ ownerState, theme }) => {
//Определяем вариант
const variant = ownerState["variant"] || "primary";
+ //Определяем доп. параметры
+ const { paddingDisabled } = ownerState["data-variant-props"] || {};
//Возвращаем стили варианта
- return P8P_DIALOG_CONTENTS(theme)[variant];
+ return P8P_DIALOG_CONTENTS(theme, paddingDisabled)[variant];
}
}
};
diff --git a/app/theme/variants/p8p_dialog_title_variants.js b/app/theme/variants/p8p_dialog_title_variants.js
index 8aaecd1..2cf532b 100644
--- a/app/theme/variants/p8p_dialog_title_variants.js
+++ b/app/theme/variants/p8p_dialog_title_variants.js
@@ -10,10 +10,11 @@
//Кастомные диалоги (заголовок)
export const P8P_DIALOG_TITLES = theme => ({
primary: {},
- P8PPrimary: { ...theme.typography.P8PH6, color: theme.palette.P8PText.primary },
- P8PInfo: { ...theme.typography.P8PH6, color: theme.palette.P8PText.primary },
+ P8PPrimary: { ...theme.typography.P8PH6, color: theme.palette.P8PSecondary.main },
+ P8PInfo: { ...theme.typography.P8PH6, color: theme.palette.P8PSecondary.main },
P8PWarn: { ...theme.typography.P8PH6, color: theme.palette.P8PWarning.main },
- P8PError: { ...theme.typography.P8PH6, color: theme.palette.P8PError.main }
+ P8PError: { ...theme.typography.P8PH6, color: theme.palette.P8PError.main },
+ P8PPrimaryDivided: { ...theme.typography.P8PH6, color: theme.palette.P8PSecondary.main, borderBottom: "1px solid rgba(42, 48, 57, 0.12)" }
});
//Наименование кастомных диалогов (заголовок)
@@ -21,7 +22,8 @@ export const P8P_DIALOG_TITLE_VARIANT = {
PRIMARY: "P8PPrimary",
INFO: "P8PInfo",
WARN: "P8PWarn",
- ERROR: "P8PError"
+ ERROR: "P8PError",
+ PRIMARY_DIVIDED: "P8PPrimaryDivided"
};
//Кастомная стилистика компонента
diff --git a/app/theme/variants/p8p_drawer_variants.js b/app/theme/variants/p8p_drawer_variants.js
index 4c88009..36063a4 100644
--- a/app/theme/variants/p8p_drawer_variants.js
+++ b/app/theme/variants/p8p_drawer_variants.js
@@ -7,7 +7,7 @@
//Подключение библиотек
//---------------------
-import { APP_STYLES } from "../../../app.styles"; //Типовые стили
+import { P8P_SCROLL } from "../styles/common"; //Стили - общие
//----------------
//Интерфейс модуля
@@ -16,7 +16,11 @@ import { APP_STYLES } from "../../../app.styles"; //Типовые стили
//Кастомные выезжающие области
export const P8P_DRAWERS = {
primary: {},
- P8PPrimary: { [`& .MuiDrawer-paper`]: { ...APP_STYLES.SCROLL } }
+ P8PPrimary: {
+ [`& .MuiDrawer-paper`]: {
+ ...P8P_SCROLL
+ }
+ }
};
//Наименование кастомных выезжающих областей
diff --git a/app/theme/variants/p8p_fab_variants.js b/app/theme/variants/p8p_fab_variants.js
new file mode 100644
index 0000000..2771db4
--- /dev/null
+++ b/app/theme/variants/p8p_fab_variants.js
@@ -0,0 +1,42 @@
+/*
+ Парус 8 - Панели мониторинга
+ Расширение стилистики Fab
+*/
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+//Кастомные плавающие кнопки действия
+export const P8P_FABS = theme => ({
+ primary: {},
+ P8PHeader: {
+ height: "100%",
+ width: "100%",
+ borderRadius: "0px",
+ borderColor: theme.palette.P8PHeader.border,
+ backgroundColor: "transparent",
+ boxShadow: "none",
+ textTransform: "none",
+ color: theme.palette.P8PHeader.link,
+ overflow: "hidden",
+ "&:hover": { backgroundColor: "inherit", opacity: "0.8" }
+ }
+});
+
+//Наименование кастомных плавающих кнопок действий
+export const P8P_FAB_VARIANT = {
+ HEADER: "P8PHeader"
+};
+
+//Кастомная стилистика компонента
+export const P8P_FAB_OVERRIDES = {
+ styleOverrides: {
+ root: ({ ownerState, theme }) => {
+ //Определяем вариант
+ const variant = ownerState["variant"] || "primary";
+ //Возвращаем стили варианта
+ return P8P_FABS(theme)[variant];
+ }
+ }
+};
diff --git a/app/theme/variants/p8p_grid_variants.js b/app/theme/variants/p8p_grid_variants.js
index b6110c9..bcebf7c 100644
--- a/app/theme/variants/p8p_grid_variants.js
+++ b/app/theme/variants/p8p_grid_variants.js
@@ -3,12 +3,6 @@
Расширение стилистики Grid
*/
-//---------------------
-//Подключение библиотек
-//---------------------
-
-import { P8P_COMPONENT_HEIGHT, P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
-
//----------------
//Интерфейс модуля
//----------------
@@ -18,17 +12,30 @@ export const P8P_GRIDS = {
primary: {},
P8PPrimary: {},
P8PSvgContainer: {
- ...P8P_COMPONENT_WIDTH({ width: "100%" }),
- ...P8P_COMPONENT_HEIGHT({ height: "100%" })
- //width: "100%",
- //height: "100%"
+ width: "100%",
+ height: "100%"
},
P8PPanelsMenu: {
- ...P8P_COMPONENT_WIDTH({ maxWidth: 1200 }),
- //maxWidth: 1200,
+ maxWidth: "1200px",
direction: "row",
justifyContent: "left",
alignItems: "stretch"
+ },
+ P8PHeaderFilterContainer: {
+ height: "100%",
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "center",
+ position: "relative",
+ marginTop: "0px",
+ "& .MuiGrid-item": {
+ paddingTop: "0 !important"
+ }
+ },
+ P8PHeaderFilterItem: {
+ minWidth: "125px",
+ height: "100%",
+ alignContent: "center"
}
};
@@ -36,7 +43,9 @@ export const P8P_GRIDS = {
export const P8P_GRID_VARIANT = {
PRIMARY: "P8PPrimary",
SVG_CONTAINER: "P8PSvgContainer",
- PANELS_MENU: "P8PPanelsMenu"
+ PANELS_MENU: "P8PPanelsMenu",
+ HEADER_FILTER_CONTAINER: "P8PHeaderFilterContainer",
+ HEADER_FILTER_ITEM: "P8PHeaderFilterItem"
};
//Кастомная стилистика компонента
diff --git a/app/theme/variants/p8p_icon_button_variants.js b/app/theme/variants/p8p_icon_button_variants.js
index 6bcc9ad..57fdbde 100644
--- a/app/theme/variants/p8p_icon_button_variants.js
+++ b/app/theme/variants/p8p_icon_button_variants.js
@@ -8,26 +8,40 @@
//----------------
//Кастомные кнопки-иконки
-export const P8P_ICON_BUTTONS = {
+export const P8P_ICON_BUTTONS = ({ theme }) => ({
primary: {},
P8PAppBarButton: {
marginRight: "16px"
+ },
+ P8PHeaderFilterMore: {
+ flexShrink: 0,
+ width: "40px",
+ alignContent: "center",
+ color: theme.palette.P8PHeader.link
+ },
+ P8PDialogClose: {
+ color: "#005EA6",
+ border: `1px solid #005EA6`,
+ padding: "0px",
+ borderRadius: "0%"
}
-};
+});
//Наименования кастомных кнопок-иконкок
export const P8P_ICON_BUTTON_VARIANT = {
- APP_BAR_BUTTON: "P8PAppBarButton"
+ APP_BAR_BUTTON: "P8PAppBarButton",
+ HEADER_FILTER_MORE: "P8PHeaderFilterMore",
+ DIALOG_CLOSE: "P8PDialogClose"
};
//Кастомная стилистика компонента
export const P8P_ICON_BUTTON_OVERRIDES = {
styleOverrides: {
- root: ({ ownerState }) => {
+ root: ({ ownerState, theme }) => {
//Определяем вариант
const variant = ownerState?.variant || "primary";
//Возвращаем стили варианта
- return P8P_ICON_BUTTONS[variant];
+ return P8P_ICON_BUTTONS({ theme })[variant];
}
}
};
diff --git a/app/theme/variants/p8p_icon_variants.js b/app/theme/variants/p8p_icon_variants.js
index f69dae4..4e7caa3 100644
--- a/app/theme/variants/p8p_icon_variants.js
+++ b/app/theme/variants/p8p_icon_variants.js
@@ -3,49 +3,41 @@
Расширение стилистики Icon
*/
-//---------------------
-//Подключение библиотек
-//---------------------
-
-import { P8P_COMPONENT_HEIGHT, P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
-
//----------------
//Интерфейс модуля
//----------------
//Кастомные иконки
-export const P8P_ICONS = {
+export const P8P_ICONS = ({ theme }) => ({
primary: {},
- P8PTableColumnMenu: {
- marginRight: "10px"
- },
- P8PPanelMenuTitle: {
- paddingTop: "4px"
- },
+ P8PTableColumnMenu: { marginRight: "10px" },
+ P8PPanelMenuTitle: { paddingTop: "4px" },
P8PDesktopPanel: {
- ...P8P_COMPONENT_WIDTH({ width: "48px" }),
- ...P8P_COMPONENT_HEIGHT({ height: "48px" }),
- // width: "48px",
- // height: "48px",
+ width: "48px",
+ height: "48px",
fontSize: "48px"
- }
-};
+ },
+ P8PHeader: { margin: "0px", fontSize: "24px", color: theme.palette.P8PHeader.link },
+ P8PHeaderFilterDelete: { fontSize: "22px" }
+});
//Наименование кастомных иконок
export const P8P_ICON_VARIANT = {
TABLE_COLUMN_MENU: "P8PTableColumnMenu",
PANEL_MENU_TITLE: "P8PPanelMenuTitle",
- DESKTOP_PANEL: "P8PDesktopPanel"
+ DESKTOP_PANEL: "P8PDesktopPanel",
+ HEADER: "P8PHeader",
+ HEADER_FILTER_DELETE: "P8PHeaderFilterDelete"
};
//Кастомная стилистика компонента
export const P8P_ICON_OVERRIDES = {
styleOverrides: {
- root: ({ ownerState }) => {
+ root: ({ ownerState, theme }) => {
//Определяем вариант
const variant = ownerState?.variant || "primary";
//Возвращаем стили варианта
- return P8P_ICONS[variant];
+ return P8P_ICONS({ theme })[variant];
}
}
};
diff --git a/app/theme/variants/p8p_list_item_variants.js b/app/theme/variants/p8p_list_item_variants.js
new file mode 100644
index 0000000..64fd1d5
--- /dev/null
+++ b/app/theme/variants/p8p_list_item_variants.js
@@ -0,0 +1,37 @@
+/*
+ Парус 8 - Панели мониторинга
+ Расширение стилистики ListItem
+*/
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+//Кастомные списки
+export const P8P_LIST_ITEMS = {
+ primary: {},
+ P8PHeaderFilterMore: {
+ flexDirection: "column",
+ alignItems: "flex-start",
+ borderBottom: "1px solid",
+ borderColor: "rgba(0, 0, 0, 0.12)",
+ "&:last-child": { borderBottom: "none" }
+ }
+};
+
+//Наименование кастомных списков
+export const P8P_LIST_ITEM_VARIANT = {
+ HEADER_FILTER_MORE: "P8PHeaderFilterMore"
+};
+
+//Кастомная стилистика компонента
+export const P8P_LIST_ITEM_OVERRIDES = {
+ styleOverrides: {
+ root: ({ ownerState }) => {
+ //Определяем вариант
+ const variant = ownerState["variant"] || "primary";
+ //Возвращаем стили варианта
+ return P8P_LIST_ITEMS[variant];
+ }
+ }
+};
diff --git a/app/theme/variants/p8p_list_variants.js b/app/theme/variants/p8p_list_variants.js
index 9cef5a7..bf1a01f 100644
--- a/app/theme/variants/p8p_list_variants.js
+++ b/app/theme/variants/p8p_list_variants.js
@@ -7,7 +7,7 @@
//Подключение библиотек
//---------------------
-import { P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общие
+import { P8P_SCROLL_AUTO } from "../styles/common"; //Стили - общие
//----------------
//Интерфейс модуля
@@ -17,20 +17,28 @@ import { P8P_COMPONENT_WIDTH } from "../styles/common"; //Стили - общи
export const P8P_LISTS = {
primary: {},
P8PGanttTask: {
- ...P8P_COMPONENT_WIDTH({ width: "100%", minWidth: 300, maxWidth: 700 })
- //width: "100%", minWidth: 300, maxWidth: 700
+ width: "100%",
+ minWidth: "300px",
+ maxWidth: "700px"
},
P8PSettings: {
- ...P8P_COMPONENT_WIDTH({ width: "510px" }),
- //width: "510px",
+ width: "510px",
overflowY: "auto"
+ },
+ P8PHeaderFilterMore: {
+ ...P8P_SCROLL_AUTO,
+ minWidth: "250px",
+ maxWidth: "400px",
+ maxHeight: "60vh",
+ padding: "8px"
}
};
//Наименование кастомных списков
export const P8P_LIST_VARIANT = {
GANTT_TASK: "P8PGanttTask",
- SETTINGS: "P8PSettings"
+ SETTINGS: "P8PSettings",
+ HEADER_FILTER_MORE: "P8PHeaderFilterMore"
};
//Кастомная стилистика компонента
diff --git a/app/theme/variants/p8p_menu_item_variants.js b/app/theme/variants/p8p_menu_item_variants.js
index c69c273..c6d7ed7 100644
--- a/app/theme/variants/p8p_menu_item_variants.js
+++ b/app/theme/variants/p8p_menu_item_variants.js
@@ -10,12 +10,14 @@
//Кастомные элементы меню
export const P8P_MENU_ITEMS = theme => ({
primary: {},
- P8PPrimary: { ...theme.typography.P8PBody1 }
+ P8PPrimary: { ...theme.typography.P8PBody1 },
+ P8PHeader: { ...theme.typography.P8PHeader, color: theme.palette.P8PHeader.link }
});
//Наименование кастомных элементов меню
export const P8P_MENU_ITEM_VARIANT = {
- PRIMARY: "P8PPrimary"
+ PRIMARY: "P8PPrimary",
+ HEADER: "P8PHeader"
};
//Кастомная стилистика компонента
diff --git a/app/theme/variants/p8p_select_variants.js b/app/theme/variants/p8p_select_variants.js
index 9d35712..5eab19d 100644
--- a/app/theme/variants/p8p_select_variants.js
+++ b/app/theme/variants/p8p_select_variants.js
@@ -17,12 +17,21 @@ export const P8P_SELECTS = theme => ({
}
},
"& .MuiSelect-select": { ...theme.typography.P8PBody1 }
+ },
+ P8PHeader: {
+ ...theme.typography.P8PHeader,
+ height: "100%",
+ color: theme.palette.P8PHeader.link,
+ "& .MuiOutlinedInput-notchedOutline": {
+ border: "none"
+ }
}
});
//Наименование кастомных полей выбора
export const P8P_SELECT_VARIANT = {
- PRIMARY: "P8PPrimary"
+ PRIMARY: "P8PPrimary",
+ HEADER: "P8PHeader"
};
//Кастомная стилистика компонента
diff --git a/app/theme/variants/p8p_table_head_variants.js b/app/theme/variants/p8p_table_head_variants.js
index 15fe169..5aaa71d 100644
--- a/app/theme/variants/p8p_table_head_variants.js
+++ b/app/theme/variants/p8p_table_head_variants.js
@@ -10,11 +10,7 @@
//Кастомные заголовки таблицы
export const P8P_TABLE_HEADS = {
primary: {},
- P8PSticky: {
- position: "sticky",
- top: 0,
- zIndex: 1000
- }
+ P8PSticky: { position: "sticky", top: 0, zIndex: 1000 }
};
//Наименование кастомных заголовков таблиц
diff --git a/app/theme/variants/p8p_text_field_variants.js b/app/theme/variants/p8p_text_field_variants.js
index ee862a0..0b557dd 100644
--- a/app/theme/variants/p8p_text_field_variants.js
+++ b/app/theme/variants/p8p_text_field_variants.js
@@ -22,6 +22,13 @@ export const P8P_TEXT_FIELDS = theme => ({
"& .MuiInputBase-input": {
...theme.typography.P8PBody1
}
+ },
+ P8PHidden: {
+ width: "100%",
+ height: "0px",
+ opacity: 0,
+ position: "absolute",
+ pointerEvents: "none"
}
});
@@ -33,7 +40,8 @@ export const P8P_TEXT_FIELD_OPTIONS = theme => ({
//Наименование кастомных полей ввода
export const P8P_TEXT_FIELD_VARIANT = {
- PRIMARY: "P8PPrimary"
+ PRIMARY: "P8PPrimary",
+ HIDDEN: "P8PHidden"
};
//Кастомная стилистика компонента
@@ -48,7 +56,6 @@ export const P8P_TEXT_FIELD_OVERRIDES = {
option: ({ ownerState, theme }) => {
//Определяем вариант
const variant = ownerState["data-variant"] || "primary";
- console.log({ option: P8P_TEXT_FIELD_OPTIONS(theme)[variant] });
//Возвращаем стили варианта
return P8P_TEXT_FIELD_OPTIONS(theme)[variant];
}