add menu dashboard svg
This commit is contained in:
17
src/App.jsx
17
src/App.jsx
@@ -35,6 +35,13 @@ import IndexUser from './pages/user/IndexUser';
|
||||
import IndexMember from './pages/shiftManagement/member/IndexMember';
|
||||
|
||||
import SvgTest from './pages/home/SvgTest';
|
||||
import SvgOverview from './pages/home/SvgOverview';
|
||||
import SvgCompressorA from './pages/home/SvgCompressorA';
|
||||
import SvgCompressorB from './pages/home/SvgCompressorB';
|
||||
import SvgCompressorC from './pages/home/SvgCompressorC';
|
||||
import SvgAirDryerA from './pages/home/SvgAirDryerA';
|
||||
import SvgAirDryerB from './pages/home/SvgAirDryerB';
|
||||
import SvgAirDryerC from './pages/home/SvgAirDryerC';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
@@ -52,6 +59,16 @@ const App = () => {
|
||||
<Route path="blank" element={<Blank />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/dashboard-svg" element={<ProtectedRoute />}>
|
||||
<Route path="overview" element={<SvgOverview />} />
|
||||
<Route path="compressor-a" element={<SvgCompressorA />} />
|
||||
<Route path="compressor-b" element={<SvgCompressorB />} />
|
||||
<Route path="compressor-c" element={<SvgCompressorC />} />
|
||||
<Route path="airdryer-a" element={<SvgAirDryerA />} />
|
||||
<Route path="airdryer-b" element={<SvgAirDryerB />} />
|
||||
<Route path="airdryer-c" element={<SvgAirDryerC />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/master" element={<ProtectedRoute />}>
|
||||
<Route path="device" element={<IndexDevice />} />
|
||||
<Route path="tag" element={<IndexTag />} />
|
||||
|
||||
@@ -26,6 +26,9 @@ import {
|
||||
TeamOutlined,
|
||||
ClockCircleOutlined,
|
||||
CalendarOutlined,
|
||||
DesktopOutlined,
|
||||
NodeExpandOutlined,
|
||||
GroupOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const { Text } = Typography;
|
||||
@@ -40,6 +43,48 @@ const allItems = [
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg',
|
||||
icon: <GroupOutlined style={{ fontSize: '19px' }} />,
|
||||
label: 'Dashboard',
|
||||
children: [
|
||||
{
|
||||
key: 'dashboard-svg-overview',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/overview">Overview</Link>,
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg-compressor-a',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/compressor-a">Compressor A</Link>,
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg-compressor-b',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/compressor-b">Compressor B</Link>,
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg-compressor-c',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/compressor-c">Compressor C</Link>,
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg-airdryer-a',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/airdryer-a">Air Dryer A</Link>,
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg-airdryer-b',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/airdryer-b">Air Dryer B</Link>,
|
||||
},
|
||||
{
|
||||
key: 'dashboard-svg-airdryer-c',
|
||||
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/dashboard-svg/airdryer-c">Air Dryer C</Link>,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'master',
|
||||
icon: <DatabaseOutlined style={{ fontSize: '19px' }} />,
|
||||
@@ -60,16 +105,16 @@ const allItems = [
|
||||
icon: <MobileOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/master/device">Device</Link>,
|
||||
},
|
||||
{
|
||||
key: 'master-tag',
|
||||
icon: <TagOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/master/tag">Tag</Link>,
|
||||
},
|
||||
{
|
||||
key: 'master-unit',
|
||||
icon: <AppstoreOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/master/unit">Unit</Link>,
|
||||
},
|
||||
{
|
||||
key: 'master-tag',
|
||||
icon: <TagOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/master/tag">Tag</Link>,
|
||||
},
|
||||
{
|
||||
key: 'master-status',
|
||||
icon: <SafetyOutlined style={{ fontSize: '19px' }} />,
|
||||
@@ -163,6 +208,7 @@ const LayoutMenu = () => {
|
||||
if (pathname === '/notification') return 'notification';
|
||||
if (pathname === '/event-alarm') return 'event-alarm';
|
||||
if (pathname === '/jadwal-shift') return 'jadwal-shift';
|
||||
if (pathname === '/dashboard-svg') return 'dashboard-svg';
|
||||
|
||||
// Handle master routes
|
||||
if (pathname.startsWith('/master/')) {
|
||||
@@ -170,6 +216,12 @@ const LayoutMenu = () => {
|
||||
return `master-${subPath}`;
|
||||
}
|
||||
|
||||
// Handle master routes
|
||||
if (pathname.startsWith('/dashboard-svg/')) {
|
||||
const subPath = pathParts[1];
|
||||
return `dashboard-svg-${subPath}`;
|
||||
}
|
||||
|
||||
// Handle history routes
|
||||
if (pathname.startsWith('/history/')) {
|
||||
const subPath = pathParts[1];
|
||||
@@ -188,6 +240,7 @@ const LayoutMenu = () => {
|
||||
// Function to get parent key from menu key
|
||||
const getParentKey = (key) => {
|
||||
if (key.startsWith('master-')) return 'master';
|
||||
if (key.startsWith('dashboard-svg-')) return 'dashboard-svg';
|
||||
if (key.startsWith('history-')) return 'history';
|
||||
if (key.startsWith('shift-')) return 'shift-management';
|
||||
return null;
|
||||
|
||||
20
src/pages/home/SvgAirDryerA.jsx
Normal file
20
src/pages/home/SvgAirDryerA.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/air_dryer_A_rev.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgAirDryerA = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgAirDryerA;
|
||||
20
src/pages/home/SvgAirDryerB.jsx
Normal file
20
src/pages/home/SvgAirDryerB.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/air_dryer_B_rev.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgAirDryerB = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgAirDryerB;
|
||||
20
src/pages/home/SvgAirDryerC.jsx
Normal file
20
src/pages/home/SvgAirDryerC.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/air_dryer_C_rev.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgAirDryerC = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgAirDryerC;
|
||||
20
src/pages/home/SvgCompressorA.jsx
Normal file
20
src/pages/home/SvgCompressorA.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgCompressorA = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgCompressorA;
|
||||
20
src/pages/home/SvgCompressorB.jsx
Normal file
20
src/pages/home/SvgCompressorB.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgCompressorB = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgCompressorB;
|
||||
20
src/pages/home/SvgCompressorC.jsx
Normal file
20
src/pages/home/SvgCompressorC.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgCompressorC = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgCompressorC;
|
||||
20
src/pages/home/SvgOverview.jsx
Normal file
20
src/pages/home/SvgOverview.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import SvgTemplate from './SvgTemplate';
|
||||
import SvgViewer from './SvgViewer';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const filePathSvg = '/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgOverview = () => {
|
||||
return (
|
||||
<SvgTemplate>
|
||||
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
|
||||
</SvgTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgOverview;
|
||||
19
src/pages/home/SvgTemplate.jsx
Normal file
19
src/pages/home/SvgTemplate.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
const SvgTemplate = ({ children }) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '80vh', // penuh 1 layar
|
||||
width: '80vw', // penuh 1 layar lebar
|
||||
overflow: 'hidden', // hilangkan scroll
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#fff', // opsional
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgTemplate;
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
|
||||
import { Card, Typography, Flex } from 'antd';
|
||||
// import { ReactSVG } from 'react-svg';
|
||||
import { setValSvg } from '../../components/Global/MqttConnection';
|
||||
import { ReactSVG } from 'react-svg';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
|
||||
19
src/pages/home/SvgViewer.jsx
Normal file
19
src/pages/home/SvgViewer.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
// SvgViewer.jsx
|
||||
import { ReactSVG } from 'react-svg';
|
||||
|
||||
const SvgViewer = ({ filePathSvg, topicMqtt, setValSvg }) => {
|
||||
return (
|
||||
<ReactSVG
|
||||
src={filePathSvg}
|
||||
beforeInjection={(svg) => {
|
||||
svg.setAttribute('width', '100%');
|
||||
svg.setAttribute('height', '100%');
|
||||
svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
||||
if (setValSvg) setValSvg(topicMqtt, svg);
|
||||
}}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvgViewer;
|
||||
Reference in New Issue
Block a user