Стили вынесены в отдельный файл

This commit is contained in:
Александр Сироткин 2022-12-08 11:48:30 +05:00
parent 65b9ede580
commit 5af996f9e5
2 changed files with 103 additions and 71 deletions

View File

@ -1,19 +1,16 @@
import { CheckOutlined, StopOutlined, QuestionCircleOutlined, WarningOutlined } from '@ant-design/icons'
import { memo, useEffect, useMemo, useState } from 'react' import { memo, useEffect, useMemo, useState } from 'react'
import {
CheckOutlined,
StopOutlined,
QuestionCircleOutlined,
WarningOutlined,
} from '@ant-design/icons'
import { Card, Empty, Popover } from 'antd' import { Card, Empty, Popover } from 'antd'
import { getWellTitle, WellView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { DateRangeWrapper, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table' import { getWellTitle, WellView } from '@components/views'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { DateRangeWrapper, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table'
import { arrayOrDefault, withPermissions } from '@utils' import { arrayOrDefault, withPermissions } from '@utils'
import { SubsystemOperationTimeService } from '@api' import { SubsystemOperationTimeService } from '@api'
import '@styles/statistics_adw.less'
const numericRender = makeNumericRender(2) const numericRender = makeNumericRender(2)
const columns = [ const columns = [
@ -31,15 +28,6 @@ const getSubsystemState = (subsystem) => {
return 'ok' return 'ok'
} }
const getSubsystemColor = (state) => {
switch (state) {
case 'ok': return '#52c41a'
case 'warn': return '#faad14'
case 'error': return '#ff4d4f'
default: return null
}
}
const getSubsystemIcon = (state) => { const getSubsystemIcon = (state) => {
switch (state) { switch (state) {
case 'ok': return <CheckOutlined /> case 'ok': return <CheckOutlined />
@ -51,7 +39,7 @@ const getSubsystemIcon = (state) => {
const getCardState = (subsystems) => { const getCardState = (subsystems) => {
if (subsystems.length <= 0) return null if (subsystems.length <= 0) return null
const states = subsystems.map((ss) => getSubsystemState(ss)) const states = subsystems.map(getSubsystemState)
if (states.some((state) => state === 'error')) return 'error' if (states.some((state) => state === 'error')) return 'error'
if (states.some((state) => state === 'warn')) return 'warn' if (states.some((state) => state === 'warn')) return 'warn'
return 'ok' return 'ok'
@ -61,33 +49,26 @@ const generateSubsystem = (subsystem) => {
const state = getSubsystemState(subsystem) const state = getSubsystemState(subsystem)
return ( return (
<div style={{ display: 'flex', gap: 5, alignItems: 'center', color: getSubsystemColor(state) }}> <div className={`subsystem-status status-${state}`}>
{getSubsystemIcon(state)} {getSubsystemIcon(state)}
<span key={subsystem.key}>{subsystem.subsystemName || subsystem.key}</span> <span key={subsystem.key}>{subsystem.subsystemName || subsystem.key}</span>
</div> </div>
) )
} }
const onRow = (record) => { const onRow = (record) => ({ className: `status-${getSubsystemState(record)}` })
const state = getSubsystemState(record) const objectToArray = (obj) => Object.entries(obj).filter(([_, v]) => v).map(([key, v]) => ({ key, ...v }))
if (state === null) return null
const color = getSubsystemColor(state)
return { style: { backgroundColor: color, color: 'white' } }
}
const GeneralSubsystemStatistics = memo(() => { const GeneralSubsystemStatistics = memo(() => {
const [data, setData] = useState([])
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [dates, setDates] = useState([null, null]) const [dates, setDates] = useState([null, null])
const [data, setData] = useState([])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const data = await SubsystemOperationTimeService.getStatByWell(dates?.[0]?.toISOString(), dates?.[1]?.toISOString()) const data = await SubsystemOperationTimeService.getStatByWell(dates?.[0]?.toISOString(), dates?.[1]?.toISOString())
const out = arrayOrDefault(data).map(({ well, ...subsystems }) => ({ const out = arrayOrDefault(data).map(({ well, ...ss }) => ({ well, subsystems: objectToArray(ss) }))
well,
subsystems: Object.entries(subsystems).filter(([_, v]) => v).map(([key, v]) => ({ key, ...v }))
}))
setData(out) setData(out)
}, },
setIsLoading, setIsLoading,
@ -96,18 +77,12 @@ const GeneralSubsystemStatistics = memo(() => {
) )
}, [dates]) }, [dates])
const cards = useMemo(() => { const cards = useMemo(() => data.map((row) => {
return data.map((row) => {
const state = getCardState(row.subsystems) const state = getCardState(row.subsystems)
const cardStyle = {
boxShadow: `0 0 5px 2px ${getSubsystemColor(state)}`,
userSelect: 'none',
}
const card = ( const card = (
<Card key={row.well.id} title={getWellTitle(row.well)} style={cardStyle}> <Card className={`subsystem-card status-${state}`} key={row.well.id} title={getWellTitle(row.well)}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}> <div className={'subsystem-card-body'}>
{state ? row.subsystems.map((ss) => generateSubsystem(ss)) : <Empty />} {state ? row.subsystems.map((ss) => generateSubsystem(ss)) : <Empty />}
</div> </div>
</Card> </Card>
@ -115,14 +90,15 @@ const GeneralSubsystemStatistics = memo(() => {
if (!state) return card if (!state) return card
const detailTitle = ( return (
<Popover
title={(
<> <>
<span style={{ paddingRight: 15 }}>Детальная информация по скважине</span> <span style={{ paddingRight: 15 }}>Детальная информация по скважине</span>
<WellView well={row.well} /> <WellView well={row.well} />
</> </>
) )}
content={(
const detailContent = (
<Table <Table
size={'small'} size={'small'}
pagination={false} pagination={false}
@ -130,22 +106,19 @@ const GeneralSubsystemStatistics = memo(() => {
columns={columns} columns={columns}
onRow={onRow} onRow={onRow}
/> />
)}
>{card}</Popover>
) )
}), [data])
return <Popover title={detailTitle} content={detailContent}>{card}</Popover>
})
}, [data])
return ( return (
<LoaderPortal show={isLoading} style={{ flex: 1 }}> <LoaderPortal show={isLoading} style={{ flex: 1 }}>
<div className={'general-statistics'} style={{ display: 'flex', flexDirection: 'column', alignItems: 'stretch', gap: 20, height: '100%' }}> <div className={'statistics-adw-page'}>
<div style={{ paddingLeft: 15, display: 'flex', gap: 10, alignItems: 'center' }}> <div className={'filter-block'}>
<span>Диапазон дат:</span> <span>Диапазон дат:</span>
<DateRangeWrapper allowClear onChange={setDates} value={dates} /> <DateRangeWrapper allowClear onChange={setDates} value={dates} />
</div> </div>
<div style={{ padding: 15, display: 'flex', flexWrap: 'wrap', alignItems: 'baseline', gap: 15 }}> <div className={'well-cards'}>{cards}</div>
{cards}
</div>
</div> </div>
</LoaderPortal> </LoaderPortal>
) )

View File

@ -0,0 +1,59 @@
@ok-color: #52c41a;
@warn-color: #faad14;
@error-color: #ff4d4f;
.statistics-adw-page {
display: flex;
flex-direction: column;
align-items: stretch;
gap: 20px;
height: 100%;
& .filter-block {
align-items: center;
padding-left: 15px;
display: flex;
gap: 10px;
}
& .well-cards {
padding: 15px;
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 15px;
& .subsystem-card {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
&.status-ok { box-shadow: 0 0 5px 2px @ok-color; }
&.status-warn { box-shadow: 0 0 5px 2px @warn-color; }
&.status-error { box-shadow: 0 0 5px 2px @error-color; }
& .subsystem-card-body {
display: flex;
flex-direction: column;
gap: 10px;
& .subsystem-status {
display: flex;
gap: 5px;
align-items: center;
&.status-ok { color: @ok-color; }
&.status-warn { color: @warn-color; }
&.status-error { color: @error-color; }
}
}
}
}
}
.ant-table-row {
&.status-ok { background-color: @ok-color; }
&.status-warn { background-color: @warn-color; }
&.status-error { background-color: @error-color; }
}