Compare commits
33 Commits
lavoce
...
c10a5bf62d
| Author | SHA1 | Date | |
|---|---|---|---|
| c10a5bf62d | |||
| 6cc5042956 | |||
| 5079f8d316 | |||
| 7073390de7 | |||
| 4226a24e79 | |||
| 038009433f | |||
| 64ba51b17c | |||
| 47d0638a42 | |||
| d8c5f3ed44 | |||
| affd9146bb | |||
| 4022b3f8f4 | |||
| 446a4e2b95 | |||
| 83a475c708 | |||
| ab1c510a77 | |||
| 59859c6d18 | |||
| 2bd27937dc | |||
| 1058c660d6 | |||
| 35b2167791 | |||
| ec676983d0 | |||
| c07c5f8235 | |||
| b32ad97034 | |||
| 76244f6f6e | |||
| 0a128cbb3c | |||
| bd4ab26680 | |||
| 3e728a1ff5 | |||
| 9db143972e | |||
| 029ea269a7 | |||
| 4cdaa042da | |||
| 56af2a16c0 | |||
| deadf2ffb4 | |||
| 4da80c7089 | |||
| 56e3ce78a6 | |||
| 7c2a019dd2 |
@@ -4,7 +4,3 @@ VITE_MQTT_SERVER=ws://localhost:1884
|
||||
VITE_MQTT_USERNAME=
|
||||
VITE_MQTT_PASSWORD=
|
||||
VITE_KEY_SESSION=PetekRombonganPetekMorekMorakMarek
|
||||
|
||||
# VITE_WHATSAPP_URL=http://192.168.1.10:9531/qrview
|
||||
VITE_WHATSAPP_URL=http://localhost:9531/qrview
|
||||
# VITE_WHATSAPP_URL=https://117.102.231.130:9531/qrview
|
||||
1
.gitignore
vendored
@@ -6,6 +6,7 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
*.config
|
||||
|
||||
node_modules
|
||||
dist
|
||||
|
||||
92
package.json
@@ -1,48 +1,48 @@
|
||||
{
|
||||
"name": "antd-vite-react-call-of-duty",
|
||||
"homepage": "/dashboard/home",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host 0.0.0.0 --port 8592",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@nivo/line": "^0.88.0",
|
||||
"@nivo/pie": "^0.88.0",
|
||||
"antd": "^5.15.2",
|
||||
"axios": "^1.8.4",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jspdf": "^3.0.4",
|
||||
"jspdf-autotable": "^5.0.2",
|
||||
"mqtt": "^5.14.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-svg": "^16.3.0",
|
||||
"recharts": "^3.6.0",
|
||||
"sweetalert2": "^11.17.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.64",
|
||||
"@types/react-dom": "^18.2.21",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.5",
|
||||
"vite": "^5.1.6"
|
||||
},
|
||||
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
|
||||
"name": "antd-vite-react-sypiu",
|
||||
"homepage": "/dashboard/home",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@nivo/line": "^0.88.0",
|
||||
"@nivo/pie": "^0.88.0",
|
||||
"antd": "^5.15.2",
|
||||
"axios": "^1.8.4",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jspdf": "^3.0.4",
|
||||
"jspdf-autotable": "^5.0.2",
|
||||
"mqtt": "^5.14.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-svg": "^16.3.0",
|
||||
"recharts": "^3.6.0",
|
||||
"sweetalert2": "^11.17.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.64",
|
||||
"@types/react-dom": "^18.2.21",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.5",
|
||||
"vite": "^5.1.6"
|
||||
},
|
||||
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="reactViteSypiu">
|
||||
<rule name="CallOfDuty">
|
||||
<match url=".*" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
|
||||
@@ -36,7 +36,6 @@ import IndexNotification from './pages/notification/IndexNotification';
|
||||
import IndexRole from './pages/role/IndexRole';
|
||||
import IndexUser from './pages/user/IndexUser';
|
||||
import IndexContact from './pages/contact/IndexContact';
|
||||
import IndexWhatsAppControl from './pages/whatsAppControl/IndexWhatsAppControl';
|
||||
import DetailNotificationTab from './pages/notificationDetail/IndexNotificationDetail';
|
||||
import IndexVerificationSparepart from './pages/verificationSparepart/IndexVerificationSparepart';
|
||||
|
||||
@@ -54,7 +53,6 @@ import IndexHistoryEvent from './pages/history/event/IndexHistoryEvent';
|
||||
|
||||
// Image Viewer
|
||||
import ImageViewer from './Utils/ImageViewer';
|
||||
import RedirectWa from './pages/blank/RedirectWa';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
@@ -74,8 +72,6 @@ const App = () => {
|
||||
element={<IndexVerificationSparepart />}
|
||||
/>
|
||||
|
||||
<Route path="/redirect" element={<RedirectWa />} />
|
||||
|
||||
{/* Protected Routes */}
|
||||
<Route path="/dashboard" element={<ProtectedRoute />}>
|
||||
<Route path="home" element={<Home />} />
|
||||
@@ -145,10 +141,6 @@ const App = () => {
|
||||
<Route index element={<IndexUser />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/whatsapp-control" element={<ProtectedRoute />}>
|
||||
<Route index element={<IndexWhatsAppControl />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/contact" element={<ProtectedRoute />}>
|
||||
<Route index element={<IndexContact />} />
|
||||
</Route>
|
||||
|
||||
@@ -46,81 +46,10 @@ const getNotificationLogByNotificationId = async (notificationId) => {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// update is_read status
|
||||
const updateIsRead = async (notificationId) => {
|
||||
const response = await SendRequest({
|
||||
method: 'put',
|
||||
prefix: `notification/${notificationId}`,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Resend notification to specific user
|
||||
const resendNotificationToUser = async (notificationId, userId) => {
|
||||
const response = await SendRequest({
|
||||
method: 'post',
|
||||
prefix: `notification/${notificationId}/resend/${userId}`,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Resend Chat by User
|
||||
const resendChatByUser = async (notificationId, userPhone) => {
|
||||
const response = await SendRequest({
|
||||
method: 'post',
|
||||
prefix: `notification-user/resend/${notificationId}/${userPhone}`,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Resend Chat All User
|
||||
const resendChatAllUser = async (notificationId) => {
|
||||
const response = await SendRequest({
|
||||
method: 'post',
|
||||
prefix: `notification/resend/${notificationId}`,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Searching
|
||||
const searchData = async (queryParams) => {
|
||||
const response = await SendRequest({
|
||||
method: 'get',
|
||||
prefix: `notification?criteria=${queryParams}`,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Reminder Monthly
|
||||
const reminderMonthly = async (id, queryParams) => {
|
||||
const response = await SendRequest({
|
||||
method: 'post',
|
||||
prefix: `notifikasi-wa/reminder-monthly/${id}`,
|
||||
params: queryParams,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
const reminderCustom= async (id, queryParams) => {
|
||||
const response = await SendRequest({
|
||||
method: 'post',
|
||||
prefix: `notifikasi-wa/reminder-custom/${id}`,
|
||||
params: queryParams,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export {
|
||||
getAllNotification,
|
||||
getNotificationById,
|
||||
getNotificationDetail,
|
||||
createNotificationLog,
|
||||
getNotificationLogByNotificationId,
|
||||
updateIsRead,
|
||||
resendNotificationToUser,
|
||||
resendChatByUser,
|
||||
resendChatAllUser,
|
||||
searchData,
|
||||
reminderMonthly,
|
||||
reminderCustom,
|
||||
getNotificationLogByNotificationId
|
||||
};
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { SendRequest } from '../components/Global/ApiRequest';
|
||||
|
||||
const resetWA = async () => {
|
||||
const response = await SendRequest({
|
||||
method: 'post',
|
||||
prefix: `notifikasi-wa/restart-wa`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export { resetWA };
|
||||
@@ -26,26 +26,27 @@
|
||||
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 490.992px 230.229px;" d="M 646.097 240.002 L 676.271 240.002"/>
|
||||
</g>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 443.701px 171.141px;" d="M 443.542 155.983 L 443.859 186.298"/>
|
||||
<g>
|
||||
<rect x="622.282" y="251.383" width="35.093" height="2.463" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<g>
|
||||
<rect x="625.861" y="254.048" width="28.143" height="37.69" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="625.711" y="248.983" width="28.143" height="2.361" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);" cx="640.016" cy="271.807" rx="9.717" ry="7.689"/>
|
||||
</g>
|
||||
<g transform="matrix(0.826913, 0, 0, 0.698383, 0.443817, 3.138935)">
|
||||
<rect x="752" y="355.455" width="42.438" height="3.527" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="756.328" y="359.271" width="34.034" height="53.968" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="756.146" y="352.019" width="34.034" height="3.38" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);" cx="773.446" cy="384.7" rx="11.751" ry="11.009"/>
|
||||
</g>
|
||||
<rect x="461.861" y="211.956" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px;" x="561" y="309.954" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp SP</text>
|
||||
<rect x="461.861" y="221.924" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="564.279" y="330.561" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="609.476" y="330.521" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<rect x="461.424" y="242.149" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="567.471" y="352.188" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
|
||||
<rect x="461.424" y="252.117" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="563.75" y="373.795" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="Dry1_HeatTempCelsius">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="608.947" y="373.755" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<rect x="535.456" y="242.272" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="659" y="352.363" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
|
||||
<rect x="535.456" y="252.24" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1; font-weight: bold;" x="748" y="347.676" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER</text>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 678.512px 258.693px;" d="M 678.467 229.321 L 678.558 288.066" transform="matrix(0, 1.184039, -0.844567, 0, -0.000022, -0.000005)"/>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 703.162px 309.166px;" d="M 703.004 258.049 L 703.32 360.282"/>
|
||||
@@ -107,10 +108,12 @@
|
||||
<rect x="427.269" y="377.282" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.167" y="545.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
|
||||
<rect x="427.269" y="387.25" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.643" y="567.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
|
||||
<rect x="427.27" y="412.201" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.168" y="595.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
|
||||
<rect x="427.27" y="422.169" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.644" y="617.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1; text-anchor: middle; font-weight: bolder;" x="602.463" y="573.003" transform="matrix(0.826913, 0, 0, 0.698383, 24.207672, -7.192523)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>OUTLET</text>
|
||||
<g transform="matrix(-0.387768, 0, 0, -0.200385, 743.634644, -199.991287)" style="transform-origin: 72.2405px 412.5px;">
|
||||
@@ -174,36 +177,43 @@
|
||||
<rect x="43.443" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="53.987" y="423.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RUN HOUR</text>
|
||||
<rect x="126.135" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="424.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="424.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="461.382" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">PURGE HOUR</text>
|
||||
<rect x="126.135" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="463.397" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="463.357" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; font-weight: 700; white-space: pre;" x="53.987" y="498.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER HOUR</text>
|
||||
<rect x="126.135" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="499.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="499.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.65" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(248, 213, 14);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="536.777" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Info</text>
|
||||
<rect x="126.341" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4501">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="56.987" y="250.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT or LT Dry</text>
|
||||
<rect x="126.135" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, -3.902357, 3.138935)" id="c_4022">#######</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">LT Dry</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177" y="251.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT Dry</text>
|
||||
<rect x="43.443" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text>
|
||||
<rect x="126.135" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -0.902357, 3.138935)" id="c_4015">#####</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HTD</text>
|
||||
<rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
|
||||
<rect x="43.443" y="241.422" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="364.271" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Cycle Timer</text>
|
||||
<rect x="126.341" y="241.068" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="365.246" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="141.894" y="324.069" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Time</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">##</text>
|
||||
<rect x="870.356" y="142.816" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="1060.06" y="224.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dryer Status</text>
|
||||
<rect x="870.356" y="170.304" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
@@ -217,31 +227,12 @@
|
||||
<rect x="870.356" y="344.9" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="366.997" rx="20.673" ry="17.46"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="380.451" y="296.591" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="334.165" cy="232.104" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="379.214" y="423.395" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.623" cy="320.662" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="897.237" y="299.014" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.502" cy="233.796" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="896" y="425.818" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 35px; stroke-width: 1; font-weight: bold;" x="348.875" y="78.242" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">AIR DRYER UNIT A (01-CL-10532-A)</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4005">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4004">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4001">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="563.75" y="373.795" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4002">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="564.279" y="330.561" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4003">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="424.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4009">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="463.397" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4010">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="499.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4011">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4008">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4007">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4006">##</text>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(255, 172, 63);" cx="640.283" cy="271.689" rx="9.717" ry="7.689" id="c_4019"/>
|
||||
<ellipse style="fill: rgb(63, 255, 69); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.254" cy="192.696" rx="20.673" ry="17.46" id="c_4016"/>
|
||||
<ellipse style="fill: rgb(255, 159, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="279.12" rx="20.673" ry="17.46" id="c_4017"/>
|
||||
<ellipse style="fill: rgb(255, 63, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="366.862" rx="20.673" ry="17.46" id="c_4020"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_4018"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517" id="c_4018"/>
|
||||
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517" id="c_4021"/>
|
||||
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.772" cy="237.876" rx="13.582" ry="12.517" id="c_4021"/>
|
||||
<!-- <ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id=""/> -->
|
||||
<!-- <ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="320.687" rx="13.582" ry="12.517" id="-2"/> -->
|
||||
<!-- <ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="322.259" rx="13.582" ry="12.517" id="c_-2"/> -->
|
||||
<!-- <ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="237.483" rx="13.582" ry="12.517" id="c_-3"/> -->
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 40 KiB |
@@ -3,7 +3,7 @@
|
||||
<defs>
|
||||
<bx:grid x="0" y="0" width="25" height="25"/>
|
||||
</defs>
|
||||
<rect y="10.407" width="972.648" height="440.159" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" x="12.119"/>
|
||||
<rect y="10.407" width="972.648" height="439.023" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" x="12.119"/>
|
||||
<g transform="matrix(0.826913, 0, 0, 0.698383, 74.03907, 53.375034)">
|
||||
<ellipse style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);" cx="315" cy="183.068" rx="45" ry="45"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);" cx="315" cy="449.112" rx="45" ry="45"/>
|
||||
@@ -26,26 +26,27 @@
|
||||
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 490.992px 230.229px;" d="M 646.097 240.002 L 676.271 240.002"/>
|
||||
</g>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 443.701px 171.141px;" d="M 443.542 155.983 L 443.859 186.298"/>
|
||||
<g>
|
||||
<rect x="622.282" y="251.383" width="35.093" height="2.463" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<g>
|
||||
<rect x="625.861" y="254.048" width="28.143" height="37.69" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="625.711" y="248.983" width="28.143" height="2.361" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);" cx="640.016" cy="271.807" rx="9.717" ry="7.689"/>
|
||||
</g>
|
||||
<g transform="matrix(0.826913, 0, 0, 0.698383, 0.443817, 3.138935)">
|
||||
<rect x="752" y="355.455" width="42.438" height="3.527" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="756.328" y="359.271" width="34.034" height="53.968" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="756.146" y="352.019" width="34.034" height="3.38" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);" cx="773.446" cy="384.7" rx="11.751" ry="11.009"/>
|
||||
</g>
|
||||
<rect x="461.861" y="211.956" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px;" x="561" y="309.954" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp SP</text>
|
||||
<rect x="461.861" y="221.924" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="564.279" y="330.561" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="609.476" y="330.521" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<rect x="461.424" y="242.149" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="567.471" y="352.188" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
|
||||
<rect x="461.424" y="252.117" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="563.75" y="373.795" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="Dry1_HeatTempCelsius">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="608.947" y="373.755" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<rect x="535.456" y="242.272" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="659" y="352.363" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
|
||||
<rect x="535.456" y="252.24" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1; font-weight: bold;" x="748" y="347.676" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER</text>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 678.512px 258.693px;" d="M 678.467 229.321 L 678.558 288.066" transform="matrix(0, 1.184039, -0.844567, 0, -0.000022, -0.000005)"/>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 703.162px 309.166px;" d="M 703.004 258.049 L 703.32 360.282"/>
|
||||
@@ -107,10 +108,12 @@
|
||||
<rect x="427.269" y="377.282" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.167" y="545.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
|
||||
<rect x="427.269" y="387.25" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.643" y="567.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
|
||||
<rect x="427.27" y="412.201" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.168" y="595.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
|
||||
<rect x="427.27" y="422.169" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.644" y="617.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1; text-anchor: middle; font-weight: bolder;" x="602.463" y="573.003" transform="matrix(0.826913, 0, 0, 0.698383, 24.207672, -7.192523)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>OUTLET</text>
|
||||
<g transform="matrix(-0.387768, 0, 0, -0.200385, 743.634644, -199.991287)" style="transform-origin: 72.2405px 412.5px;">
|
||||
@@ -174,36 +177,43 @@
|
||||
<rect x="43.443" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="53.987" y="423.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RUN HOUR</text>
|
||||
<rect x="126.135" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="424.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="424.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="461.382" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">PURGE HOUR</text>
|
||||
<rect x="126.135" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="463.397" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="463.357" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; font-weight: 700; white-space: pre;" x="53.987" y="498.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER HOUR</text>
|
||||
<rect x="126.135" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="499.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="499.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.65" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(248, 213, 14);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="536.777" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Info</text>
|
||||
<rect x="126.341" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5501">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="56.987" y="250.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT or LT Dry</text>
|
||||
<rect x="126.135" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, -3.902357, 3.138935)" id="c_5022">#######</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">LT Dry</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177" y="251.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT Dry</text>
|
||||
<rect x="43.443" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text>
|
||||
<rect x="126.135" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 0.097643, 3.138935)" id="c_5015">#####</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HTD</text>
|
||||
<rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
|
||||
<rect x="43.443" y="241.422" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="364.271" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Cycle Timer</text>
|
||||
<rect x="126.341" y="241.068" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="365.246" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="141.894" y="324.069" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Time</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">##</text>
|
||||
<rect x="870.356" y="142.816" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="1060.06" y="224.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dryer Status</text>
|
||||
<rect x="870.356" y="170.304" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
@@ -217,31 +227,12 @@
|
||||
<rect x="870.356" y="344.9" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="366.997" rx="20.673" ry="17.46"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="380.451" y="296.591" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="334.165" cy="232.104" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="379.214" y="423.395" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.623" cy="320.662" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="897.237" y="299.014" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.502" cy="233.796" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="896" y="425.818" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 35px; stroke-width: 1; font-weight: bold;" x="348.875" y="78.242" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">AIR DRYER UNIT B (01-CL-10535-B)</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5005">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5004">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5001">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="563.75" y="373.795" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5002">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="564.279" y="330.561" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5003">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="424.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5009">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="463.397" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5010">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="499.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5011">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5008">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5007">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5006">##</text>
|
||||
<!-- <ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.517" rx="13.582" ry="12.517" id=""/> -->
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(255, 172, 63);" cx="640.283" cy="271.689" rx="9.717" ry="7.689" id="c_5019"/>
|
||||
<ellipse style="fill: rgb(63, 255, 69); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.254" cy="192.696" rx="20.673" ry="17.46" id="c_5016"/>
|
||||
<ellipse style="fill: rgb(255, 159, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="279.12" rx="20.673" ry="17.46" id="c_5017"/>
|
||||
<ellipse style="fill: rgb(255, 63, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="366.862" rx="20.673" ry="17.46" id="c_5020"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_5018"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517" id="c_5018"/>
|
||||
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517" id="c_5021"/>
|
||||
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" rx="13.582" ry="12.517" id="c_5021"/>
|
||||
<!-- <ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="320.662" rx="13.582" ry="12.517" id=""/> -->
|
||||
<!-- <ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="322.125" rx="13.582" ry="12.517" id="c_-2"/> -->
|
||||
<!-- <ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.418" cy="234.26" rx="13.582" ry="12.517" id="c_-3"/> -->
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 40 KiB |
@@ -3,7 +3,7 @@
|
||||
<defs>
|
||||
<bx:grid x="0" y="0" width="25" height="25"/>
|
||||
</defs>
|
||||
<rect y="10.407" width="972.648" height="440.159" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" x="12.119"/>
|
||||
<rect y="10.407" width="972.648" height="439.023" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" x="12.119"/>
|
||||
<g transform="matrix(0.826913, 0, 0, 0.698383, 74.03907, 53.375034)">
|
||||
<ellipse style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);" cx="315" cy="183.068" rx="45" ry="45"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);" cx="315" cy="449.112" rx="45" ry="45"/>
|
||||
@@ -26,26 +26,27 @@
|
||||
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 490.992px 230.229px;" d="M 646.097 240.002 L 676.271 240.002"/>
|
||||
</g>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 443.701px 171.141px;" d="M 443.542 155.983 L 443.859 186.298"/>
|
||||
<g>
|
||||
<rect x="622.282" y="251.383" width="35.093" height="2.463" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<g>
|
||||
<rect x="625.861" y="254.048" width="28.143" height="37.69" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="625.711" y="248.983" width="28.143" height="2.361" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(243, 243, 243);" cx="640.016" cy="271.807" rx="9.717" ry="7.689"/>
|
||||
</g>
|
||||
<g transform="matrix(0.826913, 0, 0, 0.698383, 0.443817, 3.138935)">
|
||||
<rect x="752" y="355.455" width="42.438" height="3.527" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="756.328" y="359.271" width="34.034" height="53.968" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<rect x="756.146" y="352.019" width="34.034" height="3.38" style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);"/>
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1; fill: rgb(243, 243, 243);" cx="773.446" cy="384.7" rx="11.751" ry="11.009"/>
|
||||
</g>
|
||||
<rect x="461.861" y="211.956" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px;" x="561" y="309.954" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp SP</text>
|
||||
<rect x="461.861" y="221.924" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="564.279" y="330.561" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="609.476" y="330.521" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<rect x="461.424" y="242.149" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="567.471" y="352.188" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
|
||||
<rect x="461.424" y="252.117" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="563.75" y="373.795" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="Dry1_HeatTempCelsius">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="608.947" y="373.755" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<rect x="535.456" y="242.272" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="659" y="352.363" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
|
||||
<rect x="535.456" y="252.24" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1; font-weight: bold;" x="748" y="347.676" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER</text>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 678.512px 258.693px;" d="M 678.467 229.321 L 678.558 288.066" transform="matrix(0, 1.184039, -0.844567, 0, -0.000022, -0.000005)"/>
|
||||
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 703.162px 309.166px;" d="M 703.004 258.049 L 703.32 360.282"/>
|
||||
@@ -107,10 +108,12 @@
|
||||
<rect x="427.269" y="377.282" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.167" y="545.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
|
||||
<rect x="427.269" y="387.25" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.643" y="567.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
|
||||
<rect x="427.27" y="412.201" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.168" y="595.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
|
||||
<rect x="427.27" y="422.169" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.644" y="617.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1; text-anchor: middle; font-weight: bolder;" x="602.463" y="573.003" transform="matrix(0.826913, 0, 0, 0.698383, 24.207672, -7.192523)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>OUTLET</text>
|
||||
<g transform="matrix(-0.387768, 0, 0, -0.200385, 743.634644, -199.991287)" style="transform-origin: 72.2405px 412.5px;">
|
||||
@@ -174,36 +177,43 @@
|
||||
<rect x="43.443" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="53.987" y="423.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RUN HOUR</text>
|
||||
<rect x="126.135" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="424.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="424.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="461.382" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">PURGE HOUR</text>
|
||||
<rect x="126.135" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="463.397" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="463.357" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; font-weight: 700; white-space: pre;" x="53.987" y="498.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER HOUR</text>
|
||||
<rect x="126.135" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="499.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="499.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.65" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(248, 213, 14);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="536.777" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Info</text>
|
||||
<rect x="126.341" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6501">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
|
||||
<rect x="43.443" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="56.987" y="250.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT or LT Dry</text>
|
||||
<rect x="126.135" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, -3.902357, 3.138935)" id="c_6022">#######</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">LT Dry</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177" y="251.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT Dry</text>
|
||||
<rect x="43.443" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text>
|
||||
<rect x="126.135" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -1.902357, 3.138935)" id="c_6015">#####</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HTD</text>
|
||||
<rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
|
||||
<rect x="43.443" y="241.422" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="364.271" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Cycle Timer</text>
|
||||
<rect x="126.341" y="241.068" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="365.246" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="141.894" y="324.069" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Time</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">##</text>
|
||||
<rect x="870.356" y="142.816" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="1060.06" y="224.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dryer Status</text>
|
||||
<rect x="870.356" y="170.304" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
@@ -217,31 +227,12 @@
|
||||
<rect x="870.356" y="344.9" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="366.997" rx="20.673" ry="17.46"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="380.451" y="296.591" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="334.165" cy="232.104" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="379.214" y="423.395" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.623" cy="320.662" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="897.237" y="299.014" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.502" cy="233.796" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="896" y="425.818" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517"/>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 35px; stroke-width: 1; font-weight: bold;" x="348.875" y="78.242" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">AIR DRYER UNIT C (01-CL-10539-C)</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6005">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6004">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6001">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="563.75" y="373.795" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6002">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="564.279" y="330.561" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6003">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="424.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6009">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="463.397" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6010">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.05" y="499.106" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6011">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6008">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6007">####.##</text>
|
||||
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6006">##</text>
|
||||
<!-- <ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.517" rx="13.582" ry="12.517" id=""/> -->
|
||||
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(255, 172, 63);" cx="640.283" cy="271.689" rx="9.717" ry="7.689" id="c_6019"/>
|
||||
<ellipse style="fill: rgb(63, 255, 69); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.254" cy="192.696" rx="20.673" ry="17.46" id="c_6016"/>
|
||||
<ellipse style="fill: rgb(255, 159, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="279.12" rx="20.673" ry="17.46" id="c_6017"/>
|
||||
<ellipse style="fill: rgb(255, 63, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="366.862" rx="20.673" ry="17.46" id="c_6020"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_6018"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517" id="c_6018"/>
|
||||
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517" id="c_6021"/>
|
||||
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.418" cy="237.483" rx="13.582" ry="12.517" id="c_6021"/>
|
||||
<!-- <ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="322.692" rx="13.582" ry="12.517" id="c_-2"/> -->
|
||||
<!-- <ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.095" rx="13.582" ry="12.517" id=""/> -->
|
||||
<!-- <ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.418" cy="237.483" rx="13.582" ry="12.517" id="c_-3"/> -->
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
@@ -3,12 +3,12 @@
|
||||
<defs>
|
||||
<bx:grid x="0" y="0" width="25" height="25"/>
|
||||
</defs>
|
||||
<rect x="12.259" y="8.086" width="924.818" height="441.914" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<rect x="25" y="66.111" width="900" height="358.889" style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);"/>
|
||||
<rect x="75.168" y="97.354" width="100.126" height="21.994" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="75.168" y="118.75" width="100.126" height="43.75" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="150.26" cy="129.561" rx="11.265" ry="9.613"/>
|
||||
<g transform="matrix(1.133434, 0, 0, 1.08014, 15.782269, 151.992333)" style="">
|
||||
<rect x="12.226" y="12.005" width="924.818" height="476.396" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<rect x="25" y="75" width="900" height="400" style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);"/>
|
||||
<rect x="50" y="100.548" width="100.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="50" y="125" width="100.168" height="50" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="125.124" cy="137.355" rx="11.269" ry="10.987"/>
|
||||
<g transform="matrix(1.13391, 0, 0, 1.234446, -9.410634, 162.99009)" style="">
|
||||
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 363.181 109.151 L 363.181 110.989 L 460.721 110.989 L 469.183 107.313 L 469.183 105.958 L 460.721 109.151 L 363.181 109.151 Z"/>
|
||||
<path style="fill: rgb(115, 135, 166); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 361.061 109.151 L 361.061 53.909 L 462.836 53.909 L 462.836 109.151 L 361.061 109.151 Z"/>
|
||||
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 445.801 105.475 L 445.801 57.586 L 454.374 57.586 L 454.374 105.475 L 445.801 105.475 Z"/>
|
||||
@@ -53,31 +53,31 @@
|
||||
<path style="fill: rgb(89, 109, 140); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 462.836 53.909 L 471.299 50.233 L 471.299 105.475 L 462.836 109.151 L 462.836 53.909 Z"/>
|
||||
<path style="fill: rgb(191, 211, 242); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 462.836 53.909 L 471.299 50.233 L 369.521 50.233 L 361.061 53.909 L 462.836 53.909 Z"/>
|
||||
</g>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre;" x="56" y="116.982" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">AirDryer A</text>
|
||||
<rect x="75.168" y="140.625" width="99.958" height="21.875" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.368" y="141.716" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.949" y="168.123" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.007" y="167.208" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)" id="c_4009">####</text>
|
||||
<rect x="75" y="206.73" width="100.126" height="21.994" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="75" y="228.125" width="100.126" height="43.75" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="150.092" cy="238.935" rx="11.265" ry="9.613"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="241.982" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">AirDryer B</text>
|
||||
<rect x="75" y="250" width="99.958" height="21.875" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="266.716" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="293.123" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="292.208" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)" id="c_5009">####</text>
|
||||
<rect x="75" y="316.104" width="100.126" height="21.994" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="75" y="337.5" width="100.126" height="43.75" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="150.092" cy="348.311" rx="11.265" ry="9.613"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="366.982" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">AirDryer C</text>
|
||||
<rect x="75" y="359.375" width="99.958" height="21.875" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="391.716" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="418.123" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="417.208" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)" id="c_6009">####</text>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 275.084 118.75 L 375.042 118.75 L 375.042 250 L 425.021 250"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 275.084 228.125 L 375.042 228.125 L 375.042 250 L 425.021 250"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 275.084 337.5 L 375.042 337.5 L 375.042 250 L 425.021 250"/>
|
||||
<g transform="matrix(0.99958, 0, 0, 0.875, 75.168186, -78.125439)" style="">
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre;" x="56" y="116.982">AirDryer A</text>
|
||||
<rect x="50" y="150" width="100" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.368" y="141.716">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.949" y="168.123">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.007" y="167.208">####</text>
|
||||
<rect x="49.832" y="225.548" width="100.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="49.832" y="250" width="100.168" height="50" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="124.956" cy="262.355" rx="11.269" ry="10.987"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="241.982">AirDryer B</text>
|
||||
<rect x="49.832" y="275" width="100" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="266.716">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="293.123">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="292.208">####</text>
|
||||
<rect x="49.832" y="350.548" width="100.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="49.832" y="375" width="100.168" height="50" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="124.956" cy="387.355" rx="11.269" ry="10.987"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="366.982">AirDryer C</text>
|
||||
<rect x="49.832" y="400" width="100" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="391.716">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="418.123">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="417.208">####</text>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 250 125 L 350 125 L 350 275 L 400 275"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 250 250 L 350 250 L 350 275 L 400 275"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 250 375 L 350 375 L 350 275 L 400 275"/>
|
||||
<g transform="matrix(1, 0, 0, 1, 49.999999, -99.999998)" style="">
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 292.93 L 717.857 292.651 L 717.857 292.442 L 717.857 292.163 L 717.857 291.954 L 717.857 291.744 L 717.857 291.535 L 717.857 291.396 L 717.914 291.186 L 717.914 291.046 L 717.972 290.907 L 718.029 290.837 L 718.086 290.698 L 718.143 290.558 L 718.201 290.488 L 718.258 290.419 L 718.372 290.349 L 718.487 290.279 L 718.602 290.209 L 718.716 290.14 L 718.888 290.14 L 719.06 290.07 L 719.231 290.07 L 719.46 290 L 719.632 290 L 719.919 290 L 720.147 290 L 720.434 290 L 720.72 290 L 721.063 290 L 721.407 290 L 721.751 290 L 722.151 290 L 770.706 290 L 771.106 290 L 771.45 290 L 771.794 290 L 772.137 290 L 772.423 290 L 772.71 290 L 772.939 290 L 773.225 290 L 773.397 290.07 L 773.626 290.07 L 773.798 290.14 L 773.969 290.14 L 774.141 290.209 L 774.256 290.279 L 774.37 290.349 L 774.485 290.419 L 774.599 290.488 L 774.657 290.558 L 774.714 290.698 L 774.771 290.837 L 774.828 290.977 L 774.886 291.117 L 774.943 291.256 L 774.943 291.465 L 775 291.674 L 775 291.884 L 775 292.093 L 775 292.303 L 775 292.581 L 775 292.86 L 775 293.209 L 775 293.488 L 775 335.558 L 775 335.907 L 775 336.256 L 775 336.604 L 775 336.884 L 775 337.163 L 775 337.442 L 775 337.72 L 775 337.93 L 774.943 338.14 L 774.943 338.349 L 774.943 338.488 L 774.886 338.628 L 774.886 338.767 L 774.828 338.907 L 774.771 339.047 L 774.714 339.117 L 774.657 339.256 L 774.599 339.326 L 774.485 339.396 L 774.427 339.465 L 774.313 339.465 L 774.198 339.535 L 774.084 339.535 L 773.969 339.604 L 773.798 339.604 L 773.683 339.604 L 773.511 339.604 L 773.339 339.674 L 773.168 339.674 L 772.939 339.674 L 772.71 339.674 L 772.481 339.674 L 721.579 339.674 L 721.235 339.674 L 720.892 339.674 L 720.663 339.674 L 720.377 339.674 L 720.09 339.604 L 719.861 339.604 L 719.69 339.604 L 719.46 339.604 L 719.289 339.535 L 719.117 339.535 L 718.945 339.465 L 718.831 339.465 L 718.659 339.396 L 718.544 339.326 L 718.43 339.256 L 718.372 339.117 L 718.258 339.047 L 718.201 338.907 L 718.143 338.767 L 718.086 338.628 L 718.029 338.488 L 717.972 338.349 L 717.914 338.14 L 717.914 337.93 L 717.914 337.72 L 717.857 337.442 L 717.857 337.163 L 717.857 336.884 L 717.857 336.604 L 717.857 336.256 L 717.857 335.907 L 717.857 335.558 L 717.857 292.93 Z"/>
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 732.114 339.674 L 760.743 339.674 L 760.743 342.884 L 732.114 342.884 L 732.114 339.674 Z"/>
|
||||
<path style="fill: rgb(67, 67, 67); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 722.151 299.419 L 722.151 299.07 L 722.151 298.791 L 722.151 298.442 L 722.151 298.163 L 722.151 297.954 L 722.151 297.675 L 722.209 297.465 L 722.209 297.256 L 722.209 297.046 L 722.266 296.837 L 722.323 296.698 L 722.323 296.558 L 722.381 296.419 L 722.495 296.279 L 722.553 296.209 L 722.61 296.07 L 722.725 296 L 722.838 295.93 L 722.953 295.86 L 723.067 295.791 L 723.239 295.791 L 723.354 295.721 L 723.526 295.721 L 723.754 295.651 L 723.926 295.651 L 724.155 295.651 L 724.385 295.651 L 724.671 295.651 L 724.9 295.651 L 725.243 295.651 L 725.53 295.651 L 725.873 295.651 L 767.557 295.651 L 767.843 295.651 L 768.129 295.651 L 768.358 295.651 L 768.587 295.651 L 768.816 295.651 L 769.045 295.721 L 769.217 295.721 L 769.389 295.791 L 769.561 295.791 L 769.675 295.86 L 769.79 295.86 L 769.962 295.93 L 770.076 296 L 770.133 296.07 L 770.247 296.139 L 770.305 296.209 L 770.362 296.349 L 770.419 296.419 L 770.477 296.558 L 770.534 296.698 L 770.591 296.837 L 770.591 296.907 L 770.649 297.046 L 770.649 297.256 L 770.649 297.396 L 770.706 297.604 L 770.706 297.744 L 770.706 297.954 L 770.706 298.163 L 770.706 298.442 L 770.706 298.651 L 770.706 298.861 L 770.706 327.744 L 770.706 328.093 L 770.706 328.372 L 770.706 328.581 L 770.706 328.861 L 770.763 329.07 L 770.763 329.279 L 770.763 329.488 L 770.763 329.628 L 770.763 329.838 L 770.763 329.977 L 770.706 330.117 L 770.706 330.186 L 770.649 330.326 L 770.649 330.465 L 770.591 330.535 L 770.534 330.604 L 770.477 330.674 L 770.419 330.744 L 770.305 330.814 L 770.19 330.883 L 770.076 330.883 L 769.962 330.883 L 769.79 330.953 L 769.618 330.953 L 769.446 330.953 L 769.274 331.023 L 769.045 331.023 L 768.759 331.023 L 768.53 331.023 L 768.244 331.023 L 767.9 331.023 L 767.557 331.023 L 725.873 331.023 L 725.53 331.023 L 725.243 331.023 L 724.9 331.023 L 724.671 331.023 L 724.385 331.023 L 724.155 331.023 L 723.926 331.023 L 723.754 331.023 L 723.526 331.023 L 723.354 331.023 L 723.239 331.023 L 723.067 330.953 L 722.953 330.953 L 722.838 330.883 L 722.725 330.814 L 722.61 330.744 L 722.553 330.674 L 722.495 330.604 L 722.381 330.465 L 722.323 330.326 L 722.323 330.186 L 722.266 330.046 L 722.209 329.838 L 722.209 329.628 L 722.209 329.419 L 722.151 329.209 L 722.151 328.93 L 722.151 328.651 L 722.151 328.302 L 722.151 327.954 L 722.151 327.604 L 722.151 327.186 L 722.151 299.419 Z"/>
|
||||
@@ -96,17 +96,17 @@
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 291.592 L 692.847 291.592 L 692.847 292.643 L 697.566 292.643 L 697.566 291.592 Z"/>
|
||||
<circle style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="890.673" cy="114.148" r="1.051" transform="matrix(1.142857, 0, 0, 1.000013, -320.346635, 178.493448)"/>
|
||||
</g>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 549.968 228.125 L 599.947 228.125 L 599.947 184.375 L 749.884 184.375"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 549.968 228.125 L 599.947 228.125 L 599.947 359.375 L 749.884 359.375"/>
|
||||
<rect x="424.853" y="140.506" width="125.116" height="21.994" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="425.021" y="162.5" width="124.947" height="21.875" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="425.352" y="167.628" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">PLC AirDryer</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="426.101" y="192.839" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">IP : 192.168.0.3</text>
|
||||
<rect x="749.884" y="96.756" width="125.116" height="21.994" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="750.053" y="118.75" width="124.947" height="21.875" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="759.52" y="117.628" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">PC Station</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.269" y="142.839" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">IP : 192.168.0.2</text>
|
||||
<g transform="matrix(0.99958, 0, 0, 0.875, 75.168186, 96.875524)" style="">
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 525 250 L 575 250 L 575 200 L 725 200"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 525 250 L 575 250 L 575 400 L 725 400"/>
|
||||
<rect x="399.832" y="149.864" width="125.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="400" y="175" width="125" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="425.352" y="167.628">PLC AirDryer</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="426.101" y="192.839">IP : 192.168.0.3</text>
|
||||
<rect x="725" y="99.864" width="125.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="725.168" y="125" width="125" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="759.52" y="117.628">PC Station</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.269" y="142.839">IP : 192.168.0.2</text>
|
||||
<g transform="matrix(1, 0, 0, 1, 49.999999, 99.999998)" style="">
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 292.93 L 717.857 292.651 L 717.857 292.442 L 717.857 292.163 L 717.857 291.954 L 717.857 291.744 L 717.857 291.535 L 717.857 291.396 L 717.914 291.186 L 717.914 291.046 L 717.972 290.907 L 718.029 290.837 L 718.086 290.698 L 718.143 290.558 L 718.201 290.488 L 718.258 290.419 L 718.372 290.349 L 718.487 290.279 L 718.602 290.209 L 718.716 290.14 L 718.888 290.14 L 719.06 290.07 L 719.231 290.07 L 719.46 290 L 719.632 290 L 719.919 290 L 720.147 290 L 720.434 290 L 720.72 290 L 721.063 290 L 721.407 290 L 721.751 290 L 722.151 290 L 770.706 290 L 771.106 290 L 771.45 290 L 771.794 290 L 772.137 290 L 772.423 290 L 772.71 290 L 772.939 290 L 773.225 290 L 773.397 290.07 L 773.626 290.07 L 773.798 290.14 L 773.969 290.14 L 774.141 290.209 L 774.256 290.279 L 774.37 290.349 L 774.485 290.419 L 774.599 290.488 L 774.657 290.558 L 774.714 290.698 L 774.771 290.837 L 774.828 290.977 L 774.886 291.117 L 774.943 291.256 L 774.943 291.465 L 775 291.674 L 775 291.884 L 775 292.093 L 775 292.303 L 775 292.581 L 775 292.86 L 775 293.209 L 775 293.488 L 775 335.558 L 775 335.907 L 775 336.256 L 775 336.604 L 775 336.884 L 775 337.163 L 775 337.442 L 775 337.72 L 775 337.93 L 774.943 338.14 L 774.943 338.349 L 774.943 338.488 L 774.886 338.628 L 774.886 338.767 L 774.828 338.907 L 774.771 339.047 L 774.714 339.117 L 774.657 339.256 L 774.599 339.326 L 774.485 339.396 L 774.427 339.465 L 774.313 339.465 L 774.198 339.535 L 774.084 339.535 L 773.969 339.604 L 773.798 339.604 L 773.683 339.604 L 773.511 339.604 L 773.339 339.674 L 773.168 339.674 L 772.939 339.674 L 772.71 339.674 L 772.481 339.674 L 721.579 339.674 L 721.235 339.674 L 720.892 339.674 L 720.663 339.674 L 720.377 339.674 L 720.09 339.604 L 719.861 339.604 L 719.69 339.604 L 719.46 339.604 L 719.289 339.535 L 719.117 339.535 L 718.945 339.465 L 718.831 339.465 L 718.659 339.396 L 718.544 339.326 L 718.43 339.256 L 718.372 339.117 L 718.258 339.047 L 718.201 338.907 L 718.143 338.767 L 718.086 338.628 L 718.029 338.488 L 717.972 338.349 L 717.914 338.14 L 717.914 337.93 L 717.914 337.72 L 717.857 337.442 L 717.857 337.163 L 717.857 336.884 L 717.857 336.604 L 717.857 336.256 L 717.857 335.907 L 717.857 335.558 L 717.857 292.93 Z"/>
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 732.114 339.674 L 760.743 339.674 L 760.743 342.884 L 732.114 342.884 L 732.114 339.674 Z"/>
|
||||
<path style="fill: rgb(67, 67, 67); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 722.151 299.419 L 722.151 299.07 L 722.151 298.791 L 722.151 298.442 L 722.151 298.163 L 722.151 297.954 L 722.151 297.675 L 722.209 297.465 L 722.209 297.256 L 722.209 297.046 L 722.266 296.837 L 722.323 296.698 L 722.323 296.558 L 722.381 296.419 L 722.495 296.279 L 722.553 296.209 L 722.61 296.07 L 722.725 296 L 722.838 295.93 L 722.953 295.86 L 723.067 295.791 L 723.239 295.791 L 723.354 295.721 L 723.526 295.721 L 723.754 295.651 L 723.926 295.651 L 724.155 295.651 L 724.385 295.651 L 724.671 295.651 L 724.9 295.651 L 725.243 295.651 L 725.53 295.651 L 725.873 295.651 L 767.557 295.651 L 767.843 295.651 L 768.129 295.651 L 768.358 295.651 L 768.587 295.651 L 768.816 295.651 L 769.045 295.721 L 769.217 295.721 L 769.389 295.791 L 769.561 295.791 L 769.675 295.86 L 769.79 295.86 L 769.962 295.93 L 770.076 296 L 770.133 296.07 L 770.247 296.139 L 770.305 296.209 L 770.362 296.349 L 770.419 296.419 L 770.477 296.558 L 770.534 296.698 L 770.591 296.837 L 770.591 296.907 L 770.649 297.046 L 770.649 297.256 L 770.649 297.396 L 770.706 297.604 L 770.706 297.744 L 770.706 297.954 L 770.706 298.163 L 770.706 298.442 L 770.706 298.651 L 770.706 298.861 L 770.706 327.744 L 770.706 328.093 L 770.706 328.372 L 770.706 328.581 L 770.706 328.861 L 770.763 329.07 L 770.763 329.279 L 770.763 329.488 L 770.763 329.628 L 770.763 329.838 L 770.763 329.977 L 770.706 330.117 L 770.706 330.186 L 770.649 330.326 L 770.649 330.465 L 770.591 330.535 L 770.534 330.604 L 770.477 330.674 L 770.419 330.744 L 770.305 330.814 L 770.19 330.883 L 770.076 330.883 L 769.962 330.883 L 769.79 330.953 L 769.618 330.953 L 769.446 330.953 L 769.274 331.023 L 769.045 331.023 L 768.759 331.023 L 768.53 331.023 L 768.244 331.023 L 767.9 331.023 L 767.557 331.023 L 725.873 331.023 L 725.53 331.023 L 725.243 331.023 L 724.9 331.023 L 724.671 331.023 L 724.385 331.023 L 724.155 331.023 L 723.926 331.023 L 723.754 331.023 L 723.526 331.023 L 723.354 331.023 L 723.239 331.023 L 723.067 330.953 L 722.953 330.953 L 722.838 330.883 L 722.725 330.814 L 722.61 330.744 L 722.553 330.674 L 722.495 330.604 L 722.381 330.465 L 722.323 330.326 L 722.323 330.186 L 722.266 330.046 L 722.209 329.838 L 722.209 329.628 L 722.209 329.419 L 722.151 329.209 L 722.151 328.93 L 722.151 328.651 L 722.151 328.302 L 722.151 327.954 L 722.151 327.604 L 722.151 327.186 L 722.151 299.419 Z"/>
|
||||
@@ -125,13 +125,13 @@
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 291.592 L 692.847 291.592 L 692.847 292.643 L 697.566 292.643 L 697.566 291.592 Z"/>
|
||||
<circle style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="890.673" cy="114.148" r="1.051" transform="matrix(1.142857, 0, 0, 1.000013, -320.346635, 178.493448)"/>
|
||||
</g>
|
||||
<rect x="749.716" y="271.756" width="125.116" height="21.994" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="749.884" y="293.75" width="124.947" height="21.875" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="760.352" y="317.628" transform="matrix(0.99958, 0, 0, 0.875, 25.188995, 9.375002)">PC Server</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.1" y="317.975" transform="matrix(0.99958, 0, 0, 0.875, 22.190208, 31.131118)">IP : 192.168.0.99<tspan x="751.0999755859375" dy="1em"></tspan></text>
|
||||
<rect x="724.832" y="299.864" width="125.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="725" y="325" width="125" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="760.352" y="317.628">PC Server</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.1" y="317.975" transform="matrix(1, 0, 0, 1, -3.000031, 24.863983)">IP : xxx.xxx.xx.xx<tspan x="751.0999755859375" dy="1em"></tspan></text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 30px; white-space: pre; stroke-width: 1;" x="316.458" y="50.984">OVERVIEW AIR DRYER</text>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 0, 0);" d="M 649.927 75 L 649.927 109.235 L 649.927 240.485 L 649.927 425"/>
|
||||
<g transform="matrix(0.999579, 0, 0, 0.777807, -1032.377984, 48.060908)" style="">
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 0, 0);" d="M 625 75 L 625 114.125 L 625 264.125 L 625 475"/>
|
||||
<g transform="matrix(0.999999, 0, 0, 0.888921, -1058.006891, 44.212168)" style="">
|
||||
<g id="Group_Base" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
|
||||
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M4.392,105.741h62.834v2.253H4.392V105.741z"/>
|
||||
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M0,112.498l1.014-1.126H2.14v-11.261H1.014L0,98.984h4.392v13.514H0z "/>
|
||||
@@ -234,7 +234,7 @@
|
||||
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M31.418,1.466l1.576-1.464l2.252,2.365L33.67,3.943L31.418,1.466z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.999579, 0, 0, 0.777807, -1035.419488, 157.436745)" style="">
|
||||
<g transform="matrix(0.999999, 0, 0, 0.888921, -1061.049982, 169.212228)" style="">
|
||||
<g id="group-1" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
|
||||
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M4.392,105.741h62.834v2.253H4.392V105.741z"/>
|
||||
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M0,112.498l1.014-1.126H2.14v-11.261H1.014L0,98.984h4.392v13.514H0z "/>
|
||||
@@ -337,7 +337,7 @@
|
||||
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M31.418,1.466l1.576-1.464l2.252,2.365L33.67,3.943L31.418,1.466z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.999579, 0, 0, 0.777807, -1035.419366, 266.810713)" style="">
|
||||
<g transform="matrix(0.999999, 0, 0, 0.888921, -1061.04986, 294.212174)" style="">
|
||||
<g id="group-9" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
|
||||
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M4.392,105.741h62.834v2.253H4.392V105.741z"/>
|
||||
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M0,112.498l1.014-1.126H2.14v-11.261H1.014L0,98.984h4.392v13.514H0z "/>
|
||||
|
||||
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
@@ -3,12 +3,12 @@
|
||||
<defs>
|
||||
<bx:grid x="0" y="0" width="25" height="25"/>
|
||||
</defs>
|
||||
<rect y="12.005" width="924.818" height="437.995" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);" x="12.012"/>
|
||||
<rect y="59" width="900" height="375" style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);" x="25"/>
|
||||
<rect x="75" y="98.845" width="100.147" height="23.46" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="75" y="121.667" width="100.147" height="46.667" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="150.108" cy="133.198" rx="11.267" ry="10.255"/>
|
||||
<g transform="matrix(1.115917, 0, 0, 1.04224, 14.334309, 48.503848)" style="">
|
||||
<rect x="12.226" y="12.005" width="924.818" height="462.995" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<rect x="25" y="75" width="900" height="375" style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);"/>
|
||||
<rect x="50" y="100.548" width="100.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="50" y="125" width="100.168" height="50" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="125.124" cy="137.355" rx="11.269" ry="10.987"/>
|
||||
<g transform="matrix(1.116151, 0, 0, 1.116686, -10.678418, 46.611243)" style="">
|
||||
<path style="fill: rgb(204, 204, 204); stroke-width: 1;" d="M 166.356 47.81 L 278.348 47.81 L 278.348 114.973 L 166.356 114.973 L 166.356 47.81 Z"/>
|
||||
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 166.356 95.477 L 278.348 67.396 L 278.348 114.973 L 166.356 114.973 L 166.356 95.477 Z"/>
|
||||
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 166.356 98.16 L 278.348 70.258 L 278.348 114.973 L 166.356 114.973 L 166.356 98.16 Z"/>
|
||||
@@ -47,7 +47,7 @@
|
||||
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 210.637 66.859 L 222.296 84.566 L 222.296 74.729 L 217.139 66.859 L 210.637 66.859 Z"/>
|
||||
<path style="fill: none; stroke: rgb(255, 255, 255); stroke-width: 2;" d="M 222.969 50.046 L 275.434 50.046"/>
|
||||
</g>
|
||||
<g transform="matrix(1.133672, 0, 0, 1.15215, 15.601832, 157.124169)" style="">
|
||||
<g transform="matrix(1.13391, 0, 0, 1.234446, -9.410634, 162.99009)" style="">
|
||||
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 363.181 109.151 L 363.181 110.989 L 460.721 110.989 L 469.183 107.313 L 469.183 105.958 L 460.721 109.151 L 363.181 109.151 Z"/>
|
||||
<path style="fill: rgb(115, 135, 166); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 361.061 109.151 L 361.061 53.909 L 462.836 53.909 L 462.836 109.151 L 361.061 109.151 Z"/>
|
||||
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 445.801 105.475 L 445.801 57.586 L 454.374 57.586 L 454.374 105.475 L 445.801 105.475 Z"/>
|
||||
@@ -92,28 +92,28 @@
|
||||
<path style="fill: rgb(89, 109, 140); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 462.836 53.909 L 471.299 50.233 L 471.299 105.475 L 462.836 109.151 L 462.836 53.909 Z"/>
|
||||
<path style="fill: rgb(191, 211, 242); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 462.836 53.909 L 471.299 50.233 L 369.521 50.233 L 361.061 53.909 L 462.836 53.909 Z"/>
|
||||
</g>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre;" x="56" y="116.982" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">COMPRESSOR A</text>
|
||||
<rect x="75" y="145" width="99.979" height="23.333" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.368" y="141.716" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.949" y="168.123" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.007" y="167.208" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)" id="c_1012">####</text>
|
||||
<rect x="74.832" y="215.511" width="100.147" height="23.46" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="74.832" y="238.333" width="100.147" height="46.667" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="149.941" cy="249.865" rx="11.267" ry="10.255"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="241.982" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">COMPRESSOR B</text>
|
||||
<rect x="74.832" y="261.667" width="99.979" height="23.333" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="266.716" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="293.123" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="292.208" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)" id="c_2012">####</text>
|
||||
<rect x="74.832" y="332.178" width="100.147" height="23.46" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="74.832" y="355" width="100.147" height="46.667" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="149.941" cy="366.531" rx="11.267" ry="10.255"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="366.982" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">COMPRESSOR C</text>
|
||||
<rect x="74.832" y="378.333" width="99.979" height="23.333" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="391.716" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="418.123" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="417.208" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)" id="c_3012">####</text>
|
||||
<g transform="matrix(1.115917, 0, 0, 1.04224, 14.334339, 165.170587)" style="">
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre;" x="56" y="116.982">COMPRESSOR A</text>
|
||||
<rect x="50" y="150" width="100" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.368" y="141.716">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.949" y="168.123">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.007" y="167.208">####</text>
|
||||
<rect x="49.832" y="225.548" width="100.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="49.832" y="250" width="100.168" height="50" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="124.956" cy="262.355" rx="11.269" ry="10.987"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="241.982">COMPRESSOR B</text>
|
||||
<rect x="49.832" y="275" width="100" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="266.716">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="293.123">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="292.208">####</text>
|
||||
<rect x="49.832" y="350.548" width="100.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="49.832" y="375" width="100.168" height="50" style="stroke: rgb(0, 0, 0); stroke-width: 0.693; fill: rgb(244, 248, 248);"/>
|
||||
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.693;" cx="124.956" cy="387.355" rx="11.269" ry="10.987"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="55.832" y="366.982">COMPRESSOR C</text>
|
||||
<rect x="49.832" y="400" width="100" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="56.2" y="391.716">On/Off</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="120.781" y="418.123">H</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 15px; white-space: pre; stroke-width: 1;" x="55.839" y="417.208">####</text>
|
||||
<g transform="matrix(1.116151, 0, 0, 1.116686, -10.678391, 171.611261)" style="">
|
||||
<path style="fill: rgb(204, 204, 204); stroke-width: 1;" d="M 166.356 47.81 L 278.348 47.81 L 278.348 114.973 L 166.356 114.973 L 166.356 47.81 Z"/>
|
||||
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 166.356 95.477 L 278.348 67.396 L 278.348 114.973 L 166.356 114.973 L 166.356 95.477 Z"/>
|
||||
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 166.356 98.16 L 278.348 70.258 L 278.348 114.973 L 166.356 114.973 L 166.356 98.16 Z"/>
|
||||
@@ -152,7 +152,7 @@
|
||||
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 210.637 66.859 L 222.296 84.566 L 222.296 74.729 L 217.139 66.859 L 210.637 66.859 Z"/>
|
||||
<path style="fill: none; stroke: rgb(255, 255, 255); stroke-width: 2;" d="M 222.969 50.046 L 275.434 50.046"/>
|
||||
</g>
|
||||
<g transform="matrix(1.115917, 0, 0, 1.04224, 14.334345, 281.837234)" style="">
|
||||
<g transform="matrix(1.116151, 0, 0, 1.116686, -10.678387, 296.611283)" style="">
|
||||
<path style="fill: rgb(204, 204, 204); stroke-width: 1;" d="M 166.356 47.81 L 278.348 47.81 L 278.348 114.973 L 166.356 114.973 L 166.356 47.81 Z"/>
|
||||
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 166.356 95.477 L 278.348 67.396 L 278.348 114.973 L 166.356 114.973 L 166.356 95.477 Z"/>
|
||||
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 166.356 98.16 L 278.348 70.258 L 278.348 114.973 L 166.356 114.973 L 166.356 98.16 Z"/>
|
||||
@@ -191,10 +191,10 @@
|
||||
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 210.637 66.859 L 222.296 84.566 L 222.296 74.729 L 217.139 66.859 L 210.637 66.859 Z"/>
|
||||
<path style="fill: none; stroke: rgb(255, 255, 255); stroke-width: 2;" d="M 222.969 50.046 L 275.434 50.046"/>
|
||||
</g>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 324.947 121.667 L 374.937 121.667 L 374.937 261.667 L 424.926 261.667"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 324.947 238.333 L 374.937 238.333 L 374.937 261.667 L 424.926 261.667"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 324.947 355 L 374.937 355 L 374.937 261.667 L 424.926 261.667"/>
|
||||
<g transform="matrix(0.99979, 0, 0, 0.933333, 75.000027, -88.333371)" style="">
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 300 125 L 350 125 L 350 275 L 400 275"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 300 250 L 350 250 L 350 275 L 400 275"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 4, 255);" d="M 300 375 L 350 375 L 350 275 L 400 275"/>
|
||||
<g transform="matrix(1, 0, 0, 1, 49.999999, -99.999998)" style="">
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 292.93 L 717.857 292.651 L 717.857 292.442 L 717.857 292.163 L 717.857 291.954 L 717.857 291.744 L 717.857 291.535 L 717.857 291.396 L 717.914 291.186 L 717.914 291.046 L 717.972 290.907 L 718.029 290.837 L 718.086 290.698 L 718.143 290.558 L 718.201 290.488 L 718.258 290.419 L 718.372 290.349 L 718.487 290.279 L 718.602 290.209 L 718.716 290.14 L 718.888 290.14 L 719.06 290.07 L 719.231 290.07 L 719.46 290 L 719.632 290 L 719.919 290 L 720.147 290 L 720.434 290 L 720.72 290 L 721.063 290 L 721.407 290 L 721.751 290 L 722.151 290 L 770.706 290 L 771.106 290 L 771.45 290 L 771.794 290 L 772.137 290 L 772.423 290 L 772.71 290 L 772.939 290 L 773.225 290 L 773.397 290.07 L 773.626 290.07 L 773.798 290.14 L 773.969 290.14 L 774.141 290.209 L 774.256 290.279 L 774.37 290.349 L 774.485 290.419 L 774.599 290.488 L 774.657 290.558 L 774.714 290.698 L 774.771 290.837 L 774.828 290.977 L 774.886 291.117 L 774.943 291.256 L 774.943 291.465 L 775 291.674 L 775 291.884 L 775 292.093 L 775 292.303 L 775 292.581 L 775 292.86 L 775 293.209 L 775 293.488 L 775 335.558 L 775 335.907 L 775 336.256 L 775 336.604 L 775 336.884 L 775 337.163 L 775 337.442 L 775 337.72 L 775 337.93 L 774.943 338.14 L 774.943 338.349 L 774.943 338.488 L 774.886 338.628 L 774.886 338.767 L 774.828 338.907 L 774.771 339.047 L 774.714 339.117 L 774.657 339.256 L 774.599 339.326 L 774.485 339.396 L 774.427 339.465 L 774.313 339.465 L 774.198 339.535 L 774.084 339.535 L 773.969 339.604 L 773.798 339.604 L 773.683 339.604 L 773.511 339.604 L 773.339 339.674 L 773.168 339.674 L 772.939 339.674 L 772.71 339.674 L 772.481 339.674 L 721.579 339.674 L 721.235 339.674 L 720.892 339.674 L 720.663 339.674 L 720.377 339.674 L 720.09 339.604 L 719.861 339.604 L 719.69 339.604 L 719.46 339.604 L 719.289 339.535 L 719.117 339.535 L 718.945 339.465 L 718.831 339.465 L 718.659 339.396 L 718.544 339.326 L 718.43 339.256 L 718.372 339.117 L 718.258 339.047 L 718.201 338.907 L 718.143 338.767 L 718.086 338.628 L 718.029 338.488 L 717.972 338.349 L 717.914 338.14 L 717.914 337.93 L 717.914 337.72 L 717.857 337.442 L 717.857 337.163 L 717.857 336.884 L 717.857 336.604 L 717.857 336.256 L 717.857 335.907 L 717.857 335.558 L 717.857 292.93 Z"/>
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 732.114 339.674 L 760.743 339.674 L 760.743 342.884 L 732.114 342.884 L 732.114 339.674 Z"/>
|
||||
<path style="fill: rgb(67, 67, 67); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 722.151 299.419 L 722.151 299.07 L 722.151 298.791 L 722.151 298.442 L 722.151 298.163 L 722.151 297.954 L 722.151 297.675 L 722.209 297.465 L 722.209 297.256 L 722.209 297.046 L 722.266 296.837 L 722.323 296.698 L 722.323 296.558 L 722.381 296.419 L 722.495 296.279 L 722.553 296.209 L 722.61 296.07 L 722.725 296 L 722.838 295.93 L 722.953 295.86 L 723.067 295.791 L 723.239 295.791 L 723.354 295.721 L 723.526 295.721 L 723.754 295.651 L 723.926 295.651 L 724.155 295.651 L 724.385 295.651 L 724.671 295.651 L 724.9 295.651 L 725.243 295.651 L 725.53 295.651 L 725.873 295.651 L 767.557 295.651 L 767.843 295.651 L 768.129 295.651 L 768.358 295.651 L 768.587 295.651 L 768.816 295.651 L 769.045 295.721 L 769.217 295.721 L 769.389 295.791 L 769.561 295.791 L 769.675 295.86 L 769.79 295.86 L 769.962 295.93 L 770.076 296 L 770.133 296.07 L 770.247 296.139 L 770.305 296.209 L 770.362 296.349 L 770.419 296.419 L 770.477 296.558 L 770.534 296.698 L 770.591 296.837 L 770.591 296.907 L 770.649 297.046 L 770.649 297.256 L 770.649 297.396 L 770.706 297.604 L 770.706 297.744 L 770.706 297.954 L 770.706 298.163 L 770.706 298.442 L 770.706 298.651 L 770.706 298.861 L 770.706 327.744 L 770.706 328.093 L 770.706 328.372 L 770.706 328.581 L 770.706 328.861 L 770.763 329.07 L 770.763 329.279 L 770.763 329.488 L 770.763 329.628 L 770.763 329.838 L 770.763 329.977 L 770.706 330.117 L 770.706 330.186 L 770.649 330.326 L 770.649 330.465 L 770.591 330.535 L 770.534 330.604 L 770.477 330.674 L 770.419 330.744 L 770.305 330.814 L 770.19 330.883 L 770.076 330.883 L 769.962 330.883 L 769.79 330.953 L 769.618 330.953 L 769.446 330.953 L 769.274 331.023 L 769.045 331.023 L 768.759 331.023 L 768.53 331.023 L 768.244 331.023 L 767.9 331.023 L 767.557 331.023 L 725.873 331.023 L 725.53 331.023 L 725.243 331.023 L 724.9 331.023 L 724.671 331.023 L 724.385 331.023 L 724.155 331.023 L 723.926 331.023 L 723.754 331.023 L 723.526 331.023 L 723.354 331.023 L 723.239 331.023 L 723.067 330.953 L 722.953 330.953 L 722.838 330.883 L 722.725 330.814 L 722.61 330.744 L 722.553 330.674 L 722.495 330.604 L 722.381 330.465 L 722.323 330.326 L 722.323 330.186 L 722.266 330.046 L 722.209 329.838 L 722.209 329.628 L 722.209 329.419 L 722.151 329.209 L 722.151 328.93 L 722.151 328.651 L 722.151 328.302 L 722.151 327.954 L 722.151 327.604 L 722.151 327.186 L 722.151 299.419 Z"/>
|
||||
@@ -213,17 +213,17 @@
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 291.592 L 692.847 291.592 L 692.847 292.643 L 697.566 292.643 L 697.566 291.592 Z"/>
|
||||
<circle style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="890.673" cy="114.148" r="1.051" transform="matrix(1.142857, 0, 0, 1.000013, -320.346635, 178.493448)"/>
|
||||
</g>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 549.901 238.333 L 599.89 238.333 L 599.89 191.667 L 749.858 191.667"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 549.901 238.333 L 599.89 238.333 L 599.89 355 L 749.858 355"/>
|
||||
<rect x="424.759" y="144.873" width="125.142" height="23.46" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="424.926" y="168.333" width="124.974" height="23.333" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="417.352" y="167.628" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">PLC Compressor</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="426.101" y="192.839" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">IP : 192.168.0.1</text>
|
||||
<rect x="749.858" y="98.206" width="125.142" height="23.46" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="750.026" y="121.667" width="124.974" height="23.333" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="759.52" y="117.628" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">PC Station</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.269" y="142.839" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">IP : 192.168.0.2</text>
|
||||
<g transform="matrix(0.99979, 0, 0, 0.933333, 75.000027, 75.000027)" style="">
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 525 250 L 575 250 L 575 200 L 725 200"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(6, 255, 0);" d="M 525 250 L 575 250 L 575 375 L 725 375"/>
|
||||
<rect x="399.832" y="149.864" width="125.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="400" y="175" width="125" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="417.352" y="167.628">PLC Compressor</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="426.101" y="192.839">IP : 192.168.0.1</text>
|
||||
<rect x="725" y="99.864" width="125.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="725.168" y="125" width="125" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="759.52" y="117.628">PC Station</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.269" y="142.839">IP : 192.168.0.2</text>
|
||||
<g transform="matrix(1, 0, 0, 1, 49.999999, 74.999996)" style="">
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 292.93 L 717.857 292.651 L 717.857 292.442 L 717.857 292.163 L 717.857 291.954 L 717.857 291.744 L 717.857 291.535 L 717.857 291.396 L 717.914 291.186 L 717.914 291.046 L 717.972 290.907 L 718.029 290.837 L 718.086 290.698 L 718.143 290.558 L 718.201 290.488 L 718.258 290.419 L 718.372 290.349 L 718.487 290.279 L 718.602 290.209 L 718.716 290.14 L 718.888 290.14 L 719.06 290.07 L 719.231 290.07 L 719.46 290 L 719.632 290 L 719.919 290 L 720.147 290 L 720.434 290 L 720.72 290 L 721.063 290 L 721.407 290 L 721.751 290 L 722.151 290 L 770.706 290 L 771.106 290 L 771.45 290 L 771.794 290 L 772.137 290 L 772.423 290 L 772.71 290 L 772.939 290 L 773.225 290 L 773.397 290.07 L 773.626 290.07 L 773.798 290.14 L 773.969 290.14 L 774.141 290.209 L 774.256 290.279 L 774.37 290.349 L 774.485 290.419 L 774.599 290.488 L 774.657 290.558 L 774.714 290.698 L 774.771 290.837 L 774.828 290.977 L 774.886 291.117 L 774.943 291.256 L 774.943 291.465 L 775 291.674 L 775 291.884 L 775 292.093 L 775 292.303 L 775 292.581 L 775 292.86 L 775 293.209 L 775 293.488 L 775 335.558 L 775 335.907 L 775 336.256 L 775 336.604 L 775 336.884 L 775 337.163 L 775 337.442 L 775 337.72 L 775 337.93 L 774.943 338.14 L 774.943 338.349 L 774.943 338.488 L 774.886 338.628 L 774.886 338.767 L 774.828 338.907 L 774.771 339.047 L 774.714 339.117 L 774.657 339.256 L 774.599 339.326 L 774.485 339.396 L 774.427 339.465 L 774.313 339.465 L 774.198 339.535 L 774.084 339.535 L 773.969 339.604 L 773.798 339.604 L 773.683 339.604 L 773.511 339.604 L 773.339 339.674 L 773.168 339.674 L 772.939 339.674 L 772.71 339.674 L 772.481 339.674 L 721.579 339.674 L 721.235 339.674 L 720.892 339.674 L 720.663 339.674 L 720.377 339.674 L 720.09 339.604 L 719.861 339.604 L 719.69 339.604 L 719.46 339.604 L 719.289 339.535 L 719.117 339.535 L 718.945 339.465 L 718.831 339.465 L 718.659 339.396 L 718.544 339.326 L 718.43 339.256 L 718.372 339.117 L 718.258 339.047 L 718.201 338.907 L 718.143 338.767 L 718.086 338.628 L 718.029 338.488 L 717.972 338.349 L 717.914 338.14 L 717.914 337.93 L 717.914 337.72 L 717.857 337.442 L 717.857 337.163 L 717.857 336.884 L 717.857 336.604 L 717.857 336.256 L 717.857 335.907 L 717.857 335.558 L 717.857 292.93 Z"/>
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 732.114 339.674 L 760.743 339.674 L 760.743 342.884 L 732.114 342.884 L 732.114 339.674 Z"/>
|
||||
<path style="fill: rgb(67, 67, 67); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 722.151 299.419 L 722.151 299.07 L 722.151 298.791 L 722.151 298.442 L 722.151 298.163 L 722.151 297.954 L 722.151 297.675 L 722.209 297.465 L 722.209 297.256 L 722.209 297.046 L 722.266 296.837 L 722.323 296.698 L 722.323 296.558 L 722.381 296.419 L 722.495 296.279 L 722.553 296.209 L 722.61 296.07 L 722.725 296 L 722.838 295.93 L 722.953 295.86 L 723.067 295.791 L 723.239 295.791 L 723.354 295.721 L 723.526 295.721 L 723.754 295.651 L 723.926 295.651 L 724.155 295.651 L 724.385 295.651 L 724.671 295.651 L 724.9 295.651 L 725.243 295.651 L 725.53 295.651 L 725.873 295.651 L 767.557 295.651 L 767.843 295.651 L 768.129 295.651 L 768.358 295.651 L 768.587 295.651 L 768.816 295.651 L 769.045 295.721 L 769.217 295.721 L 769.389 295.791 L 769.561 295.791 L 769.675 295.86 L 769.79 295.86 L 769.962 295.93 L 770.076 296 L 770.133 296.07 L 770.247 296.139 L 770.305 296.209 L 770.362 296.349 L 770.419 296.419 L 770.477 296.558 L 770.534 296.698 L 770.591 296.837 L 770.591 296.907 L 770.649 297.046 L 770.649 297.256 L 770.649 297.396 L 770.706 297.604 L 770.706 297.744 L 770.706 297.954 L 770.706 298.163 L 770.706 298.442 L 770.706 298.651 L 770.706 298.861 L 770.706 327.744 L 770.706 328.093 L 770.706 328.372 L 770.706 328.581 L 770.706 328.861 L 770.763 329.07 L 770.763 329.279 L 770.763 329.488 L 770.763 329.628 L 770.763 329.838 L 770.763 329.977 L 770.706 330.117 L 770.706 330.186 L 770.649 330.326 L 770.649 330.465 L 770.591 330.535 L 770.534 330.604 L 770.477 330.674 L 770.419 330.744 L 770.305 330.814 L 770.19 330.883 L 770.076 330.883 L 769.962 330.883 L 769.79 330.953 L 769.618 330.953 L 769.446 330.953 L 769.274 331.023 L 769.045 331.023 L 768.759 331.023 L 768.53 331.023 L 768.244 331.023 L 767.9 331.023 L 767.557 331.023 L 725.873 331.023 L 725.53 331.023 L 725.243 331.023 L 724.9 331.023 L 724.671 331.023 L 724.385 331.023 L 724.155 331.023 L 723.926 331.023 L 723.754 331.023 L 723.526 331.023 L 723.354 331.023 L 723.239 331.023 L 723.067 330.953 L 722.953 330.953 L 722.838 330.883 L 722.725 330.814 L 722.61 330.744 L 722.553 330.674 L 722.495 330.604 L 722.381 330.465 L 722.323 330.326 L 722.323 330.186 L 722.266 330.046 L 722.209 329.838 L 722.209 329.628 L 722.209 329.419 L 722.151 329.209 L 722.151 328.93 L 722.151 328.651 L 722.151 328.302 L 722.151 327.954 L 722.151 327.604 L 722.151 327.186 L 722.151 299.419 Z"/>
|
||||
@@ -242,10 +242,10 @@
|
||||
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 291.592 L 692.847 291.592 L 692.847 292.643 L 697.566 292.643 L 697.566 291.592 Z"/>
|
||||
<circle style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="890.673" cy="114.148" r="1.051" transform="matrix(1.142857, 0, 0, 1.000013, -320.346635, 178.493448)"/>
|
||||
</g>
|
||||
<rect x="749.69" y="261.667" width="125.142" height="23.46" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="749.858" y="285.127" width="124.974" height="23.333" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="760.352" y="292.764" transform="matrix(0.99979, 0, 0, 0.933333, 25.010492, 5.000001)">PC Server</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.1" y="317.975" transform="matrix(0.99979, 0, 0, 0.933333, 22.011123, 5.000001)">IP : 192.168.0.99<tspan x="751.0999755859375" dy="1em"></tspan></text>
|
||||
<rect x="724.832" y="275" width="125.168" height="25.136" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.693;"/>
|
||||
<rect x="725" y="300.136" width="125" height="25" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 1;"/>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="760.352" y="292.764">PC Server</text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; white-space: pre; stroke-width: 1;" x="751.1" y="317.975" transform="matrix(1, 0, 0, 1, -3, 0)">IP : xxx.xxx.xx.xx<tspan x="751.0999755859375" dy="1em"></tspan></text>
|
||||
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 30px; white-space: pre; stroke-width: 1;" x="312.458" y="50.984">OVERVIEW COMPRESSOR</text>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 0, 0);" d="M 649.879 60.253 L 649.879 99.16 L 649.879 248.324 L 649.879 433.164"/>
|
||||
<path style="fill: none; stroke-width: 1.386; stroke-dasharray: 6, 4; stroke: rgb(0, 0, 0);" d="M 625 75 L 625 114.125 L 625 264.125 L 625 450"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 45 KiB |
@@ -30,18 +30,18 @@ instance.interceptors.response.use(
|
||||
originalRequest._retry = true;
|
||||
|
||||
try {
|
||||
// console.log('🔄 Refresh token dipanggil...');
|
||||
console.log('🔄 Refresh token dipanggil...');
|
||||
const refreshRes = await refreshApi.post('/auth/refresh-token');
|
||||
|
||||
const newAccessToken = refreshRes.data.data.accessToken;
|
||||
localStorage.setItem('token', newAccessToken);
|
||||
// console.log('✅ Token refreshed successfully');
|
||||
console.log('✅ Token refreshed successfully');
|
||||
|
||||
// update token di header
|
||||
instance.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
|
||||
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
|
||||
|
||||
// console.log('🔁 Retrying original request...');
|
||||
console.log('🔁 Retrying original request...');
|
||||
return instance(originalRequest);
|
||||
} catch (refreshError) {
|
||||
console.error(
|
||||
@@ -70,35 +70,24 @@ async function ApiRequest({ method = 'GET', params = {}, prefix = '/', token = t
|
||||
},
|
||||
};
|
||||
|
||||
const tokenRedirect = sessionStorage.getItem('token_redirect');
|
||||
|
||||
let rawToken = '';
|
||||
|
||||
if (tokenRedirect !== null) {
|
||||
rawToken = tokenRedirect;
|
||||
// console.log(`sessionStorage: ${tokenRedirect}`);
|
||||
} else {
|
||||
rawToken = localStorage.getItem('token');
|
||||
// console.log(`localStorage: ${rawToken}`);
|
||||
}
|
||||
|
||||
const rawToken = localStorage.getItem('token');
|
||||
if (token && rawToken) {
|
||||
const cleanToken = rawToken.replace(/"/g, '');
|
||||
request.headers['Authorization'] = `Bearer ${cleanToken}`;
|
||||
// console.log('🔐 Sending request with token:', cleanToken.substring(0, 20) + '...');
|
||||
console.log('🔐 Sending request with token:', cleanToken.substring(0, 20) + '...');
|
||||
} else {
|
||||
console.warn('⚠️ No token found in localStorage');
|
||||
}
|
||||
|
||||
// console.log('📤 API Request:', { method, url: prefix, hasToken: !!rawToken });
|
||||
console.log('📤 API Request:', { method, url: prefix, hasToken: !!rawToken });
|
||||
|
||||
try {
|
||||
const response = await instance(request);
|
||||
// console.log('✅ API Response:', {
|
||||
// url: prefix,
|
||||
// status: response.status,
|
||||
// statusCode: response.data?.statusCode,
|
||||
// });
|
||||
console.log('✅ API Response:', {
|
||||
url: prefix,
|
||||
status: response.status,
|
||||
statusCode: response.data?.statusCode,
|
||||
});
|
||||
return { ...response, error: false };
|
||||
} catch (error) {
|
||||
const status = error?.response?.status || 500;
|
||||
@@ -143,10 +132,17 @@ async function cekError(status, message = '') {
|
||||
const SendRequest = async (queryParams) => {
|
||||
try {
|
||||
const response = await ApiRequest(queryParams);
|
||||
console.log('📦 SendRequest response:', {
|
||||
hasError: response.error,
|
||||
status: response.status,
|
||||
statusCode: response.data?.statusCode,
|
||||
data: response.data,
|
||||
});
|
||||
|
||||
// If ApiRequest returned error flag, return error structure
|
||||
if (response.error) {
|
||||
const errorMsg = response.data?.message || response.statusText || 'Request failed';
|
||||
console.error('❌ SendRequest error response:', errorMsg);
|
||||
|
||||
// Return consistent error structure instead of empty array
|
||||
return {
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import { Input } from "antd";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
|
||||
const InputNumber = ({
|
||||
name,
|
||||
value = 0,
|
||||
onChange,
|
||||
...props
|
||||
}) => {
|
||||
const [inputValue, setInputValue] = useState(
|
||||
value !== null && value !== undefined ? value.toString() : ''
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const newValue = value !== null && value !== undefined ? value.toString() : '';
|
||||
setInputValue(newValue);
|
||||
}, [value]);
|
||||
|
||||
const handleChange = (e) => {
|
||||
const rawValue = e.target.value;
|
||||
if (/^\d*$/.test(rawValue)) {
|
||||
setInputValue(rawValue);
|
||||
const numValue = rawValue === '' ? 0 : parseInt(rawValue, 10);
|
||||
|
||||
// Kirim event object sintetis yang konsisten dengan handler biasa
|
||||
onChange?.({
|
||||
target: {
|
||||
name: name,
|
||||
value: numValue
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleFocus = (e) => {
|
||||
// Pilih semua teks saat fokus (opsional)
|
||||
e.target.select();
|
||||
};
|
||||
|
||||
return (
|
||||
<Input
|
||||
{...props}
|
||||
name={name} // Teruskan name ke input
|
||||
value={inputValue}
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
style={{ textAlign: 'left' }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { InputNumber };
|
||||
@@ -2,17 +2,7 @@
|
||||
import mqtt from 'mqtt';
|
||||
|
||||
const mqttUrl = `${import.meta.env.VITE_MQTT_SERVER ?? 'ws://localhost:1884'}`;
|
||||
const topics = [
|
||||
'PIU_COD/AIR_DRYER/OVERVIEW',
|
||||
'PIU_COD/AIR_DRYER/AIR_DRYER_A',
|
||||
'PIU_COD/AIR_DRYER/AIR_DRYER_B',
|
||||
'PIU_COD/AIR_DRYER/AIR_DRYER_C',
|
||||
'PIU_COD/COMPRESSOR/OVERVIEW',
|
||||
'PIU_COD/COMPRESSOR/COMPRESSOR_A',
|
||||
'PIU_COD/COMPRESSOR/COMPRESSOR_B',
|
||||
'PIU_COD/COMPRESSOR/COMPRESSOR_C',
|
||||
'PIU_COD/ERROR_CODE/SIM',
|
||||
];
|
||||
const topics = ['cod/air_dryer/air_dryer1'];
|
||||
const options = {
|
||||
keepalive: 30,
|
||||
clientId: 'react_mqtt_' + Math.random().toString(16).substr(2, 8),
|
||||
@@ -74,101 +64,29 @@ const listenMessage = (callback) => {
|
||||
});
|
||||
};
|
||||
|
||||
const colorIds = ['c_1023', 'c_2023', 'c_2023'];
|
||||
const StatusColor = (el, num) => {
|
||||
switch (num) {
|
||||
case 1:
|
||||
el.style.fill = 'orange';
|
||||
break;
|
||||
case 2:
|
||||
el.style.fill = 'rgb(7,250,14)';
|
||||
break;
|
||||
default:
|
||||
el.style.fill = 'rgb(216,216,216)';
|
||||
}
|
||||
};
|
||||
|
||||
const dryerIds = ['c_4018', 'c_4021', 'c_5018', 'c_5021', 'c_6018', 'c_6021'];
|
||||
const handleBoolean = (svg, el, value) => {
|
||||
if (!dryerIds.includes(el.id)) {
|
||||
el.style.display = value ? '' : 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
const i = dryerIds.indexOf(el.id);
|
||||
const id1 = dryerIds[i - (i % 2)];
|
||||
const id2 = dryerIds[i - (i % 2) + 1];
|
||||
|
||||
const els1 = svg.querySelectorAll(`#${id1}`);
|
||||
const els2 = svg.querySelectorAll(`#${id2}`);
|
||||
|
||||
if (!els1 || !els2) return;
|
||||
|
||||
els1.forEach(el => {
|
||||
el.style.fill = value ? 'rgb(216,216,216)' : 'rgb(255, 204, 63)';
|
||||
});
|
||||
els2.forEach(el => {
|
||||
el.style.fill = value ? 'rgb(255, 204, 63)' : 'rgb(216,216,216)';
|
||||
});
|
||||
};
|
||||
|
||||
const handleNumber = (el, value) => {
|
||||
const num = Number(value);
|
||||
|
||||
if (colorIds.includes(el.id)) {
|
||||
StatusColor(el, num);
|
||||
} else {
|
||||
el.textContent = num.toFixed(2);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOther = (el, value) => {
|
||||
el.textContent = value;
|
||||
};
|
||||
|
||||
const setValSvg = (listenTopic, svg) => {
|
||||
client.on('message', (topic, message) => {
|
||||
// console.log(topic ,' = ', listenTopic);
|
||||
if (topic === listenTopic) {
|
||||
const objChanel = JSON.parse(message);
|
||||
|
||||
Object.entries(objChanel).forEach(([key, value]) => {
|
||||
// console.log(key, value);
|
||||
const el = svg.getElementById(key);
|
||||
|
||||
if (!el) return;
|
||||
// else if (el.id === 'c_2014' || el.id === 'c_2024') {
|
||||
// el.setAttribute('text-anchor', 'middle');
|
||||
// el.setAttribute('x', '10%');
|
||||
// }
|
||||
if (typeof value === 'boolean') {
|
||||
handleBoolean(svg, el, value);
|
||||
} else if (!isNaN(value)) {
|
||||
handleNumber(el, value);
|
||||
} else {
|
||||
handleOther(el, value);
|
||||
if (el) {
|
||||
if (value === true) {
|
||||
el.style.display = ''; // sembunyikan
|
||||
} else if (value === false) {
|
||||
el.style.display = 'none';
|
||||
} else if (!isNaN(value)) {
|
||||
el.textContent = Number(value ?? 0.0).toFixed(2);
|
||||
} else {
|
||||
el.textContent = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
const target = svg.querySelector('text[x="225.25"][y="537.752"]');
|
||||
if (target) target.remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// === NOTIFICATION LISTENER ===
|
||||
const notifListeners = [];
|
||||
|
||||
const onNotifUpdate = (callback) => {
|
||||
notifListeners.push(callback);
|
||||
};
|
||||
|
||||
client.on('message', (topic, message) => {
|
||||
if (topic === import.meta.env.VITE_MQTT_TOPIC_COD) {
|
||||
try {
|
||||
const payload = JSON.parse(message.toString());
|
||||
notifListeners.forEach((cb) => cb(payload));
|
||||
} catch (err) {
|
||||
console.error('Invalid notif payload', err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export { publishMessage, listenMessage, setValSvg, onNotifUpdate };
|
||||
export { publishMessage, listenMessage, setValSvg };
|
||||
|
||||
@@ -20,19 +20,6 @@ const NotifOk = ({ icon, title, message }) => {
|
||||
});
|
||||
};
|
||||
|
||||
const NotifSmall = ({ icon, title, message }) => {
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
icon: icon,
|
||||
title: title,
|
||||
text: message,
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: true,
|
||||
});
|
||||
};
|
||||
|
||||
const NotifConfirmDialog = ({
|
||||
icon,
|
||||
title,
|
||||
@@ -80,4 +67,4 @@ const QuestionConfirmSubmit = ({ icon, title, message, onConfirm, onCancel }) =>
|
||||
});
|
||||
};
|
||||
|
||||
export { NotifAlert, NotifOk, NotifSmall, NotifConfirmDialog, QuestionConfirmSubmit };
|
||||
export { NotifAlert, NotifOk, NotifConfirmDialog, QuestionConfirmSubmit };
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
DatabaseOutlined,
|
||||
SettingOutlined,
|
||||
UserOutlined,
|
||||
GlobalOutlined,
|
||||
AntDesignOutlined,
|
||||
ShoppingCartOutlined,
|
||||
ShoppingOutlined,
|
||||
@@ -37,14 +36,6 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const { Text } = Typography;
|
||||
const host = window.location.hostname;
|
||||
|
||||
const isLocal =
|
||||
host === '127.0.0.1' ||
|
||||
host === 'localhost' ||
|
||||
host.startsWith('192.168.') ||
|
||||
host.startsWith('10.') ||
|
||||
host.startsWith('172.');
|
||||
|
||||
const allItems = [
|
||||
{
|
||||
@@ -155,7 +146,7 @@ const allItems = [
|
||||
{
|
||||
key: 'master-sparepart',
|
||||
icon: <ToolOutlined style={{ fontSize: '19px' }} />,
|
||||
label: <Link to="/master/sparepart">Sparepart</Link>,
|
||||
label: <Link to="/master/sparepart">sparepart</Link>,
|
||||
},
|
||||
// {
|
||||
// key: 'master-shift',
|
||||
@@ -234,19 +225,6 @@ const allItems = [
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
...(isLocal
|
||||
? [
|
||||
{
|
||||
key: 'whatsapp-control',
|
||||
icon: <GlobalOutlined style={{ fontSize: '19px' }} />,
|
||||
label: (
|
||||
<Link to="/whatsapp-control" className="fontMenus">
|
||||
WhatsApp Control
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
// {
|
||||
// key: 'jadwal-shift',
|
||||
// icon: <CalendarOutlined style={{ fontSize: '19px' }} />,
|
||||
@@ -272,7 +250,6 @@ const LayoutMenu = () => {
|
||||
if (pathname === '/dashboard/home') return 'home';
|
||||
if (pathname === '/user') return 'user';
|
||||
if (pathname === '/role') return 'role';
|
||||
if (pathname === '/whatsapp-control') return 'whatsapp-control';
|
||||
if (pathname === '/notification') return 'notification';
|
||||
if (pathname === '/jadwal-shift') return 'jadwal-shift';
|
||||
if (pathname === '/contact') return 'contact';
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { verifyRedirect } from '../../api/auth';
|
||||
import { encryptData } from '../../components/Global/Formatter';
|
||||
import NotFound from './NotFound';
|
||||
import Waiting from './Waiting';
|
||||
import NotificationDetailTab from '../notificationDetail/IndexNotificationDetail';
|
||||
|
||||
export default function RedirectWa() {
|
||||
const [idData, setIdData] = useState(0);
|
||||
const [ready, setReady] = useState(0);
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
// URLSearchParams untuk ambil query
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const token = queryParams.get('token');
|
||||
|
||||
const handleInitForm = async (encodedToken) => {
|
||||
const originalToken = decodeURIComponent(encodedToken);
|
||||
// console.log(originalToken);
|
||||
|
||||
const response = await verifyRedirect({
|
||||
tokenRedirect: originalToken,
|
||||
});
|
||||
|
||||
console.log('tes', response);
|
||||
|
||||
const tokenResult = JSON.stringify(response.data?.data?.accessToken);
|
||||
|
||||
sessionStorage.setItem('token_redirect', tokenResult);
|
||||
response.data.auth = true;
|
||||
sessionStorage.setItem('session', encryptData(response?.data));
|
||||
|
||||
setIdData(response.data.data.idData);
|
||||
|
||||
setReady(1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleInitForm(token);
|
||||
}, [idData]);
|
||||
|
||||
if (ready == 0) return <Waiting />;
|
||||
|
||||
if (idData === 0) return <NotFound />;
|
||||
|
||||
return <NotificationDetailTab id={idData} />;
|
||||
}
|
||||
@@ -13,7 +13,6 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
id: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
is_active: true,
|
||||
};
|
||||
|
||||
@@ -35,22 +34,6 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
[name]: value,
|
||||
}));
|
||||
}
|
||||
|
||||
if (name === 'email') {
|
||||
const email = value.trim();
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: email,
|
||||
}));
|
||||
|
||||
setErrors((prev) => ({
|
||||
...prev,
|
||||
email:
|
||||
email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
|
||||
? 'Format email tidak valid'
|
||||
: '',
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +51,6 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
const validationRules = [
|
||||
{ field: 'name', label: 'Contact Name', required: true },
|
||||
{ field: 'phone', label: 'Phone', required: true },
|
||||
{ field: 'email', label: 'Email', required: false },
|
||||
];
|
||||
|
||||
if (
|
||||
@@ -102,23 +84,10 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validasi Email
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (formData.email && !emailRegex.test(formData.email.trim())) {
|
||||
NotifOk({
|
||||
icon: 'warning',
|
||||
title: 'Peringatan',
|
||||
message: 'Format email tidak valid.',
|
||||
});
|
||||
setConfirmLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const contactData = {
|
||||
contact_name: formData.name,
|
||||
contact_phone: formData.phone.replace(/[\s\-\(\)]/g, ''), // Clean phone number
|
||||
email: formData.email?.trim(),
|
||||
is_active: formData.is_active,
|
||||
};
|
||||
|
||||
@@ -165,7 +134,6 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
setFormData({
|
||||
name: props.selectedData.contact_name || props.selectedData.name,
|
||||
phone: props.selectedData.contact_phone || props.selectedData.phone,
|
||||
email: props.selectedData.contact_email || props.selectedData.email,
|
||||
is_active:
|
||||
props.selectedData.is_active || props.selectedData.status === 'active',
|
||||
});
|
||||
@@ -173,7 +141,6 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
setFormData({
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
is_active: true,
|
||||
});
|
||||
}
|
||||
@@ -282,19 +249,6 @@ const DetailContact = memo(function DetailContact(props) {
|
||||
style={{ color: formData.is_active ? '#000000' : '#ff4d4f' }}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Email</Text>
|
||||
{/* <Text style={{ color: 'red' }}> *</Text> */}
|
||||
<Input
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Email Number"
|
||||
readOnly={props.readOnly}
|
||||
maxLength={64}
|
||||
style={{ color: formData.is_active ? '#000000' : '#ff4d4f' }}
|
||||
/>
|
||||
</div>
|
||||
{/* Contact Type */}
|
||||
{/* <div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Contact Type</Text>
|
||||
|
||||
@@ -267,6 +267,9 @@ const ListContact = memo(function ListContact(props) {
|
||||
}
|
||||
}
|
||||
|
||||
// Backend doesn't support is_active filter or order parameter
|
||||
// Contact hanya supports: criteria, name, code, limit, page
|
||||
|
||||
const queryParams = new URLSearchParams();
|
||||
Object.entries(searchParams).forEach(([key, value]) => {
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
@@ -306,10 +309,11 @@ const ListContact = memo(function ListContact(props) {
|
||||
// Listen for saved contact data
|
||||
useEffect(() => {
|
||||
if (props.lastSavedContact) {
|
||||
fetchContacts();
|
||||
fetchContacts(); // Refetch all contacts when data is saved
|
||||
}
|
||||
}, [props.lastSavedContact]);
|
||||
|
||||
// Get contacts (already filtered by backend)
|
||||
const getFilteredContacts = () => {
|
||||
return filteredContacts;
|
||||
};
|
||||
@@ -322,7 +326,7 @@ const ListContact = memo(function ListContact(props) {
|
||||
const showAddModal = () => {
|
||||
props.setSelectedData(null);
|
||||
props.setActionMode('add');
|
||||
|
||||
// Pass the current active tab to determine contact type
|
||||
props.setContactType?.(activeTab);
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/air_dryer_A_rev.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/air_dryer_A_rev.svg';
|
||||
const topicMqtt = 'PIU_COD/AIR_DRYER/AIR_DRYER_A';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgAirDryerA = () => {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/air_dryer_B_rev.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/air_dryer_B_rev.svg';
|
||||
const topicMqtt = 'PIU_COD/AIR_DRYER/AIR_DRYER_B';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgAirDryerB = () => {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/air_dryer_C_rev.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/air_dryer_C_rev.svg';
|
||||
const topicMqtt = 'PIU_COD/AIR_DRYER/AIR_DRYER_C';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgAirDryerC = () => {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/compressorA_rev.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_COD/COMPRESSOR/COMPRESSOR_A';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgCompressorA = () => {
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@ import SvgViewer from './SvgViewer';
|
||||
import filePathSvg from '../../assets/svg/compressorB_rev.svg';
|
||||
|
||||
const { Text } = Typography;
|
||||
const topicMqtt = 'PIU_COD/COMPRESSOR/COMPRESSOR_B';
|
||||
const topicMqtt = 'cod/air_dryer/air_dryer1';
|
||||
|
||||
const SvgCompressorB = () => {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/compressorC_rev.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_COD/COMPRESSOR/COMPRESSOR_C';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgCompressorC = () => {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/overview-airdryer.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_COD/AIR_DRYER/OVERVIEW';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgOverviewAirDryer = () => {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ import filePathSvg from '../../assets/svg/overview-compressor.svg';
|
||||
const { Text } = Typography;
|
||||
|
||||
// const filePathSvg = '/src/assets/svg/test-new.svg';
|
||||
const topicMqtt = 'PIU_COD/COMPRESSOR/OVERVIEW';
|
||||
const topicMqtt = 'PIU_GGCP/Devices/PB';
|
||||
|
||||
const SvgOverviewCompressor = () => {
|
||||
return (
|
||||
|
||||
@@ -352,7 +352,7 @@ const ListJadwalShift = memo(function ListJadwalShift(props) {
|
||||
<Title level={3}>Jadwal Shift</Title>
|
||||
<Divider />
|
||||
|
||||
{/* <Row>
|
||||
<Row>
|
||||
<Col xs={24}>
|
||||
<Row justify="end" align="middle" gutter={[8, 8]}>
|
||||
<Col xs={24} sm={24} md={12} lg={12}>
|
||||
@@ -383,7 +383,7 @@ const ListJadwalShift = memo(function ListJadwalShift(props) {
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row> */}
|
||||
</Row>
|
||||
|
||||
<div style={{ marginTop: '24px' }}>
|
||||
{loading ? (
|
||||
|
||||
@@ -13,18 +13,13 @@ import {
|
||||
Space,
|
||||
ConfigProvider,
|
||||
} from 'antd';
|
||||
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
EditOutlined,
|
||||
DeleteOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
|
||||
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
|
||||
import {
|
||||
getBrandById,
|
||||
createBrand,
|
||||
createErrorCode,
|
||||
getErrorCodesByBrandId,
|
||||
updateErrorCode,
|
||||
deleteErrorCode,
|
||||
deleteBrand,
|
||||
} from '../../../api/master-brand';
|
||||
import { getBrandById, createBrand, createErrorCode, getErrorCodesByBrandId, updateErrorCode, deleteErrorCode, deleteBrand } from '../../../api/master-brand';
|
||||
import BrandForm from './component/BrandForm';
|
||||
import ErrorCodeForm from './component/ErrorCodeForm';
|
||||
import SolutionForm from './component/SolutionForm';
|
||||
@@ -47,9 +42,7 @@ const AddBrandDevice = () => {
|
||||
const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const tab = searchParams.get('tab');
|
||||
const [currentStep, setCurrentStep] = useState(
|
||||
tab === 'error-codes' ? 1 : location.state?.phase || 0
|
||||
);
|
||||
const [currentStep, setCurrentStep] = useState(tab === 'error-codes' ? 1 : (location.state?.phase || 0));
|
||||
const [editingErrorCodeKey, setEditingErrorCodeKey] = useState(null);
|
||||
const [isErrorCodeFormReadOnly, setIsErrorCodeFormReadOnly] = useState(false);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
@@ -75,7 +68,7 @@ const AddBrandDevice = () => {
|
||||
const values = solutionForm.getFieldsValue(true);
|
||||
const solutions = [];
|
||||
|
||||
solutionFields.forEach((fieldKey) => {
|
||||
solutionFields.forEach(fieldKey => {
|
||||
let solution = null;
|
||||
|
||||
if (values.solution_items && values.solution_items[fieldKey]) {
|
||||
@@ -92,16 +85,9 @@ const AddBrandDevice = () => {
|
||||
if (solutionType === 'text') {
|
||||
isValid = solution.text && solution.text.trim() !== '';
|
||||
} else if (solutionType === 'file') {
|
||||
const hasPathSolution =
|
||||
solution.path_solution && solution.path_solution.trim() !== '';
|
||||
const hasFileUpload =
|
||||
solution.fileUpload &&
|
||||
typeof solution.fileUpload === 'object' &&
|
||||
Object.keys(solution.fileUpload).length > 0;
|
||||
const hasFile =
|
||||
solution.file &&
|
||||
typeof solution.file === 'object' &&
|
||||
Object.keys(solution.file).length > 0;
|
||||
const hasPathSolution = solution.path_solution && solution.path_solution.trim() !== '';
|
||||
const hasFileUpload = (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0);
|
||||
const hasFile = (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0);
|
||||
isValid = hasPathSolution || hasFileUpload || hasFile;
|
||||
}
|
||||
|
||||
@@ -132,9 +118,9 @@ const AddBrandDevice = () => {
|
||||
text: '',
|
||||
status: true,
|
||||
file: null,
|
||||
fileUpload: null,
|
||||
},
|
||||
},
|
||||
fileUpload: null
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
@@ -142,6 +128,7 @@ const AddBrandDevice = () => {
|
||||
};
|
||||
|
||||
const setSolutionsForExistingRecord = (solutions, targetForm) => {
|
||||
|
||||
if (!targetForm || !solutions || solutions.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -166,14 +153,11 @@ const AddBrandDevice = () => {
|
||||
fileObject = {
|
||||
uploadPath: solution.path_solution || solution.path_document,
|
||||
path_solution: solution.path_solution || solution.path_document,
|
||||
name:
|
||||
solution.file_upload_name ||
|
||||
(solution.path_solution || solution.path_document).split('/').pop() ||
|
||||
'File',
|
||||
name: solution.file_upload_name || (solution.path_solution || solution.path_document).split('/').pop() || 'File',
|
||||
type_solution: solution.type_solution,
|
||||
isExisting: true,
|
||||
size: 0,
|
||||
url: solution.path_solution || solution.path_document,
|
||||
url: solution.path_solution || solution.path_document
|
||||
};
|
||||
}
|
||||
|
||||
@@ -186,7 +170,7 @@ const AddBrandDevice = () => {
|
||||
file: fileObject,
|
||||
fileUpload: fileObject,
|
||||
path_solution: solution.path_solution || solution.path_document || null,
|
||||
fileName: solution.file_upload_name || null,
|
||||
fileName: solution.file_upload_name || null
|
||||
};
|
||||
});
|
||||
|
||||
@@ -196,35 +180,28 @@ const AddBrandDevice = () => {
|
||||
|
||||
setSolutionStatuses(newSolutionStatuses);
|
||||
|
||||
|
||||
targetForm.resetFields();
|
||||
|
||||
setTimeout(() => {
|
||||
targetForm.setFieldsValue({
|
||||
solution_items: solutionItems,
|
||||
solution_items: solutionItems
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
Object.keys(solutionItems).forEach((key) => {
|
||||
Object.keys(solutionItems).forEach(key => {
|
||||
const solution = solutionItems[key];
|
||||
targetForm.setFieldValue(['solution_items', key, 'name'], solution.name);
|
||||
targetForm.setFieldValue(['solution_items', key, 'type'], solution.type);
|
||||
targetForm.setFieldValue(['solution_items', key, 'text'], solution.text);
|
||||
targetForm.setFieldValue(['solution_items', key, 'file'], solution.file);
|
||||
targetForm.setFieldValue(
|
||||
['solution_items', key, 'fileUpload'],
|
||||
solution.fileUpload
|
||||
);
|
||||
targetForm.setFieldValue(['solution_items', key, 'fileUpload'], solution.fileUpload);
|
||||
targetForm.setFieldValue(['solution_items', key, 'status'], solution.status);
|
||||
targetForm.setFieldValue(
|
||||
['solution_items', key, 'path_solution'],
|
||||
solution.path_solution
|
||||
);
|
||||
targetForm.setFieldValue(
|
||||
['solution_items', key, 'fileName'],
|
||||
solution.fileName
|
||||
);
|
||||
targetForm.setFieldValue(['solution_items', key, 'path_solution'], solution.path_solution);
|
||||
targetForm.setFieldValue(['solution_items', key, 'fileName'], solution.fileName);
|
||||
});
|
||||
|
||||
|
||||
const finalValues = targetForm.getFieldsValue();
|
||||
}, 100);
|
||||
}, 100);
|
||||
@@ -232,14 +209,14 @@ const AddBrandDevice = () => {
|
||||
|
||||
const handleAddSolutionField = () => {
|
||||
const newKey = Math.max(...solutionFields, 0) + 1;
|
||||
setSolutionFields((prev) => [...prev, newKey]);
|
||||
setSolutionTypes((prev) => ({ ...prev, [newKey]: 'text' }));
|
||||
setSolutionStatuses((prev) => ({ ...prev, [newKey]: true }));
|
||||
setSolutionFields(prev => [...prev, newKey]);
|
||||
setSolutionTypes(prev => ({ ...prev, [newKey]: 'text' }));
|
||||
setSolutionStatuses(prev => ({ ...prev, [newKey]: true }));
|
||||
};
|
||||
|
||||
const handleRemoveSolutionField = (fieldKey) => {
|
||||
if (solutionFields.length > 1) {
|
||||
setSolutionFields((prev) => prev.filter((key) => key !== fieldKey));
|
||||
setSolutionFields(prev => prev.filter(key => key !== fieldKey));
|
||||
const newTypes = { ...solutionTypes };
|
||||
const newStatuses = { ...solutionStatuses };
|
||||
delete newTypes[fieldKey];
|
||||
@@ -256,7 +233,7 @@ const AddBrandDevice = () => {
|
||||
};
|
||||
|
||||
const handleSolutionTypeChange = (fieldKey, type) => {
|
||||
setSolutionTypes((prev) => ({ ...prev, [fieldKey]: type }));
|
||||
setSolutionTypes(prev => ({ ...prev, [fieldKey]: type }));
|
||||
|
||||
if (type === 'file') {
|
||||
solutionForm.setFieldValue(['solution_items', fieldKey, 'text'], '');
|
||||
@@ -269,7 +246,7 @@ const AddBrandDevice = () => {
|
||||
};
|
||||
|
||||
const handleSolutionStatusChange = (fieldKey, status) => {
|
||||
setSolutionStatuses((prev) => ({ ...prev, [fieldKey]: status }));
|
||||
setSolutionStatuses(prev => ({ ...prev, [fieldKey]: status }));
|
||||
};
|
||||
|
||||
const handleNextStep = async () => {
|
||||
@@ -282,7 +259,7 @@ const AddBrandDevice = () => {
|
||||
brand_type: brandValues.brand_type || '',
|
||||
brand_manufacture: brandValues.brand_manufacture || '',
|
||||
brand_model: brandValues.brand_model || '',
|
||||
is_active: brandValues.is_active !== undefined ? brandValues.is_active : true,
|
||||
is_active: brandValues.is_active !== undefined ? brandValues.is_active : true
|
||||
};
|
||||
|
||||
const response = await createBrand(brandApiData);
|
||||
@@ -291,7 +268,7 @@ const AddBrandDevice = () => {
|
||||
const newBrandInfo = {
|
||||
...brandValues,
|
||||
brand_id: response.data.brand_id,
|
||||
brand_code: response.data.brand_code,
|
||||
brand_code: response.data.brand_code
|
||||
};
|
||||
setBrandInfo(newBrandInfo);
|
||||
setTemporaryBrandId(response.data.brand_id);
|
||||
@@ -330,7 +307,8 @@ const AddBrandDevice = () => {
|
||||
if (isTemporaryBrand && temporaryBrandId) {
|
||||
try {
|
||||
await deleteBrand(temporaryBrandId);
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
navigate('/master/brand-device');
|
||||
};
|
||||
@@ -382,6 +360,8 @@ const AddBrandDevice = () => {
|
||||
setTrigerFilter((prev) => !prev);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const resetErrorCodeForm = () => {
|
||||
errorCodeForm.resetFields();
|
||||
errorCodeForm.setFieldsValue({
|
||||
@@ -411,16 +391,16 @@ const AddBrandDevice = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!solutionData || solutionData.length === 0) {
|
||||
// NotifAlert({
|
||||
// icon: 'warning',
|
||||
// title: 'Perhatian',
|
||||
// message: 'Setiap error code harus memiliki minimal 1 solution!',
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
if (!solutionData || solutionData.length === 0) {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message: 'Setiap error code harus memiliki minimal 1 solution!',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const formattedSolutions = solutionData.map((solution) => {
|
||||
const formattedSolutions = solutionData.map(solution => {
|
||||
const solutionType = solution.type || 'text';
|
||||
|
||||
let typeSolution = solutionType === 'text' ? 'text' : 'image';
|
||||
@@ -442,11 +422,7 @@ const AddBrandDevice = () => {
|
||||
} else {
|
||||
formattedSolution.text_solution = '';
|
||||
|
||||
formattedSolution.path_solution =
|
||||
solution.path_solution ||
|
||||
solution.file?.uploadPath ||
|
||||
solution.fileUpload?.uploadPath ||
|
||||
'';
|
||||
formattedSolution.path_solution = solution.path_solution || solution.file?.uploadPath || solution.fileUpload?.uploadPath || '';
|
||||
}
|
||||
|
||||
if (formattedSolution.brand_code_solution_id) {
|
||||
@@ -464,7 +440,7 @@ const AddBrandDevice = () => {
|
||||
path_icon: errorCodeIcon?.uploadPath || '',
|
||||
is_active: errorCodeValues.status === undefined ? true : errorCodeValues.status,
|
||||
solution: formattedSolutions,
|
||||
spareparts: selectedSparepartIds || [],
|
||||
spareparts: selectedSparepartIds || []
|
||||
};
|
||||
|
||||
let response;
|
||||
@@ -480,13 +456,11 @@ const AddBrandDevice = () => {
|
||||
NotifOk({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
message: editingErrorCodeKey
|
||||
? 'Error code berhasil diupdate!'
|
||||
: 'Error code berhasil ditambahkan!',
|
||||
message: editingErrorCodeKey ? 'Error code berhasil diupdate!' : 'Error code berhasil ditambahkan!',
|
||||
});
|
||||
|
||||
resetErrorCodeForm();
|
||||
setTrigerFilter((prev) => !prev);
|
||||
setTrigerFilter(prev => !prev);
|
||||
} else {
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
@@ -505,10 +479,12 @@ const AddBrandDevice = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleErrorCodeIconRemove = () => {
|
||||
setErrorCodeIcon(null);
|
||||
};
|
||||
|
||||
|
||||
const handleFinish = async () => {
|
||||
setConfirmLoading(true);
|
||||
try {
|
||||
@@ -530,10 +506,10 @@ const AddBrandDevice = () => {
|
||||
const response = await getErrorCodesByBrandId(brandInfo.brand_id, queryParams);
|
||||
|
||||
if (response && response.statusCode === 200 && response.data) {
|
||||
const freshErrorCodes = response.data.map((ec) => ({
|
||||
const freshErrorCodes = response.data.map(ec => ({
|
||||
...ec,
|
||||
tempId: `existing_${ec.error_code_id}`,
|
||||
status: 'existing',
|
||||
status: 'existing'
|
||||
}));
|
||||
setApiErrorCodes(freshErrorCodes);
|
||||
|
||||
@@ -541,8 +517,7 @@ const AddBrandDevice = () => {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message:
|
||||
'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
|
||||
message: 'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -551,8 +526,7 @@ const AddBrandDevice = () => {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message:
|
||||
'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
|
||||
message: 'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -617,7 +591,11 @@ const AddBrandDevice = () => {
|
||||
<Spin size="large" />
|
||||
</div>
|
||||
)}
|
||||
<BrandForm form={brandForm} isEdit={false} brandInfo={brandInfo} />
|
||||
<BrandForm
|
||||
form={brandForm}
|
||||
isEdit={false}
|
||||
brandInfo={brandInfo}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -657,39 +635,31 @@ const AddBrandDevice = () => {
|
||||
</Col>
|
||||
|
||||
<Col xs={24} md={16} lg={16}>
|
||||
<div
|
||||
style={{
|
||||
paddingLeft: '12px',
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
paddingLeft: '12px'
|
||||
}}>
|
||||
<Card
|
||||
title={
|
||||
<div
|
||||
style={{
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%'
|
||||
}}>
|
||||
<span style={{
|
||||
fontSize: '16px',
|
||||
fontWeight: '600',
|
||||
color: '#262626',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontSize: '16px',
|
||||
fontWeight: '600',
|
||||
color: '#262626',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
width: '4px',
|
||||
height: '20px',
|
||||
backgroundColor: '#23A55A',
|
||||
borderRadius: '2px',
|
||||
}}
|
||||
></span>
|
||||
gap: '8px'
|
||||
}}>
|
||||
<span style={{
|
||||
width: '4px',
|
||||
height: '20px',
|
||||
backgroundColor: '#23A55A',
|
||||
borderRadius: '2px'
|
||||
}}></span>
|
||||
Error Code Form
|
||||
</span>
|
||||
<Button
|
||||
@@ -705,51 +675,43 @@ const AddBrandDevice = () => {
|
||||
padding: '0 24px',
|
||||
fontWeight: '500',
|
||||
boxShadow: '0 2px 4px rgba(35, 165, 90, 0.2)',
|
||||
transition: 'all 0.3s ease',
|
||||
transition: 'all 0.3s ease'
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.target.style.boxShadow =
|
||||
'0 4px 8px rgba(35, 165, 90, 0.3)';
|
||||
e.target.style.boxShadow = '0 4px 8px rgba(35, 165, 90, 0.3)';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.target.style.boxShadow =
|
||||
'0 2px 4px rgba(35, 165, 90, 0.2)';
|
||||
e.target.style.boxShadow = '0 2px 4px rgba(35, 165, 90, 0.2)';
|
||||
}}
|
||||
>
|
||||
{editingErrorCodeKey
|
||||
? 'Update Error Code'
|
||||
: 'Save Error Code'}
|
||||
{editingErrorCodeKey ? 'Update Error Code' : 'Save Error Code'}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
style={{
|
||||
width: '100%',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.06)',
|
||||
borderRadius: '12px',
|
||||
borderRadius: '12px'
|
||||
}}
|
||||
styles={{
|
||||
body: { padding: '16px 24px 12px 24px' },
|
||||
header: {
|
||||
padding: '16px 24px',
|
||||
borderBottom: '1px solid #f0f0f0',
|
||||
backgroundColor: '#fafafa',
|
||||
},
|
||||
backgroundColor: '#fafafa'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
padding: '16px',
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
marginBottom: '0',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
marginBottom: '0',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.04)'
|
||||
}}>
|
||||
<ErrorCodeForm
|
||||
errorCodeForm={errorCodeForm}
|
||||
isErrorCodeFormReadOnly={isErrorCodeFormReadOnly}
|
||||
@@ -762,42 +724,29 @@ const AddBrandDevice = () => {
|
||||
|
||||
<Row gutter={[20, 0]} style={{ marginTop: '0' }}>
|
||||
<Col xs={24} md={12} lg={12}>
|
||||
<div
|
||||
style={{
|
||||
padding: '16px',
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginBottom: '12px',
|
||||
paddingBottom: '8px',
|
||||
borderBottom: '1px solid #f5f5f5',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: '3px',
|
||||
height: '16px',
|
||||
backgroundColor: '#1890ff',
|
||||
borderRadius: '2px',
|
||||
}}
|
||||
></div>
|
||||
<h4
|
||||
style={{
|
||||
margin: 0,
|
||||
color: '#262626',
|
||||
fontSize: '14px',
|
||||
fontWeight: '600',
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.04)'
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginBottom: '12px',
|
||||
paddingBottom: '8px',
|
||||
borderBottom: '1px solid #f5f5f5'
|
||||
}}>
|
||||
<div style={{
|
||||
width: '3px',
|
||||
height: '16px',
|
||||
backgroundColor: '#1890ff',
|
||||
borderRadius: '2px'
|
||||
}}></div>
|
||||
<h4 style={{ margin: 0, color: '#262626', fontSize: '14px', fontWeight: '600' }}>
|
||||
Solution
|
||||
</h4>
|
||||
</div>
|
||||
@@ -807,23 +756,14 @@ const AddBrandDevice = () => {
|
||||
solutionTypes={solutionTypes}
|
||||
solutionStatuses={solutionStatuses}
|
||||
onAddSolutionField={handleAddSolutionField}
|
||||
onRemoveSolutionField={
|
||||
handleRemoveSolutionField
|
||||
}
|
||||
onRemoveSolutionField={handleRemoveSolutionField}
|
||||
onSolutionTypeChange={handleSolutionTypeChange}
|
||||
onSolutionStatusChange={
|
||||
handleSolutionStatusChange
|
||||
}
|
||||
onSolutionFileUpload={(fileData) => {}}
|
||||
onSolutionStatusChange={handleSolutionStatusChange}
|
||||
onSolutionFileUpload={(fileData) => {
|
||||
}}
|
||||
onFileView={(fileData) => {
|
||||
if (
|
||||
fileData &&
|
||||
(fileData.url || fileData.uploadPath)
|
||||
) {
|
||||
window.open(
|
||||
fileData.url || fileData.uploadPath,
|
||||
'_blank'
|
||||
);
|
||||
if (fileData && (fileData.url || fileData.uploadPath)) {
|
||||
window.open(fileData.url || fileData.uploadPath, '_blank');
|
||||
}
|
||||
}}
|
||||
isReadOnly={false}
|
||||
@@ -832,55 +772,40 @@ const AddBrandDevice = () => {
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={24} md={12} lg={12}>
|
||||
<div
|
||||
style={{
|
||||
padding: '16px',
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginBottom: '12px',
|
||||
paddingBottom: '8px',
|
||||
borderBottom: '1px solid #f5f5f5',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: '3px',
|
||||
height: '16px',
|
||||
backgroundColor: '#faad14',
|
||||
borderRadius: '2px',
|
||||
}}
|
||||
></div>
|
||||
<h4
|
||||
style={{
|
||||
margin: 0,
|
||||
color: '#262626',
|
||||
fontSize: '14px',
|
||||
fontWeight: '600',
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.04)'
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginBottom: '12px',
|
||||
paddingBottom: '8px',
|
||||
borderBottom: '1px solid #f5f5f5'
|
||||
}}>
|
||||
<div style={{
|
||||
width: '3px',
|
||||
height: '16px',
|
||||
backgroundColor: '#faad14',
|
||||
borderRadius: '2px'
|
||||
}}></div>
|
||||
<h4 style={{ margin: 0, color: '#262626', fontSize: '14px', fontWeight: '600' }}>
|
||||
Sparepart Selection
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
maxHeight: '45vh',
|
||||
overflow: 'auto',
|
||||
border: '1px solid #e8e8e8',
|
||||
borderRadius: '8px',
|
||||
padding: '12px',
|
||||
backgroundColor: '#fafafa',
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
maxHeight: '45vh',
|
||||
overflow: 'auto',
|
||||
border: '1px solid #e8e8e8',
|
||||
borderRadius: '8px',
|
||||
padding: '12px',
|
||||
backgroundColor: '#fafafa'
|
||||
}}>
|
||||
<SparepartSelect
|
||||
selectedSparepartIds={selectedSparepartIds}
|
||||
onSparepartChange={setSelectedSparepartIds}
|
||||
@@ -891,16 +816,15 @@ const AddBrandDevice = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: '16px 0 0 0',
|
||||
borderTop: '1px solid #f0f0f0',
|
||||
marginTop: '12px',
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: '16px 0 0 0',
|
||||
borderTop: '1px solid #f0f0f0',
|
||||
marginTop: '12px'
|
||||
}}>
|
||||
|
||||
{editingErrorCodeKey && (
|
||||
<Button
|
||||
size="large"
|
||||
@@ -913,7 +837,7 @@ const AddBrandDevice = () => {
|
||||
height: '40px',
|
||||
padding: '0 24px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.3s ease',
|
||||
transition: 'all 0.3s ease'
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.target.style.borderColor = '#ff4d4f';
|
||||
@@ -947,7 +871,7 @@ const AddBrandDevice = () => {
|
||||
|
||||
setBreadcrumbItems([
|
||||
{
|
||||
title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}>• Master</span>,
|
||||
title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}>• Master</span>
|
||||
},
|
||||
{
|
||||
title: (
|
||||
@@ -971,11 +895,12 @@ const AddBrandDevice = () => {
|
||||
if (location.state?.fromFileViewer && location.state.phase !== undefined) {
|
||||
setCurrentStep(location.state.phase);
|
||||
}
|
||||
|
||||
}, [setBreadcrumbItems, navigate, searchParams, location.state]);
|
||||
|
||||
useEffect(() => {
|
||||
if (brandInfo.brand_id && currentStep === 1) {
|
||||
setTrigerFilter((prev) => !prev);
|
||||
setTrigerFilter(prev => !prev);
|
||||
}
|
||||
}, [brandInfo.brand_id, currentStep]);
|
||||
|
||||
@@ -988,7 +913,8 @@ const AddBrandDevice = () => {
|
||||
const errorCodes = response.data || [];
|
||||
setApiErrorCodes(errorCodes);
|
||||
}
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
};
|
||||
fetchErrorCodes();
|
||||
@@ -999,7 +925,8 @@ const AddBrandDevice = () => {
|
||||
if (isTemporaryBrand && temporaryBrandId && currentStep === 0) {
|
||||
try {
|
||||
await deleteBrand(temporaryBrandId);
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1010,6 +937,7 @@ const AddBrandDevice = () => {
|
||||
};
|
||||
}, [isTemporaryBrand, temporaryBrandId, currentStep]);
|
||||
|
||||
|
||||
return (
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
@@ -1060,9 +988,14 @@ const AddBrandDevice = () => {
|
||||
<Divider />
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<div>
|
||||
<Button onClick={handleCancel}>Cancel</Button>
|
||||
<Button onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
{currentStep === 1 && (
|
||||
<Button onClick={handlePrevStep} style={{ marginLeft: 8 }}>
|
||||
<Button
|
||||
onClick={handlePrevStep}
|
||||
style={{ marginLeft: 8 }}
|
||||
>
|
||||
Kembali ke Brand Info
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -479,14 +479,14 @@ const EditBrandDevice = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!solutionData || solutionData.length === 0) {
|
||||
// NotifAlert({
|
||||
// icon: 'warning',
|
||||
// title: 'Perhatian',
|
||||
// message: 'Setiap error code harus memiliki minimal 1 solution!',
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
if (!solutionData || solutionData.length === 0) {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message: 'Setiap error code harus memiliki minimal 1 solution!',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const formattedSolutions = solutionData.map(solution => {
|
||||
const solutionType = solution.type || 'text';
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { Card, Input, Button, Row, Col, Empty } from 'antd';
|
||||
import {
|
||||
PlusOutlined,
|
||||
SearchOutlined,
|
||||
DeleteOutlined,
|
||||
LeftOutlined,
|
||||
RightOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { PlusOutlined, SearchOutlined, DeleteOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { getErrorCodesByBrandId, deleteErrorCode } from '../../../../api/master-brand';
|
||||
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../../components/Global/ToastNotif';
|
||||
|
||||
@@ -22,7 +16,7 @@ const ListErrorCode = ({
|
||||
onSearch,
|
||||
onSearchClear,
|
||||
isReadOnly = false,
|
||||
errorCodes: propErrorCodes = null,
|
||||
errorCodes: propErrorCodes = null
|
||||
}) => {
|
||||
const [errorCodes, setErrorCodes] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -58,12 +52,12 @@ const ListErrorCode = ({
|
||||
if (response && response.statusCode === 200) {
|
||||
const apiErrorData = response.data || [];
|
||||
const allErrorCodes = [
|
||||
...apiErrorData.map((ec) => ({
|
||||
...apiErrorData.map(ec => ({
|
||||
...ec,
|
||||
tempId: `existing_${ec.error_code_id}`,
|
||||
status: 'existing',
|
||||
status: 'existing'
|
||||
})),
|
||||
...tempErrorCodes.filter((ec) => ec.status !== 'deleted'),
|
||||
...tempErrorCodes.filter(ec => ec.status !== 'deleted')
|
||||
];
|
||||
|
||||
setErrorCodes(allErrorCodes);
|
||||
@@ -88,9 +82,11 @@ const ListErrorCode = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (isReadOnly && propErrorCodes) {
|
||||
|
||||
setErrorCodes(propErrorCodes);
|
||||
setLoading(false);
|
||||
} else {
|
||||
|
||||
fetchErrorCodes();
|
||||
}
|
||||
}, [brandId, queryParams, tempErrorCodes, trigerFilter, isReadOnly, propErrorCodes]);
|
||||
@@ -130,19 +126,20 @@ const ListErrorCode = ({
|
||||
title: 'Hapus Error Code',
|
||||
message: `Apakah Anda yakin ingin menghapus error code ${item.error_code}?`,
|
||||
onConfirm: () => performDelete(item),
|
||||
onCancel: () => {},
|
||||
confirmButtonText: 'Hapus',
|
||||
onCancel: () => { },
|
||||
confirmButtonText: 'Hapus'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const performDelete = async (item) => {
|
||||
try {
|
||||
|
||||
if (!item.error_code_id || item.error_code_id === 'undefined') {
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
message: 'Error code ID tidak valid',
|
||||
message: 'Error code ID tidak valid'
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +148,7 @@ const ListErrorCode = ({
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
message: 'Brand ID tidak valid',
|
||||
message: 'Brand ID tidak valid'
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -162,21 +159,21 @@ const ListErrorCode = ({
|
||||
NotifOk({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
message: 'Error code berhasil dihapus',
|
||||
message: 'Error code berhasil dihapus'
|
||||
});
|
||||
fetchErrorCodes();
|
||||
} else {
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
title: 'Gagal',
|
||||
message: 'Gagal menghapus error code',
|
||||
message: 'Gagal menghapus error code'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
message: 'Terjadi kesalahan saat menghapus error code',
|
||||
message: 'Terjadi kesalahan saat menghapus error code'
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -184,8 +181,8 @@ const ListErrorCode = ({
|
||||
return (
|
||||
<Card
|
||||
title="Daftar Error Code"
|
||||
style={{ width: '100%', minWidth: '300px' }}
|
||||
bodyStyle={{ padding: '12px' }}
|
||||
style={{ width: '100%', minWidth: '472px' }}
|
||||
styles={{ body: { padding: '12px' } }}
|
||||
>
|
||||
<Input.Search
|
||||
placeholder="Cari error code..."
|
||||
@@ -206,7 +203,7 @@ const ListErrorCode = ({
|
||||
style={{
|
||||
backgroundColor: '#23A55A',
|
||||
borderColor: '#23A55A',
|
||||
height: '32px',
|
||||
height: '32px'
|
||||
}}
|
||||
>
|
||||
Search
|
||||
@@ -217,21 +214,23 @@ const ListErrorCode = ({
|
||||
marginBottom: 12,
|
||||
height: '32px',
|
||||
width: '100%',
|
||||
maxWidth: '300px'
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '90vh',
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: '6px',
|
||||
overflow: 'auto',
|
||||
marginBottom: 12,
|
||||
backgroundColor: '#fafafa',
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
height: '90vh',
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: '6px',
|
||||
overflow: 'auto',
|
||||
marginBottom: 12,
|
||||
backgroundColor: '#fafafa'
|
||||
}}>
|
||||
{errorCodes.length === 0 ? (
|
||||
<Empty description="Belum ada error code" style={{ marginTop: 50 }} />
|
||||
<Empty
|
||||
description="Belum ada error code"
|
||||
style={{ marginTop: 50 }}
|
||||
/>
|
||||
) : (
|
||||
<div style={{ padding: '8px' }}>
|
||||
{errorCodes.map((item) => (
|
||||
@@ -242,25 +241,13 @@ const ListErrorCode = ({
|
||||
padding: '8px 12px',
|
||||
borderRadius: '6px',
|
||||
marginBottom: '4px',
|
||||
border:
|
||||
selectedErrorCode?.tempId === item.tempId
|
||||
? '2px solid #23A55A'
|
||||
: '1px solid #d9d9d9',
|
||||
backgroundColor:
|
||||
selectedErrorCode?.tempId === item.tempId
|
||||
? '#f6ffed'
|
||||
: '#fff',
|
||||
transition: 'all 0.2s ease',
|
||||
border: selectedErrorCode?.tempId === item.tempId ? '2px solid #23A55A' : '1px solid #d9d9d9',
|
||||
backgroundColor: selectedErrorCode?.tempId === item.tempId ? '#f6ffed' : '#fff',
|
||||
transition: 'all 0.2s ease'
|
||||
}}
|
||||
onClick={() => onErrorCodeSelect(item)}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{ fontWeight: 'bold', fontSize: '12px' }}>
|
||||
{item.error_code}
|
||||
@@ -280,7 +267,7 @@ const ListErrorCode = ({
|
||||
padding: '2px 6px',
|
||||
height: '24px',
|
||||
fontSize: '11px',
|
||||
border: '1px solid #ff4d4f',
|
||||
border: '1px solid #ff4d4f'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -306,15 +293,9 @@ const ListErrorCode = ({
|
||||
onClick={handlePrevious}
|
||||
disabled={pagination.current_page <= 1}
|
||||
size="small"
|
||||
></Button>
|
||||
<span
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
color: '#666',
|
||||
minWidth: '60px',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
</Button>
|
||||
<span style={{ fontSize: '12px', color: '#666', minWidth: '60px', textAlign: 'center' }}>
|
||||
{pagination.current_page} / {pagination.total_page}
|
||||
</span>
|
||||
<Button
|
||||
@@ -322,7 +303,8 @@ const ListErrorCode = ({
|
||||
onClick={handleNext}
|
||||
disabled={pagination.current_page >= pagination.total_page}
|
||||
size="small"
|
||||
></Button>
|
||||
>
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -36,7 +36,7 @@ const SparepartSelect = ({
|
||||
setLoading(true);
|
||||
try {
|
||||
const params = new URLSearchParams();
|
||||
params.set('limit', '10');
|
||||
params.set('limit', '1000');
|
||||
|
||||
if (searchQuery && searchQuery.trim() !== '') {
|
||||
params.set('criteria', searchQuery.trim());
|
||||
@@ -137,7 +137,7 @@ const SparepartSelect = ({
|
||||
>
|
||||
{spareparts
|
||||
.filter(sparepart => !selectedSpareparts.some(sp => sp.sparepart_id === sparepart.sparepart_id))
|
||||
.slice(0, 10)
|
||||
.slice(0, 5)
|
||||
.map((sparepart) => (
|
||||
<Option key={sparepart.sparepart_id} value={sparepart.sparepart_id}>
|
||||
<div>
|
||||
|
||||
263
src/pages/master/brandDevice/hooks/errorCode.js
Normal file
@@ -0,0 +1,263 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
||||
|
||||
export const useErrorCodeLogic = (errorCodeForm, fileList) => {
|
||||
const [solutionFields, setSolutionFields] = useState([0]);
|
||||
const [solutionTypes, setSolutionTypes] = useState({ 0: 'text' });
|
||||
const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
|
||||
const [firstSolutionValid, setFirstSolutionValid] = useState(false);
|
||||
const [solutionsToDelete, setSolutionsToDelete] = useState(new Set());
|
||||
|
||||
const checkPreviousSolutionValid = (currentSolutionIndex) => {
|
||||
for (let i = 0; i < currentSolutionIndex; i++) {
|
||||
const fieldId = solutionFields[i];
|
||||
const solutionType = solutionTypes[fieldId];
|
||||
|
||||
const solutionName = errorCodeForm.getFieldValue(`solution_name_${fieldId}`);
|
||||
if (!solutionName || solutionName.trim() === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (solutionType === 'text') {
|
||||
const textSolution = errorCodeForm.getFieldValue(`text_solution_${fieldId}`);
|
||||
if (!textSolution || textSolution.trim() === '') {
|
||||
return false;
|
||||
}
|
||||
} else if (solutionType === 'file') {
|
||||
const filesForSolution = fileList.filter(file => file.solutionId === fieldId);
|
||||
if (filesForSolution.length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const checkFirstSolutionValid = () => {
|
||||
if (solutionFields.length === 0) {
|
||||
setFirstSolutionValid(false);
|
||||
return false;
|
||||
}
|
||||
const isValid = checkPreviousSolutionValid(1);
|
||||
setFirstSolutionValid(isValid);
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const handleAddSolutionField = () => {
|
||||
const currentSolutionCount = solutionFields.length;
|
||||
const nextSolutionNumber = currentSolutionCount + 1;
|
||||
|
||||
if (!checkPreviousSolutionValid(currentSolutionCount)) {
|
||||
let incompleteSolutionIndex = -1;
|
||||
for (let i = 0; i < currentSolutionCount; i++) {
|
||||
const fieldId = solutionFields[i];
|
||||
const solutionType = solutionTypes[fieldId];
|
||||
const solutionName = errorCodeForm.getFieldValue(`solution_name_${fieldId}`);
|
||||
let hasContent = false;
|
||||
|
||||
if (solutionType === 'text') {
|
||||
const textSolution = errorCodeForm.getFieldValue(`text_solution_${fieldId}`);
|
||||
hasContent = textSolution && textSolution.trim();
|
||||
} else if (solutionType === 'file') {
|
||||
const filesForSolution = fileList.filter(file => file.solutionId === fieldId);
|
||||
hasContent = filesForSolution.length > 0;
|
||||
}
|
||||
|
||||
if (!solutionName?.trim() || !hasContent) {
|
||||
incompleteSolutionIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message: `Harap lengkapi Solution ${incompleteSolutionIndex} terlebih dahulu sebelum menambah Solution ${nextSolutionNumber}!`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const newId = `new-${Date.now()}`;
|
||||
setSolutionFields(prev => [...prev, newId]);
|
||||
setSolutionTypes(prev => ({ ...prev, [newId]: 'text' }));
|
||||
setSolutionStatuses(prev => ({ ...prev, [newId]: true }));
|
||||
errorCodeForm.setFieldValue(`solution_status_${newId}`, true);
|
||||
errorCodeForm.setFieldValue(`solution_type_${newId}`, 'text');
|
||||
};
|
||||
|
||||
const handleRemoveSolutionField = (id) => {
|
||||
const isNewSolution = !id.toString().startsWith('existing-');
|
||||
|
||||
if (isNewSolution) {
|
||||
if (solutionFields.length > 1) {
|
||||
setSolutionFields(solutionFields.filter(fieldId => fieldId !== id));
|
||||
setSolutionTypes(prev => {
|
||||
const newTypes = { ...prev };
|
||||
delete newTypes[id];
|
||||
return newTypes;
|
||||
});
|
||||
setSolutionStatuses(prev => {
|
||||
const newStatuses = { ...prev };
|
||||
delete newStatuses[id];
|
||||
return newStatuses;
|
||||
});
|
||||
setSolutionsToDelete(prev => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.delete(id);
|
||||
return newSet;
|
||||
});
|
||||
} else {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message: 'Setiap error code harus memiliki minimal 1 solution!'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const solutionName = errorCodeForm.getFieldValue(`solution_name_${id}`);
|
||||
const solutionType = solutionTypes[id];
|
||||
let isEmpty = true;
|
||||
|
||||
const existingSolution = window.currentSolutionData?.[id];
|
||||
const hasExistingData = existingSolution && (
|
||||
(existingSolution.solution_name && existingSolution.solution_name.trim()) ||
|
||||
(existingSolution.text_solution && existingSolution.text_solution.trim()) ||
|
||||
(existingSolution.path_solution && existingSolution.path_solution.trim())
|
||||
);
|
||||
|
||||
if (solutionType === 'text') {
|
||||
const textSolution = errorCodeForm.getFieldValue(`text_solution_${id}`);
|
||||
isEmpty = !solutionName?.trim() && !textSolution?.trim() && !hasExistingData;
|
||||
} else if (solutionType === 'file') {
|
||||
const filesForSolution = fileList.filter(file => file.solutionId === id);
|
||||
isEmpty = !solutionName?.trim() && filesForSolution.length === 0 && !hasExistingData;
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
if (solutionFields.length > 1) {
|
||||
setSolutionFields(solutionFields.filter(fieldId => fieldId !== id));
|
||||
setSolutionTypes(prev => {
|
||||
const newTypes = { ...prev };
|
||||
delete newTypes[id];
|
||||
return newTypes;
|
||||
});
|
||||
setSolutionStatuses(prev => {
|
||||
const newStatuses = { ...prev };
|
||||
delete newStatuses[id];
|
||||
return newStatuses;
|
||||
});
|
||||
|
||||
if (window.currentSolutionData) {
|
||||
delete window.currentSolutionData[id];
|
||||
}
|
||||
|
||||
setSolutionsToDelete(prev => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.delete(id);
|
||||
return newSet;
|
||||
});
|
||||
} else {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message: 'Setiap error code harus memiliki minimal 1 solution!'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (solutionFields.length > 1) {
|
||||
setSolutionsToDelete(prev => new Set(prev).add(id));
|
||||
|
||||
const solutionElement = document.querySelector(`[data-solution-id="${id}"]`);
|
||||
if (solutionElement) {
|
||||
solutionElement.style.opacity = '0.5';
|
||||
solutionElement.style.border = '2px dashed #ff4d4f';
|
||||
}
|
||||
|
||||
NotifOk({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
message: 'Solution ditandai untuk dihapus. Klik "Update Error Code" untuk menyimpan perubahan.'
|
||||
});
|
||||
} else {
|
||||
NotifAlert({
|
||||
icon: 'warning',
|
||||
title: 'Perhatian',
|
||||
message: 'Setiap error code harus memiliki minimal 1 solution!'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleSolutionTypeChange = (fieldId, type) => {
|
||||
setSolutionTypes(prev => ({ ...prev, [fieldId]: type }));
|
||||
};
|
||||
|
||||
const handleSolutionStatusChange = (fieldId, status) => {
|
||||
setSolutionStatuses(prev => ({
|
||||
...prev,
|
||||
[fieldId]: status
|
||||
}));
|
||||
};
|
||||
|
||||
const setSolutionsForExistingRecord = (solutions, errorCodeForm) => {
|
||||
const newSolutionFields = [];
|
||||
const newSolutionTypes = {};
|
||||
const newSolutionStatuses = {};
|
||||
const newSolutionData = {};
|
||||
|
||||
solutions.forEach((solution, index) => {
|
||||
const fieldId = `existing-${index}`;
|
||||
newSolutionFields.push(fieldId);
|
||||
newSolutionTypes[fieldId] = solution.type_solution || 'text';
|
||||
newSolutionStatuses[fieldId] = solution.is_active !== false;
|
||||
newSolutionData[fieldId] = {
|
||||
...solution
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
errorCodeForm.setFieldsValue({
|
||||
[`solution_name_${fieldId}`]: solution.solution_name,
|
||||
[`text_solution_${fieldId}`]: solution.text_solution || '',
|
||||
[`solution_status_${fieldId}`]: solution.is_active !== false,
|
||||
[`solution_type_${fieldId}`]: solution.type_solution === 'image' || solution.type_solution === 'pdf' ? 'file' : solution.type_solution
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
|
||||
setSolutionFields(newSolutionFields);
|
||||
setSolutionTypes(newSolutionTypes);
|
||||
setSolutionStatuses(newSolutionStatuses);
|
||||
window.currentSolutionData = newSolutionData;
|
||||
};
|
||||
|
||||
const resetSolutionFields = () => {
|
||||
setSolutionFields([0]);
|
||||
setSolutionTypes({ 0: 'text' });
|
||||
setSolutionStatuses({ 0: true });
|
||||
setFirstSolutionValid(false);
|
||||
setSolutionsToDelete(new Set());
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
checkFirstSolutionValid();
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}, [solutionFields, solutionTypes, fileList, errorCodeForm]);
|
||||
|
||||
return {
|
||||
solutionFields,
|
||||
solutionTypes,
|
||||
solutionStatuses,
|
||||
firstSolutionValid,
|
||||
solutionsToDelete,
|
||||
handleAddSolutionField,
|
||||
handleRemoveSolutionField,
|
||||
handleSolutionTypeChange,
|
||||
handleSolutionStatusChange,
|
||||
resetSolutionFields,
|
||||
checkFirstSolutionValid,
|
||||
setSolutionsForExistingRecord
|
||||
};
|
||||
};
|
||||
453
src/pages/master/brandDevice/hooks/solution.js
Normal file
@@ -0,0 +1,453 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export const useSolutionLogic = (solutionForm) => {
|
||||
const [solutionFields, setSolutionFields] = useState([0]);
|
||||
const [solutionTypes, setSolutionTypes] = useState({ 0: 'text' });
|
||||
const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
|
||||
const [solutionsToDelete, setSolutionsToDelete] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (solutionForm) {
|
||||
solutionForm.setFieldsValue({
|
||||
solution_items: {
|
||||
0: {
|
||||
name: 'Solution 1',
|
||||
status: true,
|
||||
type: 'text',
|
||||
text: 'Solution description',
|
||||
file: null,
|
||||
fileUpload: null
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
}, [solutionForm]);
|
||||
|
||||
const handleAddSolutionField = () => {
|
||||
const newKey = Date.now();
|
||||
|
||||
setSolutionFields(prev => [...prev, newKey]);
|
||||
setSolutionTypes(prev => ({ ...prev, [newKey]: 'text' }));
|
||||
setSolutionStatuses(prev => ({ ...prev, [newKey]: true }));
|
||||
|
||||
setTimeout(() => {
|
||||
const currentFormValues = solutionForm.getFieldsValue(true);
|
||||
const existingNames = [];
|
||||
|
||||
Object.keys(currentFormValues).forEach(key => {
|
||||
if (key.startsWith('solution_items,') || key.startsWith('solution_items.')) {
|
||||
const solutionData = currentFormValues[key];
|
||||
if (solutionData && solutionData.name) {
|
||||
existingNames.push(solutionData.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (currentFormValues.solution_items) {
|
||||
Object.values(currentFormValues.solution_items).forEach(solution => {
|
||||
if (solution && solution.name) {
|
||||
existingNames.push(solution.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let solutionNumber = solutionFields.length + 1;
|
||||
let defaultName = `Solution ${solutionNumber}`;
|
||||
|
||||
while (existingNames.includes(defaultName)) {
|
||||
solutionNumber++;
|
||||
defaultName = `Solution ${solutionNumber}`;
|
||||
}
|
||||
|
||||
solutionForm.setFieldValue(['solution_items', newKey, 'name'], defaultName);
|
||||
solutionForm.setFieldValue(['solution_items', newKey, 'type'], 'text');
|
||||
solutionForm.setFieldValue(['solution_items', newKey, 'text'], 'Solution description');
|
||||
solutionForm.setFieldValue(['solution_items', newKey, 'status'], true);
|
||||
solutionForm.setFieldValue(['solution_items', newKey, 'file'], null);
|
||||
solutionForm.setFieldValue(['solution_items', newKey, 'fileUpload'], null);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
const handleRemoveSolutionField = (key) => {
|
||||
if (solutionFields.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSolutionFields(prev => prev.filter(field => field !== key));
|
||||
|
||||
const newTypes = { ...solutionTypes };
|
||||
const newStatuses = { ...solutionStatuses };
|
||||
delete newTypes[key];
|
||||
delete newStatuses[key];
|
||||
|
||||
setSolutionTypes(newTypes);
|
||||
setSolutionStatuses(newStatuses);
|
||||
|
||||
setTimeout(() => {
|
||||
try {
|
||||
solutionForm.setFieldValue(['solution_items', key], undefined);
|
||||
solutionForm.setFieldValue(['solution_items', key, 'name'], undefined);
|
||||
solutionForm.setFieldValue(['solution_items', key, 'type'], undefined);
|
||||
solutionForm.setFieldValue(['solution_items', key, 'text'], undefined);
|
||||
solutionForm.setFieldValue(['solution_items', key, 'status'], undefined);
|
||||
solutionForm.setFieldValue(['solution_items', key, 'file'], undefined);
|
||||
solutionForm.setFieldValue(['solution_items', key, 'fileUpload'], undefined);
|
||||
} catch (error) {
|
||||
}
|
||||
}, 50);
|
||||
};
|
||||
|
||||
const handleSolutionTypeChange = (key, value) => {
|
||||
setSolutionTypes(prev => ({ ...prev, [key]: value }));
|
||||
|
||||
setTimeout(() => {
|
||||
const fieldName = ['solution_items', key];
|
||||
const currentSolutionData = solutionForm.getFieldsValue([fieldName]) || {};
|
||||
const solutionData = currentSolutionData[`solution_items,${key}`] || currentSolutionData[`solution_items.${key}`] || {};
|
||||
|
||||
if (value === 'text') {
|
||||
const updatedSolutionData = {
|
||||
...solutionData,
|
||||
fileUpload: null,
|
||||
file: null,
|
||||
path_solution: null,
|
||||
fileName: null,
|
||||
text: solutionData.text || 'Solution description'
|
||||
};
|
||||
|
||||
solutionForm.setFieldValue([...fieldName, 'fileUpload'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'file'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'path_solution'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'fileName'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'text'], updatedSolutionData.text);
|
||||
} else if (value === 'file') {
|
||||
const updatedSolutionData = {
|
||||
...solutionData,
|
||||
text: '',
|
||||
fileUpload: null,
|
||||
file: null,
|
||||
path_solution: null,
|
||||
fileName: null
|
||||
};
|
||||
solutionForm.setFieldValue([...fieldName, 'text'], '');
|
||||
solutionForm.setFieldValue([...fieldName, 'fileUpload'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'file'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'path_solution'], null);
|
||||
solutionForm.setFieldValue([...fieldName, 'fileName'], null);
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const handleSolutionStatusChange = (key, value) => {
|
||||
setSolutionStatuses(prev => ({ ...prev, [key]: value }));
|
||||
};
|
||||
|
||||
const resetSolutionFields = () => {
|
||||
setSolutionFields([0]);
|
||||
setSolutionTypes({ 0: 'text' });
|
||||
setSolutionStatuses({ 0: true });
|
||||
|
||||
if (!solutionForm || !solutionForm.resetFields) {
|
||||
return;
|
||||
}
|
||||
|
||||
solutionForm.resetFields();
|
||||
setTimeout(() => {
|
||||
solutionForm.setFieldsValue({
|
||||
solution_items: {
|
||||
0: {
|
||||
name: 'Solution 1',
|
||||
status: true,
|
||||
type: 'text',
|
||||
text: 'Solution description',
|
||||
file: null,
|
||||
fileUpload: null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
solutionForm.setFieldValue(['solution_items', 0, 'name'], 'Solution 1');
|
||||
solutionForm.setFieldValue(['solution_items', 0, 'type'], 'text');
|
||||
solutionForm.setFieldValue(['solution_items', 0, 'text'], 'Solution description');
|
||||
solutionForm.setFieldValue(['solution_items', 0, 'status'], true);
|
||||
solutionForm.setFieldValue(['solution_items', 0, 'file'], null);
|
||||
solutionForm.setFieldValue(['solution_items', 0, 'fileUpload'], null);
|
||||
|
||||
}, 100);
|
||||
};
|
||||
|
||||
const checkFirstSolutionValid = () => {
|
||||
if (!solutionForm || !solutionForm.getFieldsValue) {
|
||||
return false;
|
||||
}
|
||||
const values = solutionForm.getFieldsValue();
|
||||
|
||||
const firstField = solutionFields[0];
|
||||
if (!firstField) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const solutionKey = firstField.key || firstField;
|
||||
const commaPath = `solution_items,${solutionKey}`;
|
||||
const dotPath = `solution_items.${solutionKey}`;
|
||||
const firstSolution = values[commaPath] || values[dotPath];
|
||||
|
||||
if (!firstSolution || !firstSolution.name || firstSolution.name.trim() === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (solutionTypes[solutionKey] === 'text' && (!firstSolution.text || firstSolution.text.trim() === '')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const getSolutionData = () => {
|
||||
try {
|
||||
const values = solutionForm.getFieldsValue(true);
|
||||
const result = [];
|
||||
|
||||
solutionFields.forEach(key => {
|
||||
let solution = null;
|
||||
|
||||
try {
|
||||
solution = solutionForm.getFieldValue(['solution_items', key]);
|
||||
} catch (error) {
|
||||
}
|
||||
|
||||
if (!solution && values.solution_items && values.solution_items[key]) {
|
||||
solution = values.solution_items[key];
|
||||
}
|
||||
|
||||
if (!solution) {
|
||||
const commaKey = `solution_items,${key}`;
|
||||
solution = values[commaKey];
|
||||
}
|
||||
|
||||
if (!solution) {
|
||||
const dotKey = `solution_items.${key}`;
|
||||
solution = values[dotKey];
|
||||
}
|
||||
|
||||
if (!solution) {
|
||||
const allKeys = Object.keys(values);
|
||||
const foundKey = allKeys.find(k =>
|
||||
k.includes(key.toString()) &&
|
||||
k.includes('solution_items')
|
||||
);
|
||||
if (foundKey) {
|
||||
solution = values[foundKey];
|
||||
}
|
||||
}
|
||||
|
||||
if (!solution) {
|
||||
const rawValues = solutionForm.getFieldsValue();
|
||||
|
||||
if (rawValues.solution_items && rawValues.solution_items[key]) {
|
||||
solution = rawValues.solution_items[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (!solution) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const hasName = solution.name && solution.name.trim() !== '';
|
||||
|
||||
if (!hasName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const solutionType = solutionTypes[key] || solution.type || 'text';
|
||||
let isValidType = true;
|
||||
|
||||
if (solutionType === 'text') {
|
||||
isValidType = solution.text && solution.text.trim() !== '';
|
||||
if (!isValidType) {
|
||||
return;
|
||||
}
|
||||
} else if (solutionType === 'file') {
|
||||
const hasPathSolution = solution.path_solution && solution.path_solution.trim() !== '';
|
||||
const hasFileUpload = (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0);
|
||||
const hasFile = (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0);
|
||||
|
||||
isValidType = hasPathSolution || hasFileUpload || hasFile;
|
||||
if (!isValidType) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let pathSolution = '';
|
||||
let fileObject = null;
|
||||
const typeSolution = solutionTypes[key] || solution.type || 'text';
|
||||
|
||||
if (typeSolution === 'file') {
|
||||
if (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0) {
|
||||
pathSolution = solution.fileUpload.path_solution || solution.fileUpload.uploadPath || '';
|
||||
fileObject = solution.fileUpload;
|
||||
} else if (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0) {
|
||||
pathSolution = solution.file.path_solution || solution.file.uploadPath || '';
|
||||
fileObject = solution.file;
|
||||
} else if (solution.file && typeof solution.file === 'string' && solution.file.trim() !== '') {
|
||||
pathSolution = solution.file;
|
||||
} else if (solution.path_solution && solution.path_solution.trim() !== '') {
|
||||
pathSolution = solution.path_solution;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
let finalTypeSolution = typeSolution;
|
||||
if (typeSolution === 'file') {
|
||||
if (fileObject && fileObject.type_solution) {
|
||||
finalTypeSolution = fileObject.type_solution;
|
||||
} else {
|
||||
finalTypeSolution = 'image';
|
||||
}
|
||||
}
|
||||
|
||||
const finalSolution = {
|
||||
solution_name: solution.name,
|
||||
type_solution: finalTypeSolution,
|
||||
is_active: solution.status !== false && solution.status !== undefined ? solution.status : (solutionStatuses[key] !== false),
|
||||
};
|
||||
|
||||
if (typeSolution === 'text') {
|
||||
finalSolution.text_solution = solution.text || '';
|
||||
finalSolution.path_solution = '';
|
||||
} else {
|
||||
finalSolution.text_solution = '';
|
||||
finalSolution.path_solution = pathSolution;
|
||||
}
|
||||
|
||||
result.push(finalSolution);
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const setSolutionsForExistingRecord = (solutions, form) => {
|
||||
if (!solutions || solutions.length === 0) return;
|
||||
|
||||
const newFields = solutions.map((solution, index) => solution.id || index);
|
||||
|
||||
setSolutionFields(newFields);
|
||||
|
||||
const solutionsValues = {};
|
||||
const newTypes = {};
|
||||
const newStatuses = {};
|
||||
|
||||
solutions.forEach((solution, index) => {
|
||||
const key = solution.brand_code_solution_id || solution.id || index;
|
||||
|
||||
let fileObject = null;
|
||||
if (solution.path_solution && solution.path_solution.trim() !== '') {
|
||||
const fileName = solution.file_upload_name || solution.path_solution.split('/').pop() || `file_${index}`;
|
||||
|
||||
fileObject = {
|
||||
uploadPath: solution.path_solution,
|
||||
path_solution: solution.path_solution,
|
||||
name: fileName,
|
||||
type_solution: solution.type_solution || 'image',
|
||||
isExisting: true,
|
||||
size: 0,
|
||||
type: solution.type_solution === 'pdf' ? 'application/pdf' : 'image/jpeg',
|
||||
fileExtension: solution.type_solution === 'pdf' ? 'pdf' : (fileName.split('.').pop().toLowerCase() || 'jpg')
|
||||
};
|
||||
}
|
||||
|
||||
const isFileType = solution.type_solution && solution.type_solution !== 'text' && fileObject;
|
||||
|
||||
solutionsValues[key] = {
|
||||
name: solution.solution_name || '',
|
||||
type: isFileType ? 'file' : 'text',
|
||||
text: solution.text_solution || '',
|
||||
file: fileObject,
|
||||
fileUpload: fileObject,
|
||||
status: solution.is_active !== false,
|
||||
path_solution: solution.path_solution || ''
|
||||
};
|
||||
newTypes[key] = isFileType ? 'file' : 'text';
|
||||
newStatuses[key] = solution.is_active !== false;
|
||||
});
|
||||
|
||||
const nestedFormValues = {
|
||||
solution_items: {}
|
||||
};
|
||||
|
||||
Object.keys(solutionsValues).forEach(key => {
|
||||
const solution = solutionsValues[key];
|
||||
nestedFormValues.solution_items[key] = {
|
||||
name: solution.name,
|
||||
type: solution.type,
|
||||
text: solution.text,
|
||||
file: solution.file,
|
||||
fileUpload: solution.fileUpload,
|
||||
status: solution.status,
|
||||
path_solution: solution.path_solution
|
||||
};
|
||||
});
|
||||
|
||||
form.setFieldsValue(nestedFormValues);
|
||||
|
||||
const fallbackFormValues = {};
|
||||
Object.keys(solutionsValues).forEach(key => {
|
||||
const solution = solutionsValues[key];
|
||||
fallbackFormValues[`solution_items,${key}`] = {
|
||||
name: solution.name,
|
||||
type: solution.type,
|
||||
text: solution.text,
|
||||
file: solution.file,
|
||||
fileUpload: solution.fileUpload,
|
||||
status: solution.status,
|
||||
path_solution: solution.path_solution
|
||||
};
|
||||
});
|
||||
|
||||
form.setFieldsValue(fallbackFormValues);
|
||||
|
||||
Object.keys(solutionsValues).forEach(key => {
|
||||
const solution = solutionsValues[key];
|
||||
form.setFieldValue([`solution_items,${key}`, 'name'], solution.name);
|
||||
form.setFieldValue([`solution_items,${key}`, 'type'], solution.type);
|
||||
form.setFieldValue([`solution_items,${key}`, 'text'], solution.text);
|
||||
form.setFieldValue([`solution_items,${key}`, 'file'], solution.file);
|
||||
form.setFieldValue([`solution_items,${key}`, 'fileUpload'], solution.fileUpload);
|
||||
form.setFieldValue([`solution_items,${key}`, 'status'], solution.status);
|
||||
form.setFieldValue([`solution_items,${key}`, 'path_solution'], solution.path_solution);
|
||||
|
||||
form.setFieldValue(['solution_items', key, 'name'], solution.name);
|
||||
form.setFieldValue(['solution_items', key, 'type'], solution.type);
|
||||
form.setFieldValue(['solution_items', key, 'text'], solution.text);
|
||||
form.setFieldValue(['solution_items', key, 'file'], solution.file);
|
||||
form.setFieldValue(['solution_items', key, 'fileUpload'], solution.fileUpload);
|
||||
form.setFieldValue(['solution_items', key, 'status'], solution.status);
|
||||
form.setFieldValue(['solution_items', key, 'path_solution'], solution.path_solution);
|
||||
});
|
||||
|
||||
setSolutionTypes(newTypes);
|
||||
setSolutionStatuses(newStatuses);
|
||||
};
|
||||
|
||||
return {
|
||||
solutionFields,
|
||||
solutionTypes,
|
||||
solutionStatuses,
|
||||
solutionsToDelete,
|
||||
firstSolutionValid: checkFirstSolutionValid(),
|
||||
handleAddSolutionField,
|
||||
handleRemoveSolutionField,
|
||||
handleSolutionTypeChange,
|
||||
handleSolutionStatusChange,
|
||||
resetSolutionFields,
|
||||
checkFirstSolutionValid,
|
||||
getSolutionData,
|
||||
setSolutionsForExistingRecord,
|
||||
};
|
||||
};
|
||||
@@ -1,22 +1,9 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Modal,
|
||||
Input,
|
||||
Divider,
|
||||
Typography,
|
||||
Switch,
|
||||
Button,
|
||||
ConfigProvider,
|
||||
Select,
|
||||
DatePicker,
|
||||
} from 'antd';
|
||||
import { NotifAlert, NotifOk, NotifSmall } from '../../../../components/Global/ToastNotif';
|
||||
import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, Select } from 'antd';
|
||||
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
||||
import { createDevice, updateDevice } from '../../../../api/master-device';
|
||||
import { reminderMonthly, reminderCustom } from '../../../../api/notification';
|
||||
import { getAllBrands } from '../../../../api/master-brand';
|
||||
import { validateRun } from '../../../../Utils/validate';
|
||||
import { toApiDateFormatter } from '../../../../components/Global/Formatter';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const { Text } = Typography;
|
||||
const { TextArea } = Input;
|
||||
@@ -36,12 +23,7 @@ const DetailDevice = (props) => {
|
||||
device_location: '',
|
||||
device_description: '',
|
||||
ip_address: '',
|
||||
listen_channel: null,
|
||||
reminder_at: null,
|
||||
reminder_at_monthly: null,
|
||||
start_date: null,
|
||||
end_date: null,
|
||||
period: null,
|
||||
listen_channel: '',
|
||||
};
|
||||
|
||||
const [formData, setFormData] = useState(defaultData);
|
||||
@@ -85,26 +67,12 @@ const DetailDevice = (props) => {
|
||||
ip_address: formData.ip_address,
|
||||
brand_id: formData.brand_id,
|
||||
listen_channel: formData.listen_channel,
|
||||
listen_channel_reminder: formData.listen_channel_reminder,
|
||||
reminder_at: formData.reminder_at,
|
||||
reminder_at_monthly: formData.period !== 'custom' ? formData.reminder_at_monthly : null,
|
||||
start_date: formData.start_date,
|
||||
end_date: formData.end_date,
|
||||
};
|
||||
|
||||
console.log(payload);
|
||||
|
||||
const response = formData.device_id
|
||||
? await updateDevice(formData.device_id, payload)
|
||||
: await createDevice(payload);
|
||||
|
||||
const response2 = formData.period !== 'custom'
|
||||
? await updateDevice(formData.device_id, { reminder_at_monthly: formData.reminder_at_monthly,})
|
||||
: await updateDevice(formData.device_id, {
|
||||
start_date: formData.start_date,
|
||||
end_date: formData.end_date,
|
||||
});
|
||||
|
||||
// Check if response is successful
|
||||
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
||||
const deviceName = response.data?.device_name || formData.device_name;
|
||||
@@ -125,25 +93,6 @@ const DetailDevice = (props) => {
|
||||
message: response?.message || 'Terjadi kesalahan saat menyimpan data.',
|
||||
});
|
||||
}
|
||||
|
||||
// Check if response Reminder At(Monthly) or Period are successful
|
||||
const tipe = formData.period !== 'custom' ? 'Reminder At(Monthly)' : 'Period';
|
||||
if (response2 && (response2.statusCode === 200 || response2.statusCode === 201)) {
|
||||
NotifSmall({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
message: `${tipe} berhasil disimpan`,
|
||||
});
|
||||
} else {
|
||||
NotifSmall({
|
||||
icon: 'error',
|
||||
title: 'Gagal',
|
||||
message:
|
||||
response?.message ||
|
||||
`Terjadi kesalahan saat menyimpan ${tipe}`,
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Save Device Error:', error);
|
||||
NotifAlert({
|
||||
@@ -179,13 +128,6 @@ const DetailDevice = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleDateChange = (field, value) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[field]: value,
|
||||
});
|
||||
};
|
||||
|
||||
// Fungsi untuk mengambil daftar brand
|
||||
const fetchBrands = async () => {
|
||||
setLoadingBrands(true);
|
||||
@@ -206,56 +148,6 @@ const DetailDevice = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (formData.start_date && formData.end_date) {
|
||||
const start = dayjs(formData.start_date);
|
||||
const end = dayjs(formData.end_date);
|
||||
|
||||
let periodValue = 'custom';
|
||||
|
||||
if (end.isSame(start.add(1, 'month').subtract(1, 'day'), 'day')) {
|
||||
periodValue = '1';
|
||||
} else if (end.isSame(start.add(3, 'month').subtract(1, 'day'), 'day')) {
|
||||
periodValue = '3';
|
||||
} else if (end.isSame(start.add(6, 'month').subtract(1, 'day'), 'day')) {
|
||||
periodValue = '6';
|
||||
}
|
||||
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
period: periodValue,
|
||||
}));
|
||||
}
|
||||
}, [formData.start_date, formData.end_date]);
|
||||
|
||||
const handleMonthly = (field, value) => {
|
||||
setFormData((prev) => {
|
||||
const data = {
|
||||
...prev,
|
||||
[field]: value,
|
||||
};
|
||||
|
||||
if (value !== 'custom') {
|
||||
const months = Number(value);
|
||||
|
||||
const startDate = dayjs().startOf('day');
|
||||
const endDate = startDate
|
||||
.add(months, 'month')
|
||||
.subtract(1, 'day')
|
||||
.endOf('day');
|
||||
|
||||
data.start_date = startDate.toISOString();
|
||||
data.end_date = endDate.toISOString();
|
||||
data.reminder_at_monthly = null;
|
||||
} else {
|
||||
data.start_date = null;
|
||||
data.end_date = null;
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.showModal && (props.actionMode === 'add' || props.actionMode === 'edit')) {
|
||||
fetchBrands();
|
||||
@@ -277,8 +169,8 @@ const DetailDevice = (props) => {
|
||||
props.actionMode === 'add'
|
||||
? 'Tambah'
|
||||
: props.actionMode === 'preview'
|
||||
? 'Preview'
|
||||
: 'Edit'
|
||||
? 'Preview'
|
||||
: 'Edit'
|
||||
} Device`}
|
||||
open={props.showModal}
|
||||
// open={true}
|
||||
@@ -326,10 +218,9 @@ const DetailDevice = (props) => {
|
||||
</React.Fragment>,
|
||||
]}
|
||||
>
|
||||
<Divider />
|
||||
{formData && (
|
||||
<div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<div>
|
||||
<div>
|
||||
<Text strong>Device Status</Text>
|
||||
</div>
|
||||
@@ -356,7 +247,7 @@ const DetailDevice = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <Divider style={{ margin: '12px 0' }} /> */}
|
||||
<Divider style={{ margin: '12px 0' }} />
|
||||
<div hidden>
|
||||
<Text strong>Device ID</Text>
|
||||
<Input
|
||||
@@ -439,149 +330,15 @@ const DetailDevice = (props) => {
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}></div>
|
||||
<div style={{ marginBottom: 12 }}></div>
|
||||
<div style={{ display: 'flex', gap: 16 }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
{' '}
|
||||
<Text strong>Channel Error</Text>
|
||||
<Input
|
||||
name="listen_channel"
|
||||
value={formData.listen_channel}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Listen Channel"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Text strong>Channel Reminder</Text>
|
||||
<Input
|
||||
name="listen_channel_reminder"
|
||||
value={formData.listen_channel_reminder}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Listen Channel Reminder"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Reminder At(Yearly)</Text>
|
||||
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
||||
<DatePicker
|
||||
value={
|
||||
formData.reminder_at
|
||||
? dayjs(formData.reminder_at) // ✅ langsung parse ISO
|
||||
: null
|
||||
}
|
||||
onChange={(date) =>
|
||||
handleDateChange(
|
||||
'reminder_at',
|
||||
date ? date.toISOString() : null
|
||||
)
|
||||
}
|
||||
format="DD-MM-YYYY HH:mm"
|
||||
showTime={{ format: 'HH:mm' }}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
|
||||
<Button
|
||||
danger
|
||||
onClick={() =>
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
reminder_at: null,
|
||||
}))
|
||||
}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Period</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
|
||||
<Select
|
||||
value={formData.period}
|
||||
onChange={(value) => handleMonthly('period', value)}
|
||||
placeholder="Select Period"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Select.Option value="1">1 Monthly</Select.Option>
|
||||
<Select.Option value="3">3 Monthly</Select.Option>
|
||||
<Select.Option value="6">6 Monthly</Select.Option>
|
||||
<Select.Option value="custom">Custom</Select.Option>
|
||||
</Select>
|
||||
</div>
|
||||
{formData.period === 'custom' && (
|
||||
<div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
|
||||
<DatePicker
|
||||
placeholder="Start Date"
|
||||
value={formData.start_date ? dayjs(formData.start_date) : null}
|
||||
onChange={(date) =>
|
||||
handleDateChange('start_date', date ? date.toISOString() : null)
|
||||
}
|
||||
disabledDate={(current) =>
|
||||
formData.end_date &&
|
||||
current &&
|
||||
current.isAfter(dayjs(formData.end_date), 'day')
|
||||
}
|
||||
format="DD-MM-YYYY HH:mm"
|
||||
showTime={{ format: 'HH:mm' }}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
|
||||
<DatePicker
|
||||
placeholder="End Date"
|
||||
value={formData.end_date ? dayjs(formData.end_date) : null}
|
||||
onChange={(date) =>
|
||||
handleDateChange('end_date', date ? date.toISOString() : null)
|
||||
}
|
||||
disabledDate={(current) =>
|
||||
formData.start_date &&
|
||||
current &&
|
||||
current.isBefore(dayjs(formData.start_date), 'day')
|
||||
}
|
||||
format="DD-MM-YYYY HH:mm"
|
||||
showTime={{ format: 'HH:mm' }}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Reminder At(Monthly)</Text>
|
||||
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
||||
<DatePicker
|
||||
disabled={formData.period === 'custom'}
|
||||
value={
|
||||
formData.reminder_at_monthly
|
||||
? dayjs(formData.reminder_at_monthly) // ✅ langsung parse ISO
|
||||
: null
|
||||
}
|
||||
onChange={(date) =>
|
||||
handleDateChange(
|
||||
'reminder_at_monthly',
|
||||
date ? date.toISOString() : null
|
||||
)
|
||||
}
|
||||
format="DD-MM-YYYY HH:mm"
|
||||
showTime={{ format: 'HH:mm' }}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
|
||||
<Button
|
||||
disabled={formData.period === 'custom'}
|
||||
danger
|
||||
onClick={() =>
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
reminder_at_monthly: null,
|
||||
}))
|
||||
}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
<Text strong>Listen Channel</Text>
|
||||
<Input
|
||||
name="listen_channel"
|
||||
value={formData.listen_channel}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Listen Channel"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Device Description</Text>
|
||||
|
||||
@@ -38,7 +38,7 @@ const DetailPlantSubSection = (props) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log(`📝 Input change: ${name} = ${value}`);
|
||||
console.log(`📝 Input change: ${name} = ${value}`);
|
||||
|
||||
if (name) {
|
||||
setFormData((prev) => ({
|
||||
@@ -74,20 +74,16 @@ const DetailPlantSubSection = (props) => {
|
||||
return;
|
||||
|
||||
try {
|
||||
// console.log('💾 Current formData before save:', formData);
|
||||
console.log('💾 Current formData before save:', formData);
|
||||
|
||||
const payload = {
|
||||
plant_sub_section_name: formData.plant_sub_section_name,
|
||||
plant_sub_section_description:
|
||||
formData.plant_sub_section_description &&
|
||||
formData.plant_sub_section_description.trim() !== ''
|
||||
? formData.plant_sub_section_description
|
||||
: ' ',
|
||||
plant_sub_section_description: (formData.plant_sub_section_description && formData.plant_sub_section_description.trim() !== '') ? formData.plant_sub_section_description : ' ',
|
||||
table_name_value: formData.table_name_value, // Fix field name
|
||||
is_active: formData.is_active,
|
||||
};
|
||||
|
||||
// console.log('📤 Payload to be sent:', payload);
|
||||
console.log('📤 Payload to be sent:', payload);
|
||||
|
||||
const response =
|
||||
props.actionMode === 'edit'
|
||||
@@ -130,17 +126,17 @@ const DetailPlantSubSection = (props) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('🔄 Modal state changed:', {
|
||||
// showModal: props.showModal,
|
||||
// actionMode: props.actionMode,
|
||||
// selectedData: props.selectedData,
|
||||
// });
|
||||
console.log('🔄 Modal state changed:', {
|
||||
showModal: props.showModal,
|
||||
actionMode: props.actionMode,
|
||||
selectedData: props.selectedData,
|
||||
});
|
||||
|
||||
if (props.selectedData) {
|
||||
// console.log('📋 Setting form data from selectedData:', props.selectedData);
|
||||
console.log('📋 Setting form data from selectedData:', props.selectedData);
|
||||
setFormData(props.selectedData);
|
||||
} else {
|
||||
// console.log('📋 Resetting to default data');
|
||||
console.log('📋 Resetting to default data');
|
||||
setFormData(defaultData);
|
||||
}
|
||||
}, [props.showModal, props.selectedData, props.actionMode]);
|
||||
|
||||
@@ -112,9 +112,9 @@ const DetailShift = (props) => {
|
||||
is_active: formData.is_active,
|
||||
};
|
||||
|
||||
// console.log('Payload yang dikirim:', payload);
|
||||
// console.log('Type start_time:', typeof payload.start_time, payload.start_time);
|
||||
// console.log('Type end_time:', typeof payload.end_time, payload.end_time);
|
||||
console.log('Payload yang dikirim:', payload);
|
||||
console.log('Type start_time:', typeof payload.start_time, payload.start_time);
|
||||
console.log('Type end_time:', typeof payload.end_time, payload.end_time);
|
||||
|
||||
const response =
|
||||
props.actionMode === 'edit'
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
Row,
|
||||
Col,
|
||||
Image,
|
||||
Checkbox,
|
||||
} from 'antd';
|
||||
import { PlusOutlined, EyeOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
||||
@@ -38,68 +37,9 @@ const DetailSparepart = (props) => {
|
||||
const [previewTitle, setPreviewTitle] = useState('');
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
|
||||
const optionsMonthly = [
|
||||
{
|
||||
key: 1,
|
||||
value: 1,
|
||||
text: '1 Month',
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
value: 3,
|
||||
text: '3 Month',
|
||||
},
|
||||
{
|
||||
key: 6,
|
||||
value: 6,
|
||||
text: '6 Month',
|
||||
},
|
||||
];
|
||||
|
||||
const optionsYearly = [
|
||||
{
|
||||
key: 1,
|
||||
value: 1,
|
||||
text: '1 Year',
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
value: 2,
|
||||
text: '2 Year',
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
value: 3,
|
||||
text: '3 Year',
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
value: 4,
|
||||
text: '4 Year',
|
||||
},
|
||||
{
|
||||
key: 5,
|
||||
value: 5,
|
||||
text: '5 Year',
|
||||
},
|
||||
{
|
||||
key: 6,
|
||||
value: 6,
|
||||
text: '6 Year',
|
||||
},
|
||||
];
|
||||
const [checkedListM, setCheckedListM] = useState([]);
|
||||
const [checkAllM, setCheckAllM] = useState(false);
|
||||
const [indeterminateM, setIndeterminateM] = useState(false);
|
||||
|
||||
const [checkedList, setCheckedList] = useState([]);
|
||||
const [checkAll, setCheckAll] = useState(false);
|
||||
const [indeterminate, setIndeterminate] = useState(false);
|
||||
|
||||
const defaultData = {
|
||||
sparepart_id: '',
|
||||
sparepart_name: '',
|
||||
sparepart_number: '',
|
||||
sparepart_description: '',
|
||||
sparepart_model: '',
|
||||
sparepart_item_type: null,
|
||||
@@ -155,11 +95,11 @@ const DetailSparepart = (props) => {
|
||||
const newFile = fileList.length > 0 ? fileList[0] : null;
|
||||
|
||||
if (newFile && newFile.originFileObj) {
|
||||
// console.log('Uploading file:', newFile.originFileObj);
|
||||
console.log('Uploading file:', newFile.originFileObj);
|
||||
const uploadResponse = await uploadFile(newFile.originFileObj, 'images');
|
||||
|
||||
// Log untuk debugging
|
||||
// console.log('Upload response:', uploadResponse);
|
||||
console.log('Upload response:', uploadResponse);
|
||||
|
||||
// Cek berbagai kemungkinan struktur respons dari API
|
||||
let uploadedUrl = null;
|
||||
@@ -229,7 +169,7 @@ const DetailSparepart = (props) => {
|
||||
}
|
||||
|
||||
if (uploadedUrl) {
|
||||
// console.log('Successfully extracted image URL:', uploadedUrl);
|
||||
console.log('Successfully extracted image URL:', uploadedUrl);
|
||||
imageUrl = uploadedUrl;
|
||||
} else {
|
||||
console.error('Upload response structure:', uploadResponse);
|
||||
@@ -269,10 +209,7 @@ const DetailSparepart = (props) => {
|
||||
sparepart_name: formData.sparepart_name, // Wajib
|
||||
};
|
||||
|
||||
payload.sparepart_description =
|
||||
formData.sparepart_description && formData.sparepart_description.trim() !== ''
|
||||
? formData.sparepart_description
|
||||
: ' ';
|
||||
payload.sparepart_description = (formData.sparepart_description && formData.sparepart_description.trim() !== '') ? formData.sparepart_description : ' ';
|
||||
if (formData.sparepart_model && formData.sparepart_model.trim() !== '') {
|
||||
payload.sparepart_model = formData.sparepart_model;
|
||||
}
|
||||
@@ -296,17 +233,13 @@ const DetailSparepart = (props) => {
|
||||
payload.sparepart_foto = imageUrl;
|
||||
}
|
||||
|
||||
payload.sparepart_number = formData.sparepart_number;
|
||||
payload.sparepart_yearly = checkedList;
|
||||
payload.sparepart_monthly = checkedListM;
|
||||
|
||||
// console.log('Sending payload:', payload);
|
||||
console.log('Sending payload:', payload);
|
||||
|
||||
const response = formData.sparepart_id
|
||||
? await updateSparepart(formData.sparepart_id, payload)
|
||||
: await createSparepart(payload);
|
||||
|
||||
// console.log('API response:', response);
|
||||
console.log('API response:', response);
|
||||
|
||||
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
||||
NotifOk({
|
||||
@@ -346,36 +279,6 @@ const DetailSparepart = (props) => {
|
||||
setFormData({ ...formData, [name]: value });
|
||||
};
|
||||
|
||||
const onChangeCheckboxM = (list) => {
|
||||
setCheckedListM(list);
|
||||
|
||||
setIndeterminateM(!!list.length && list.length < optionsMonthly.length);
|
||||
setCheckAllM(list.length === optionsMonthly.length);
|
||||
};
|
||||
|
||||
const onCheckAllChangeM = (e) => {
|
||||
const checked = e.target.checked;
|
||||
|
||||
setCheckedListM(checked ? optionsMonthly.map((item) => item.value) : []);
|
||||
setIndeterminateM(false);
|
||||
setCheckAllM(checked);
|
||||
};
|
||||
|
||||
const onChangeCheckbox = (list) => {
|
||||
setCheckedList(list);
|
||||
|
||||
setIndeterminate(!!list.length && list.length < optionsYearly.length);
|
||||
setCheckAll(list.length === optionsYearly.length);
|
||||
};
|
||||
|
||||
const onCheckAllChange = (e) => {
|
||||
const checked = e.target.checked;
|
||||
|
||||
setCheckedList(checked ? optionsYearly.map((item) => item.value) : []);
|
||||
setIndeterminate(false);
|
||||
setCheckAll(checked);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.selectedData) {
|
||||
setFormData(props.selectedData);
|
||||
@@ -412,19 +315,9 @@ const DetailSparepart = (props) => {
|
||||
} else {
|
||||
setFileList([]);
|
||||
}
|
||||
setCheckedListM(JSON.parse(props.selectedData.sparepart_monthly));
|
||||
setCheckedList(JSON.parse(props.selectedData.sparepart_yearly));
|
||||
} else {
|
||||
setFormData(defaultData);
|
||||
setFileList([]);
|
||||
|
||||
setIndeterminateM(false);
|
||||
setCheckedListM([]);
|
||||
setCheckAllM(false);
|
||||
|
||||
setIndeterminate(false);
|
||||
setCheckedList([]);
|
||||
setCheckAll(false);
|
||||
}
|
||||
}, [props.showModal, props.selectedData, props.actionMode]);
|
||||
|
||||
@@ -437,13 +330,12 @@ const DetailSparepart = (props) => {
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width="40rem"
|
||||
title={`${
|
||||
props.actionMode === 'add'
|
||||
? 'Tambah'
|
||||
: props.actionMode === 'preview'
|
||||
? 'Preview'
|
||||
: 'Edit'
|
||||
? 'Preview'
|
||||
: 'Edit'
|
||||
} Sparepart`}
|
||||
open={props.showModal}
|
||||
onCancel={handleCancel}
|
||||
@@ -568,7 +460,7 @@ const DetailSparepart = (props) => {
|
||||
<div
|
||||
style={{
|
||||
width: '180px', // Fixed width for square
|
||||
height: '240px',
|
||||
height: '180px',
|
||||
border: '1px dashed #d9d9d9',
|
||||
borderRadius: '8px',
|
||||
display: 'flex',
|
||||
@@ -590,17 +482,6 @@ const DetailSparepart = (props) => {
|
||||
{/* Kolom untuk field lainnya */}
|
||||
<Col span={14}>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Text strong>Part Number</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_number"
|
||||
value={formData.sparepart_number}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Number"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text strong>Sparepart Name</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
@@ -676,78 +557,7 @@ const DetailSparepart = (props) => {
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
colorPrimary: '#23A55A',
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
{/* Yearly */}
|
||||
<Row style={{ marginTop: 16 }}>
|
||||
<Col>
|
||||
<Checkbox
|
||||
indeterminate={indeterminate}
|
||||
onChange={onCheckAllChange}
|
||||
checked={checkAll}
|
||||
>
|
||||
{checkAll ? 'Unselect All Years' : 'Select All Years'}
|
||||
</Checkbox>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ marginTop: 10 }}>
|
||||
<Col span={24}>
|
||||
<Checkbox.Group
|
||||
value={checkedList}
|
||||
onChange={onChangeCheckbox}
|
||||
style={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
{optionsYearly.map((item) => (
|
||||
<Checkbox key={item.key} value={item.value}>
|
||||
{item.text}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Checkbox.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* Monthly */}
|
||||
<Row style={{ marginTop: 16 }}>
|
||||
<Col>
|
||||
<Checkbox
|
||||
indeterminate={indeterminateM}
|
||||
onChange={onCheckAllChangeM}
|
||||
checked={checkAllM}
|
||||
>
|
||||
{checkAllM ? 'Unselect All Months' : 'Select All Months'}
|
||||
</Checkbox>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ marginTop: 10 }}>
|
||||
<Col span={24}>
|
||||
<Checkbox.Group
|
||||
value={checkedListM}
|
||||
onChange={onChangeCheckboxM}
|
||||
style={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
{optionsMonthly.map((item) => (
|
||||
<Checkbox key={item.key} value={item.value}>
|
||||
{item.text}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Checkbox.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
</ConfigProvider>
|
||||
<Row gutter={[16, 16]} style={{ marginTop: 16 }}>
|
||||
<Col span={24}>
|
||||
<Text strong>Description</Text>
|
||||
|
||||
@@ -36,12 +36,6 @@ const columns = (showPreviewModal, showEditModal, showDeleteDialog) => [
|
||||
key: 'sparepart_name',
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: 'Sparepart Number',
|
||||
dataIndex: 'sparepart_number',
|
||||
key: 'sparepart_number',
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
dataIndex: 'sparepart_description',
|
||||
@@ -283,8 +277,8 @@ const ListSparepart = memo(function ListSparepart(props) {
|
||||
onStockUpdate={doFilter}
|
||||
onGetData={(data) => {
|
||||
if(data && data.length > 0) {
|
||||
// console.log('Sample sparepart data from API:', data[0]);
|
||||
// console.log('Available fields:', Object.keys(data[0] || {}));
|
||||
console.log('Sample sparepart data from API:', data[0]);
|
||||
console.log('Available fields:', Object.keys(data[0] || {}));
|
||||
}
|
||||
}} // Log untuk debugging field-field yang tersedia
|
||||
/>
|
||||
|
||||
@@ -164,7 +164,7 @@ const ListUnit = memo(function ListUnit(props) {
|
||||
const handleDelete = async (param) => {
|
||||
try {
|
||||
const response = await deleteUnit(param.unit_id);
|
||||
// console.log('deleteUnit response:', response);
|
||||
console.log('deleteUnit response:', response);
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
NotifAlert({
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Modal, Typography, Card, Row, Col, Avatar, Tag, Button, Space } from 'antd';
|
||||
import {
|
||||
UserOutlined,
|
||||
PhoneOutlined,
|
||||
CheckCircleOutlined,
|
||||
SyncOutlined,
|
||||
SendOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { UserOutlined, PhoneOutlined, CheckCircleOutlined, SyncOutlined, SendOutlined } from '@ant-design/icons';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
@@ -47,17 +41,9 @@ const UserHistoryModal = ({ visible, onCancel, notificationData }) => {
|
||||
const getStatusTag = (status) => {
|
||||
switch (status) {
|
||||
case 'delivered':
|
||||
return (
|
||||
<Tag icon={<CheckCircleOutlined />} color="success">
|
||||
Delivered
|
||||
</Tag>
|
||||
);
|
||||
return <Tag icon={<CheckCircleOutlined />} color="success">Delivered</Tag>;
|
||||
case 'sent':
|
||||
return (
|
||||
<Tag icon={<SyncOutlined spin />} color="processing">
|
||||
Sent
|
||||
</Tag>
|
||||
);
|
||||
return <Tag icon={<SyncOutlined spin />} color="processing">Sent</Tag>;
|
||||
case 'failed':
|
||||
return <Tag color="error">Failed</Tag>;
|
||||
default:
|
||||
@@ -69,7 +55,7 @@ const UserHistoryModal = ({ visible, onCancel, notificationData }) => {
|
||||
<Modal
|
||||
title={
|
||||
<Text strong style={{ fontSize: '18px' }}>
|
||||
History User Notification
|
||||
User History Notification
|
||||
</Text>
|
||||
}
|
||||
open={visible}
|
||||
@@ -92,13 +78,7 @@ const UserHistoryModal = ({ visible, onCancel, notificationData }) => {
|
||||
<Avatar size="large" icon={<UserOutlined />} />
|
||||
<div>
|
||||
<Text strong>{user.name}</Text>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '4px',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<PhoneOutlined style={{ color: '#8c8c8c' }} />
|
||||
<Text type="secondary">{user.phone}</Text>
|
||||
</div>
|
||||
|
||||
@@ -1,37 +1,14 @@
|
||||
import React from 'react';
|
||||
import { Button, Row, Col, Card, Badge, Typography, Space, Divider } from 'antd';
|
||||
import {
|
||||
SendOutlined,
|
||||
MobileOutlined,
|
||||
CheckCircleFilled,
|
||||
ArrowLeftOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { SendOutlined, MobileOutlined, CheckCircleFilled, ArrowLeftOutlined } from '@ant-design/icons';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
// Dummy data for user history
|
||||
const userHistoryData = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'John Doe',
|
||||
phone: '081234567890',
|
||||
status: 'Delivered',
|
||||
timestamp: '04-11-2025 11:40 WIB',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Jane Smith',
|
||||
phone: '087654321098',
|
||||
status: 'Delivered',
|
||||
timestamp: '04-11-2025 11:41 WIB',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Peter Jones',
|
||||
phone: '082345678901',
|
||||
status: 'Delivered',
|
||||
timestamp: '04-11-2025 11:42 WIB',
|
||||
},
|
||||
{ id: 1, name: 'John Doe', phone: '081234567890', status: 'Delivered', timestamp: '04-11-2025 11:40 WIB' },
|
||||
{ id: 2, name: 'Jane Smith', phone: '087654321098', status: 'Delivered', timestamp: '04-11-2025 11:41 WIB' },
|
||||
{ id: 3, name: 'Peter Jones', phone: '082345678901', status: 'Delivered', timestamp: '04-11-2025 11:42 WIB' },
|
||||
];
|
||||
|
||||
const UserHistory = ({ notification, onBack }) => {
|
||||
@@ -41,9 +18,7 @@ const UserHistory = ({ notification, onBack }) => {
|
||||
<Col>
|
||||
<Space align="center">
|
||||
<Button type="text" icon={<ArrowLeftOutlined />} onClick={onBack} />
|
||||
<Typography.Title level={4} style={{ margin: 0 }}>
|
||||
History User Notification
|
||||
</Typography.Title>
|
||||
<Typography.Title level={4} style={{ margin: 0 }}>User History Notification</Typography.Title>
|
||||
</Space>
|
||||
<Text type="secondary" style={{ marginLeft: '40px' }}>
|
||||
{notification.title} - {notification.issue}
|
||||
@@ -52,34 +27,25 @@ const UserHistory = ({ notification, onBack }) => {
|
||||
</Row>
|
||||
|
||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||
{userHistoryData.map((user) => (
|
||||
<Card
|
||||
key={user.id}
|
||||
style={{ backgroundColor: '#e6f7ff', borderColor: '#91d5ff' }}
|
||||
>
|
||||
{userHistoryData.map(user => (
|
||||
<Card key={user.id} style={{ backgroundColor: '#e6f7ff', borderColor: '#91d5ff' }}>
|
||||
<Row align="middle" justify="space-between">
|
||||
<Col>
|
||||
<Space align="center">
|
||||
<Text strong>{user.name}</Text>
|
||||
<Text>|</Text>
|
||||
<Text>
|
||||
<MobileOutlined /> {user.phone}
|
||||
</Text>
|
||||
<Text><MobileOutlined /> {user.phone}</Text>
|
||||
<Text>|</Text>
|
||||
<Badge status="success" text={user.status} />
|
||||
</Space>
|
||||
<Divider style={{ margin: '8px 0' }} />
|
||||
<Space align="center">
|
||||
<CheckCircleFilled style={{ color: '#52c41a' }} />
|
||||
<Text type="secondary">
|
||||
Success Delivered at {user.timestamp}
|
||||
</Text>
|
||||
<Text type="secondary">Success Delivered at {user.timestamp}</Text>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col>
|
||||
<Button type="primary" ghost icon={<SendOutlined />}>
|
||||
Resend
|
||||
</Button>
|
||||
<Button type="primary" ghost icon={<SendOutlined />}>Resend</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
@@ -9,8 +9,6 @@ import {
|
||||
import { getAllPlantSection } from '../../../../api/master-plant-section';
|
||||
import jsPDF from 'jspdf';
|
||||
import autoTable from 'jspdf-autotable';
|
||||
import ExcelJS from 'exceljs';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
@@ -56,9 +54,9 @@ const ListReport = memo(function ListReport(props) {
|
||||
};
|
||||
|
||||
const fetchData = async (page = 1, pageSize = 10, showModal = false) => {
|
||||
// if (!plantSubSection) {
|
||||
// return;
|
||||
// }
|
||||
if (!plantSubSection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (showModal) {
|
||||
setIsLoadingModal(true);
|
||||
@@ -197,34 +195,8 @@ const ListReport = memo(function ListReport(props) {
|
||||
fetchData(pagination.current, pagination.pageSize, false);
|
||||
};
|
||||
|
||||
const handleSearch = async () => {
|
||||
setIsLoadingModal(true);
|
||||
|
||||
try {
|
||||
const formattedDateStart = startDate.format('YYYY-MM-DD');
|
||||
const formattedDateEnd = endDate.format('YYYY-MM-DD');
|
||||
|
||||
const params = new URLSearchParams({
|
||||
plant_sub_section_id: plantSubSection,
|
||||
from: formattedDateStart,
|
||||
to: formattedDateEnd,
|
||||
interval: periode,
|
||||
page: 1,
|
||||
limit: 1000,
|
||||
});
|
||||
|
||||
const pivotResponse = await getAllHistoryValueReportPivot(params);
|
||||
|
||||
// Jika response sukses, proses data
|
||||
if (pivotResponse && pivotResponse.data) {
|
||||
await fetchData(1, pagination.pageSize, false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
// Error akan ditangkap oleh api-request.js dan muncul Swal otomatis
|
||||
} finally {
|
||||
setIsLoadingModal(false);
|
||||
}
|
||||
const handleSearch = () => {
|
||||
fetchData(1, pagination.pageSize, true);
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
@@ -275,168 +247,6 @@ const ListReport = memo(function ListReport(props) {
|
||||
{ value: 120, label: '2 Hour', disabled: false },
|
||||
];
|
||||
|
||||
const exportToExcel = async () => {
|
||||
if (pivotData.length === 0) {
|
||||
alert('No data to export');
|
||||
return;
|
||||
}
|
||||
|
||||
const tagMapping = {};
|
||||
valueReportData.forEach(item => {
|
||||
if (item.tag_name && item.tag_number) {
|
||||
tagMapping[item.tag_name] = item.tag_number;
|
||||
}
|
||||
});
|
||||
|
||||
const selectedSection = plantSubSectionList.find(
|
||||
item => item.plant_sub_section_id === plantSubSection
|
||||
);
|
||||
const sectionName = selectedSection ? selectedSection.plant_sub_section_name : 'Unknown';
|
||||
|
||||
// Buat struktur pivot yang sama seperti di tabel
|
||||
const timeMap = new Map();
|
||||
const tagSet = new Set();
|
||||
|
||||
pivotData.forEach((row) => {
|
||||
const tagName = row.id;
|
||||
tagSet.add(tagName);
|
||||
|
||||
const dataPoints = row.data || [];
|
||||
dataPoints.forEach((item) => {
|
||||
if (item && typeof item === 'object' && 'x' in item && 'y' in item) {
|
||||
const datetime = item.x;
|
||||
if (!timeMap.has(datetime)) {
|
||||
timeMap.set(datetime, {});
|
||||
}
|
||||
timeMap.get(datetime)[tagName] = item.y;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const sortedTimes = Array.from(timeMap.keys()).sort();
|
||||
const sortedTags = Array.from(tagSet).sort();
|
||||
|
||||
const pivotTableData = sortedTimes.map((datetime) => {
|
||||
const rowData = {
|
||||
datetime: datetime,
|
||||
};
|
||||
|
||||
sortedTags.forEach((tagName) => {
|
||||
rowData[tagName] = timeMap.get(datetime)[tagName];
|
||||
});
|
||||
|
||||
return rowData;
|
||||
});
|
||||
|
||||
console.log('Excel Pivot data:', pivotTableData.slice(0, 5));
|
||||
console.log('Total rows for Excel:', pivotTableData.length);
|
||||
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const ws = workbook.addWorksheet('Pivot Report');
|
||||
|
||||
// Buat header info (3 baris pertama)
|
||||
ws.addRow(['PT. PUPUK INDONESIA UTILITAS']);
|
||||
ws.addRow(['GRESIK GAS COGENERATION PLANT']);
|
||||
ws.addRow([`${sectionName}`]);
|
||||
ws.addRow([]); // Baris kosong sebagai pemisah
|
||||
|
||||
// Buat header kolom dengan tag number
|
||||
const headerRow = [
|
||||
'Datetime',
|
||||
...sortedTags.map(tag => tagMapping[tag] || tag)
|
||||
];
|
||||
ws.addRow(headerRow);
|
||||
|
||||
// Buat data rows - PERBAIKAN: Simpan sebagai number murni
|
||||
pivotTableData.forEach((rowData) => {
|
||||
const row = [dayjs(rowData.datetime).format('DD-MM-YYYY HH:mm')];
|
||||
sortedTags.forEach((tagName) => {
|
||||
const value = rowData[tagName];
|
||||
// Simpan sebagai number, bukan string
|
||||
if (value !== undefined && value !== null) {
|
||||
row.push(Number(value));
|
||||
} else {
|
||||
row.push('-');
|
||||
}
|
||||
});
|
||||
ws.addRow(row);
|
||||
});
|
||||
|
||||
// Set column widths
|
||||
ws.getColumn(1).width = 18; // Datetime column
|
||||
for (let i = 2; i <= sortedTags.length + 1; i++) {
|
||||
ws.getColumn(i).width = 12; // Tag columns
|
||||
}
|
||||
|
||||
// Merge cells untuk header info
|
||||
const totalCols = sortedTags.length + 1;
|
||||
ws.mergeCells(1, 1, 1, totalCols); // Baris 1
|
||||
ws.mergeCells(2, 1, 2, totalCols); // Baris 2
|
||||
ws.mergeCells(3, 1, 3, totalCols); // Baris 3
|
||||
|
||||
// Style untuk header info (3 baris pertama - bold dan center)
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
const cell = ws.getCell(i, 1);
|
||||
cell.font = { bold: true, size: 12 };
|
||||
cell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
|
||||
}
|
||||
|
||||
// Style untuk header kolom (bold, background color, center, border)
|
||||
const headerRowIndex = 5; // Baris header
|
||||
for (let col = 1; col <= totalCols; col++) {
|
||||
const cell = ws.getCell(headerRowIndex, col);
|
||||
cell.font = { bold: true, size: 11 };
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFDCDCDC' }
|
||||
};
|
||||
cell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
left: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
right: { style: 'thin', color: { argb: 'FF000000' } }
|
||||
};
|
||||
}
|
||||
|
||||
// Style untuk data cells (border dan alignment) - PERBAIKAN: Format number dengan 2 desimal
|
||||
for (let row = headerRowIndex + 1; row <= ws.rowCount; row++) {
|
||||
for (let col = 1; col <= totalCols; col++) {
|
||||
const cell = ws.getCell(row, col);
|
||||
|
||||
cell.alignment = {
|
||||
horizontal: 'center',
|
||||
vertical: 'middle',
|
||||
wrapText: true
|
||||
};
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
left: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
right: { style: 'thin', color: { argb: 'FF000000' } }
|
||||
};
|
||||
|
||||
// Format number dengan 2 desimal untuk kolom value (kolom 2 dst)
|
||||
if (col > 1) {
|
||||
const cellValue = cell.value;
|
||||
// Hanya set format number jika cell berisi angka
|
||||
if (typeof cellValue === 'number') {
|
||||
cell.numFmt = '0.00';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate file name
|
||||
const fileName = `Report_Pivot_${startDate.format('DD-MM-YYYY')}_to_${endDate.format('DD-MM-YYYY')}.xlsx`;
|
||||
|
||||
// Save file
|
||||
const buffer = await workbook.xlsx.writeBuffer();
|
||||
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
saveAs(blob, fileName);
|
||||
};
|
||||
|
||||
const exportToPDF = async () => {
|
||||
if (pivotData.length === 0) {
|
||||
alert('No data to export');
|
||||
@@ -583,7 +393,7 @@ const ListReport = memo(function ListReport(props) {
|
||||
doc.setFontSize(9);
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(10);
|
||||
doc.text(`${sectionName}`, marginLeft + col1Width + col2Width / 2, 38, { align: 'center' });
|
||||
doc.text(`Plant Section : ${sectionName}`, marginLeft + col1Width + col2Width / 2, 41, { align: 'center' });
|
||||
};
|
||||
|
||||
// Hitung total kolom tag chunks
|
||||
@@ -724,7 +534,7 @@ const ListReport = memo(function ListReport(props) {
|
||||
autoTable(doc, {
|
||||
head: [headerRow],
|
||||
body: pdfRows,
|
||||
startY: isFirstPage ? 43 : 15,
|
||||
startY: isFirstPage ? 50 : 15,
|
||||
theme: 'grid',
|
||||
rowPageBreak: 'avoid',
|
||||
styles: {
|
||||
@@ -732,7 +542,7 @@ const ListReport = memo(function ListReport(props) {
|
||||
cellPadding: 1.5,
|
||||
minCellHeight: 8,
|
||||
lineColor: [0, 0, 0],
|
||||
lineWidth: 0.5,
|
||||
lineWidth: 0.1,
|
||||
halign: 'center',
|
||||
valign: 'middle',
|
||||
overflow: 'linebreak',
|
||||
@@ -744,7 +554,7 @@ const ListReport = memo(function ListReport(props) {
|
||||
halign: 'center',
|
||||
valign: 'middle',
|
||||
lineColor: [0, 0, 0],
|
||||
lineWidth: 0.5,
|
||||
lineWidth: 0.3,
|
||||
},
|
||||
columnStyles: {
|
||||
0: {
|
||||
@@ -884,23 +694,11 @@ const ListReport = memo(function ListReport(props) {
|
||||
type="primary"
|
||||
icon={<DownloadOutlined />}
|
||||
onClick={exportToPDF}
|
||||
disabled={pivotData.length === 0}
|
||||
style={{ backgroundColor: '#1890ff', borderColor: '#1890ff' }}
|
||||
disabled={false}
|
||||
>
|
||||
Export PDF
|
||||
</Button>
|
||||
</Col>
|
||||
<Col>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<DownloadOutlined />}
|
||||
onClick={exportToExcel}
|
||||
disabled={pivotData.length === 0}
|
||||
style={{ backgroundColor: '#28a745', borderColor: '#28a745' }}
|
||||
>
|
||||
Export Excel
|
||||
</Button>
|
||||
</Col>
|
||||
<Col>
|
||||
<Button
|
||||
onClick={handleReset}
|
||||
|
||||
@@ -130,26 +130,9 @@ const ReportTrending = memo(function ReportTrending(props) {
|
||||
}
|
||||
};
|
||||
|
||||
// Fungsi untuk menentukan apakah rentang tanggal lebih dari 1 hari
|
||||
const isMultipleDays = () => {
|
||||
return !startDate.isSame(endDate, 'day');
|
||||
};
|
||||
|
||||
// Format sumbu X yang otomatis menyesuaikan
|
||||
const formatXAxis = (tickItem) => {
|
||||
const date = new Date(tickItem);
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
|
||||
// Jika rentang lebih dari 1 hari, tampilkan tanggal + waktu
|
||||
if (isMultipleDays()) {
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
return `${day}/${month} ${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
// Jika hanya 1 hari, tampilkan waktu saja
|
||||
return `${hours}:${minutes}`;
|
||||
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const CustomTooltip = ({ active, payload, label }) => {
|
||||
|
||||
@@ -115,7 +115,7 @@ const ChangePasswordModal = (props) => {
|
||||
try {
|
||||
const response = await changePassword(props.selectedUser.user_id, formData.newPassword);
|
||||
|
||||
// console.log('Change Password Response:', response);
|
||||
console.log('Change Password Response:', response);
|
||||
|
||||
if (response && response.statusCode === 200) {
|
||||
NotifOk({
|
||||
|
||||
@@ -220,27 +220,35 @@ const DetailUser = (props) => {
|
||||
|
||||
// For update mode: only send email if it has changed
|
||||
if (FormData.user_id) {
|
||||
// Only include email if it has changed from original
|
||||
if (FormData.user_email !== originalEmail) {
|
||||
payload.user_email = FormData.user_email;
|
||||
}
|
||||
|
||||
// Add is_active for update mode
|
||||
payload.is_active = FormData.is_active;
|
||||
} else {
|
||||
// For create mode: always send email
|
||||
payload.user_email = FormData.user_email;
|
||||
}
|
||||
|
||||
// Only add role_id if it exists (backend requires number >= 1, no null)
|
||||
if (FormData.role_id) {
|
||||
payload.role_id = FormData.role_id;
|
||||
}
|
||||
|
||||
// Add password and name for new user (create mode)
|
||||
if (!FormData.user_id) {
|
||||
payload.user_name = FormData.user_name;
|
||||
payload.user_password = FormData.password;
|
||||
payload.user_name = FormData.user_name; // Username only for create
|
||||
payload.user_password = FormData.password; // Backend expects 'user_password'
|
||||
// Don't send confirmPassword, is_sa for create
|
||||
}
|
||||
// For update mode:
|
||||
// - Don't send 'user_name' (username is immutable)
|
||||
// - is_active is now sent for update mode
|
||||
// - Only send email if it has changed
|
||||
|
||||
try {
|
||||
// console.log('Payload being sent:', payload);
|
||||
console.log('Payload being sent:', payload);
|
||||
|
||||
let response;
|
||||
if (!FormData.user_id) {
|
||||
@@ -249,10 +257,11 @@ const DetailUser = (props) => {
|
||||
response = await updateUser(FormData.user_id, payload);
|
||||
}
|
||||
|
||||
// console.log('Save User Response:', response);
|
||||
console.log('Save User Response:', response);
|
||||
|
||||
// Check if response is successful
|
||||
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
||||
// If in edit mode and newPassword is provided, change password
|
||||
if (FormData.user_id && FormData.newPassword) {
|
||||
try {
|
||||
const passwordResponse = await changePassword(
|
||||
@@ -376,9 +385,9 @@ const DetailUser = (props) => {
|
||||
search: '',
|
||||
});
|
||||
|
||||
// console.log('Fetching roles with params:', queryParams.toString());
|
||||
console.log('Fetching roles with params:', queryParams.toString());
|
||||
const response = await getAllRole(queryParams);
|
||||
// console.log('Fetched roles response:', response);
|
||||
console.log('Fetched roles response:', response);
|
||||
|
||||
// Handle different response structures
|
||||
if (response && response.data) {
|
||||
@@ -399,7 +408,7 @@ const DetailUser = (props) => {
|
||||
}
|
||||
|
||||
setRoleList(roles);
|
||||
// console.log('Setting role list:', roles);
|
||||
console.log('Setting role list:', roles);
|
||||
} else {
|
||||
// Add mock data as fallback
|
||||
console.warn('No response data, using mock data');
|
||||
@@ -409,7 +418,7 @@ const DetailUser = (props) => {
|
||||
{ role_id: 3, role_name: 'User', role_level: 3 },
|
||||
];
|
||||
setRoleList(mockRoles);
|
||||
// console.log('Setting mock role list:', mockRoles);
|
||||
console.log('Setting mock role list:', mockRoles);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching roles:', error);
|
||||
@@ -420,7 +429,7 @@ const DetailUser = (props) => {
|
||||
{ role_id: 3, role_name: 'User', role_level: 3 },
|
||||
];
|
||||
setRoleList(mockRoles);
|
||||
// console.log('Setting mock role list due to error:', mockRoles);
|
||||
console.log('Setting mock role list due to error:', mockRoles);
|
||||
|
||||
// Only show error notification if we don't have fallback data
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
@@ -1137,7 +1146,9 @@ const DetailUser = (props) => {
|
||||
))}
|
||||
</Select>
|
||||
{errors.role_id && (
|
||||
<Text style={{ color: 'red', fontSize: '12px' }}>{errors.role_id}</Text>
|
||||
<Text style={{ color: 'red', fontSize: '12px' }}>
|
||||
{errors.role_id}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import React, { useState, useEffect, memo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, Typography } from 'antd';
|
||||
import { resetWA } from '../../api/whatsapp-control';
|
||||
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
|
||||
import { ReloadOutlined } from '@ant-design/icons';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const IndexWhatsAppControl = memo(function IndexWhatsAppControl() {
|
||||
const navigate = useNavigate();
|
||||
const { setBreadcrumbItems } = useBreadcrumb();
|
||||
|
||||
const [isPlaying, setIsPlaying] = useState(true);
|
||||
|
||||
const url = import.meta.env.VITE_WHATSAPP_URL;
|
||||
|
||||
const handleReset = async () => {
|
||||
setIsPlaying(false);
|
||||
await resetWA();
|
||||
setIsPlaying(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
if (token) {
|
||||
setBreadcrumbItems([
|
||||
{
|
||||
title: (
|
||||
<Text strong style={{ fontSize: '14px' }}>
|
||||
• WhatsApp Control Panel
|
||||
</Text>
|
||||
),
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
navigate('/signin');
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<Button type="primary" onClick={handleReset} style={{ marginRight: 10 }}>
|
||||
<ReloadOutlined /> Restart WhatsApp
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
border: '1px solid #ddd',
|
||||
height: '700px',
|
||||
background: '#fafafa',
|
||||
}}
|
||||
>
|
||||
{isPlaying ? (
|
||||
<iframe
|
||||
src={url}
|
||||
title="WhatsApp Preview"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
border: 'none',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
color: '#888',
|
||||
}}
|
||||
>
|
||||
Memuat Halaman WhatsApp QR Code
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default IndexWhatsAppControl;
|
||||
@@ -1,172 +0,0 @@
|
||||
import React, { useState, useEffect, useRef, memo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, Typography, message } from 'antd';
|
||||
import { resetWA } from '../../api/web-control';
|
||||
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
|
||||
import { ReloadOutlined } from '@ant-design/icons';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const IndexWebControl = memo(function IndexWebControl() {
|
||||
const navigate = useNavigate();
|
||||
const { setBreadcrumbItems } = useBreadcrumb();
|
||||
|
||||
const [isPlaying, setIsPlaying] = useState(true);
|
||||
const [currentUrl, setCurrentUrl] = useState('http://localhost:9531');
|
||||
const iframeRef = useRef(null);
|
||||
|
||||
const handleReset = async () => {
|
||||
setIsPlaying(false);
|
||||
await resetWA();
|
||||
setIsPlaying(true);
|
||||
// Kembali ke halaman login setelah reset
|
||||
setCurrentUrl('https://localhost:9531');
|
||||
message.success('WhatsApp berhasil di-restart');
|
||||
};
|
||||
|
||||
// Fungsi untuk redirect ke QR View
|
||||
const redirectToQRView = () => {
|
||||
setCurrentUrl('https://localhost:9531/qrview');
|
||||
message.info('Redirecting to QR View...');
|
||||
};
|
||||
|
||||
// Fungsi untuk kembali ke login
|
||||
const backToLogin = () => {
|
||||
setCurrentUrl('https://localhost:9531');
|
||||
message.info('Back to login page');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (token) {
|
||||
setBreadcrumbItems([
|
||||
{
|
||||
title: (
|
||||
<Text strong style={{ fontSize: '14px' }}>
|
||||
• Web Control Panel
|
||||
</Text>
|
||||
),
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
navigate('/signin');
|
||||
}
|
||||
}, [navigate, setBreadcrumbItems]);
|
||||
|
||||
// Mendengarkan pesan dari iframe
|
||||
useEffect(() => {
|
||||
const handleMessage = (event) => {
|
||||
// Terima pesan dari domain manapun untuk testing
|
||||
console.log('Message received from:', event.origin);
|
||||
console.log('Message data:', event.data);
|
||||
|
||||
// Cek apakah ini pesan login success
|
||||
if (event.data) {
|
||||
// Jika pesan adalah string
|
||||
if (typeof event.data === 'string') {
|
||||
const lowerData = event.data.toLowerCase();
|
||||
if (
|
||||
lowerData.includes('login') ||
|
||||
lowerData.includes('success') ||
|
||||
lowerData.includes('authenticated') ||
|
||||
lowerData.includes('qrview')
|
||||
) {
|
||||
console.log('Login detected via string message');
|
||||
redirectToQRView();
|
||||
}
|
||||
}
|
||||
|
||||
// Jika pesan adalah object
|
||||
if (typeof event.data === 'object') {
|
||||
if (
|
||||
event.data.type === 'LOGIN_SUCCESS' ||
|
||||
event.data.status === 'success' ||
|
||||
event.data.logged_in === true ||
|
||||
event.data.redirect === true
|
||||
) {
|
||||
console.log('Login detected via object message');
|
||||
redirectToQRView();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleMessage);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', handleMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Alternative: Coba dengan timer (jika postMessage tidak berfungsi)
|
||||
useEffect(() => {
|
||||
// Jika tidak ada pesan dari iframe, coba redirect otomatis setelah 10 detik
|
||||
// Asumsi: login biasanya selesai dalam 10 detik
|
||||
const timer = setTimeout(() => {
|
||||
if (currentUrl === 'https://localhost:9531') {
|
||||
console.log('Auto redirect after 10 seconds (fallback)');
|
||||
redirectToQRView();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [currentUrl]);
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<div style={{ marginBottom: 20, display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
||||
<Button type="primary" onClick={handleReset}>
|
||||
<ReloadOutlined /> Restart WhatsApp
|
||||
</Button>
|
||||
{/* <Button onClick={redirectToQRView} type="default">
|
||||
Redirect ke QR View
|
||||
</Button>
|
||||
<Button onClick={backToLogin} type="default">
|
||||
Kembali ke Login
|
||||
</Button> */}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
border: '1px solid #ddd',
|
||||
height: '700px',
|
||||
background: '#fafafa',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
{isPlaying ? (
|
||||
<iframe
|
||||
key={currentUrl} // Force re-render saat URL berubah
|
||||
ref={iframeRef}
|
||||
src={currentUrl}
|
||||
title="Web Preview"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
border: 'none',
|
||||
}}
|
||||
onLoad={() => {
|
||||
console.log('Iframe loaded with URL:', currentUrl);
|
||||
// Hanya log, tidak mencoba mengakses URL untuk menghindari error CORS
|
||||
}}
|
||||
onError={(e) => console.error('Iframe error:', e)}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
color: '#888',
|
||||
}}
|
||||
>
|
||||
Memuat Halaman WhatsApp QR Code
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default IndexWebControl;
|
||||