Compare commits

..

No commits in common. 'english' and 'main' have entirely different histories.

@ -1 +1 @@
VITE_API_URL=https://geoenergy.spatialsystems.ru VITE_API_URL=https://geoheat.spatialsystems.ru

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/index.html vendored

@ -5,7 +5,7 @@
<link href="/vite.svg" rel="icon"/> <link href="/vite.svg" rel="icon"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DZKH by Spatial</title> <title>DZKH by Spatial</title>
<script type="module" crossorigin src="/assets/index.d44a9096.js"></script> <script type="module" crossorigin src="/assets/index.e851803c.js"></script>
<link rel="stylesheet" href="/assets/index.767ffdb3.css"> <link rel="stylesheet" href="/assets/index.767ffdb3.css">
</head> </head>
<body> <body>

@ -1,33 +1,33 @@
import { Button, Col, Row } from "antd"; import {commonPopupConfig,} from "./config";
import { useGetRegions } from "../../../components/RegionSelect.jsx"; import {Button, Col, Row} from "antd";
import { tempMapper } from "../../../config.js"; import {isNil} from "../../../utils.js";
import { useWeatherFilter } from "../../../dzkh-features/WeatherSlider/useWeatherFilter.js"; import {useGetRegions} from "../../../components/RegionSelect.jsx";
import { useSimulateAccident } from "../../../stores/useSimulateAccident.js"; import {useSimulateAccident} from "../../../stores/useSimulateAccident.js";
import { isNil } from "../../../utils.js"; import {useWeatherFilter} from "../../../dzkh-features/WeatherSlider/useWeatherFilter.js";
import { commonPopupConfig, } from "./config"; import {tempMapper} from "../../../config.js";
const dynamicFields = [ const dynamicFields = [
{ {
field: 'prob1', field: 'prob1',
name: 'No heating in the building' name: 'Отсутствие отопления в доме'
},{ },{
field: 'prob2', field: 'prob2',
name: 'Leaking pipes in the entrance' name: 'Протечка труб в подъезде'
},{ },{
field: 'prob3', field: 'prob3',
name: 'Apartment temperature below standard' name: 'Температура в квартире ниже нормативной'
},{ },{
field: 'prob4', field: 'prob4',
name: 'Common area temperature below standard' name: 'Температура в помещении общего пользования ниже нормативной'
},{ },{
field: 'prob5', field: 'prob5',
name: 'Leak in the heating system' name: 'Течь в системе отопления'
},{ },{
field: 'cooling_time', field: 'cooling_time',
name: 'Cooling time (hours)' name: 'Время остывания (часы)'
},{ },{
field: 'priority', field: 'priority',
name: 'Building priority' name: 'Приоритет здания'
} }
] ]
@ -44,7 +44,7 @@ export const FeatureProperties = ({ feature }) => {
if (isSourcePoint) { if (isSourcePoint) {
return [ return [
...commonPopupConfig, {field: `prob6_${tempMapper[temperature]}`, name: 'Energy source failure'} ...commonPopupConfig, {field: `prob6_${tempMapper[temperature]}`, name: 'Авария на ТП'}
] ]
} }
@ -91,7 +91,7 @@ export const FeatureProperties = ({ feature }) => {
})} })}
{isSourcePoint ? {isSourcePoint ?
<div className={'mt-3 text-center'}> <div className={'mt-3 text-center'}>
<Button type={'primary'} onClick={simulateAccident}>Simulate failure</Button> <Button type={'primary'} onClick={simulateAccident}>Смоделировать аварию</Button>
</div> </div>
: null} : null}
</div> </div>

@ -3,19 +3,19 @@ export const getRegionNameById = (id, normalizedRegions) =>
export const commonPopupConfig = [ export const commonPopupConfig = [
{ {
name: "Address", name: "Адрес",
field: "building_address", field: "building_address",
}, },
{ {
name: "TP number", name: "Номер ТП",
field: "tp_number", field: "tp_number",
}, },
{ {
name: "Dispatcher center number", name: "Номер ОДС",
field: "ods_number", field: "ods_number",
}, },
{ {
name: "Dispatcher phone", name: "Телефон ОДС",
field: "phone_number", field: "phone_number",
} }
]; ];

