fix: 优化实时监控布局
This commit is contained in:
parent
faf0a5682e
commit
93bc21a29a
@ -35,6 +35,7 @@ interface RealTimeMonitorProps {
|
|||||||
size: ISize;
|
size: ISize;
|
||||||
setSize: React.Dispatch<React.SetStateAction<ISize>>
|
setSize: React.Dispatch<React.SetStateAction<ISize>>
|
||||||
maxRecordCount?: number;
|
maxRecordCount?: number;
|
||||||
|
warningImgStyle?: React.CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
|
export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
|
||||||
@ -55,14 +56,15 @@ export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
|
|||||||
isRecordListLoading,
|
isRecordListLoading,
|
||||||
size,
|
size,
|
||||||
setSize,
|
setSize,
|
||||||
maxRecordCount
|
maxRecordCount,
|
||||||
|
warningImgStyle,
|
||||||
} = props
|
} = props
|
||||||
const toggleRef = useRef<HTMLDivElement>()
|
const toggleRef = useRef<HTMLDivElement>()
|
||||||
const componentName = getPrefixCls('biz-real-time-monitor', customizePrefixCls);
|
const componentName = getPrefixCls('biz-real-time-monitor', customizePrefixCls);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={componentName} style={{ display: 'flex' }} >
|
<div className={componentName} style={{ display: 'flex' }} >
|
||||||
<WindowToggle
|
<WindowToggle
|
||||||
toggleRef={toggleRef}
|
toggleRef={toggleRef}
|
||||||
selectedWindowKey={selectedWindowKey}
|
selectedWindowKey={selectedWindowKey}
|
||||||
dataSource={videoDataSource}
|
dataSource={videoDataSource}
|
||||||
@ -81,6 +83,7 @@ export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
|
|||||||
recordListTitle="监控预警记录"
|
recordListTitle="监控预警记录"
|
||||||
maxHeight={toggleRef.current?.offsetHeight}
|
maxHeight={toggleRef.current?.offsetHeight}
|
||||||
maxRecordCount={maxRecordCount}
|
maxRecordCount={maxRecordCount}
|
||||||
|
imgStyle={warningImgStyle}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -51,7 +51,7 @@ const WarningRecordList: React.FC<WarningRecordListProps> = (props) => {
|
|||||||
maxRecordCount = 10
|
maxRecordCount = 10
|
||||||
} = props
|
} = props
|
||||||
return (
|
return (
|
||||||
<div className='zhst-biz-warning-record-list' style={{ maxHeight : `${pxToRem(`${maxHeight}`)}` , ...style }} >
|
<div className='zhst-biz-warning-record-list' style={{ maxHeight: `${pxToRem(`${maxHeight}`)}`, ...style }} >
|
||||||
<div className='header'>{recordListTitle}</div>
|
<div className='header'>{recordListTitle}</div>
|
||||||
<div className='body'>
|
<div className='body'>
|
||||||
{
|
{
|
||||||
@ -62,14 +62,14 @@ const WarningRecordList: React.FC<WarningRecordListProps> = (props) => {
|
|||||||
: (dataSource?.length) > 0 ?
|
: (dataSource?.length) > 0 ?
|
||||||
<Space direction='vertical' size={10} >
|
<Space direction='vertical' size={10} >
|
||||||
{dataSource?.map((record, index) => {
|
{dataSource?.map((record, index) => {
|
||||||
if (index > maxRecordCount -1) return
|
if (index > maxRecordCount - 1) return
|
||||||
return (<WarningRecordCard
|
return (<WarningRecordCard
|
||||||
key={record?.id}
|
key={record?.id}
|
||||||
record={record}
|
record={record}
|
||||||
onRecordClick={(record) => { onRecordClick?.(record) }}
|
onRecordClick={(record) => { onRecordClick?.(record) }}
|
||||||
selectedRecordId={selectedRecordId}
|
selectedRecordId={selectedRecordId}
|
||||||
cardStyle={{ width: 300, height: 264, ...cardStyle }}
|
cardStyle={{ ...cardStyle }}
|
||||||
imgStyle={{ width: 280, height: 169, ...imgStyle }}
|
imgStyle={{ ...imgStyle }}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
.body {
|
.body {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
// overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import VideoPlayerCard from '../../../VideoPlayerCard';
|
import VideoPlayerCard from '../../../VideoPlayerCard';
|
||||||
import { VideoPlayerCardProps } from '../../../VideoPlayerCard';
|
import { VideoPlayerCardProps } from '../../../VideoPlayerCard';
|
||||||
import { Segmented, theme } from 'antd';
|
import { Row, Col, Segmented, theme } from 'antd';
|
||||||
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
||||||
import { pxToRem } from '@zhst/func'
|
import { pxToRem } from '@zhst/func'
|
||||||
import './index.less'
|
import './index.less'
|
||||||
|
|
||||||
|
|
||||||
export type ISize = 'large' | 'small'
|
export type ISize = 'large' | 'small'
|
||||||
|
|
||||||
interface WindowToggleProps {
|
interface WindowToggleProps {
|
||||||
|
|
||||||
dataSource?: VideoPlayerCardProps[];
|
dataSource?: VideoPlayerCardProps[];
|
||||||
handleWindowClick?: (key?: string) => void;
|
handleWindowClick?: (key?: string) => void;
|
||||||
handleCloseButtonClick?: (key?: string) => void;
|
handleCloseButtonClick?: (key?: string) => void;
|
||||||
@ -25,50 +23,73 @@ export const WindowToggle: React.FC<WindowToggleProps> = (props) => {
|
|||||||
const { dataSource = [], handleWindowClick, handleCloseButtonClick, selectedWindowKey, size = "large", setSize, toggleRef } = props
|
const { dataSource = [], handleWindowClick, handleCloseButtonClick, selectedWindowKey, size = "large", setSize, toggleRef } = props
|
||||||
const { useToken } = theme
|
const { useToken } = theme
|
||||||
const { token } = useToken()
|
const { token } = useToken()
|
||||||
|
|
||||||
const getLabelStyle = (isSelected: boolean) => ({
|
const getLabelStyle = (isSelected: boolean) => ({
|
||||||
padding: `0 ${pxToRem("11px")}`, background: "#fff",
|
padding: `0 ${pxToRem("11px")}`, background: "#fff",
|
||||||
...(isSelected ? { background: token.colorPrimary, color: '#fff' } : {}),
|
...(isSelected ? { background: token.colorPrimary, color: '#fff' } : {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='zhst-biz-window-toggle' ref={toggleRef}>
|
<div className='zhst-biz-window-toggle' ref={toggleRef}>
|
||||||
{/* 切换按钮 */}
|
{/* 切换按钮 */}
|
||||||
<div className='header'>
|
<div className='header'>
|
||||||
<Segmented
|
<Segmented
|
||||||
defaultValue='large'
|
defaultValue='large'
|
||||||
options={[
|
options={[
|
||||||
{ value: 'large', label: <div style={getLabelStyle(size === 'large')}><BarsOutlined /></div> },
|
{ value: 'large', label: <div style={getLabelStyle(size === 'large')}><BarsOutlined /></div> },
|
||||||
{ value: 'small', label: <div style={getLabelStyle(size === 'small')}><AppstoreOutlined /></div> },
|
{ value: 'small', label: <div style={getLabelStyle(size === 'small')}><AppstoreOutlined /></div> },
|
||||||
]}
|
]}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
// 当一个窗口时 默认 selectedkey 第一条数据的 windowkey
|
// 当一个窗口时 默认 selectedkey 第一条数据的 windowkey
|
||||||
if (value === 'large' && dataSource.length > 0) {
|
if (value === 'large' && dataSource.length > 0) {
|
||||||
const { windowKey } = dataSource[0]
|
const { windowKey } = dataSource[0]
|
||||||
handleWindowClick?.(windowKey)
|
handleWindowClick?.(windowKey)
|
||||||
}
|
}
|
||||||
setSize(value as ISize)
|
setSize(value as ISize)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='body'>
|
<div className='body'>
|
||||||
{
|
|
||||||
dataSource?.map((item, index) => {
|
|
||||||
|
|
||||||
if (size === "large" && index > 0) return
|
<Row gutter={[0, 20]} style={{ width: "100%" }}> {/* 设置栅格间距 */}
|
||||||
return (
|
{
|
||||||
<VideoPlayerCard
|
size === "large" ?
|
||||||
key={size === "large" ? "" : item.windowKey}
|
<>
|
||||||
selectedWindowKey={selectedWindowKey}
|
{
|
||||||
size={size}
|
dataSource?.map((item, index) => { // 仅显示前四个元素,即两行两列
|
||||||
handleWindowClick={handleWindowClick}
|
if (index > 0) return null
|
||||||
handleCloseButtonClick={handleCloseButtonClick}
|
return (
|
||||||
{...item}
|
<Col xs={24} sm={24} md={24} lg={24} xl={24} >
|
||||||
/>)
|
<VideoPlayerCard
|
||||||
})
|
key={""}
|
||||||
}
|
selectedWindowKey={selectedWindowKey}
|
||||||
|
size={size}
|
||||||
|
handleWindowClick={handleWindowClick}
|
||||||
|
handleCloseButtonClick={handleCloseButtonClick}
|
||||||
|
{...item}
|
||||||
|
/>
|
||||||
|
</Col>)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
: <>
|
||||||
|
{dataSource?.map((item) => {
|
||||||
|
return (
|
||||||
|
<Col xs={24} sm={12} md={12} lg={12} xl={12} className='sm-card'>
|
||||||
|
<VideoPlayerCard
|
||||||
|
key={item.windowKey}
|
||||||
|
selectedWindowKey={selectedWindowKey}
|
||||||
|
size={size}
|
||||||
|
handleWindowClick={handleWindowClick}
|
||||||
|
handleCloseButtonClick={handleCloseButtonClick}
|
||||||
|
{...item}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}</>
|
||||||
|
}
|
||||||
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -29,17 +29,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
flex: 1;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #E5EAEC;
|
background-color: #E5EAEC;
|
||||||
padding: 10px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
>div {
|
.sm-card:nth-child(odd) {
|
||||||
margin: 10px;
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm-card:nth-child(even) {
|
||||||
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ import React, { useState } from 'react';
|
|||||||
import { IRecord, RealTimeMonitor, VideoPlayerCardProps, useViewLargerImageModal } from '@zhst/biz';
|
import { IRecord, RealTimeMonitor, VideoPlayerCardProps, useViewLargerImageModal } from '@zhst/biz';
|
||||||
import { videoData, warningData } from './mock';
|
import { videoData, warningData } from './mock';
|
||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
|
import { pxToRem } from '@zhst/func';
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import './index.less'
|
import './index.less'
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ export default () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 对后端返回数据进行处理 组装一套符合属性的 数据
|
// 对后端返回数据进行处理 组装一套符合属性的 数据
|
||||||
// videoSrc : videoData.videoSrc
|
// videoSrc : videoData.videoSrc
|
||||||
const newVideoData: VideoPlayerCardProps = { imageKey: videoData.imageKey, title: videoData.title, odRect: videoData.odRect}
|
const newVideoData: VideoPlayerCardProps = { imageKey: videoData.imageKey, title: videoData.title, odRect: videoData.odRect }
|
||||||
setVideoDataSource((pre) => {
|
setVideoDataSource((pre) => {
|
||||||
const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => {
|
const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => {
|
||||||
// 传给 选中的视频窗口
|
// 传给 选中的视频窗口
|
||||||
@ -153,6 +154,7 @@ export default () => {
|
|||||||
recordListTitle="监控预警记录"
|
recordListTitle="监控预警记录"
|
||||||
size={size}
|
size={size}
|
||||||
setSize={setSize}
|
setSize={setSize}
|
||||||
|
warningImgStyle={{ width: `${pxToRem("280px")}`, height: `${pxToRem("169px")}` }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button onClick={() => { mockData() }}>模拟请求</button>
|
<button onClick={() => { mockData() }}>模拟请求</button>
|
||||||
|
@ -3,7 +3,6 @@ import { theme } from 'antd/lib';
|
|||||||
import { ConfigProvider, VideoPlayer, CropperImage, type VideoViewRef, } from '@zhst/meta';
|
import { ConfigProvider, VideoPlayer, CropperImage, type VideoViewRef, } from '@zhst/meta';
|
||||||
import React, { useState, useEffect, ReactNode, useRef, useContext } from 'react';
|
import React, { useState, useEffect, ReactNode, useRef, useContext } from 'react';
|
||||||
import { CloseOutlined, LoadingOutlined } from '@ant-design/icons';
|
import { CloseOutlined, LoadingOutlined } from '@ant-design/icons';
|
||||||
import { pxToRem } from '@zhst/func'
|
|
||||||
import './index.less'
|
import './index.less'
|
||||||
export interface VideoPlayerCardProps {
|
export interface VideoPlayerCardProps {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
@ -32,7 +31,6 @@ export interface VideoPlayerCardProps {
|
|||||||
|
|
||||||
export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
||||||
|
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider;
|
const { ConfigContext } = ConfigProvider;
|
||||||
const { getPrefixCls } = useContext(ConfigContext);
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
const { prefixCls: customizePrefixCls, showType, imageKey, videoSrc, cardProps, isWindowLoading, errorReasonText, size, title, handleCloseButtonClick, handleWindowClick, windowKey, selectedWindowKey = '', odRect = [] } = props;
|
const { prefixCls: customizePrefixCls, showType, imageKey, videoSrc, cardProps, isWindowLoading, errorReasonText, size, title, handleCloseButtonClick, handleWindowClick, windowKey, selectedWindowKey = '', odRect = [] } = props;
|
||||||
@ -49,10 +47,8 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
|||||||
border: `2px solid ${token.colorPrimary}`, boxShadow: " 0px 2px 9px 0px rgba(0,0,0,0.16)"
|
border: `2px solid ${token.colorPrimary}`, boxShadow: " 0px 2px 9px 0px rgba(0,0,0,0.16)"
|
||||||
}
|
}
|
||||||
const cardStyle: React.CSSProperties = {
|
const cardStyle: React.CSSProperties = {
|
||||||
...(size === 'large' ? { height: `${pxToRem("931px")}` } : { height: `${pxToRem("456px")}` , cursor: 'pointer' }),
|
|
||||||
...(size === 'small' && selectedWindowKey === windowKey ? selectedBorderStyle : {})
|
...(size === 'small' && selectedWindowKey === windowKey ? selectedBorderStyle : {})
|
||||||
};
|
};
|
||||||
const videoPlayerCardStyle = size === 'small' ? { width: `calc(50% - ${pxToRem("20px")})` } : { flex: 1 }
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isWindowLoading && (videoSrc || imageKey)) {
|
if (!isWindowLoading && (videoSrc || imageKey)) {
|
||||||
let contentElement: JSX.Element | null = null;
|
let contentElement: JSX.Element | null = null;
|
||||||
@ -64,7 +60,6 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
|||||||
|
|
||||||
} else if (imageKey) {
|
} else if (imageKey) {
|
||||||
contentElement = (
|
contentElement = (
|
||||||
|
|
||||||
<div style={{ width: "100%", height: "100%" }}>
|
<div style={{ width: "100%", height: "100%" }}>
|
||||||
<CropperImage
|
<CropperImage
|
||||||
// editAble={true}
|
// editAble={true}
|
||||||
@ -72,7 +67,6 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
|||||||
url={imageKey}
|
url={imageKey}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
setCardContent(contentElement);
|
setCardContent(contentElement);
|
||||||
@ -80,10 +74,10 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
|||||||
setCardContent(null)
|
setCardContent(null)
|
||||||
}
|
}
|
||||||
}, [showType, imageKey, videoSrc, isWindowLoading]);
|
}, [showType, imageKey, videoSrc, isWindowLoading]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={componentName} onClick={() => { handleWindowClick?.(windowKey) }} style={videoPlayerCardStyle}>
|
<div className={componentName} onClick={() => { handleWindowClick?.(windowKey) }} >
|
||||||
<Card
|
<Card
|
||||||
|
className={`${size === 'large' ? `${componentName}-large` : `${componentName}-small`}`}
|
||||||
title={
|
title={
|
||||||
<Space style={{ width: "100%", justifyContent: "space-between" }}>
|
<Space style={{ width: "100%", justifyContent: "space-between" }}>
|
||||||
<div>{title}</div>
|
<div>{title}</div>
|
||||||
@ -102,7 +96,7 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
|
|||||||
{cardContent}
|
{cardContent}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ backgroundColor: '#000', height: '100%', display: 'flex', padding: `${pxToRem("20px")}`, boxSizing: 'border-box' }}>
|
<div className={`${componentName}-error`} >
|
||||||
{
|
{
|
||||||
isWindowLoading ?
|
isWindowLoading ?
|
||||||
<div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
<div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
@ -1,4 +1,21 @@
|
|||||||
.zhst-biz-video-player-card {
|
.zhst-biz-video-player-card {
|
||||||
|
&-large {
|
||||||
|
height: 931px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-small {
|
||||||
|
height: 456px;
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
&-error {
|
||||||
|
background-color: #000;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-card-head {
|
.ant-card-head {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useImperativeHandle, useRef, useState, forwardRef, useContext } from 'react';
|
import React, { useImperativeHandle, useRef, useState, forwardRef, useContext } from 'react';
|
||||||
import { Modal, ModalProps, Space, SpaceProps } from 'antd';
|
import { Modal, ModalProps, Space, SpaceProps, theme } from 'antd';
|
||||||
import theme from 'antd/lib/theme';
|
|
||||||
import { DownloadOutlined } from '@ant-design/icons';
|
import { DownloadOutlined } from '@ant-design/icons';
|
||||||
import { ConfigProvider, CropperImage } from '@zhst/meta';
|
import { ConfigProvider, CropperImage } from '@zhst/meta';
|
||||||
|
|
||||||
@ -44,8 +43,6 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
|
|||||||
const { getPrefixCls } = useContext(ConfigContext);
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
const { prefixCls: customizePrefixCls, modalProps, downloadImg, imgStyle, title = '预警大图', downloadText = '下载大图', spaceProps } = props
|
const { prefixCls: customizePrefixCls, modalProps, downloadImg, imgStyle, title = '预警大图', downloadText = '下载大图', spaceProps } = props
|
||||||
const componentName = getPrefixCls('biz-warning-larger-image', customizePrefixCls);
|
const componentName = getPrefixCls('biz-warning-larger-image', customizePrefixCls);
|
||||||
|
|
||||||
|
|
||||||
const { useToken } = theme
|
const { useToken } = theme
|
||||||
const { token } = useToken()
|
const { token } = useToken()
|
||||||
const [open, setOpen] = useState<boolean>(false);
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
@ -85,14 +82,13 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
|
|||||||
{...modalProps}
|
{...modalProps}
|
||||||
>
|
>
|
||||||
<Space size={0} {...spaceProps}>
|
<Space size={0} {...spaceProps}>
|
||||||
<div className={`${componentName}-left-img`} style={{ ...imgStyle }}>
|
<div className={`${componentName}-left-img`} style={{ ...imgStyle }}>
|
||||||
|
<CropperImage
|
||||||
<CropperImage
|
// editAble={false}
|
||||||
// editAble={false}
|
// selectAble={false}
|
||||||
// selectAble={false}
|
odList={odRectDefault}
|
||||||
odList={odRectDefault}
|
url={imageKey}
|
||||||
url={imageKey}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='right-context'>
|
<div className='right-context'>
|
||||||
{warningData?.map(({ label, value }) => (
|
{warningData?.map(({ label, value }) => (
|
||||||
|
Loading…
Reference in New Issue
Block a user