@ -15,9 +15,9 @@ const SingleFeaturePopup = ({ feature }) => {
}; };
const typeMapper = { const typeMapper = {
potreb: 'Consumer', potreb: 'Потребитель',
tp: 'Source', tp: 'Источник',
ods: 'Dispatch center' ods: 'Диспетчерская'
} }
const MultipleFeaturesPopup = ({ features }) => { const MultipleFeaturesPopup = ({ features }) => {

@ -3,7 +3,7 @@ import { Button } from "antd";
export const ClearFiltersButton = ({ onClick, disabled }) => { export const ClearFiltersButton = ({ onClick, disabled }) => {
return ( return (
<Button block className={"mt-2"} onClick={onClick} disabled={disabled}> <Button block className={"mt-2"} onClick={onClick} disabled={disabled}>
Reset filters Сбросить фильтры
</Button> </Button>
); );
}; };

@ -77,13 +77,13 @@ export const RegionSelect = ({
return ( return (
<div> <div>
<Title text={"District / area"} /> <Title text={"АО / район"} />
<TreeSelect <TreeSelect
showSearch showSearch
style={{ width: "100%" }} style={{ width: "100%" }}
value={selectedRegionId} value={selectedRegionId}
dropdownStyle={{ maxHeight: 400, overflow: "auto" }} dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
placeholder="Select district or area" placeholder="Выберите АО или район"
allowClear allowClear
treeDefaultExpandAll={false} treeDefaultExpandAll={false}
onChange={handleChange} onChange={handleChange}
@ -93,7 +93,7 @@ export const RegionSelect = ({
notFoundContent={ notFoundContent={
<Empty <Empty
image={Empty.PRESENTED_IMAGE_SIMPLE} image={Empty.PRESENTED_IMAGE_SIMPLE}
description={"Not found"} description={"Не найдено"}
/> />
} }
disabled={disabled} disabled={disabled}

@ -1,43 +1,43 @@
export const CONSUMER_OPTIONS = [ export const CONSUMER_OPTIONS = [
{ {
value: "category1", value: "category1",
title: " Emergency forecasting", title: "Прогнозирование",
selectable: false, selectable: false,
children: [ children: [
{ {
value: "prob1", value: "prob1",
title: "No heating in the building", title: "Отсутствие отопления в доме",
}, },
{ {
value: "prob2", value: "prob2",
title: "Leaking pipes in the entrance", title: "Протечка труб в подъезде",
}, },
{ {
value: "prob3", value: "prob3",
title: "Apartment temperature below standard", title: "Температура в квартире ниже нормативной",
}, },
{ {
value: "prob4", value: "prob4",
title: "Common area temperature below standard", title: "Температура в помещении общего пользования ниже нормативной",
}, },
{ {
value: "prob5", value: "prob5",
title: "Leak in the heating system", title: "Течь в системе отопления",
}, },
] ]
}, },
{ {
value: "category2", value: "category2",
title: "Emergency response", title: "Реагирование",
selectable: false, selectable: false,
children: [ children: [
{ {
value: "cooling_time", value: "cooling_time",
title: "Cooling time, h", title: "Время остывания, ч",
}, },
{ {
value: "priority", value: "priority",
title: "Building priority", title: "Приоритет здания",
}, },
] ]
} }

@ -11,27 +11,28 @@ export const AccidentSimulationModal = ({id, modalOpen, setModalOpen}) => {
return ( return (
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<Row className={twMerge("font-bold")}> <Row className={twMerge("font-bold")}>
In the failure area there are: В зоне аварии оказалось:
</Row> </Row>
{!isNil(data?.potreb_count) && !isNil(data?.potreb_soc_count) && ( {!isNil(data?.potreb_count) && !isNil(data?.potreb_soc_count) && (
<Row> <Row>
{data?.potreb_count + data?.potreb_soc_count} consumers (of which {data?.potreb_soc_count} are social facilities) {data?.potreb_count + data?.potreb_soc_count} потребителей (из них {data?.potreb_soc_count} - социальные
объекты)
</Row> </Row>
)} )}
{!isNil(data?.total_area) && ( {!isNil(data?.total_area) && (
<Row> <Row>
Total consumer area - {Math.ceil(data?.total_area)} sq. meters Общая площадь потребителей - {Math.ceil(data?.total_area)} кв. метров
</Row> </Row>
)} )}
{!isNil(data?.number_of_apartments) && ( {!isNil(data?.number_of_apartments) && (
<Row> <Row>
{data?.number_of_apartments} apartments {data?.number_of_apartments} квартир
</Row> </Row>
)} )}
{!isNil(data?.data_min_cooling_time) && !isNil(data?.min_cooling_time) && ( {!isNil(data?.data_min_cooling_time) && !isNil(data?.min_cooling_time) && (
<Row> <Row>
The fastest cooling building is at Быстрее всего остынет здание по
address {data?.data_min_cooling_time.building_address} ({data?.min_cooling_time} hours) адресу {data?.data_min_cooling_time.building_address} ({data?.min_cooling_time} часов)
</Row> </Row>
)} )}

@ -1,9 +1,9 @@
import { Button, Popover } from "antd"; import { Button, Col, Divider, Modal, Popover, Row, Tooltip } from "antd";
import {useSimulateAccident} from "../stores/useSimulateAccident.js";
import {Title} from "../components/Title.jsx";
import { AccidentSimulationModal } from "./AccidentSimulation/AccidentSimulationModal.jsx";
import { useState } from "react"; import { useState } from "react";
import { BiInfoCircle } from "react-icons/all.js"; import { BiInfoCircle } from "react-icons/all.js";
import { Title } from "../components/Title.jsx";
import { useSimulateAccident } from "../stores/useSimulateAccident.js";
import { AccidentSimulationModal } from "./AccidentSimulation/AccidentSimulationModal.jsx";
export const AccidentSimulationResults = () => { export const AccidentSimulationResults = () => {
const {selectedSourceConfig, setSelectedSourceConfig} = useSimulateAccident(); const {selectedSourceConfig, setSelectedSourceConfig} = useSimulateAccident();
@ -17,9 +17,9 @@ export const AccidentSimulationResults = () => {
return ( return (
<> <>
<div className='absolute bottom-[20px] left-[20px] text-grey z-10 bg-white-background rounded-xl p-3 text-center'> <div className='absolute bottom-[20px] left-[20px] text-grey z-10 bg-white-background rounded-xl p-3 text-center'>
<Title text={`Results of Energy source failure simulation ${selectedSourceConfig?.sourceId}`}/> <Title text={`Результаты моделирования аварии на ТП ${selectedSourceConfig?.sourceId}`}/>
<div className="flex justify-center flex-row gap-2"> <div className="flex justify-center flex-row gap-2">
<Button type="primary" onClick={stopSimulation}>Cancel</Button> <Button type="primary" onClick={stopSimulation}>Отменить</Button>
{!!pointId && ( {!!pointId && (
<Popover content={<AccidentSimulationModal id={pointId} />}> <Popover content={<AccidentSimulationModal id={pointId} />}>
<Button className="flex justify-center items-center" type="primary" onClick={() => setModalOpen(true)}> <Button className="flex justify-center items-center" type="primary" onClick={() => setModalOpen(true)}>

@ -25,27 +25,27 @@ ChartJS.register(
); );
const GRAPH_LABELS_MAP= { const GRAPH_LABELS_MAP= {
t_shap: "Air temperature", t_shap: "Температура воздуха",
fi_remont1_shap: "Replacement of cold water risers", fi_remont1_shap: "Замена стояков ХВС",
fi_remont2_shap: "Repair of internal cold water mains", fi_remont2_shap: "Ремонт разводящих внутридомовых магистралей ХВС",
fi_remont3_shap: "Replacement of hot water risers", fi_remont3_shap: "Замена стояков ГВС",
fi_remont4_shap: "Repair of internal hot water mains", fi_remont4_shap: "Ремонт разводящих внутридомовых магистралей ГВС",
fi_remont5_shap: "Repair of sewer risers", fi_remont5_shap: "Ремонт стояков канализации",
fi_remont6_shap: "Repair of sewer outlets and collector pipelines", fi_remont6_shap: "Ремонт выпусков и сборных трубопроводов системы канализации",
fi_remont7_shap: "Repair of internal heating systems (with riser replacement)", fi_remont7_shap: "Ремонт внутридомовых систем теплоснабжения (с заменой стояков)",
fi_remont8_shap: "Repair of heating mains", fi_remont8_shap: "Ремонт разводящих магистралей системы теплоснабжения",
total_area_shap: "Total area", total_area_shap: "Общая площадь",
fi_is_block_shap: "Material - block", fi_is_block_shap: "Материал - блочный",
fi_is_brick_shap: "Material - brick", fi_is_brick_shap: "Материал - кирпичный",
fi_is_panel_shap: "Material - panel", fi_is_panel_shap: "Материал - панельный",
building_wear_shap: "Wear", building_wear_shap: "Износ",
fi_is_monolit_shap: "Material - monolithic", fi_is_monolit_shap: "Материал - монолитный",
fi_energy_class_shap: "Energy efficiency class", fi_energy_class_shap: "Класс энергоэффективности",
fi_building_year_shap: "Year of construction", fi_building_year_shap: "Год постройки",
gvs_avg_heat_load_shap: "Average hot water heat load", gvs_avg_heat_load_shap: "Средняя тепловая нагрузка ГВС",
heating_heat_load_shap: "Heating heat load", heating_heat_load_shap: "Тепловая нагрузка на отопление",
gvs_fact_heat_load_shap: "Actual hot water heat load", gvs_fact_heat_load_shap: "Фактическая тепловая нагрузка ГВС",
ventilation_heat_load_shap: "Ventilation heat load" ventilation_heat_load_shap: "Тепловая нагрузка на вентиляцию"
}; };
export const PointChart = ({ point }) => { export const PointChart = ({ point }) => {
const { data: shapData } = useShap(point.id); const { data: shapData } = useShap(point.id);
@ -84,7 +84,7 @@ export const PointChart = ({ point }) => {
x: { x: {
title: { title: {
display: true, display: true,
text: 'Contribution to forecast, %', text: 'Вклад в прогноз, %',
}, },
grid: { grid: {
color: function(context) { color: function(context) {

@ -6,9 +6,9 @@ import { PointChart } from "./Chart.jsx";
const ChartHelp = () => { const ChartHelp = () => {
return ( return (
<div className="w-[200px]"> <div className="w-[200px]">
The chart shows the top 15 factors that have the greatest impact on the failure forecast for the object.<br/><br/> График показывает топ-15 факторов, которые оказывают наибольшее влияние на прогноз аварийности объекта.<br/><br/>
Factors can have a positive or negative impact.<br/><br/> Факторы могут оказывать положительное или отрицательное влияние.<br/><br/>
The stronger the factor's impact on failures, the closer its value is to 100% (-100%). Чем больше влияния оказывает фактор на аварийность, тем ближе его значение к 100% (-100%).
</div> </div>
) )
} }
@ -23,21 +23,21 @@ export const ChartModal = ({point}) => {
type="primary" type="primary"
onClick={() => setIsOpened(false)} onClick={() => setIsOpened(false)}
> >
Close Закрыть
</Button>, </Button>,
] ]
} }
return ( return (
<div className="flex items-center"> <div className="flex items-center">
<Tooltip title="Impact of factors on forecast"> <Tooltip title="Влияние факторов на прогноз">
<Button className="flex justify-center items-center h-6 ml-1 mb-1 p-2" type="primary" onClick={() => setIsOpened(true)}> <Button className="flex justify-center items-center h-6 ml-1 mb-1 p-2" type="primary" onClick={() => setIsOpened(true)}>
Impact of factors on forecast Влияние факторов на прогноз
</Button> </Button>
</Tooltip> </Tooltip>
<Modal <Modal
open={isOpened} open={isOpened}
title="Contribution of factors to failure forecast" title="Вклад факторов в прогноз аварийности"
onCancel={() => setIsOpened(false)} onCancel={() => setIsOpened(false)}
width={800} width={800}
footer={getFooter()} footer={getFooter()}
@ -47,7 +47,7 @@ export const ChartModal = ({point}) => {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Row className={twMerge("p-1")}> <Row className={twMerge("p-1")}>
<Col className={"font-semibold"} span={12}> <Col className={"font-semibold"} span={12}>
Point address: Адрес точки:
</Col> </Col>
<Col span={12}>{point.building_address}</Col> <Col span={12}>{point.building_address}</Col>
</Row> </Row>
@ -60,7 +60,7 @@ export const ChartModal = ({point}) => {
placement="leftBottom" placement="leftBottom"
color="#ffffff" color="#ffffff"
> >
<Button type="text" className="text-[#1890FF] p-0">How to read the chart?</Button> <Button type="text" className="text-[#1890FF] p-0">Как читать график?</Button>
</Popover> </Popover>
</div> </div>

@ -3,7 +3,7 @@ import {UploadOutlined} from "@ant-design/icons";
export const ImportDataButton = ({onClick}) => { export const ImportDataButton = ({onClick}) => {
return <div className='absolute top-[20px] left-[20px]'> return <div className='absolute top-[20px] left-[20px]'>
<Tooltip title='Data import' placement='right'> <Tooltip title='Импорт данных' placement='right'>
<Button <Button
type="primary" type="primary"
icon={<UploadOutlined />} icon={<UploadOutlined />}

@ -67,8 +67,8 @@ const Uploader = ({text, dataType, onSuccess, onError}) => {
} }
const getMessage = () => { const getMessage = () => {
if (isInitialUploading) return 'Data import' if (isInitialUploading) return 'Импорт данных'
if (isFinished) return 'Data import completed' if (isFinished) return 'Импорт данных завершен'
return uploadData.description return uploadData.description
} }
@ -87,7 +87,7 @@ const Uploader = ({text, dataType, onSuccess, onError}) => {
return <div> return <div>
<div className='space-x-3'> <div className='space-x-3'>
<Tooltip title={'Overwrite data'}> <Tooltip title={'Перезаписать данные'}>
<Checkbox checked={shouldRefill} onChange={e => setShouldRefill(e.target.checked)}/> <Checkbox checked={shouldRefill} onChange={e => setShouldRefill(e.target.checked)}/>
</Tooltip> </Tooltip>
<Upload <Upload
@ -103,7 +103,7 @@ const Uploader = ({text, dataType, onSuccess, onError}) => {
type="text" type="text"
onClick={onTemplateDownload} onClick={onTemplateDownload}
> >
Download template Скачать шаблон
</Button> </Button>
</div> </div>
{getStatusInfo()} {getStatusInfo()}
@ -167,7 +167,7 @@ export const ImportDataModal = ({onClose}) => {
const getMessage = () => { const getMessage = () => {
if (isInitialAnalysisStarting) return 'Начало анализа' if (isInitialAnalysisStarting) return 'Начало анализа'
if (isFinished) return 'Data analysis completed' if (isFinished) return 'Анализ данных завершен'
return uploadData.description return uploadData.description
} }
@ -187,24 +187,24 @@ export const ImportDataModal = ({onClose}) => {
return ( return (
<Modal <Modal
open={true} open={true}
title="Data import" title="Импорт данных"
width={400} width={400}
footer={null} footer={null}
onCancel={onClose} onCancel={onClose}
> >
<div className='text-center space-y-3'> <div className='text-center space-y-3'>
<Alert <Alert
message="Please note that import time can be significant (up to 10 minutes) depending on the size of the input data." message="Обращаем ваше внимание, что импорт в зависимости от размера входных данных может занимать значительное время (до 10 мин)"
type="warning" type="warning"
className={'mb-5'} className={'mb-5'}
showIcon showIcon
closable closable
/> />
<Uploader dataType={'odpu'} text={'Select ODPU file'} onSuccess={handleUploadSuccess} onError={handleUploadError}/> <Uploader dataType={'odpu'} text={'Выбрать файл с ОДПУ'} onSuccess={handleUploadSuccess} onError={handleUploadError}/>
<Uploader dataType={'asupr'} text={'Select ASUPR file'} onSuccess={handleUploadSuccess} onError={handleUploadError} /> <Uploader dataType={'asupr'} text={'Выбрать файл с АСУПР'} onSuccess={handleUploadSuccess} onError={handleUploadError} />
<Uploader dataType={'moek_scheme'} text={'Select MOEK file'} onSuccess={handleUploadSuccess} onError={handleUploadError} /> <Uploader dataType={'moek_scheme'} text={'Выбрать файл с МОЭК'} onSuccess={handleUploadSuccess} onError={handleUploadError} />
<Uploader dataType={'events'} text={'Select events file'} onSuccess={handleUploadSuccess} onError={handleUploadError} /> <Uploader dataType={'events'} text={'Выбрать файл с событиями'} onSuccess={handleUploadSuccess} onError={handleUploadError} />
<Uploader dataType={'houses'} text={'Select houses file'} onSuccess={handleUploadSuccess} onError={handleUploadError} /> <Uploader dataType={'houses'} text={'Выбрать файл с домами'} onSuccess={handleUploadSuccess} onError={handleUploadError} />
<Button <Button
key="start-upload" key="start-upload"
className='mt-5' className='mt-5'
@ -213,10 +213,10 @@ export const ImportDataModal = ({onClose}) => {
loading={isInitialAnalysisStarting} loading={isInitialAnalysisStarting}
disabled={hasUploadError || isLoading} disabled={hasUploadError || isLoading}
> >
Start data analysis Начать анализ данных
</Button> </Button>
{getStatusInfo()} {getStatusInfo()}
{isError && <p className='text-red-600'>An error occurred</p>} {isError && <p className='text-red-600'>Произошла ошибка</p>}
</div> </div>
</Modal> </Modal>
); );

@ -70,9 +70,9 @@ export function Legend() {
{ {
consumer_filter ? <LegendColorRampItem consumer_filter ? <LegendColorRampItem
colors={consumerColors} colors={consumerColors}
name="Consumer" name="Потребитель"
desc={consumer_filter.key.includes("prob") ? "failure likelihood" : consumer_filter.key.includes("cooling_time") ? "cooling time, h" : "building priority"} desc={consumer_filter.key.includes("prob") ? "склонность к аварийности" : consumer_filter.key.includes("cooling_time") ? "время остывания, ч" : "приоритет здания"}
/> : <LegendPointItem name="Consumer"/> /> : <LegendPointItem name="Потребитель"/>
} }
</Checkbox> </Checkbox>
@ -85,9 +85,9 @@ export function Legend() {
{ {
source_filter ? <LegendColorRampItem source_filter ? <LegendColorRampItem
colors={sourceColors} colors={sourceColors}
name="Source" name="Источник"
desc={'failure likelihood'} desc={'склонность к аварийности'}
/> : <LegendPointItem name="Source"/> /> : <LegendPointItem name="Источник"/>
} }
</Checkbox> </Checkbox>
@ -96,7 +96,7 @@ export function Legend() {
onChange={() => toggleVisibility(LAYER_IDS.dispatcher)} onChange={() => toggleVisibility(LAYER_IDS.dispatcher)}
checked={isVisible[LAYER_IDS.dispatcher]} checked={isVisible[LAYER_IDS.dispatcher]}
> >
<LegendPointItem name="Dispatch center" imageSrc={dispIcon} /> <LegendPointItem name="Диспетчерская" imageSrc={dispIcon} />
</Checkbox> </Checkbox>
</div> </div>
</div> </div>

@ -11,14 +11,14 @@ export const ConsumerParameterSelect = ({ disabled }) => {
return ( return (
<div> <div>
<Title text={"Energy consumer parameter"} /> <Title text={"Показатель потребителя"} />
<TreeSelect <TreeSelect
mode="tags" mode="tags"
style={{ style={{
width: "100%", width: "100%",
}} }}
placeholder="Select parameter" placeholder="Выберите показатель"
onChange={(key) => setConsumerFilter(key)} onChange={(key) => setConsumerFilter(key)}
treeData={CONSUMER_OPTIONS} treeData={CONSUMER_OPTIONS}
allowClear={true} allowClear={true}

@ -51,7 +51,7 @@ export const ConsumerParameterSlider = ({ disabled, isLoading }) => {
<> <>
{consumer_filter && range && ( {consumer_filter && range && (
<Slider <Slider
title={key.includes("prob") ? "Failure likelihood" : key.includes("cooling_time") ? "Cooling time, h" : "Building priority"} title={key.includes("prob") ? "Склонность к аварийности" : key.includes("cooling_time") ? "Время остывания, ч" : "Приоритет здания"}
value={[values[0], values[1]]} value={[values[0], values[1]]}
onAfterChange={handleAfterChange} onAfterChange={handleAfterChange}
min={range[0]} min={range[0]}

@ -6,8 +6,8 @@ import { useMemo } from "react";
const key = "potreb_type"; const key = "potreb_type";
const mapper = { const mapper = {
living_house: "Residential building", living_house: "Жилой дом",
soc_object: "Social facility" soc_object: "Социальный объект"
} }
export const ConsumerTypeSelect = ({ disabled }) => { export const ConsumerTypeSelect = ({ disabled }) => {
const { const {
@ -28,13 +28,13 @@ export const ConsumerTypeSelect = ({ disabled }) => {
}, [data]) }, [data])
return ( return (
<div> <div>
<Title text={"Consumer type"} /> <Title text={"Тип потребителя"} />
<Select <Select
style={{ style={{
width: "100%", width: "100%",
}} }}
placeholder="Select type" placeholder="Выберите тип"
onChange={(v, o) => setConsumerType(o)} onChange={(v, o) => setConsumerType(o)}
options={options} options={options}
allowClear={true} allowClear={true}

@ -25,13 +25,13 @@ export const EnergyClassSelect = ({ disabled }) => {
}, [data]) }, [data])
return ( return (
<div> <div>
<Title text={"Energy efficiency class"} /> <Title text={"Класс энергоэффективности"} />
<Select <Select
style={{ style={{
width: "100%", width: "100%",
}} }}
placeholder="Select type" placeholder="Выберите тип"
onChange={(v, o) => setEnergyClass(o)} onChange={(v, o) => setEnergyClass(o)}
options={options} options={options}
allowClear={true} allowClear={true}

@ -27,7 +27,7 @@ export const DzkhFilters = () => {
{(consumer_filter || source_filter) && <div className="flex items-center justify-end pt-4"> {(consumer_filter || source_filter) && <div className="flex items-center justify-end pt-4">
<div className="flex gap-2"> <div className="flex gap-2">
<Button onClick={() => clear()} type="secondary"> <Button onClick={() => clear()} type="secondary">
Reset filters Сбросить фильтры
</Button> </Button>
</div> </div>
</div>} </div>}

@ -4,7 +4,7 @@ import { useDzkhFilters } from "../../stores/useDzkhFilters.js";
const options = [{ const options = [{
value: "prob6", value: "prob6",
label: "Energy source failure" label: "Авария на ТП"
}]; }];
export const SourceParameterSelect = ({ disabled }) => { export const SourceParameterSelect = ({ disabled }) => {
@ -15,14 +15,14 @@ export const SourceParameterSelect = ({ disabled }) => {
return ( return (
<div> <div>
<Title text={"Energy source parameter"} /> <Title text={"Показатель источника"} />
<TreeSelect <TreeSelect
mode="tags" mode="tags"
style={{ style={{
width: "100%", width: "100%",
}} }}
placeholder="Select parameter" placeholder="Выберите показатель"
onChange={(key) => setSourceFilter(key)} onChange={(key) => setSourceFilter(key)}
treeData={options} treeData={options}
allowClear={true} allowClear={true}

@ -51,7 +51,7 @@ export const SourceParameterSlider = ({ disabled, isLoading }) => {
<> <>
{source_filter && range && ( {source_filter && range && (
<Slider <Slider
title={"Filter by parameter"} title={"Фильтр по показателю"}
value={[values[0], values[1]]} value={[values[0], values[1]]}
onAfterChange={handleAfterChange} onAfterChange={handleAfterChange}
min={range[0]} min={range[0]}

@ -25,13 +25,13 @@ export const WallMaterialSelect = ({ disabled }) => {
}, [data]) }, [data])
return ( return (
<div> <div>
<Title text={"Wall material"} /> <Title text={"Материал стен"} />
<Select <Select
style={{ style={{
width: "100%", width: "100%",
}} }}
placeholder="Select type" placeholder="Выберите тип"
onChange={(v, o) => setWallMaterial(o)} onChange={(v, o) => setWallMaterial(o)}
options={options} options={options}
allowClear={true} allowClear={true}

@ -16,7 +16,7 @@ export const WeatherSlider = ({ disabled, fullRange, isLoading }) => {
return ( return (
<div className="absolute w-[200px] top-[20px] right-[20px] text-xs text-grey z-10 bg-white-background rounded-xl p-3 space-y-3"> <div className="absolute w-[200px] top-[20px] right-[20px] text-xs text-grey z-10 bg-white-background rounded-xl p-3 space-y-3">
<Slider <Slider
title={"Outdoor air temperature"} title={"Температура воздуха на улице"}
value={value} value={value}
onAfterChange={setValue} onAfterChange={setValue}
min={range[0]} min={range[0]}

@ -18,7 +18,7 @@ export const ExportButton = ({ provider }) => {
}; };
return ( return (
<Tooltip title="Download data"> <Tooltip title="Скачать данные">
<Button <Button
onClick={handleExport} onClick={handleExport}
loading={startExport} loading={startExport}

@ -32,7 +32,7 @@ const ToggleFullScreenButton = () => {
return ( return (
<Tooltip <Tooltip
title={fullScreen ? "Collapse" : "Expand to full screen"} title={fullScreen ? "Свернуть" : "Раскрыть на полный экран"}
placement={"topRight"} placement={"topRight"}
open={hover} open={hover}
> >
@ -57,7 +57,7 @@ export const HeaderWrapper = ({
return ( return (
<div className={"flex items-center w-full justify-between"}> <div className={"flex items-center w-full justify-between"}>
<div className={classes?.leftColumn}> <div className={classes?.leftColumn}>
<span className="py-[5px]">Attribute table</span> <span className="py-[5px]">Таблица атрибутов</span>
{leftColumn} {leftColumn}
</div> </div>
<div className={classes?.rightColumn}> <div className={classes?.rightColumn}>

@ -60,7 +60,7 @@ export const Table = React.memo(
"table__wrapper", "table__wrapper",
tableState.fullScreen && "table__wrapper__fullScreen" tableState.fullScreen && "table__wrapper__fullScreen"
)} )}
locale={{ emptyText: <Empty description="No data" /> }} locale={{ emptyText: <Empty description="Нет данных" /> }}
pagination={{ pagination={{
pageSize, pageSize,
current: page, current: page,

@ -1,9 +1,9 @@
import { useEffect, useMemo } from "react"; import {tempMapper} from "../../config";
import { useGetRegions } from "../../components/RegionSelect.jsx"; import {useEffect, useMemo} from "react";
import { tempMapper } from "../../config"; import {useGetRegions} from "../../components/RegionSelect.jsx";
import { useWeatherFilter } from "../../dzkh-features/WeatherSlider/useWeatherFilter.js"; import {useTable} from "../../stores/useTable.js";
import useLocalStorage from "../../hooks/useLocalStorage.js"; import useLocalStorage from "../../hooks/useLocalStorage.js";
import { useTable } from "../../stores/useTable.js"; import {useWeatherFilter} from "../../dzkh-features/WeatherSlider/useWeatherFilter.js";
export const useColumns = (key) => { export const useColumns = (key) => {
const { data: regions } = useGetRegions(); const { data: regions } = useGetRegions();
@ -18,7 +18,7 @@ export const useColumns = (key) => {
const defaultColumns = useMemo(() => { const defaultColumns = useMemo(() => {
return [ return [
{ {
title: "Address", title: "Адрес",
dataIndex: "building_address", dataIndex: "building_address",
key: "building_address", key: "building_address",
width: "120px", width: "120px",
@ -27,7 +27,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "TP number", title: "Номер ТП",
dataIndex: "tp_number", dataIndex: "tp_number",
key: "tp_number", key: "tp_number",
width: "120px", width: "120px",
@ -36,7 +36,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Dispatcher center number", title: "Номер ОДС",
dataIndex: "ods_number", dataIndex: "ods_number",
key: "ods_number", key: "ods_number",
width: "120px", width: "120px",
@ -45,7 +45,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Dispatcher phone", title: "Телефон ОДС",
dataIndex: "phone_number", dataIndex: "phone_number",
key: "phone_number", key: "phone_number",
width: "120px", width: "120px",
@ -54,7 +54,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "No heating in the building", title: "Отсутствие отопления в доме",
dataIndex: `prob1_${tempMapper[temperature]}`, dataIndex: `prob1_${tempMapper[temperature]}`,
key: "prob1", key: "prob1",
width: "120px", width: "120px",
@ -63,7 +63,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Leaking pipes in the entrance", title: "Протечка труб в подъезде",
dataIndex: `prob2_${tempMapper[temperature]}`, dataIndex: `prob2_${tempMapper[temperature]}`,
key: "prob2", key: "prob2",
width: "120px", width: "120px",
@ -72,7 +72,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Apartment temperature below standard", title: "Температура в квартире ниже нормативной",
dataIndex: `prob3_${tempMapper[temperature]}`, dataIndex: `prob3_${tempMapper[temperature]}`,
key: "prob3", key: "prob3",
width: "120px", width: "120px",
@ -81,7 +81,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Common area temperature below standard", title: "Температура в помещении общего пользования ниже нормативной",
dataIndex: `prob4_${tempMapper[temperature]}`, dataIndex: `prob4_${tempMapper[temperature]}`,
key: "prob4", key: "prob4",
width: "120px", width: "120px",
@ -90,7 +90,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Leak in the heating system", title: "Течь в системе отопления",
dataIndex: `prob5_${tempMapper[temperature]}`, dataIndex: `prob5_${tempMapper[temperature]}`,
key: "prob5", key: "prob5",
width: "120px", width: "120px",
@ -99,7 +99,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Energy source failure", title: "Авария на ТП",
dataIndex: `prob6_${tempMapper[temperature]}`, dataIndex: `prob6_${tempMapper[temperature]}`,
key: "prob6", key: "prob6",
width: "120px", width: "120px",
@ -109,7 +109,7 @@ export const useColumns = (key) => {
}, },
{ {
title: "Cooling time, h", title: "Время остывания, ч",
dataIndex: `cooling_time_${tempMapper[temperature]}`, dataIndex: `cooling_time_${tempMapper[temperature]}`,
key: "cooling_time", key: "cooling_time",
width: "120px", width: "120px",
@ -118,7 +118,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Building priority", title: "Приоритет здания",
dataIndex: `priority_${tempMapper[temperature]}`, dataIndex: `priority_${tempMapper[temperature]}`,
key: "priority", key: "priority",
width: "120px", width: "120px",
@ -127,7 +127,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Wall material", title: "Материал стен",
dataIndex: "wall_materials", dataIndex: "wall_materials",
key: "wall_materials", key: "wall_materials",
width: "120px", width: "120px",
@ -136,7 +136,7 @@ export const useColumns = (key) => {
showSorterTooltip: false, showSorterTooltip: false,
}, },
{ {
title: "Energy efficiency class", title: "Класс энергоэффективности",
dataIndex: "fi_energy_class", dataIndex: "fi_energy_class",
key: "fi_energy_class", key: "fi_energy_class",
width: "120px", width: "120px",

@ -1479,7 +1479,7 @@ kdbush@^3.0.0:
resolved "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz" resolved "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz"
integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew== integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==
keycloak-js@>=9.0.2: keycloak-js@>=9.0.2, keycloak-js@22.0.5:
version "22.0.5" version "22.0.5"
resolved "https://registry.npmjs.org/keycloak-js/-/keycloak-js-22.0.5.tgz" resolved "https://registry.npmjs.org/keycloak-js/-/keycloak-js-22.0.5.tgz"
integrity sha512-a7ZwCZeHl8tpeJBy102tZtAnHslDUOA1Nf/sHNF3HYLchKpwoDuaitwIUiS2GnNUe+tlNKLlCqZS+Mi5K79m1w== integrity sha512-a7ZwCZeHl8tpeJBy102tZtAnHslDUOA1Nf/sHNF3HYLchKpwoDuaitwIUiS2GnNUe+tlNKLlCqZS+Mi5K79m1w==

Loading…
Cancel
Save