Compare commits

...

366 Commits

Author SHA1 Message Date
03d5646565 Merge pull request 'lavoce' (#37) from lavoce into main
Reviewed-on: #37
2026-01-08 07:44:22 +00:00
6fdb259246 fixing validate solution optional in brand error code 2026-01-08 14:32:27 +07:00
0aad43c751 add label error code in list notification 2026-01-08 14:24:32 +07:00
d988d47e30 fixing layout mobile detail notification 2026-01-08 14:17:38 +07:00
zain94rif
e08eaaa43e fix(text): add 'error code' & move solution name 2026-01-08 13:55:01 +07:00
zain94rif
f6ca54f5b4 Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2026-01-08 13:07:27 +07:00
zain94rif
a9b8053bd8 fix: change message 'Setiap error code harus memiliki minimal 1 solution!' disabled 2026-01-08 13:07:21 +07:00
4d8af01316 Merge pull request 'fixing typo detail notification user' (#36) from lavoce into main
Reviewed-on: #36
2026-01-08 05:38:53 +00:00
600c101c68 fixing typo detail notification user 2026-01-08 12:17:13 +07:00
8f32f29c03 Merge pull request 'lavoce' (#35) from lavoce into main
Reviewed-on: #35
2026-01-08 04:52:16 +00:00
zain94rif
14a6884f43 Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2026-01-07 17:07:46 +07:00
zain94rif
8e151ffe0b fix(comp): modified the card in notification detail 2026-01-07 17:07:42 +07:00
8f64843613 fixing redirect wa session token 2026-01-07 16:10:23 +07:00
zain94rif
fe8f6d1002 fix: move update is read's api after fetchLogHistory 2026-01-07 14:40:36 +07:00
zain94rif
5281e288a9 feat(var): add update at from create at 2026-01-07 11:00:35 +07:00
5a7d64a05b Merge pull request 'fix: resize add log card' (#34) from lavoce into main
Reviewed-on: #34
2026-01-07 03:33:48 +00:00
zain94rif
4ed05cc640 fix: resize add log card 2026-01-07 10:30:03 +07:00
e74b802a60 Merge pull request 'lavoce' (#33) from lavoce into main
Reviewed-on: #33
2026-01-06 11:30:27 +00:00
zain94rif
14e97fead2 feat(api): add update is_read for detail 2026-01-06 16:12:58 +07:00
zain94rif
0935d7c9f5 fix(var): use notification_error_id from item, not from users 2026-01-06 09:53:15 +07:00
zain94rif
3266641f81 fix(api): fixing put to post 2026-01-05 14:48:46 +07:00
zain94rif
739c55c0bc fix(api): fixing endpoint notification 2026-01-05 14:26:12 +07:00
zain94rif
5b4485d20d feat(api): add API for resend chat user 2026-01-05 14:08:02 +07:00
f436865b7f Merge pull request 'lavoce' (#32) from lavoce into main
Reviewed-on: #32
2026-01-05 03:41:39 +00:00
98057beb0f Merge pull request 'fix-lav-notification' (#31) from fix-lav-notification into lavoce
Reviewed-on: #31
2026-01-05 03:40:24 +00:00
zain94rif
b342289888 fix(view): adjustment view page notification 2026-01-05 10:39:01 +07:00
d03bbf2a41 Repair topic mqtt 2026-01-05 10:38:24 +07:00
zain94rif
ec094b8f55 fix(text): change 'User History' to 'History User' 2026-01-05 09:38:27 +07:00
48437c3c50 Merge pull request 'lavoce' (#30) from lavoce into main
Reviewed-on: #30
2025-12-31 03:20:51 +00:00
b6d941ba2d refactor: comment out console logs for cleaner production code 2025-12-29 10:58:03 +07:00
167abcaa43 refactor: enhance notification log layout and styling for better readability 2025-12-24 11:51:39 +07:00
beb8ccbaee feat: integration notification functionality and user history fetching 2025-12-23 22:10:11 +07:00
797f6c2383 refactor: clean up comments and streamline payload handling in user detail form 2025-12-23 20:10:33 +07:00
a33c9b3b92 Merge pull request 'lavoce' (#29) from lavoce into main
Reviewed-on: #29
2025-12-23 05:22:06 +00:00
016c77a586 fixing redirect detail notification tab 2025-12-23 12:17:17 +07:00
36ebab7f9a refactor: remove unused UserHistoryModal and related state management 2025-12-23 10:30:44 +07:00
a5b1fbef74 repair: layout & sparepart brand-device 2025-12-23 10:26:30 +07:00
Athif
cb0c53daea update Menu Report 2025-12-23 02:20:16 +07:00
978e020305 feat: update notification data transformation and enhance user history display 2025-12-22 20:49:48 +07:00
4508738958 feat: implement log history fetching and display in ListNotification component 2025-12-22 18:47:42 +07:00
58d1f5c7ab Merge pull request 'Repair and replace svg' (#28) from lavoce into main
Reviewed-on: #28
2025-12-22 09:38:05 +00:00
eb23612444 Repair and replace svg 2025-12-22 16:37:11 +07:00
c10a5bf62d Merge pull request 'lavoce' (#27) from lavoce into main
Reviewed-on: #27
2025-12-22 09:28:34 +00:00
bee196e299 feat: add notification log creation and retrieval functionality 2025-12-22 14:34:14 +07:00
d19f555c7c repair: layout error code form brand-device 2025-12-19 12:43:56 +07:00
1d7253f9a1 repair: sparepart select brand-device 2025-12-19 12:43:19 +07:00
d8a1878ab1 refactor: adjust spacing and layout in NotificationDetailTab for improved readability 2025-12-18 21:11:49 +07:00
e4af2d6e18 refactor: improve timestamp display and code formatting in notification detail 2025-12-18 19:34:20 +07:00
8cf21643ea refactor: update notification handling to prioritize active solutions and improve data extraction 2025-12-18 17:57:25 +07:00
Athif
6b75f6f4b9 update menu report 2025-12-18 15:03:39 +07:00
Athif
dc78add71d Perbaikan Menu Report dan Trending 2025-12-18 13:02:52 +07:00
1ce922ff4c minor fix notif 2025-12-18 12:36:46 +07:00
3a4b0f0748 repair: ErrorCode brand-device 2025-12-18 10:51:35 +07:00
4bffbb3798 repair: add clear selected error code 2025-12-13 14:25:30 +07:00
b9cdfcb1e9 repair: sollution field, handle clear form 2025-12-13 14:15:35 +07:00
49ba00d886 repair: view brand device, add: read only 2025-12-12 23:02:09 +07:00
cf1ccb0fd0 repair: sollution brand-device 2025-12-12 16:55:05 +07:00
fb790e5e37 repair: error code brand-device 2025-12-12 16:54:52 +07:00
ea3adf40cc repair: brandDevice add edit page 2025-12-12 16:54:30 +07:00
2ff50342e8 repair: sollution brand-device 2025-12-12 15:58:11 +07:00
1f8ee62721 fix: improve formatting and consistency in DetailDevice and GeneratePdf components 2025-12-12 15:53:29 +07:00
96d6367dbd add: image viewer 2025-12-12 12:46:05 +07:00
8afff23ffe update: brand device 2025-12-12 12:45:46 +07:00
512282f367 repair: sollution brand-device 2025-12-12 12:45:00 +07:00
4fab5df300 repair: error code brand-device 2025-12-12 12:44:16 +07:00
9e8191f8f8 repair: sparepart brand-device 2025-12-12 12:43:14 +07:00
13255f9713 feat: add getNotificationDetail API function and integrate it into DetailNotification component for enhanced notification handling 2025-12-11 17:07:06 +07:00
e23215b6c1 refactor: adjust layout and styling in DetailNotification and ListNotification components; remove pagination in LogHistoryCard for improved UI 2025-12-11 09:53:44 +07:00
a014d6b370 feat: replace LogHistoryModal with LogHistoryCard and update DetailNotification for improved log history display 2025-12-09 13:32:53 +07:00
3225a0865e repair: delete error code 2025-12-09 11:06:28 +07:00
5703ff0e8d repair: add edit brand device 2025-12-08 16:45:49 +07:00
03be3a6a99 fix: update column title from 'Aksi' to 'Action' in ListUser component for clarity 2025-12-08 13:48:15 +07:00
fe5f081b92 feat: update handling of description fields in multiple components to ensure non-empty values are stored 2025-12-05 13:13:30 +07:00
acaf1b3946 feat: add listen channel field to DetailDevice component and update ListDevice to display it; enhance quantity handling in SparepartCardList to prevent negative adjustments 2025-12-04 15:59:57 +07:00
147171373c feat: update quantity display and stock update button visibility in SparepartCardList component 2025-12-04 13:59:25 +07:00
f22e120204 update ui brand device 2025-12-04 01:17:25 +07:00
1bc98de564 feat: enhance image URL handling in DetailSparepart component and remove status field display 2025-12-03 16:58:58 +07:00
991a3eaa66 feat: update quantity handling in DetailSparepart and SparepartCardList components to allow zero values 2025-12-03 16:45:44 +07:00
7a5a9aafd1 feat: update sparepart quantity and stock status handling in DetailSparepart and SparepartCardList components 2025-12-03 13:26:54 +07:00
0694497f8d feat: remove contact_type from DetailContact component 2025-12-03 10:49:16 +07:00
c82d6d39c1 feat: conditionally display status field in add mode for DetailContact component 2025-12-02 15:39:20 +07:00
edf20050db feat: hide tabs and improve UI elements 2025-12-02 14:05:35 +07:00
2e98dc168a feat: enhance DetailSparepart component with image upload and preview functionality 2025-12-02 13:48:56 +07:00
1797058526 repair: brandDevice sparepart integration 2025-12-02 11:10:36 +07:00
1c2ddca9d4 fix: update isReadFilter 2025-12-01 10:51:11 +07:00
6cc5042956 Merge pull request 'repair' (#26) from lavoce into main
Reviewed-on: #26
2025-11-28 07:17:06 +00:00
61ca7249cd repair 2025-11-28 14:16:45 +07:00
5079f8d316 Merge pull request 'lavoce' (#25) from lavoce into main
Reviewed-on: #25
2025-11-28 07:12:41 +00:00
a98edbe658 Add scroll for overflow menus 2025-11-28 14:10:22 +07:00
fbc5473f2b feat: implement sparepart selection functionality and refactor related components 2025-11-28 14:00:17 +07:00
7073390de7 Merge pull request 'lavoce' (#24) from lavoce into main
Reviewed-on: #24
2025-11-28 05:50:36 +00:00
55a47c3a25 Repair svg compressor B 2025-11-28 12:50:09 +07:00
94e011e5c7 Repair topic mqtt 2025-11-28 12:49:56 +07:00
db9b40f2fc Repair compresso 2025-11-28 12:28:17 +07:00
4226a24e79 Merge pull request 'lavoce' (#23) from lavoce into main
Reviewed-on: #23
2025-11-28 05:10:26 +00:00
5fdfb47f9e fix: update error code icon handling to use URL if available 2025-11-27 17:39:39 +07:00
55c50f6f7f Refactor code structure for improved readability and maintainability 2025-11-27 16:58:27 +07:00
ed4570e8dd feat: add onGetData callback to TableList and enhance DetailSparepart with improved image handling 2025-11-27 13:30:45 +07:00
572042ab53 feat: enhance DetailSparepart component with image upload and preview functionality 2025-11-27 11:36:23 +07:00
afcb85a323 feat: add image upload functionality and stock update feature in sparepart components 2025-11-26 17:16:09 +07:00
14f8a5d472 feat: enhance notification fetching with pagination and filtering options 2025-11-26 11:44:50 +07:00
309d191bce feat: add custom card component for sparepart display in ListSparepart 2025-11-25 16:49:46 +07:00
038009433f Merge pull request 'lavoce' (#22) from lavoce into main
Reviewed-on: #22
2025-11-25 03:50:54 +00:00
7e5105392c feat: add activity log functionality with log history display and input for new logs 2025-11-25 10:22:55 +07:00
7e16bf63aa refactor: consolidate SolutionField components and remove obsolete files 2025-11-24 21:44:44 +07:00
3e384f89b1 feat: integrate sparepart management into AddBrandDevice and EditBrandDevice components 2025-11-24 21:25:24 +07:00
b05e3fe5d9 feat: implement sparepart management with CRUD operations and UI components 2025-11-24 20:40:38 +07:00
1986368c1c feat: update button label from 'Add Data' to 'Add Role' in ListRole component 2025-11-24 15:58:23 +07:00
1cd9cf765c fix dual action 2025-11-24 15:57:12 +07:00
908788f41d feat: enhance error code management with table display and action buttons 2025-11-24 13:05:33 +07:00
899695f548 feat: add sparepart management page and update routing in App component 2025-11-24 12:17:31 +07:00
7d2b18a94d refactor: remove sparepart handling from AddBrandDevice and EditBrandDevice components 2025-11-24 11:59:26 +07:00
1eab3fe845 feat: refactor notification detail handling and add verification spare part page 2025-11-21 16:25:50 +07:00
c4f290bfcb fix: improve success message in DetailContact 2025-11-20 19:52:03 +07:00
f304a28493 enhance search and pagination functionality to ListNotification component 2025-11-20 19:45:45 +07:00
73b5cd6e97 feat: add detail notification page and update notification links 2025-11-20 16:41:21 +07:00
2d0c28bc48 fix: validation in DetailContact component 2025-11-20 15:55:03 +07:00
1413d0ef33 fix: header list tag plant sub section 2025-11-20 15:40:06 +07:00
fde71818e2 fix: enhance tag duplication check and handle varied response structures in DetailTag component 2025-11-20 15:25:07 +07:00
85017cd88c fix: update header label from 'tag_name' to 'brand_name' in ListBrandDevice component 2025-11-20 15:14:30 +07:00
f1c7ae5e20 fix: update header label for clarity in ListPlantSubSection component 2025-11-20 15:09:16 +07:00
5989948bf9 refactor: simplify log history display in ListNotification component 2025-11-20 11:00:46 +07:00
64ba51b17c Merge pull request 'lavoce' (#21) from lavoce into main
Reviewed-on: #21
2025-11-20 03:44:05 +00:00
6a21b65808 konect brand device on device 2025-11-19 15:57:38 +07:00
b5fbf2f745 fix color contact 2025-11-19 15:40:15 +07:00
3b7ba28053 fix color number contact 2025-11-19 15:02:47 +07:00
47d0638a42 Merge pull request 'lavoce' (#20) from lavoce into main
Reviewed-on: #20
2025-11-19 01:05:19 +00:00
f4caac55e6 feat: add API function to retrieve all notifications 2025-11-18 19:55:11 +07:00
34e38b3969 refactor: Improve code formatting and readability in SparepartForm component 2025-11-18 13:09:39 +07:00
3198b71f7e feat: Enhance delete confirmation with brand name in notification message 2025-11-18 12:43:00 +07:00
8405568e85 fix: Update Brand Code input to always be disabled with consistent placeholder and styling 2025-11-18 11:51:28 +07:00
ecf59fa9c6 refactor: Improve code readability and structure in EditBrandDevice component 2025-11-18 11:34:03 +07:00
d8c5f3ed44 Merge pull request 'lavoce' (#19) from lavoce into main
Reviewed-on: #19
2025-11-18 00:26:36 +00:00
0e8078c29f feat: Enhance notification system with device alerts, user history, and log history modals 2025-11-18 04:04:25 +07:00
1d06963f67 Load solutions and spareparts into forms with image handling in EditBrandDevice 2025-11-17 22:37:58 +07:00
affd9146bb Merge pull request 'lavoce' (#18) from lavoce into main
Reviewed-on: #18
2025-11-17 08:27:39 +00:00
8de195d961 Add custom validation for contact name and display type badge in contact list 2025-11-17 12:29:42 +07:00
da9cf0d554 hidden jadwal shift and master-shift 2025-11-15 14:57:25 +07:00
8cf5878d46 Add contact management functionality with CRUD operations and UI enhancements 2025-11-15 13:36:38 +07:00
7dd38aa50c Change inactive contact status color to red for better visibility 2025-11-13 15:22:45 +07:00
b2bcaa6b5f Add ErrorCodeListModal component for managing error codes with enhanced UI and functionality 2025-11-13 14:22:49 +07:00
5822dbbc82 Refactor Add and Edit Brand Device components to include solutions and spareparts forms, enhancing error code management and UI layout 2025-11-13 14:22:42 +07:00
de8f0ba2b6 Add forms and hooks for managing error codes and spare parts 2025-11-13 14:22:23 +07:00
08f8c4708f add menu contact 2025-11-13 13:58:52 +07:00
85db9e0a52 Enhance notification list with search functionality and improved layout 2025-11-13 13:16:31 +07:00
4022b3f8f4 Merge pull request 'lavoce' (#17) from lavoce into main
Reviewed-on: #17
2025-11-10 07:57:17 +00:00
0916ea7103 Repair file route air dryer and cmpressor 2025-11-10 14:56:52 +07:00
5952858dca Repair sub menu air dryer and compressor 2025-11-10 14:56:31 +07:00
7064ec8587 Repair and add overview air dryer compressor 2025-11-10 14:56:08 +07:00
446a4e2b95 Merge pull request 'lavoce' (#16) from lavoce into main
Reviewed-on: #16
2025-11-10 06:33:35 +00:00
d2f9d6aacc Add svg compressor 2025-11-10 13:33:09 +07:00
7ef6d71be8 Repair header 2025-11-10 13:32:55 +07:00
83a475c708 Merge pull request 'Repair beautiful apps' (#15) from lavoce into main
Reviewed-on: #15
2025-11-04 10:01:47 +00:00
d955cc7942 Repair beautiful apps 2025-11-04 17:01:27 +07:00
ab1c510a77 Merge pull request 'Repair bg-signin' (#14) from lavoce into main
Reviewed-on: #14
2025-11-04 08:48:59 +00:00
2ac707611f Repair bg-signin 2025-11-04 15:48:20 +07:00
59859c6d18 Update public/web.config 2025-11-04 07:03:57 +00:00
2bd27937dc Update public/web.config 2025-11-04 07:02:55 +00:00
1058c660d6 Update public/web.config 2025-11-04 07:01:10 +00:00
35b2167791 Update public/web.config 2025-11-04 06:53:05 +00:00
ec676983d0 Update .gitignore 2025-11-04 06:51:39 +00:00
c07c5f8235 Update .gitignore 2025-11-04 06:47:31 +00:00
b32ad97034 Merge pull request 'Add side bar menus mobile mode' (#13) from lavoce into main
Reviewed-on: #13
2025-11-04 06:42:09 +00:00
71f42f4149 Add side bar menus mobile mode 2025-11-04 13:41:25 +07:00
76244f6f6e Merge pull request 'lavoce' (#12) from lavoce into main
Reviewed-on: #12
2025-11-04 06:23:15 +00:00
4544e33d01 fix is_active error code ft vinix 2025-10-30 15:15:26 +07:00
114ef96de8 translate UI text from Indonesian to English for consistency 2025-10-28 19:10:30 +07:00
0a128cbb3c Merge pull request 'lavoce' (#11) from lavoce into main
Reviewed-on: #11
2025-10-28 09:47:36 +00:00
259ee474aa refactor ErrorCodeForm component for improved readability and structure 2025-10-28 13:15:22 +07:00
da14ed4e74 add error code icon functionality and color selection in forms 2025-10-28 13:07:25 +07:00
3738adf85a integration jadwal shift 2025-10-28 12:54:24 +07:00
6b727c84d8 integration history event alarm 2025-10-28 12:24:25 +07:00
9a483aa873 30:70 interface brand device 2025-10-28 12:20:54 +07:00
1d408ef3c1 change color sidebar 2025-10-28 12:12:30 +07:00
e8c3f259bf replace: unit code field 2025-10-28 12:09:25 +07:00
7050d7ca84 fix preview brand device error code , solution 2025-10-28 12:07:31 +07:00
bd4ab26680 Merge pull request 'lavoce' (#10) from lavoce into main
Reviewed-on: #10
2025-10-28 04:48:54 +00:00
fd361f21cf Fixing report 2025-10-28 11:47:15 +07:00
47f7c7b682 integration api brandDevice, file upload in brand device 2025-10-28 11:07:54 +07:00
3e728a1ff5 Merge pull request 'lavoce' (#9) from lavoce into main
Reviewed-on: #9
2025-10-27 03:48:58 +00:00
39d8be10cc progress history report 2025-10-27 10:28:42 +07:00
5a8e2dee2f integration api history alarm and event alarm 2025-10-25 23:54:22 +07:00
9db143972e Merge pull request 'lavoce' (#8) from lavoce into main
Reviewed-on: #8
2025-10-25 09:19:36 +00:00
a86795fdf6 fixing ui master 2025-10-25 16:08:42 +07:00
a3e5fdd138 refactor: update is_active rendering to use 'Running' and 'Offline' labels 2025-10-24 19:51:34 +07:00
2abed31bde fix field + role user 2025-10-24 18:44:08 +07:00
c3fadb9382 fix: plant sub section 2025-10-24 15:42:29 +07:00
7eabb2c7c8 fix description field 2025-10-24 14:53:02 +07:00
029ea269a7 Merge pull request 'lavoce' (#7) from lavoce into main
Reviewed-on: #7
2025-10-24 05:43:32 +00:00
50d040953f color picker 2025-10-24 11:46:58 +07:00
dd874cbe9c Add brand device field to DetailDevice component and ListDevice table 2025-10-24 11:07:06 +07:00
f2b652abe3 radio button color status 2025-10-24 10:53:07 +07:00
b5c1888153 Enhance DetailJadwalShift and ListJadwalShift components with improved employee fetching, form handling, and UI updates 2025-10-24 10:52:03 +07:00
cf1ad6d511 Refactor: integration shift 2025-10-24 10:27:56 +07:00
a3d24a9426 margin segmented 2025-10-23 16:50:25 +07:00
3873ba5285 Fixing header list master brand device 2025-10-23 16:12:29 +07:00
034cf636f9 Slicing menu history alarm and event alarm 2025-10-23 15:57:26 +07:00
bddd249e07 join tag on unit 2025-10-23 15:27:37 +07:00
1c3f80bc26 update: add description field 2025-10-23 15:15:01 +07:00
9ac2942ace clean code role 2025-10-23 15:11:26 +07:00
4cdaa042da Merge pull request 'lavoce' (#6) from lavoce into main
Reviewed-on: #6
2025-10-23 07:28:11 +00:00
5a1bd4e16f Repair path svg 2025-10-23 14:27:23 +07:00
8c9ef41704 update menu event alarm 2025-10-23 12:57:54 +07:00
4f518dba9c upt 2025-10-23 12:21:03 +07:00
893852f929 fix: correct property name from 'description' to 'unit_description' in DetailUnit component 2025-10-23 12:17:54 +07:00
3a057f7ef0 refactor: simplify ListStatus rendering in IndexStatus component 2025-10-23 11:55:28 +07:00
56af2a16c0 Merge pull request 'update file svg to src assets' (#5) from lavoce into main
Reviewed-on: #5
2025-10-23 04:52:13 +00:00
1189115359 update file svg to src assets 2025-10-23 11:50:31 +07:00
deadf2ffb4 Merge pull request 'lavoce' (#4) from lavoce into main
Reviewed-on: #4
2025-10-23 04:27:57 +00:00
15d836c627 repair: fix maxLength 2025-10-23 11:24:55 +07:00
5baaf14bd9 feat: add maxLength 2025-10-23 11:16:37 +07:00
873434ff84 style: update button styles in ListShift component for improved UI consistency 2025-10-23 10:51:34 +07:00
e9d047fdf3 feat: add description field to DetailUnit component and ListUnit table 2025-10-23 10:48:54 +07:00
4079466deb feat: enhance AddBrandDevice component with error code management, improved UI, and file upload functionality 2025-10-22 16:45:03 +07:00
98e5ed250c modify color card by data 2025-10-22 16:11:52 +07:00
f52d61da62 feat: enhance DetailTag component with improved validation, UI updates, and refactored state management 2025-10-22 15:58:17 +07:00
6e256e3c42 fixing card list master status 2025-10-22 15:53:22 +07:00
784ffc5e87 Repair Layout 2025-10-22 15:28:58 +07:00
cb98d91577 Repair layout 2025-10-22 15:26:38 +07:00
988dcda0e2 feat: enhance DetailShift and ListShift components with improved validation and UI updates 2025-10-22 14:24:52 +07:00
4da80c7089 Merge pull request 'lavoce' (#3) from lavoce into main
Reviewed-on: #3
2025-10-22 05:59:57 +00:00
85afb9d332 feat: add brand code, country, and description fields to AddBrandDevice form 2025-10-22 12:04:39 +07:00
dca0a37774 feat: refactor DetailUnit component for improved state management and validation 2025-10-22 10:29:21 +07:00
9091392dfb feat: enhance status management with validation and improved UI components 2025-10-21 23:05:39 +07:00
5ec26ecbe8 feat: update device management to include device description and change status display 2025-10-21 15:23:02 +07:00
4bd0348a2a clean code master plant sub section and master device 2025-10-21 20:26:05 +07:00
55213480c9 Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2025-10-21 17:07:37 +07:00
cf063822eb feat: add brand device management with error code handling and navigation 2025-10-21 17:07:36 +07:00
94d395fe49 feat: implement CRUD operations for status management in master-status API 2025-10-21 08:39:17 +07:00
cc12455564 fix: improve time extraction by utilizing dayjs for ISO timestamp formatting 2025-10-21 14:45:22 +07:00
f7f11907dc add menu dashboard svg 2025-10-21 13:01:37 +07:00
fb3e500139 feat: implement field auto-incrementing code 2025-10-20 19:19:59 +07:00
6d45b5bf11 fix CardList 2025-10-20 16:00:15 +07:00
6a9bbb2b5e fix: correct initial state values and improve pagination handling in TableList component 2025-10-20 15:41:16 +07:00
d2c755c03d Refactor: shift management API and UI components 2025-10-20 13:49:42 +07:00
56e3ce78a6 Merge pull request 'lavoce' (#2) from lavoce into main
Reviewed-on: #2
2025-10-20 04:06:02 +00:00
4a9b6c9d01 feat: enhance jadwal shift management with improved component structure and dummy data handling 2025-10-17 15:49:49 +07:00
6be90b6ea9 feat: add unit management functionality with list, detail, and API integration 2025-10-17 15:48:14 +07:00
2df7c953c7 feat: remove unused activeTab state and related props from ListBrandDevice component 2025-10-17 15:39:34 +07:00
e42d1fa3ce feat: update data structure for tag history and adjust related components for consistency 2025-10-17 14:57:15 +07:00
15b3339dcb feat: refactor plant section components to use sub-section terminology and improve modal handling 2025-10-17 14:42:55 +07:00
c7c5a33613 feat: remove section name handling from DetailPlantSection and ListPlantSection components 2025-10-17 11:13:05 +07:00
f049902d2c feat: update delete confirmation dialog title and message in ListDevice component 2025-10-17 00:55:18 +07:00
2bf83619c7 feat: replace device location select with input field for direct entry in DetailDevice component 2025-10-17 00:45:32 +07:00
fcf1deaa26 feat: update button label in DetailPlantSection based on action mode 2025-10-17 00:31:29 +07:00
6348c1e2b4 feat: add section name field to DetailPlantSection and update ListPlantSection to include section name in data handling 2025-10-17 00:09:39 +07:00
2f621fc6c2 update status active inactive 2025-10-16 23:39:41 +07:00
956730135e refactor: streamline IndexPlantSection and DetailPlantSection components, enhance ListPlantSection with improved search and action handling 2025-10-16 23:05:26 +07:00
7538c18624 feat: convert line chart data to table format and enhance filtering options in IndexReport 2025-10-16 15:36:01 +07:00
61ec188d59 fix: adjust content margin in MainLayout for improved layout consistency 2025-10-16 15:27:13 +07:00
1ba83ec105 fix: update device filtering logic and improve UI labels in DetailTag component 2025-10-16 15:07:25 +07:00
9f46908d79 template card or table in component table list 2025-10-16 14:55:57 +07:00
9bb07b1224 feat: enhance device selection with code and name display, filter active devices 2025-10-16 14:12:18 +07:00
c0f7b8eeb4 center 2025-10-16 13:11:24 +07:00
a4f7eaf422 hardcode signin 2025-10-16 13:02:46 +07:00
172e14e77d update handle reject & is_active 2025-10-16 11:30:00 +07:00
77a89489cd fix: rename alarm property to is_alarm 2025-10-15 22:32:27 +07:00
23db974695 feat: add alarm toggle functionality in DetailTag component 2025-10-15 22:19:16 +07:00
1bde2a0fd0 feat: swap Tag Name and Tag Number fields in DetailTag component 2025-10-15 21:25:17 +07:00
4e2da7d4fa feat: refactor Plant Sub Section dropdown in DetailTag component 2025-10-15 21:17:37 +07:00
05be0b6738 feat: add dropdown field for plant sub sections in DetailTag component 2025-10-15 20:48:30 +07:00
2d2b1a6b0c pending reject handle 2025-10-15 19:42:47 +07:00
aa68c6690e update LayoutMenu , LayoutSidebar components 2025-10-15 19:42:01 +07:00
7b56f9690d feat: add duplicate tag number validation in DetailTag component 2025-10-15 18:15:42 +07:00
9fc1c7cb40 feat: implement card view for device listing with actions for preview, edit, and delete 2025-10-14 19:06:23 +07:00
fc1ce7281e fix signup 2025-10-14 16:57:11 +07:00
9f6cb66c37 feat: add password requirements validation and indicators in ChangePasswordModal and DetailUser components 2025-10-14 15:42:28 +07:00
eb90d89e0e feat: enhance DetailTag and ListTag components with improved device handling and search functionality 2025-10-14 14:40:01 +07:00
251ad44371 fix detail tag 2025-10-14 12:24:47 +07:00
e13d7eb3be refactor: update tag management with improved validation and device integration 2025-10-14 12:18:08 +07:00
973713286f feat: update shift management with jadwal shift integration and improved error handling 2025-10-13 23:13:40 +07:00
5ed5ee26bf feat: implement shift management with CRUD operations and local storage integration 2025-10-13 20:26:29 +07:00
bfe38d5955 fix notif alert delete 2025-10-13 11:14:47 +07:00
d9fb7c9fce refactor plant section 2025-10-13 11:02:17 +07:00
577d8c8585 integrasi plant section 2025-10-13 10:17:16 +07:00
54290baaac feat: add shift management functionality with CRUD operations and UI components 2025-10-13 02:25:16 +07:00
af6c6de301 fix field from be 2025-10-12 23:18:47 +07:00
5e728a6ff3 refactor: enhance error handling and logging in API requests 2025-10-12 22:08:57 +07:00
be17c43499 refactor update field user_prefix 2025-10-12 18:33:14 +07:00
d0bf6782d5 update mengikuti pusat 2025-10-11 03:07:27 +07:00
337598085a refactor: change role search parameter from 'search' to 'criteria'
- Update defaultFilter to use criteria instead of search
- Update handleSearch to use criteria parameter
- Update handleSearchClear to use criteria parameter
- Update auto-clear onChange to use criteria parameter

API endpoint now uses: /api/roles?page=1&limit=10&criteria=keyword
2025-10-11 00:01:45 +07:00
6381235e14 refactor: change device search parameter from 'search' to 'criteria'
- Update defaultFilter to use criteria instead of search
- Update handleSearch to use criteria parameter
- Update handleSearchClear to use criteria parameter
- Update auto-clear onChange to use criteria parameter

API endpoint now uses: /api/device?page=1&limit=10&criteria=keyword
2025-10-10 16:06:58 +07:00
c5f0c73ae1 refactor: change search parameter from 'search' to 'criteria'
- Update defaultFilter to use criteria instead of search
- Update handleSearch to use criteria parameter
- Update handleSearchClear to use criteria parameter
- Update auto-clear onChange to use criteria parameter

API endpoint now uses: /api/user?page=1&limit=10&criteria=keyword
2025-10-10 15:59:38 +07:00
d7a09840b9 feat: update device API with server-side pagination support
- Add support for backend pagination with current_page, current_limit, total_limit, total_page
- Handle multiple sources for total count (total_data, rows, data.length)
- Transform backend paging structure to frontend format
- Maintain client-side pagination as fallback
- Add comprehensive error handling with try-catch
- Add detailed console logging for debugging
- Map backend fields: current_page->page, current_limit->limit, total_limit->total
- Calculate total_page if not provided by backend

Backend response format: GET /api/device?page=1&limit=10
Supports both server-side and client-side pagination modes
2025-10-10 15:50:20 +07:00
e00ecbf116 feat: add change password functionality for users
Add ChangePasswordModal component:
- Create modal with new password and confirmation fields
- Implement password validation (min 8 chars, uppercase, lowercase, number, special char)
- Add real-time error validation and display
- Show password requirements info box
- Display username for confirmation
- Add loading state during password change
- Success/error notifications

Update IndexUser:
- Add state management for change password modal
- Pass props to ListUser and ChangePasswordModal
- Integrate ChangePasswordModal component

Update ListUser:
- Add KeyOutlined icon for change password button
- Add purple change password button in action column
- Implement showChangePasswordModal function
- Update columns to include change password handler
- Increase action column width to 18%

API endpoint: PUT /api/user/change-password/:id
2025-10-10 15:49:31 +07:00
2817f3c31c feat: update user API with server-side pagination and enhanced filtering
- Add support for server-side pagination from backend
- Maintain client-side pagination as fallback
- Filter out super admin users (is_sa = true or 1) in both paths
- Add comprehensive error handling with try-catch
- Add console logging for debugging
- Return standardized response structure
- Handle both boolean and integer values for is_sa field
- Recalculate pagination info after filtering SA users

API now supports both backend pagination and ensures SA users are always hidden from the list
2025-10-10 15:48:22 +07:00
7a8a46ee64 fix: remove duplicate /roles in API endpoints
- Fix getAllRole endpoint from roles/roles to roles
- Fix getRoleById endpoint from roles/roles/:id to roles/:id
- Fix createRole endpoint from roles/roles to roles
- Fix updateRole endpoint from roles/roles/:id to roles/:id
- Fix deleteRole endpoint from roles/roles/:id to roles/:id
- Add try-catch error handling in getAllRole
- Support both server-side and client-side pagination

This fixes SQL error: Conversion failed when converting the nvarchar value 'roles' to data type int
Backend was interpreting duplicate /roles as an ID parameter
2025-10-10 15:45:39 +07:00
c3b5ec2121 feat: refactor role display with dynamic colors and capitalize
- Add helper function capitalizeFirstLetter for consistent formatting
- Add helper function getRoleColor to determine tag color by role_level or role_name
- Refactor role_name column render to use dynamic helpers
- Replace 30+ lines of hardcoded conditions with 8 lines of clean code
- Support any role name from database without code changes
- Display role names with first letter capitalized
- Color mapping: Level 1=purple, Level 2=blue, Level 3=cyan, Level 4=green
- Add KeyOutlined icon import for change password feature
2025-10-10 15:44:46 +07:00
59c90c3519 feat: integrate dynamic role selection in user form
- Add getAllRole API import to fetch roles dynamically
- Add roleList and loadingRoles state management
- Implement fetchRoles function to get all roles from API
- Update Select component to display roles dynamically from database
- Display role format: Role Name (Level X)
- Add loading indicator while fetching roles
- Fetch roles automatically when modal opens
2025-10-10 15:44:21 +07:00
76e40ced3f integrasi role user 2025-10-10 14:59:21 +07:00
5f6c156c12 feat: add role fetching functionality to DetailUser component 2025-10-10 14:49:16 +07:00
c312577d50 dynamic active sidebar 2025-10-10 15:07:00 +07:00
a3666dbf41 add status toggle switch to DetailBrandDevice and update ListBrandDevice 2025-10-10 14:40:41 +07:00
49dda8621b refactor: remove IndexErrorCode component and update ListErrorMaster 2025-10-10 14:21:48 +07:00
bf03891142 refactor: streamline brand device management components and add error master view 2025-10-10 14:14:10 +07:00
3ce9b3772d remove IndexErrorCode component 2025-10-10 14:12:37 +07:00
27c901d08f role-based access control 2025-10-10 11:40:33 +07:00
a6e8c39ed8 integrasi role 2025-10-10 11:39:31 +07:00
7d10c3f5b2 update history trending 2025-10-10 10:58:45 +07:00
76cf2de6ed fix signin bug identifier 2025-10-09 23:12:54 +07:00
823492a381 add detailuser file 2025-10-09 22:53:06 +07:00
25e31c58bd add detail user 2025-10-09 22:52:37 +07:00
f1fe0e0bc4 filter hide superadmin from get all user 2025-10-09 22:51:27 +07:00
c6957b46c6 add notification management with list and detail views, including modal handling and state management 2025-10-09 16:45:52 +07:00
a7af974108 add status management with list and detail views, including routing and mock data 2025-10-09 16:43:03 +07:00
dcdd8c9b8d refactor ListEventAlarm component by removing unused detail view handler and adjusting column widths 2025-10-09 14:50:26 +07:00
406b306275 refactor event alarm components to improve detail view and add action buttons 2025-10-09 14:48:36 +07:00
6807be41b6 update validation message for email/username field in SignIn component 2025-10-09 14:42:21 +07:00
7a9cf46e39 add event alarm management with list and detail views 2025-10-09 14:30:37 +07:00
0a2c23fa9c add route for plant section in App component 2025-10-09 10:59:52 +07:00
e13539618b add plant section management with list and detail views 2025-10-09 10:50:27 +07:00
8ef1bdb142 update data index username, fullname, user phone 2025-10-09 03:47:13 +07:00
930ee1708a Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2025-10-09 03:44:52 +07:00
2fddc7f098 add role management components with list and detail views 2025-10-09 10:26:13 +07:00
1613ee52d3 login identifier email dan username 2025-10-09 03:44:48 +07:00
148bca0e55 fix: update signin dan signup 2025-10-08 15:47:00 +07:00
7b78755ee1 delet background piu 2025-10-08 15:02:33 +07:00
678dd12a18 Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2025-10-08 14:45:52 +07:00
bc46328832 feat: implement user management API functions and create ListUser component for user listing 2025-10-08 14:45:41 +07:00
9806593319 update: enhance global card styling and sidebar menu appearance 2025-10-08 14:38:00 +07:00
dcedf9fe19 update background cod signin&up 2025-10-08 14:33:21 +07:00
2f678cef03 Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2025-10-07 14:46:19 +07:00
32d88df400 update: implement brand device management with listing, detail view, and search functionality 2025-10-07 12:37:40 +07:00
f21174e5d0 update: implement ListTag and DetailTag components for enhanced tag management functionality 2025-10-07 12:37:40 +07:00
676fb64554 update: adjust TableList component for improved data display and enhance ListDevice component styles 2025-10-07 12:37:40 +07:00
0beb46e318 Merge branch 'lavoce' of https://gitea.idetama.id/yogiedigital/cod-fe into lavoce 2025-10-07 12:07:31 +07:00
b2e1bca4ab update: implement brand device management with listing, detail view, and search functionality 2025-10-07 12:07:29 +07:00
317610e552 update: implement ListTag and DetailTag components for enhanced tag management functionality 2025-10-07 12:01:15 +07:00
0d97a1978e update: adjust TableList component for improved data display and enhance ListDevice component styles 2025-10-06 08:47:07 +07:00
d469992ee2 menambahkan halaman awal untuk setiap menu sidebar 2025-10-03 17:05:50 +07:00
e3b7792f9b update tambah route 2025-10-03 17:05:00 +07:00
600e6c8593 update: enhance LayoutMenu component with additional menu items and icons 2025-10-03 17:03:59 +07:00
fbf8231050 update: remove fixed horizontal scroll width in TableList component for improved responsiveness 2025-10-02 15:36:59 +07:00
50aa323b5f update: improve code formatting and error handling in SignIn component 2025-10-02 15:35:07 +07:00
3484683074 fix: refresh token cookies 2025-10-02 15:32:32 +07:00
1c0ac6930e update: adjust horizontal scroll width in TableList component for better data visibility 2025-10-02 14:05:09 +07:00
1687f3b952 update signup 2025-10-02 11:45:20 +07:00
992dcc47ea update: refactor action buttons in ListDevice component for improved functionality and layout 2025-10-02 10:40:48 +07:00
2d5a1b00ea update clear all localStorage data on logout 2025-10-01 15:15:58 +07:00
3f39923070 update: adjust column widths in ListDevice component for better layout 2025-10-01 15:14:17 +07:00
3b51f59679 update: enhance device API functions with pagination and response structure; modify device form validation and UI components 2025-10-01 14:33:55 +07:00
2778c96143 add: device API functions for CRUD device 2025-10-01 11:33:10 +07:00
fb5528616c update: api request 2025-10-01 11:03:11 +07:00
6a5b01bf0c add: auth context 2025-10-01 11:02:59 +07:00
d362c041ac add: credential true 2025-10-01 10:49:05 +07:00
ef67cdd91c update layout header 2025-10-01 10:27:58 +07:00
6b4b511d66 fix: error 2025-10-01 10:11:56 +07:00
9dabbd60ea fix: handle submit 2025-10-01 10:11:30 +07:00
ba0b145bda update: credentials true 2025-10-01 10:11:20 +07:00
b73abf2fa2 simplyfy code svg value mqtt 2025-09-29 16:38:00 +07:00
6de6d35a6b example dashboard svg mqtt 2025-09-29 16:23:20 +07:00
b9b5704232 update signup 2025-09-29 11:48:54 +07:00
42fff789e3 fix register request 2025-09-29 11:48:36 +07:00
c64b7b3490 update: route 2025-09-26 11:07:03 +07:00
7c2a019dd2 Merge pull request 'lavoce' (#1) from lavoce into main
Reviewed-on: #1
2025-09-17 08:39:35 +00:00
27b060845b Add api 2025-09-17 12:19:00 +07:00
85baae5e30 Add freepik 2025-09-17 12:18:51 +07:00
80a3a304e0 Add asset 2025-09-17 12:18:39 +07:00
8d6eb175e7 Add images 2025-09-17 12:17:50 +07:00
4a3ae20b84 Add component 2025-09-17 12:17:14 +07:00
b25aaf124c Add layout 2025-09-17 12:17:02 +07:00
291cbd5f94 Add pages 2025-09-17 12:16:50 +07:00
bc60728369 Add src 2025-09-17 12:16:35 +07:00
b51e4a8131 Add public skeleton 2025-09-17 12:15:29 +07:00
f8846d4bcb Repair skeleton 2025-09-17 12:14:25 +07:00
3e7fc17c46 Repair git ignore 2025-09-17 12:13:25 +07:00
178 changed files with 35618 additions and 1 deletions

6
.env.example Normal file
View File

@@ -0,0 +1,6 @@
VITE_API_SERVER=http://localhost:9530/api
# VITE_API_SERVER=https://117.102.231.130:9528/api
VITE_MQTT_SERVER=ws://localhost:1884
VITE_MQTT_USERNAME=
VITE_MQTT_PASSWORD=
VITE_KEY_SESSION=PetekRombonganPetekMorekMorakMarek

21
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,21 @@
// module.exports = {
// root: true,
// env: { browser: true, es2020: true },
// extends: [
// 'eslint:recommended',
// 'plugin:react/recommended',
// 'plugin:react/jsx-runtime',
// 'plugin:react-hooks/recommended',
// ],
// ignorePatterns: ['dist', '.eslintrc.cjs'],
// parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
// settings: { react: { version: '18.2' } },
// plugins: ['react-refresh'],
// rules: {
// 'react/jsx-no-target-blank': 'off',
// 'react-refresh/only-export-components': [
// 'warn',
// { allowConstantExport: true },
// ],
// },
// }

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

5
.gitignore vendored
View File

@@ -6,11 +6,14 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
pnpm-debug.log* pnpm-debug.log*
lerna-debug.log* lerna-debug.log*
*.config
node_modules node_modules
dist dist
dist-ssr dist-ssr
*.local *.local
.env
package-lock.json
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
@@ -21,4 +24,4 @@ dist-ssr
*.ntvs* *.ntvs*
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?

10
.prettierrc.json Normal file
View File

@@ -0,0 +1,10 @@
{
"printWidth": 100,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true
}

22
index.html Normal file
View File

@@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/freepik/logo-web.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="COD Maintenance Machine" />
<meta name="keywords" content="sypiu, piu, ggcp, permit, cod" />
<meta name="author" content="idetama" />
<meta property="og:title" content="COD system machine" />
<meta property="og:description" content="app for machine system piu" />
<meta property="og:image" content="https://www.pi-utilitas.com/img/LOGO_PIU_BnW.ee2ccd30.png" />
<meta property="og:url" content="https://www.pi-utilitas.com/" />
<title>Call of Duty</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

48
package.json Normal file
View File

@@ -0,0 +1,48 @@
{
"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"
}

BIN
public/assets/contohpdf.pdf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

1
public/vite.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

18
public/web.config Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="CallOfDuty">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

6
src/App.css Normal file
View File

@@ -0,0 +1,6 @@
/* Global Card Styling */
.ant-card {
border-radius: 12px !important;
box-shadow: 0 5px 10px 5px rgba(0, 0, 0, 0.07) !important;
margin-bottom: 24px !important;
}

161
src/App.jsx Normal file
View File

@@ -0,0 +1,161 @@
import React from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import SignIn from './pages/auth/SignIn';
import SignUp from './pages/auth/Signup';
import { ProtectedRoute } from './ProtectedRoute';
import NotFound from './pages/blank/NotFound';
// Dashboard
import Home from './pages/home/Home';
import Blank from './pages/blank/Blank';
// Master
import IndexPlantSubSection from './pages/master/plantSubSection/IndexPlantSubSection';
import IndexBrandDevice from './pages/master/brandDevice/IndexBrandDevice';
import IndexDevice from './pages/master/device/IndexDevice';
import IndexUnit from './pages/master/unit/IndexUnit';
import IndexTag from './pages/master/tag/IndexTag';
import IndexStatus from './pages/master/status/IndexStatus';
import IndexSparepart from './pages/master/sparepart/IndexSparepart';
import IndexShift from './pages/master/shift/IndexShift';
// Brand device
import AddBrandDevice from './pages/master/brandDevice/AddBrandDevice';
import EditBrandDevice from './pages/master/brandDevice/EditBrandDevice';
import ViewBrandDevice from './pages/master/brandDevice/ViewBrandDevice';
import ViewFilePage from './pages/master/brandDevice/ViewFilePage';
// Jadwal Shift
import IndexJadwalShift from './pages/jadwalShift/IndexJadwalShift';
// History
import IndexTrending from './pages/report/trending/IndexTrending';
import IndexReport from './pages/report/report/IndexReport';
// Other Pages
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 DetailNotificationTab from './pages/notificationDetail/IndexNotificationDetail';
import IndexVerificationSparepart from './pages/verificationSparepart/IndexVerificationSparepart';
import SvgTest from './pages/home/SvgTest';
import SvgOverviewCompressor from './pages/home/SvgOverviewCompressor';
import SvgCompressorA from './pages/home/SvgCompressorA';
import SvgCompressorB from './pages/home/SvgCompressorB';
import SvgCompressorC from './pages/home/SvgCompressorC';
import SvgOverviewAirDryer from './pages/home/SvgOverviewAirDryer';
import SvgAirDryerA from './pages/home/SvgAirDryerA';
import SvgAirDryerB from './pages/home/SvgAirDryerB';
import SvgAirDryerC from './pages/home/SvgAirDryerC';
import IndexHistoryAlarm from './pages/history/alarm/IndexHistoryAlarm';
import IndexHistoryEvent from './pages/history/event/IndexHistoryEvent';
// Image Viewer
import ImageViewer from './Utils/ImageViewer';
import RedirectWa from './pages/blank/RedirectWa';
const App = () => {
return (
<BrowserRouter>
<Routes>
{/* Public Routes */}
<Route path="/" element={<Navigate to="/signin" replace />} />
<Route path="/signin" element={<SignIn />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/svg" element={<SvgTest />} />
<Route
path="/notification-detail/:notificationId"
element={<DetailNotificationTab />}
/>
<Route
path="/verification-sparepart/:notificationId"
element={<IndexVerificationSparepart />}
/>
<Route path="/redirect" element={<RedirectWa />} />
{/* Protected Routes */}
<Route path="/dashboard" element={<ProtectedRoute />}>
<Route path="home" element={<Home />} />
<Route path="blank" element={<Blank />} />
</Route>
<Route path="/image-viewer/:fileName" element={<ImageViewer />} />
<Route path="/dashboard-svg" element={<ProtectedRoute />}>
<Route path="overview-compressor" element={<SvgOverviewCompressor />} />
<Route path="compressor-a" element={<SvgCompressorA />} />
<Route path="compressor-b" element={<SvgCompressorB />} />
<Route path="compressor-c" element={<SvgCompressorC />} />
<Route path="overview-airdryer" element={<SvgOverviewAirDryer />} />
<Route path="airdryer-a" element={<SvgAirDryerA />} />
<Route path="airdryer-b" element={<SvgAirDryerB />} />
<Route path="airdryer-c" element={<SvgAirDryerC />} />
</Route>
<Route path="/master" element={<ProtectedRoute />}>
<Route path="device" element={<IndexDevice />} />
<Route path="tag" element={<IndexTag />} />
<Route path="unit" element={<IndexUnit />} />
<Route path="sparepart" element={<IndexSparepart />} />
<Route path="plant-sub-section" element={<IndexPlantSubSection />} />
<Route path="shift" element={<IndexShift />} />
<Route path="status" element={<IndexStatus />} />
{/* Brand Device Routes */}
<Route path="brand-device" element={<IndexBrandDevice />} />
<Route path="brand-device/add" element={<AddBrandDevice />} />
<Route path="brand-device/edit/:id" element={<EditBrandDevice />} />
<Route path="brand-device/view/:id" element={<ViewBrandDevice />} />
<Route
path="brand-device/edit/:id/files/:fileType/:fileName"
element={<ViewFilePage />}
/>
<Route
path="brand-device/view/:id/files/:fileType/:fileName"
element={<ViewFilePage />}
/>
<Route
path="brand-device/view/temp/files/:fileName"
element={<ViewFilePage />}
/>
</Route>
<Route path="/report" element={<ProtectedRoute />}>
<Route path="trending" element={<IndexTrending />} />
<Route path="report" element={<IndexReport />} />
</Route>
<Route path="/history" element={<ProtectedRoute />}>
<Route path="alarm" element={<IndexHistoryAlarm />} />
<Route path="event" element={<IndexHistoryEvent />} />
</Route>
<Route path="/notification" element={<ProtectedRoute />}>
<Route index element={<IndexNotification />} />
</Route>
<Route path="/role" element={<ProtectedRoute />}>
<Route index element={<IndexRole />} />
</Route>
<Route path="/user" element={<ProtectedRoute />}>
<Route index element={<IndexUser />} />
</Route>
<Route path="/contact" element={<ProtectedRoute />}>
<Route index element={<IndexContact />} />
</Route>
<Route path="/jadwal-shift" element={<ProtectedRoute />}>
<Route index element={<IndexJadwalShift />} />
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
};
export default App;

25
src/ProtectedRoute.jsx Normal file
View File

@@ -0,0 +1,25 @@
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import MainLayout from './layout/MainLayout';
import { NotifAlert } from './components/Global/ToastNotif';
export const ProtectedRoute = () => {
// cek token di localStorage
const token = localStorage.getItem('token');
const isAuthenticated = !!token;
if (!isAuthenticated) {
NotifAlert({
icon: 'warning',
title: 'Session Habis',
message: 'Silahkan login terlebih dahulu',
});
return <Navigate to="/signin" replace />;
}
return (
<MainLayout>
<Outlet />
</MainLayout>
);
};

13
src/Utils/Auth/Logout.jsx Normal file
View File

@@ -0,0 +1,13 @@
const handleLogOut = (navigate) => {
// Hapus semua data localStorage
localStorage.clear();
// Redirect ke halaman signin
if (navigate) {
navigate('/signin', { replace: true });
} else {
window.location.replace('/signin');
}
};
export default handleLogOut;

28
src/Utils/Auth/SignIn.jsx Normal file
View File

@@ -0,0 +1,28 @@
import { login } from '../../api/auth';
import { encryptData } from '../../components/Global/Formatter';
import { NotifAlert } from '../../components/Global/ToastNotif';
const handleSignIn = async (values) => {
const response = await login(values);
// return false
if (response?.status == 200) {
let token = JSON.stringify(response.data?.token);
localStorage.setItem('token', token);
response.data.auth = true;
localStorage.setItem('session', encryptData(response?.data));
// langsung redirect ke dashboard utama
window.location.replace('/dashboard/home');
} else {
NotifAlert({
icon: 'error',
title: 'Gagal',
message: response?.data?.message || 'Terjadi kesalahan saat menyimpan data.',
});
}
};
export default handleSignIn;

248
src/Utils/ImageViewer.jsx Normal file
View File

@@ -0,0 +1,248 @@
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { getFileUrl, getFolderFromFileType } from '../api/file-uploads';
const ImageViewer = () => {
const { fileName } = useParams();
const [fileUrl, setFileUrl] = useState('');
const [error, setError] = useState('');
const [zoom, setZoom] = useState(1);
const [isImage, setIsImage] = useState(false);
useEffect(() => {
if (!fileName) {
setError('No file specified');
return;
}
try {
const decodedFileName = decodeURIComponent(fileName);
const fileExtension = decodedFileName.split('.').pop()?.toLowerCase();
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
setIsImage(imageExtensions.includes(fileExtension));
const folder = getFolderFromFileType(fileExtension);
const url = getFileUrl(folder, decodedFileName);
setFileUrl(url);
document.title = `File Viewer - ${decodedFileName}`;
} catch (error) {
setError('Failed to load file');
}
}, [fileName]);
useEffect(() => {
const handleKeyDown = (e) => {
if (!isImage) return;
if (e.key === '+' || e.key === '=') {
setZoom(prev => Math.min(prev + 0.1, 3));
} else if (e.key === '-' || e.key === '_') {
setZoom(prev => Math.max(prev - 0.1, 0.1));
} else if (e.key === '0') {
setZoom(1);
} else if (e.key === 'Escape') {
window.close();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [isImage]);
const handleWheel = (e) => {
if (!isImage || !e.ctrlKey) return;
e.preventDefault();
const delta = e.deltaY > 0 ? -0.1 : 0.1;
setZoom(prev => Math.min(Math.max(prev + delta, 0.1), 3));
};
const handleZoomIn = () => setZoom(prev => Math.min(prev + 0.1, 3));
const handleZoomOut = () => setZoom(prev => Math.max(prev - 0.1, 0.1));
const handleResetZoom = () => setZoom(1);
if (error) {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
fontFamily: 'Arial, sans-serif',
backgroundColor: '#f5f5f5'
}}>
<div style={{ textAlign: 'center' }}>
<h1>Error</h1>
<p>{error}</p>
</div>
</div>
);
}
if (!isImage) {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
fontFamily: 'Arial, sans-serif',
backgroundColor: '#f5f5f5'
}}>
<div style={{ textAlign: 'center' }}>
<h1>File Type Not Supported</h1>
<p>Image viewer only supports image files.</p>
<p>Please use direct file preview for PDFs and other documents.</p>
</div>
</div>
);
}
return (
<div
style={{
margin: 0,
padding: 0,
height: '100vh',
width: '100vw',
backgroundColor: '#000',
overflow: 'hidden',
position: 'relative'
}}
onWheel={handleWheel}
>
{isImage && (
<div style={{
position: 'fixed',
top: '20px',
right: '20px',
display: 'flex',
gap: '10px',
backgroundColor: 'rgba(0, 0, 0, 0.7)',
padding: '10px',
borderRadius: '8px',
zIndex: 1000
}}>
<button
onClick={handleZoomOut}
style={{
backgroundColor: 'rgba(255, 255, 255, 0.2)',
color: '#fff',
border: '1px solid rgba(255, 255, 255, 0.3)',
padding: '8px 12px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px'
}}
title="Zoom Out (-)"
>
</button>
<span style={{
color: '#fff',
padding: '8px 12px',
minWidth: '60px',
textAlign: 'center',
fontSize: '14px'
}}>
{Math.round(zoom * 100)}%
</span>
<button
onClick={handleZoomIn}
style={{
backgroundColor: 'rgba(255, 255, 255, 0.2)',
color: '#fff',
border: '1px solid rgba(255, 255, 255, 0.3)',
padding: '8px 12px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px'
}}
title="Zoom In (+)"
>
+
</button>
<button
onClick={handleResetZoom}
style={{
backgroundColor: 'rgba(255, 255, 255, 0.2)',
color: '#fff',
border: '1px solid rgba(255, 255, 255, 0.3)',
padding: '8px 12px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '14px'
}}
title="Reset Zoom (0)"
>
Reset
</button>
</div>
)}
{isImage && fileUrl ? (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
overflow: 'auto'
}}>
<img
src={fileUrl}
alt={decodeURIComponent(fileName)}
style={{
maxWidth: 'none',
maxHeight: 'none',
transform: `scale(${zoom})`,
transformOrigin: 'center',
transition: 'transform 0.1s ease-out',
cursor: zoom > 1 ? 'move' : 'default'
}}
onError={() => setError('Failed to load image')}
draggable={false}
/>
</div>
) : isImage ? (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
color: '#fff',
fontFamily: 'Arial, sans-serif'
}}>
<p>Loading image...</p>
</div>
) : null}
{isImage && (
<div style={{
position: 'fixed',
bottom: '20px',
left: '20px',
backgroundColor: 'rgba(0, 0, 0, 0.7)',
color: '#fff',
padding: '10px 15px',
borderRadius: '8px',
fontSize: '12px',
zIndex: 1000
}}>
<div>Mouse wheel + Ctrl: Zoom</div>
<div>Keyboard: +/ Zoom, 0: Reset, ESC: Close</div>
</div>
)}
</div>
);
};
export default ImageViewer;

71
src/Utils/validate.js Normal file
View File

@@ -0,0 +1,71 @@
// utils/validate.js
// Daftar aturan validasi
const validationRules = [
{ field: 'name', label: 'Nama', required: true },
{
field: 'email',
label: 'Email',
required: true,
pattern: /\S+@\S+\.\S+/,
patternMessage: 'Format email tidak valid',
},
{
field: 'age',
label: 'Umur',
required: true,
validator: (v) => !isNaN(v) && Number(v) >= 18,
message: 'Umur harus angka dan minimal 18 tahun',
},
];
/**
* Fungsi validasi dinamis berbasis array objek aturan.
* @param {Object} data - data form (misal { name: '', email: '' })
* @param {Array} rules - array aturan validasi
* @returns {Object} errors - object berisi pesan error per field
*/
export const validateRun = (data, rules, onError) => {
const errors = {};
const messages = [];
const ipRegex = /^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$/;
rules.forEach((rule) => {
const value = data[rule.field]?.toString().trim();
const fieldErrors = [];
if (rule.required && !value) {
fieldErrors.push(`${rule.label} wajib diisi`);
}
// ✅ IP Address check
if (rule.ip && value && !ipRegex.test(value)) {
fieldErrors.push(`${rule.label} harus berupa alamat IP yang valid`);
}
if (rule.pattern && value && !rule.pattern.test(value)) {
fieldErrors.push(rule.patternMessage || `${rule.label} tidak valid`);
}
if (rule.validator && value && !rule.validator(value)) {
fieldErrors.push(rule.message || `${rule.label} tidak valid`);
}
// Gabungkan error satu field jadi satu string (pisah baris)
if (fieldErrors.length > 0) {
errors[rule.field] = fieldErrors.join("\n");
messages.push(...fieldErrors);
}
});
// Jika ada error total, tampilkan callback dan return false
if (messages.length > 0) {
if (onError) onError(messages.join("\n"));
return true;
}
return false
};

42
src/api/auth.jsx Normal file
View File

@@ -0,0 +1,42 @@
import { SendRequest } from '../components/Global/ApiRequest';
import RegistrationRequest from '../components/Global/RegisterRequest';
const login = async (params) => {
const response = await SendRequest({
method: 'post',
prefix: `auth/login`,
params: params,
});
return response || [];
};
const register = async (params) => {
const response = await RegistrationRequest({
method: 'post',
prefix: 'auth/register',
params: params,
headers: { 'Content-Type': 'application/json' },
});
return response || {};
};
const verifyRedirect = async (params) => {
const response = await SendRequest({
method: 'post',
prefix: 'auth/verify-redirect',
params: params,
token: false,
});
return response || {};
};
const checkUsername = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `register/check-username?${queryParams.toString()}`,
});
return response || {};
};
export { login, register, verifyRedirect, checkUsername };

56
src/api/contact.jsx Normal file
View File

@@ -0,0 +1,56 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllContact = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `contact?${queryParams.toString()}`,
});
return response.data;
};
const getContactById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `contact/${id}`,
});
return response.data;
};
const createContact = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `contact`,
params: queryParams,
});
return response.data;
};
const updateContact = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `contact/${id}`,
params: queryParams,
});
return response.data;
};
const deleteContact = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `contact/${id}`,
});
return response.data;
};
export {
getAllContact,
getContactById,
createContact,
updateContact,
deleteContact,
};

135
src/api/file-uploads.jsx Normal file
View File

@@ -0,0 +1,135 @@
import { SendRequest } from '../components/Global/ApiRequest';
import axios from 'axios';
const API_BASE_URL = import.meta.env.VITE_API_SERVER;
// Get file from uploads directory
const getFile = async (folder, filename) => {
const token = localStorage.getItem('token');
if (!token) {
throw new Error('No authentication token found');
}
const response = await axios.get(`${API_BASE_URL}/file-uploads/${folder}/${encodeURIComponent(filename)}`, {
responseType: 'blob',
headers: {
'Authorization': `Bearer ${token.replace(/"/g, '')}`
}
});
return response.data;
};
// Download file as blob with proper handling
const downloadFile = async (folder, filename) => {
try {
const response = await getFile(folder, filename);
const blob = new Blob([response], {
type: 'application/octet-stream'
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
return { success: true, filename };
} catch (error) {
console.error('Error downloading file:', error);
throw error;
}
};
// Get file info (metadata)
const getFileInfo = async (folder, filename) => {
const response = await SendRequest({
method: 'head',
prefix: `file-uploads/${folder}/${encodeURIComponent(filename)}`
});
if (response.error) {
throw new Error(response.message);
}
return {
contentType: response.headers?.['content-type'],
contentLength: response.headers?.['content-length'],
lastModified: response.headers?.['last-modified'],
filename: filename,
folder: folder
};
};
// Get file URL for iframe
const getFileUrl = (folder, filename) => {
const token = localStorage.getItem('token');
if (token) {
return `${API_BASE_URL}/file-uploads/${folder}/${encodeURIComponent(filename)}?token=${encodeURIComponent(token)}`;
}
return `${API_BASE_URL}/file-uploads/${folder}/${encodeURIComponent(filename)}`;
};
// Check if file exists
const checkFileExists = async (folder, filename) => {
const response = await SendRequest({
method: 'head',
prefix: `file-uploads/${folder}/${encodeURIComponent(filename)}`
});
if (response.error && response.statusCode === 404) {
return false;
} else if (response.error) {
throw new Error(response.message);
}
return true;
};
const getFileType = (filename) => {
const ext = filename.split('.').pop().toLowerCase();
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
const pdfExtensions = ['pdf'];
if (imageExtensions.includes(ext)) {
return 'image';
} else if (pdfExtensions.includes(ext)) {
return 'pdf';
}
return 'unknown';
};
// Upload file to server
const uploadFile = async (file, folder) => {
const formData = new FormData();
formData.append('file', file);
formData.append('folder', folder);
const response = await SendRequest({
method: 'post',
prefix: 'file-uploads',
params: formData
});
return response.data;
};
const getFolderFromFileType = (fileType) => {
return fileType === 'pdf' ? 'pdf' : 'images';
};
export {
getFile,
downloadFile,
getFileInfo,
getFileUrl,
checkFileExists,
getFileType,
getFolderFromFileType,
uploadFile
};

54
src/api/history-value.jsx Normal file
View File

@@ -0,0 +1,54 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllHistoryAlarm = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `history/alarm?${queryParams.toString()}`,
});
return response.data;
};
const getAllHistoryEvent = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `history/event?${queryParams.toString()}`,
});
return response.data;
};
const getAllHistoryValueReport = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `history/value-report?${queryParams.toString()}`,
});
return response.data;
};
const getAllHistoryValueReportPivot = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `history/value-report-pivot?${queryParams.toString()}`,
});
return response.data;
};
const getAllHistoryValueTrendingPivot = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `history/value-trending?${queryParams.toString()}`,
});
return response.data;
};
export {
getAllHistoryAlarm,
getAllHistoryEvent,
getAllHistoryValueReport,
getAllHistoryValueReportPivot,
getAllHistoryValueTrendingPivot,
};

55
src/api/jadwal-shift.jsx Normal file
View File

@@ -0,0 +1,55 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllJadwalShift = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `user-schedule?${queryParams.toString()}`,
});
return response.data;
};
const getJadwalShiftById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `user-schedule/${id}`,
});
return response.data;
};
const createJadwalShift = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `user-schedule`,
params: queryParams,
});
return response.data;
};
const updateJadwalShift = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `user-schedule/${id}`,
params: queryParams,
});
return response.data;
};
const deleteJadwalShift = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `user-schedule/${id}`,
});
return response.data;
};
export {
getAllJadwalShift,
getJadwalShiftById,
createJadwalShift,
updateJadwalShift,
deleteJadwalShift,
};

109
src/api/master-brand.jsx Normal file
View File

@@ -0,0 +1,109 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllBrands = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `brand?${queryParams.toString()}`,
});
return response.data;
};
const getBrandById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `brand/${id}`,
});
return response.data;
};
const createBrand = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `brand`,
params: queryParams,
});
return response.data;
};
const updateBrand = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `brand/${id}`,
params: queryParams,
});
return response.data;
};
const deleteBrand = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `brand/${id}`,
});
return response.data;
};
const getErrorCodesByBrandId = async (brandId, queryParams) => {
const query = queryParams ? `?${queryParams.toString()}` : '';
const response = await SendRequest({
method: 'get',
prefix: `error-code/brand/${brandId}${query}`,
});
return response.data;
};
const getErrorCodeById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `error-code/${id}`,
});
return response.data;
};
const createErrorCode = async (brandId, queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `error-code/brand/${brandId}`,
params: queryParams,
});
return response.data;
};
const updateErrorCode = async (brandId, errorCodeId, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `error-code/brand/${brandId}/${errorCodeId}`,
params: queryParams,
});
return response.data;
};
const deleteErrorCode = async (brandId, errorCode) => {
const response = await SendRequest({
method: 'delete',
prefix: `error-code/brand/${brandId}/${errorCode}`,
});
return response.data;
};
export {
getAllBrands,
getBrandById,
createBrand,
updateBrand,
deleteBrand,
getErrorCodesByBrandId,
getErrorCodeById,
createErrorCode,
updateErrorCode,
deleteErrorCode
};

50
src/api/master-device.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllDevice = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `device?${queryParams.toString()}`,
});
return response.data;
};
const getDeviceById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `device/${id}`,
});
return response.data;
};
const createDevice = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `device`,
params: queryParams,
});
return response.data;
};
const updateDevice = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `device/${id}`,
params: queryParams,
});
return response.data;
};
const deleteDevice = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `device/${id}`,
});
return response.data;
};
export { getAllDevice, getDeviceById, createDevice, updateDevice, deleteDevice };

View File

@@ -0,0 +1,56 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllPlantSection = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `plant-sub-section?${queryParams.toString()}`,
});
return response.data;
};
const getPlantSectionById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `plant-sub-section/${id}`,
});
return response.data;
};
const createPlantSection = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `plant-sub-section`,
params: queryParams,
});
return response.data;
};
const updatePlantSection = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `plant-sub-section/${id}`,
params: queryParams,
});
return response.data;
};
const deletePlantSection = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `plant-sub-section/${id}`,
});
return response.data;
};
export {
getAllPlantSection,
getPlantSectionById,
createPlantSection,
updatePlantSection,
deletePlantSection,
};

50
src/api/master-shift.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllShift = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `shift?${queryParams.toString()}`,
});
return response.data;
};
const getShiftById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `shift/${id}`,
});
return response.data;
};
const createShift = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `shift`,
params: queryParams,
});
return response.data;
};
const updateShift = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `shift/${id}`,
params: queryParams,
});
return response.data;
};
const deleteShift = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `shift/${id}`,
});
return response.data;
};
export { getAllShift, getShiftById, createShift, updateShift, deleteShift };

50
src/api/master-status.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllStatuss = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `status?${queryParams.toString()}`,
});
return response.data;
};
const getStatusById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `status/${id}`,
});
return response.data;
};
const createStatus = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `status`,
params: queryParams,
});
return response.data;
};
const updateStatus = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `status/${id}`,
params: queryParams,
});
return response.data;
};
const deleteStatus = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `status/${id}`,
});
return response.data;
};
export { getAllStatuss, getStatusById, createStatus, updateStatus, deleteStatus };

50
src/api/master-tag.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllTag = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `tags?${queryParams.toString()}`,
});
return response.data;
};
const getTagById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `tags/${id}`,
});
return response.data;
};
const createTag = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `tags`,
params: queryParams,
});
return response.data;
};
const updateTag = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `tags/${id}`,
params: queryParams,
});
return response.data;
};
const deleteTag = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `tags/${id}`,
});
return response.data;
};
export { getAllTag, getTagById, createTag, updateTag, deleteTag };

50
src/api/master-unit.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllUnit = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `unit?${queryParams.toString()}`,
});
return response.data;
};
const getUnitById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `unit/${id}`,
});
return response.data;
};
const createUnit = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `unit`,
params: queryParams,
});
return response.data;
};
const updateUnit = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `unit/${id}`,
params: queryParams,
});
return response.data;
};
const deleteUnit = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `unit/${id}`,
});
return response.data;
};
export { getAllUnit, getUnitById, createUnit, updateUnit, deleteUnit };

95
src/api/notification.jsx Normal file
View File

@@ -0,0 +1,95 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllNotification = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `notification?${queryParams.toString()}`,
});
return response.data;
};
const getNotificationById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `notification/${id}`,
});
return response.data;
};
const getNotificationDetail = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `notification/${id}`,
});
return response.data;
};
// Create new notification log
const createNotificationLog = async (data) => {
const response = await SendRequest({
method: 'post',
prefix: 'notification-log',
params: data,
});
return response.data;
};
// Get notification logs by notification_error_id
const getNotificationLogByNotificationId = async (notificationId) => {
const response = await SendRequest({
method: 'get',
prefix: `notification-log/notification_error/${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;
};
export {
getAllNotification,
getNotificationById,
getNotificationDetail,
createNotificationLog,
getNotificationLogByNotificationId,
updateIsRead,
resendNotificationToUser,
resendChatByUser,
resendChatAllUser,
};

50
src/api/role.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllRole = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `roles?${queryParams.toString()}`,
});
return response.data;
};
const getRoleById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `roles/${id}`,
});
return response.data;
};
const createRole = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `roles`,
params: queryParams,
});
return response.data;
};
const updateRole = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `roles/${id}`,
params: queryParams,
});
return response.data;
};
const deleteRole = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `roles/${id}`,
});
return response.data;
};
export { getAllRole, getRoleById, createRole, updateRole, deleteRole };

50
src/api/sparepart.jsx Normal file
View File

@@ -0,0 +1,50 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllSparepart = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `sparepart?${queryParams.toString()}`,
});
return response.data;
};
const getSparepartById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `sparepart/${id}`,
});
return response.data;
};
const createSparepart = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `sparepart`,
params: queryParams,
});
return response.data;
};
const updateSparepart = async (id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `sparepart/${id}`,
params: queryParams,
});
return response.data;
};
const deleteSparepart = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `sparepart/${id}`,
});
return response.data;
};
export { getAllSparepart, getSparepartById, createSparepart, updateSparepart, deleteSparepart };

45
src/api/user-admin.jsx Normal file
View File

@@ -0,0 +1,45 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllUser = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `admin-user?${queryParams.toString()}`,
});
return response.data;
};
const getUserDetail = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `admin-user/${id}`,
});
return response.data;
};
const updateUser = async (id, data) => {
const response = await SendRequest({
method: 'put',
prefix: `admin-user/${id}`,
params: data,
});
return response.data;
};
const deleteUser = async (id) => {
const response = await SendRequest({
method: 'delete',
prefix: `admin-user/${id}`,
});
return response.data;
};
const approvalUser = async (id, queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `admin-user/approve/${id}`,
params: queryParams,
});
return response.data;
};
export { getAllUser, getUserDetail, updateUser, deleteUser, approvalUser };

102
src/api/user.jsx Normal file
View File

@@ -0,0 +1,102 @@
import { SendRequest } from '../components/Global/ApiRequest';
const getAllUser = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `user?${queryParams.toString()}`,
});
return response.data;
};
const getUserById = async (id) => {
const response = await SendRequest({
method: 'get',
prefix: `user/${id}`,
});
return response.data;
};
const createUser = async (queryParams) => {
const response = await SendRequest({
method: 'post',
prefix: `user`,
params: queryParams,
});
return response.data;
};
const updateUser = async (user_id, queryParams) => {
const response = await SendRequest({
method: 'put',
prefix: `user/${user_id}`,
params: queryParams,
});
return response.data;
};
const deleteUser = async (queryParams) => {
const response = await SendRequest({
method: 'delete',
prefix: `user/${queryParams}`,
});
return response.data;
};
const approveUser = async (user_id) => {
const response = await SendRequest({
method: 'put',
prefix: `user/${user_id}/approve`,
});
return response.data;
};
const rejectUser = async (user_id) => {
const response = await SendRequest({
method: 'put',
prefix: `user/${user_id}/reject`,
});
return response.data;
};
const toggleActiveUser = async (user_id, is_active) => {
const response = await SendRequest({
method: 'put',
prefix: `user/${user_id}`,
params: {
is_active: is_active,
},
});
return response.data;
};
const changePassword = async (user_id, new_password) => {
const response = await SendRequest({
method: 'put',
prefix: `user/change-password/${user_id}`,
params: {
new_password: new_password,
},
});
return response.data;
};
export {
getAllUser,
getUserById,
createUser,
updateUser,
deleteUser,
approveUser,
rejectUser,
toggleActiveUser,
changePassword,
};

BIN
src/assets/bg-cod-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
src/assets/bg_cod.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

BIN
src/assets/freepik/404.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

1
src/assets/react.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1,261 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500" xmlns:bx="https://boxy-svg.com">
<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"/>
<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"/>
<rect x="270" y="180" width="90" height="270" style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);"/>
</g>
<g transform="matrix(0.826913, 0, 0, 0.698383, 500.726135, 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"/>
<rect x="270" y="180" width="90" height="270" style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);"/>
</g>
<rect x="371.728" y="182.483" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-box: fill-box; transform-origin: 50% 50%;" d="M 551.111 -16.154 L 551.202 389.079" transform="matrix(0, -1.184039, 0.844567, 0, 0.000036, 0.000096)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 479.043 149.568 L 495.765 149.568 L 495.765 166.035 L 479.043 166.035 L 479.043 149.568 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 598.485px 226.003px;" d="M 478.737 156.666 L 495.763 156.666"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 465.169 193.204 L 511.13 179.759 L 511.13 193.204 L 465.169 179.759 L 465.169 193.204 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 487.934 186.514 L 487.934 157.095"/>
<rect x="715.724" y="182.138" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<g transform="matrix(0.826913, 0, 0, 0.698383, -2.11712, 3.138935)">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 660.838px 251.447px;" d="M 660.846 262.894 L 660.846 240"/>
<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>
<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="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="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; 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"/>
<rect x="371.639" y="358.212" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 692.133px 361.256px;" d="M 692.126 397.022 L 692.14 325.49" transform="matrix(0, -1.184039, 0.844567, 0, 0.000011, 0.00005)"/>
<rect x="715.635" y="357.867" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 798px 493.641px;" d="M 661.975 334.874 L 661.975 360.911"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 552.59px 334.782px;" d="M 552.508 244.429 L 552.665 425.136" transform="matrix(0, 1.184039, -0.844567, 0, -0.000058, 0.000018)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 601.786px 283.137px;" d="M 601.741 312.51 L 601.832 253.764" transform="matrix(0, 1.184039, -0.844567, 0, -0.000063, 0.000028)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 577.266px 308.682px;" d="M 577.237 334.87 L 577.295 282.492" transform="matrix(-1, 0, 0, -1, -0.000041, -0.00003)"/>
<g transform="matrix(-0.491177, 0, 0, 0.523644, 491.13504, 29.785091)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 406.945px 361.188px;" d="M 406.92 329.322 L 406.969 393.054" transform="matrix(0, 1.184039, -0.844567, 0, 0.00001, 0.00007)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 521.472px 494.156px;" d="M 433.307 334.116 L 433.308 362.382"/>
<g transform="matrix(0.491177, 0, 0, 0.523644, 419.010895, 56.68491)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<g transform="matrix(0.491177, 0, 0, 0.523644, 603.674133, 29.692444)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<g transform="matrix(-0.491177, 0, 0, 0.523644, 677.00824, 56.209183)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 548.454px 361.62px;" d="M 548.372 271.267 L 548.529 451.974" transform="matrix(0, 1.184039, -0.844567, 0, 0.00006, -0.000036)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 578.392px 383.459px;" d="M 578.329 405.407 L 578.456 361.51" transform="matrix(-1, 0, 0, -1, -0.000055, -0.000003)"/>
<g transform="matrix(0.826913, 0, 0, -0.698383, 0.257882, 545.083069)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 660.838px 251.447px;" d="M 660.846 262.894 L 660.846 240"/>
<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(76, 76, 76); stroke-width: 1.525; transform-origin: 704.638px 576.106px;" d="M 621.828 405.49 L 634.485 405.49"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 584.749px 405.496px;" d="M 591.042 405.497 L 578.456 405.498"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 606.436px 405.492px;" d="M 591.042 398.364 L 591.042 412.623 L 621.831 398.364 L 621.831 412.623 L 591.042 398.364 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 599.432px 413.831px;" d="M 592.464 422.169 L 592.464 405.493 L 606.401 405.493" transform="matrix(-1, 0, 0, -1, -0.000078, -0.000049)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 648.376px 405.65px;" d="M 648.369 435.621 L 648.383 375.678" transform="matrix(0, -1.184039, 0.844567, 0, 0.000012, -0.00004)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 673.882px 406.067px;" d="M 673.869 398.172 L 673.893 413.963" transform="matrix(-1, 0, 0, -1, -0.000092, -0.000022)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 692.821px 404.67px;" d="M 692.786 392.381 L 692.854 416.962" transform="matrix(0, 1.184039, -0.844567, 0, 0.000001, -0.000097)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 703.406px 383.726px;" d="M 703.396 405.334 L 703.415 362.116"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 681.807px 406.051px;" d="M 681.793 398.157 L 681.818 413.948" transform="matrix(-1, 0, 0, -1, 0.000055, 0.000046)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 677.987px 397.326px;" d="M 677.977 403.041 L 677.995 391.61"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 677.933px 411.78px;" d="M 677.924 417.977 L 677.941 405.582"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="650.811" cy="385.504" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%; stroke-width: 0.763;" transform="matrix(0.000343, -1, 1, 0.000266, 743.834961, 473.853179)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 651.034px 399.693px;" d="M 651.025 405.408 L 651.042 393.977"/>
<path d="M -546.834 -405.87 L -543.785 -398.138 L -550.56 -398.138 L -546.834 -405.87 Z" bx:shape="triangle -550.56 -405.87 6.775 7.732 0.55 0 1@11f2e68a" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%; stroke-width: 0.763;" transform="matrix(-1, 0, 0, -1, 1094.344971, 804.007996)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 546.953px 390.056px;" d="M 546.94 382.161 L 546.965 397.952" transform="matrix(-1, 0, 0, -1, -0.000013, 0.000046)"/>
<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="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="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;">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 53.913 425 L 53.913 400 L 90.568 425 L 90.568 400"/>
</g>
<g style="transform-origin: 227.882px 539.536px;" transform="matrix(0, 0.626201, -0.563979, 0, 588.703491, -326.882202)">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 550 L 243.484 529.073 L 243.484 550 L 212.224 529.073 L 212.224 550 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 539.499 L 200 539.499"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 243.484 539.499 L 255.764 539.499"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 807.67px 264.838px;" d="M 807.657 276.289 L 807.693 253.387" transform="matrix(0, -1.184039, 0.844567, 0, 0.000035, 0.000091)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 816.592px 247.829px;" d="M 816.56 230.114 L 816.655 265.543" transform="matrix(-1, 0, 0, -1, 0.000101, 0.000009)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="840.215" cy="233.608" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 933.237163, 321.956912)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="839.876" cy="254.847" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 932.895305, 343.197025)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 823.288px 234.151px;" d="M 823.282 242.163 L 823.294 226.137" transform="matrix(0, 1.184039, -0.844567, 0, -0.000084, 0.000084)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 822.751px 254.694px;" d="M 822.745 262.706 L 822.763 246.68" transform="matrix(0, 1.184039, -0.844567, 0, -0.00002, 0.000032)"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 909.661358, 277.142276)"/>
<g transform="matrix(0.387768, 0, 0, -0.200385, 207.60318, -199.315506)" style="transform-origin: 72.2406px 412.5px;">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 53.913 425 L 53.913 400 L 90.568 425 L 90.568 400"/>
</g>
<g style="transform-origin: 227.882px 539.536px;" transform="matrix(0, 0.626201, 0.563979, 0, 51.251434, -326.206329)">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 550 L 243.484 529.073 L 243.484 550 L 212.224 529.073 L 212.224 550 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 539.499 L 200 539.499"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 243.484 539.499 L 255.764 539.499"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 288.049px 265.514px;" d="M 288.037 254.064 L 288.073 276.966" transform="matrix(0, -1.184039, 0.844567, 0, -0.000019, 0.000042)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 279.127px 248.505px;" d="M 279.095 266.219 L 279.19 230.79"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="-255.5" cy="234.284" rx="10.336" ry="8.73" transform="matrix(-1, 0, 0, 1, 0, 0)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 147.108874, 140.490195)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="-255.84" cy="255.523" rx="10.336" ry="8.73" transform="matrix(-1, 0, 0, 1, 0, 0)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 147.450457, 161.730307)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 272.43px 234.827px;" d="M 272.424 226.815 L 272.436 242.841" transform="matrix(0, 1.184039, -0.844567, 0, 0.000012, -0.000015)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 272.968px 255.37px;" d="M 272.962 247.358 L 272.98 263.384" transform="matrix(0, 1.184039, -0.844567, 0, -0.000011, 0.000034)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 170.68468, 95.675559)"/>
<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, 47.595016, -269.416931)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>INLET</text>
<path d="M -544.544 -165.9 L -541.495 -158.168 L -548.27 -158.168 L -544.544 -165.9 Z" bx:shape="triangle -548.27 -165.9 6.775 7.732 0.55 0 1@12a1c9af" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -544.876px -162.033px;" transform="matrix(-1, 0, 0, -1, 1089.751221, 324.066467)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 544.653px 150.086px;" d="M 544.639 142.192 L 544.664 157.983" transform="matrix(-1, 0, 0, -1, -0.000086, 0.000018)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 404.306 125.878 L 416.234 125.878 L 416.234 148.965 L 404.306 148.965 L 404.306 125.878 Z" transform="matrix(0, -1.184039, 0.844567, 0, -0.000039, -0.000007)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 498.152px 180.679px;" d="M 408.92 144.738 L 408.92 130.357"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 427.836 146.217 L 460.619 127.367 L 460.619 146.217 L 427.836 127.367 L 427.836 146.217 Z" transform="matrix(0, -1.184039, 0.844567, 0, 0.000009, 0.000009)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 426.851 157.594 L 426.851 116.351" transform="matrix(0, -1.18404, 0.844567, 0, -0.000439, -0.000081)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 647.335px 171.745px;" d="M 647.177 186.902 L 647.494 156.588" transform="matrix(-1, 0, 0, -1, -0.000021, -0.000027)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 680.766px 138.025px;" d="M 674.802 149.569 L 686.73 149.569 L 686.73 126.482 L 674.802 126.482 L 674.802 149.569 Z" transform="matrix(0, -1.184039, 0.844567, 0, 0.000004, 0.000043)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 897.148px 118.148px;" d="M 682.129 145.344 L 682.129 130.964"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 646.809px 137.396px;" d="M 630.417 127.971 L 663.201 146.821 L 663.201 127.971 L 630.417 146.821 L 630.417 127.971 Z" transform="matrix(0, -1.184039, 0.844567, 0, -0.000004, -0.000033)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 664.185px 137.577px;" d="M 664.185 116.956 L 664.186 158.199" transform="matrix(0, -1.184039, 0.844567, 0, -0.000026, -0.000041)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 590.855 148.509 L 607.577 148.509 L 607.577 164.977 L 590.855 164.977 L 590.855 148.509 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 733.701px 224.488px;" d="M 590.555 155.608 L 607.58 155.608"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 576.981 192.146 L 622.941 178.701 L 622.941 192.146 L 576.981 178.701 L 576.981 192.146 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 599.746 185.455 L 599.746 156.037"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 640.474 90.952 L 652.913 90.952 L 652.913 107.419 L 640.474 107.419 L 640.474 90.952 Z"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 646.819px 113.115px;" d="M 646.799 107.896 L 646.839 118.334"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 650.466px 95.308px;" d="M 650.455 97.624 L 650.476 92.992" transform="matrix(0, -1.184039, 0.844567, 0, 0.000035, 0.00002)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 642.857px 102.712px;" d="M 642.846 105.028 L 642.867 100.396" transform="matrix(0, -1.184039, 0.844567, 0, 0.000009, 0.000035)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 437.929 90.244 L 450.367 90.244 L 450.367 106.712 L 437.929 106.712 L 437.929 90.244 Z"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 444.274px 112.408px;" d="M 444.253 107.189 L 444.293 117.627"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 447.919px 94.601px;" d="M 447.909 96.917 L 447.93 92.285" transform="matrix(0, -1.184039, 0.844567, 0, -0.000022, 0.000005)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 440.31px 102.004px;" d="M 440.3 104.321 L 440.32 99.689" transform="matrix(0, -1.184039, 0.844567, 0, -0.000028, -0.000004)"/>
<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="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="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="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)">####.##</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, 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, 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="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="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>
<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);"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="192.401" rx="20.673" ry="17.46"/>
<rect x="870.356" y="230.113" 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="1069.06" y="349.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Shutdown</text>
<rect x="870.356" y="257.602" 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="279.699" rx="20.673" ry="17.46"/>
<rect x="870.356" y="317.411" 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="1059.06" y="474.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Status</text>
<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="336.418" cy="237.483" 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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517"/>
<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" id="c_4021"/>
<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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" 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: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 1.386371, 4.000207)">HTLS</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, -1.613663, 3.937793)">BLWR</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="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="c_4018"/>
<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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.685" cy="322.259" 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.031" cy="234.094" rx="13.582" ry="12.517" id="c_4021"/>
</svg>

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -0,0 +1,250 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500" xmlns:bx="https://boxy-svg.com">
<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"/>
<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"/>
<rect x="270" y="180" width="90" height="270" style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);"/>
</g>
<g transform="matrix(0.826913, 0, 0, 0.698383, 500.726135, 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"/>
<rect x="270" y="180" width="90" height="270" style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);"/>
</g>
<rect x="371.728" y="182.483" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-box: fill-box; transform-origin: 50% 50%;" d="M 551.111 -16.154 L 551.202 389.079" transform="matrix(0, -1.184039, 0.844567, 0, 0.000036, 0.000096)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 479.043 149.568 L 495.765 149.568 L 495.765 166.035 L 479.043 166.035 L 479.043 149.568 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 598.485px 226.003px;" d="M 478.737 156.666 L 495.763 156.666"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 465.169 193.204 L 511.13 179.759 L 511.13 193.204 L 465.169 179.759 L 465.169 193.204 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 487.934 186.514 L 487.934 157.095"/>
<rect x="715.724" y="182.138" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<g transform="matrix(0.826913, 0, 0, 0.698383, -2.11712, 3.138935)">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 660.838px 251.447px;" d="M 660.846 262.894 L 660.846 240"/>
<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>
<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="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="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; 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"/>
<rect x="371.639" y="358.212" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 692.133px 361.256px;" d="M 692.126 397.022 L 692.14 325.49" transform="matrix(0, -1.184039, 0.844567, 0, 0.000011, 0.00005)"/>
<rect x="715.635" y="357.867" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 798px 493.641px;" d="M 661.975 334.874 L 661.975 360.911"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 552.59px 334.782px;" d="M 552.508 244.429 L 552.665 425.136" transform="matrix(0, 1.184039, -0.844567, 0, -0.000058, 0.000018)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 601.786px 283.137px;" d="M 601.741 312.51 L 601.832 253.764" transform="matrix(0, 1.184039, -0.844567, 0, -0.000063, 0.000028)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 577.266px 308.682px;" d="M 577.237 334.87 L 577.295 282.492" transform="matrix(-1, 0, 0, -1, -0.000041, -0.00003)"/>
<g transform="matrix(-0.491177, 0, 0, 0.523644, 491.13504, 29.785091)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 406.945px 361.188px;" d="M 406.92 329.322 L 406.969 393.054" transform="matrix(0, 1.184039, -0.844567, 0, 0.00001, 0.00007)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 521.472px 494.156px;" d="M 433.307 334.116 L 433.308 362.382"/>
<g transform="matrix(0.491177, 0, 0, 0.523644, 419.010895, 56.68491)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<g transform="matrix(0.491177, 0, 0, 0.523644, 603.674133, 29.692444)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<g transform="matrix(-0.491177, 0, 0, 0.523644, 677.00824, 56.209183)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 548.454px 361.62px;" d="M 548.372 271.267 L 548.529 451.974" transform="matrix(0, 1.184039, -0.844567, 0, 0.00006, -0.000036)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 578.392px 383.459px;" d="M 578.329 405.407 L 578.456 361.51" transform="matrix(-1, 0, 0, -1, -0.000055, -0.000003)"/>
<g transform="matrix(0.826913, 0, 0, -0.698383, 0.257882, 545.083069)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 660.838px 251.447px;" d="M 660.846 262.894 L 660.846 240"/>
<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(76, 76, 76); stroke-width: 1.525; transform-origin: 704.638px 576.106px;" d="M 621.828 405.49 L 634.485 405.49"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 584.749px 405.496px;" d="M 591.042 405.497 L 578.456 405.498"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 606.436px 405.492px;" d="M 591.042 398.364 L 591.042 412.623 L 621.831 398.364 L 621.831 412.623 L 591.042 398.364 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 599.432px 413.831px;" d="M 592.464 422.169 L 592.464 405.493 L 606.401 405.493" transform="matrix(-1, 0, 0, -1, -0.000078, -0.000049)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 648.376px 405.65px;" d="M 648.369 435.621 L 648.383 375.678" transform="matrix(0, -1.184039, 0.844567, 0, 0.000012, -0.00004)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 673.882px 406.067px;" d="M 673.869 398.172 L 673.893 413.963" transform="matrix(-1, 0, 0, -1, -0.000092, -0.000022)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 692.821px 404.67px;" d="M 692.786 392.381 L 692.854 416.962" transform="matrix(0, 1.184039, -0.844567, 0, 0.000001, -0.000097)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 703.406px 383.726px;" d="M 703.396 405.334 L 703.415 362.116"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 681.807px 406.051px;" d="M 681.793 398.157 L 681.818 413.948" transform="matrix(-1, 0, 0, -1, 0.000055, 0.000046)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 677.987px 397.326px;" d="M 677.977 403.041 L 677.995 391.61"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 677.933px 411.78px;" d="M 677.924 417.977 L 677.941 405.582"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="650.811" cy="385.504" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%; stroke-width: 0.763;" transform="matrix(0.000343, -1, 1, 0.000266, 743.834961, 473.853179)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 651.034px 399.693px;" d="M 651.025 405.408 L 651.042 393.977"/>
<path d="M -546.834 -405.87 L -543.785 -398.138 L -550.56 -398.138 L -546.834 -405.87 Z" bx:shape="triangle -550.56 -405.87 6.775 7.732 0.55 0 1@11f2e68a" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%; stroke-width: 0.763;" transform="matrix(-1, 0, 0, -1, 1094.344971, 804.007996)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 546.953px 390.056px;" d="M 546.94 382.161 L 546.965 397.952" transform="matrix(-1, 0, 0, -1, -0.000013, 0.000046)"/>
<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="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="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;">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 53.913 425 L 53.913 400 L 90.568 425 L 90.568 400"/>
</g>
<g style="transform-origin: 227.882px 539.536px;" transform="matrix(0, 0.626201, -0.563979, 0, 588.703491, -326.882202)">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 550 L 243.484 529.073 L 243.484 550 L 212.224 529.073 L 212.224 550 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 539.499 L 200 539.499"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 243.484 539.499 L 255.764 539.499"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 807.67px 264.838px;" d="M 807.657 276.289 L 807.693 253.387" transform="matrix(0, -1.184039, 0.844567, 0, 0.000035, 0.000091)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 816.592px 247.829px;" d="M 816.56 230.114 L 816.655 265.543" transform="matrix(-1, 0, 0, -1, 0.000101, 0.000009)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="840.215" cy="233.608" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 933.237163, 321.956912)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="839.876" cy="254.847" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 932.895305, 343.197025)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 823.288px 234.151px;" d="M 823.282 242.163 L 823.294 226.137" transform="matrix(0, 1.184039, -0.844567, 0, -0.000084, 0.000084)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 822.751px 254.694px;" d="M 822.745 262.706 L 822.763 246.68" transform="matrix(0, 1.184039, -0.844567, 0, -0.00002, 0.000032)"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 909.661358, 277.142276)"/>
<g transform="matrix(0.387768, 0, 0, -0.200385, 207.60318, -199.315506)" style="transform-origin: 72.2406px 412.5px;">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 53.913 425 L 53.913 400 L 90.568 425 L 90.568 400"/>
</g>
<g style="transform-origin: 227.882px 539.536px;" transform="matrix(0, 0.626201, 0.563979, 0, 51.251434, -326.206329)">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 550 L 243.484 529.073 L 243.484 550 L 212.224 529.073 L 212.224 550 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 539.499 L 200 539.499"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 243.484 539.499 L 255.764 539.499"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 288.049px 265.514px;" d="M 288.037 254.064 L 288.073 276.966" transform="matrix(0, -1.184039, 0.844567, 0, -0.000019, 0.000042)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 279.127px 248.505px;" d="M 279.095 266.219 L 279.19 230.79"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="-255.5" cy="234.284" rx="10.336" ry="8.73" transform="matrix(-1, 0, 0, 1, 0, 0)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 147.108874, 140.490195)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="-255.84" cy="255.523" rx="10.336" ry="8.73" transform="matrix(-1, 0, 0, 1, 0, 0)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 147.450457, 161.730307)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 272.43px 234.827px;" d="M 272.424 226.815 L 272.436 242.841" transform="matrix(0, 1.184039, -0.844567, 0, 0.000012, -0.000015)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 272.968px 255.37px;" d="M 272.962 247.358 L 272.98 263.384" transform="matrix(0, 1.184039, -0.844567, 0, -0.000011, 0.000034)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 170.68468, 95.675559)"/>
<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, 47.595016, -269.416931)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>INLET</text>
<path d="M -544.544 -165.9 L -541.495 -158.168 L -548.27 -158.168 L -544.544 -165.9 Z" bx:shape="triangle -548.27 -165.9 6.775 7.732 0.55 0 1@12a1c9af" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -544.876px -162.033px;" transform="matrix(-1, 0, 0, -1, 1089.751221, 324.066467)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 544.653px 150.086px;" d="M 544.639 142.192 L 544.664 157.983" transform="matrix(-1, 0, 0, -1, -0.000086, 0.000018)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 404.306 125.878 L 416.234 125.878 L 416.234 148.965 L 404.306 148.965 L 404.306 125.878 Z" transform="matrix(0, -1.184039, 0.844567, 0, -0.000039, -0.000007)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 498.152px 180.679px;" d="M 408.92 144.738 L 408.92 130.357"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 427.836 146.217 L 460.619 127.367 L 460.619 146.217 L 427.836 127.367 L 427.836 146.217 Z" transform="matrix(0, -1.184039, 0.844567, 0, 0.000009, 0.000009)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 426.851 157.594 L 426.851 116.351" transform="matrix(0, -1.18404, 0.844567, 0, -0.000439, -0.000081)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 647.335px 171.745px;" d="M 647.177 186.902 L 647.494 156.588" transform="matrix(-1, 0, 0, -1, -0.000021, -0.000027)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 680.766px 138.025px;" d="M 674.802 149.569 L 686.73 149.569 L 686.73 126.482 L 674.802 126.482 L 674.802 149.569 Z" transform="matrix(0, -1.184039, 0.844567, 0, 0.000004, 0.000043)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 897.148px 118.148px;" d="M 682.129 145.344 L 682.129 130.964"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 646.809px 137.396px;" d="M 630.417 127.971 L 663.201 146.821 L 663.201 127.971 L 630.417 146.821 L 630.417 127.971 Z" transform="matrix(0, -1.184039, 0.844567, 0, -0.000004, -0.000033)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 664.185px 137.577px;" d="M 664.185 116.956 L 664.186 158.199" transform="matrix(0, -1.184039, 0.844567, 0, -0.000026, -0.000041)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 590.855 148.509 L 607.577 148.509 L 607.577 164.977 L 590.855 164.977 L 590.855 148.509 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 733.701px 224.488px;" d="M 590.555 155.608 L 607.58 155.608"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 576.981 192.146 L 622.941 178.701 L 622.941 192.146 L 576.981 178.701 L 576.981 192.146 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 599.746 185.455 L 599.746 156.037"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 640.474 90.952 L 652.913 90.952 L 652.913 107.419 L 640.474 107.419 L 640.474 90.952 Z"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 646.819px 113.115px;" d="M 646.799 107.896 L 646.839 118.334"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 650.466px 95.308px;" d="M 650.455 97.624 L 650.476 92.992" transform="matrix(0, -1.184039, 0.844567, 0, 0.000035, 0.00002)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 642.857px 102.712px;" d="M 642.846 105.028 L 642.867 100.396" transform="matrix(0, -1.184039, 0.844567, 0, 0.000009, 0.000035)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 437.929 90.244 L 450.367 90.244 L 450.367 106.712 L 437.929 106.712 L 437.929 90.244 Z"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 444.274px 112.408px;" d="M 444.253 107.189 L 444.293 117.627"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 447.919px 94.601px;" d="M 447.909 96.917 L 447.93 92.285" transform="matrix(0, -1.184039, 0.844567, 0, -0.000022, 0.000005)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 440.31px 102.004px;" d="M 440.3 104.321 L 440.32 99.689" transform="matrix(0, -1.184039, 0.844567, 0, -0.000028, -0.000004)"/>
<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="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="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="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)">####.##</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, 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, 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="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="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>
<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);"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="192.401" rx="20.673" ry="17.46"/>
<rect x="870.356" y="230.113" 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="1069.06" y="349.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Shutdown</text>
<rect x="870.356" y="257.602" 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="279.699" rx="20.673" ry="17.46"/>
<rect x="870.356" y="317.411" 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="1059.06" y="474.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Status</text>
<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="336.418" cy="237.483" 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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" 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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" 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: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 1.386371, 4.000207)">HTLS</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, -1.613663, 3.937793)">BLWR</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.483" rx="13.582" ry="12.517" id="c_5018"/>
<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="335.623" cy="320.662" 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="762.685" cy="322.259" 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.031" cy="234.094" rx="13.582" ry="12.517" id="c_5021"/>
</svg>

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500" xmlns:bx="https://boxy-svg.com">
<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"/>
<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"/>
<rect x="270" y="180" width="90" height="270" style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);"/>
</g>
<g transform="matrix(0.826913, 0, 0, 0.698383, 500.726135, 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"/>
<rect x="270" y="180" width="90" height="270" style="stroke: rgb(0, 0, 0); fill: rgb(243, 243, 243);"/>
</g>
<rect x="371.728" y="182.483" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-box: fill-box; transform-origin: 50% 50%;" d="M 551.111 -16.154 L 551.202 389.079" transform="matrix(0, -1.184039, 0.844567, 0, 0.000036, 0.000096)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 479.043 149.568 L 495.765 149.568 L 495.765 166.035 L 479.043 166.035 L 479.043 149.568 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 598.485px 226.003px;" d="M 478.737 156.666 L 495.763 156.666"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 465.169 193.204 L 511.13 179.759 L 511.13 193.204 L 465.169 179.759 L 465.169 193.204 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 487.934 186.514 L 487.934 157.095"/>
<rect x="715.724" y="182.138" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<g transform="matrix(0.826913, 0, 0, 0.698383, -2.11712, 3.138935)">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 660.838px 251.447px;" d="M 660.846 262.894 L 660.846 240"/>
<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>
<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="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="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; 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"/>
<rect x="371.639" y="358.212" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 692.133px 361.256px;" d="M 692.126 397.022 L 692.14 325.49" transform="matrix(0, -1.184039, 0.844567, 0, 0.000011, 0.00005)"/>
<rect x="715.635" y="357.867" width="8.269" height="6.984" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 798px 493.641px;" d="M 661.975 334.874 L 661.975 360.911"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 552.59px 334.782px;" d="M 552.508 244.429 L 552.665 425.136" transform="matrix(0, 1.184039, -0.844567, 0, -0.000058, 0.000018)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 601.786px 283.137px;" d="M 601.741 312.51 L 601.832 253.764" transform="matrix(0, 1.184039, -0.844567, 0, -0.000063, 0.000028)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 577.266px 308.682px;" d="M 577.237 334.87 L 577.295 282.492" transform="matrix(-1, 0, 0, -1, -0.000041, -0.00003)"/>
<g transform="matrix(-0.491177, 0, 0, 0.523644, 491.13504, 29.785091)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 406.945px 361.188px;" d="M 406.92 329.322 L 406.969 393.054" transform="matrix(0, 1.184039, -0.844567, 0, 0.00001, 0.00007)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 521.472px 494.156px;" d="M 433.307 334.116 L 433.308 362.382"/>
<g transform="matrix(0.491177, 0, 0, 0.523644, 419.010895, 56.68491)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<g transform="matrix(0.491177, 0, 0, 0.523644, 603.674133, 29.692444)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<g transform="matrix(-0.491177, 0, 0, 0.523644, 677.00824, 56.209183)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 582.89 L 30 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 98.289 582.89 L 118.071 582.89"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 49.894 600 L 49.894 565.78 L 98.289 600 L 98.289 565.78"/>
<circle style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" cx="1094.77" cy="561.359" r="39" transform="matrix(0.17796, 0, 0, 0.155258, -141.765747, 481.674255)"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 548.454px 361.62px;" d="M 548.372 271.267 L 548.529 451.974" transform="matrix(0, 1.184039, -0.844567, 0, 0.00006, -0.000036)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 578.392px 383.459px;" d="M 578.329 405.407 L 578.456 361.51" transform="matrix(-1, 0, 0, -1, -0.000055, -0.000003)"/>
<g transform="matrix(0.826913, 0, 0, -0.698383, 0.257882, 545.083069)" style="">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.222; transform-origin: 660.838px 251.447px;" d="M 660.846 262.894 L 660.846 240"/>
<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(76, 76, 76); stroke-width: 1.525; transform-origin: 704.638px 576.106px;" d="M 621.828 405.49 L 634.485 405.49"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 584.749px 405.496px;" d="M 591.042 405.497 L 578.456 405.498"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 606.436px 405.492px;" d="M 591.042 398.364 L 591.042 412.623 L 621.831 398.364 L 621.831 412.623 L 591.042 398.364 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1.525; transform-origin: 599.432px 413.831px;" d="M 592.464 422.169 L 592.464 405.493 L 606.401 405.493" transform="matrix(-1, 0, 0, -1, -0.000078, -0.000049)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 648.376px 405.65px;" d="M 648.369 435.621 L 648.383 375.678" transform="matrix(0, -1.184039, 0.844567, 0, 0.000012, -0.00004)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 673.882px 406.067px;" d="M 673.869 398.172 L 673.893 413.963" transform="matrix(-1, 0, 0, -1, -0.000092, -0.000022)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 692.821px 404.67px;" d="M 692.786 392.381 L 692.854 416.962" transform="matrix(0, 1.184039, -0.844567, 0, 0.000001, -0.000097)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 703.406px 383.726px;" d="M 703.396 405.334 L 703.415 362.116"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 681.807px 406.051px;" d="M 681.793 398.157 L 681.818 413.948" transform="matrix(-1, 0, 0, -1, 0.000055, 0.000046)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 677.987px 397.326px;" d="M 677.977 403.041 L 677.995 391.61"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 677.933px 411.78px;" d="M 677.924 417.977 L 677.941 405.582"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="650.811" cy="385.504" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%; stroke-width: 0.763;" transform="matrix(0.000343, -1, 1, 0.000266, 743.834961, 473.853179)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 651.034px 399.693px;" d="M 651.025 405.408 L 651.042 393.977"/>
<path d="M -546.834 -405.87 L -543.785 -398.138 L -550.56 -398.138 L -546.834 -405.87 Z" bx:shape="triangle -550.56 -405.87 6.775 7.732 0.55 0 1@11f2e68a" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%; stroke-width: 0.763;" transform="matrix(-1, 0, 0, -1, 1094.344971, 804.007996)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 546.953px 390.056px;" d="M 546.94 382.161 L 546.965 397.952" transform="matrix(-1, 0, 0, -1, -0.000013, 0.000046)"/>
<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="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="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;">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 53.913 425 L 53.913 400 L 90.568 425 L 90.568 400"/>
</g>
<g style="transform-origin: 227.882px 539.536px;" transform="matrix(0, 0.626201, -0.563979, 0, 588.703491, -326.882202)">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 550 L 243.484 529.073 L 243.484 550 L 212.224 529.073 L 212.224 550 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 539.499 L 200 539.499"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 243.484 539.499 L 255.764 539.499"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 807.67px 264.838px;" d="M 807.657 276.289 L 807.693 253.387" transform="matrix(0, -1.184039, 0.844567, 0, 0.000035, 0.000091)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 816.592px 247.829px;" d="M 816.56 230.114 L 816.655 265.543" transform="matrix(-1, 0, 0, -1, 0.000101, 0.000009)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="840.215" cy="233.608" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 933.237163, 321.956912)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="839.876" cy="254.847" rx="10.336" ry="8.73"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 932.895305, 343.197025)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 823.288px 234.151px;" d="M 823.282 242.163 L 823.294 226.137" transform="matrix(0, 1.184039, -0.844567, 0, -0.000084, 0.000084)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 822.751px 254.694px;" d="M 822.745 262.706 L 822.763 246.68" transform="matrix(0, 1.184039, -0.844567, 0, -0.00002, 0.000032)"/>
<path d="M -100.83 -89.11 H -94.198 L -94.198 -91.071 L -85.458 -88.012 L -94.198 -84.954 L -94.198 -86.915 H -100.83 V -89.11 Z" bx:shape="arrow -100.83 -91.071 15.372 6.118 2.195 8.74 0 1@7c71f9c2" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -93.144px -88.013px;" transform="matrix(0.000343, -1, 1, 0.000266, 909.661358, 277.142276)"/>
<g transform="matrix(0.387768, 0, 0, -0.200385, 207.60318, -199.315506)" style="transform-origin: 72.2406px 412.5px;">
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 53.913 425 L 53.913 400 L 90.568 425 L 90.568 400"/>
</g>
<g style="transform-origin: 227.882px 539.536px;" transform="matrix(0, 0.626201, 0.563979, 0, 51.251434, -326.206329)">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 550 L 243.484 529.073 L 243.484 550 L 212.224 529.073 L 212.224 550 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 212.224 539.499 L 200 539.499"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 243.484 539.499 L 255.764 539.499"/>
</g>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 288.049px 265.514px;" d="M 288.037 254.064 L 288.073 276.966" transform="matrix(0, -1.184039, 0.844567, 0, -0.000019, 0.000042)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 279.127px 248.505px;" d="M 279.095 266.219 L 279.19 230.79"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="-255.5" cy="234.284" rx="10.336" ry="8.73" transform="matrix(-1, 0, 0, 1, 0, 0)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 147.108874, 140.490195)"/>
<ellipse style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="-255.84" cy="255.523" rx="10.336" ry="8.73" transform="matrix(-1, 0, 0, 1, 0, 0)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 147.450457, 161.730307)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 272.43px 234.827px;" d="M 272.424 226.815 L 272.436 242.841" transform="matrix(0, 1.184039, -0.844567, 0, 0.000012, -0.000015)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 272.968px 255.37px;" d="M 272.962 247.358 L 272.98 263.384" transform="matrix(0, 1.184039, -0.844567, 0, -0.000011, 0.000034)"/>
<path d="M 100.83 93.032 H 107.463 L 107.463 91.071 L 116.203 94.13 L 107.463 97.189 L 107.463 95.228 H 100.83 V 93.032 Z" bx:shape="arrow 100.83 91.071 15.372 6.118 2.195 8.74 0 1@116e726f" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 108.517px 94.13px;" transform="matrix(-0.000343, -1, -1, 0.000266, 170.68468, 95.675559)"/>
<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, 47.595016, -269.416931)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>INLET</text>
<path d="M -544.544 -165.9 L -541.495 -158.168 L -548.27 -158.168 L -544.544 -165.9 Z" bx:shape="triangle -548.27 -165.9 6.775 7.732 0.55 0 1@12a1c9af" style="fill: rgb(0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: -544.876px -162.033px;" transform="matrix(-1, 0, 0, -1, 1089.751221, 324.066467)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 544.653px 150.086px;" d="M 544.639 142.192 L 544.664 157.983" transform="matrix(-1, 0, 0, -1, -0.000086, 0.000018)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 404.306 125.878 L 416.234 125.878 L 416.234 148.965 L 404.306 148.965 L 404.306 125.878 Z" transform="matrix(0, -1.184039, 0.844567, 0, -0.000039, -0.000007)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 498.152px 180.679px;" d="M 408.92 144.738 L 408.92 130.357"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 427.836 146.217 L 460.619 127.367 L 460.619 146.217 L 427.836 127.367 L 427.836 146.217 Z" transform="matrix(0, -1.184039, 0.844567, 0, 0.000009, 0.000009)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-box: fill-box; transform-origin: 50% 50%;" d="M 426.851 157.594 L 426.851 116.351" transform="matrix(0, -1.18404, 0.844567, 0, -0.000439, -0.000081)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 647.335px 171.745px;" d="M 647.177 186.902 L 647.494 156.588" transform="matrix(-1, 0, 0, -1, -0.000021, -0.000027)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 680.766px 138.025px;" d="M 674.802 149.569 L 686.73 149.569 L 686.73 126.482 L 674.802 126.482 L 674.802 149.569 Z" transform="matrix(0, -1.184039, 0.844567, 0, 0.000004, 0.000043)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 897.148px 118.148px;" d="M 682.129 145.344 L 682.129 130.964"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 646.809px 137.396px;" d="M 630.417 127.971 L 663.201 146.821 L 663.201 127.971 L 630.417 146.821 L 630.417 127.971 Z" transform="matrix(0, -1.184039, 0.844567, 0, -0.000004, -0.000033)"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 664.185px 137.577px;" d="M 664.185 116.956 L 664.186 158.199" transform="matrix(0, -1.184039, 0.844567, 0, -0.000026, -0.000041)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 590.855 148.509 L 607.577 148.509 L 607.577 164.977 L 590.855 164.977 L 590.855 148.509 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932; transform-origin: 733.701px 224.488px;" d="M 590.555 155.608 L 607.58 155.608"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 576.981 192.146 L 622.941 178.701 L 622.941 192.146 L 576.981 178.701 L 576.981 192.146 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 599.746 185.455 L 599.746 156.037"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 640.474 90.952 L 652.913 90.952 L 652.913 107.419 L 640.474 107.419 L 640.474 90.952 Z"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 646.819px 113.115px;" d="M 646.799 107.896 L 646.839 118.334"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 650.466px 95.308px;" d="M 650.455 97.624 L 650.476 92.992" transform="matrix(0, -1.184039, 0.844567, 0, 0.000035, 0.00002)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 642.857px 102.712px;" d="M 642.846 105.028 L 642.867 100.396" transform="matrix(0, -1.184039, 0.844567, 0, 0.000009, 0.000035)"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 0.932;" d="M 437.929 90.244 L 450.367 90.244 L 450.367 106.712 L 437.929 106.712 L 437.929 90.244 Z"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 444.274px 112.408px;" d="M 444.253 107.189 L 444.293 117.627"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 447.919px 94.601px;" d="M 447.909 96.917 L 447.93 92.285" transform="matrix(0, -1.184039, 0.844567, 0, -0.000022, 0.000005)"/>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.763; transform-origin: 440.31px 102.004px;" d="M 440.3 104.321 L 440.32 99.689" transform="matrix(0, -1.184039, 0.844567, 0, -0.000028, -0.000004)"/>
<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="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="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="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)">####.##</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, 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, 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="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="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>
<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);"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="192.401" rx="20.673" ry="17.46"/>
<rect x="870.356" y="230.113" 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="1069.06" y="349.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Shutdown</text>
<rect x="870.356" y="257.602" 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="279.699" rx="20.673" ry="17.46"/>
<rect x="870.356" y="317.411" 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="1059.06" y="474.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Status</text>
<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="336.418" cy="237.483" 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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" 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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" 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: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 1.386371, 4.000207)">HTLS</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, -1.613663, 3.937793)">BLWR</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.483" rx="13.582" ry="12.517" id="c_6018"/>
<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(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.685" cy="322.259" 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="335.623" cy="320.662" rx="13.582" ry="12.517" id="c_6021"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.031" cy="234.094" rx="13.582" ry="12.517" id="c_6021"/>
</svg>

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 177 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 177 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 177 KiB

View File

@@ -0,0 +1,443 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com" viewBox="0 0 950 500">
<defs>
<bx:grid x="0" y="0" width="25" height="25"/>
</defs>
<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"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 433.101 105.475 L 433.101 57.586 L 441.571 57.586 L 441.571 105.475 L 433.101 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 420.411 105.475 L 420.411 57.586 L 428.871 57.586 L 428.871 105.475 L 420.411 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 407.721 105.475 L 407.721 57.586 L 416.181 57.586 L 416.181 105.475 L 407.721 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 395.021 105.475 L 395.021 57.586 L 403.481 57.586 L 403.481 105.475 L 395.021 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 382.221 105.475 L 382.221 57.586 L 390.791 57.586 L 390.791 105.475 L 382.221 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 369.521 105.475 L 369.521 57.586 L 377.991 57.586 L 377.991 105.475 L 369.521 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.641 81.579 L 371.641 76.064 L 375.871 76.064 L 375.871 81.579 L 371.641 81.579 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.531 94.446 L 371.531 88.931 L 375.871 88.931 L 375.871 94.446 L 371.531 94.446 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.641 87.093 L 371.641 83.417 L 375.981 83.417 L 375.981 87.093 L 371.641 87.093 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.641 99.96 L 371.641 96.284 L 375.871 96.284 L 375.871 99.96 L 371.641 99.96 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 81.579 L 384.331 76.064 L 388.561 76.064 L 388.561 81.579 L 384.331 81.579 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 94.446 L 384.331 88.931 L 388.561 88.931 L 388.561 94.446 L 384.331 94.446 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 87.093 L 384.331 83.417 L 388.671 83.417 L 388.671 87.093 L 384.331 87.093 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 99.96 L 384.331 96.284 L 388.561 96.284 L 388.561 99.96 L 384.331 99.96 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.031 81.579 L 397.031 76.064 L 401.371 76.064 L 401.371 81.579 L 397.031 81.579 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.031 94.446 L 397.031 88.931 L 401.261 88.931 L 401.261 94.446 L 397.031 94.446 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.141 87.093 L 397.141 83.417 L 401.371 83.417 L 401.371 87.093 L 397.141 87.093 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.031 99.96 L 397.031 96.284 L 401.371 96.284 L 401.371 99.96 L 397.031 99.96 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 385.451 105.475 L 385.451 101.798 L 387.561 101.798 L 387.561 105.475 L 385.451 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 372.751 105.475 L 372.751 101.798 L 374.871 101.798 L 374.871 105.475 L 372.751 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 372.751 61.262 L 372.751 57.586 L 374.871 57.586 L 374.871 61.262 L 372.751 61.262 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 385.451 61.262 L 385.451 57.586 L 387.561 57.586 L 387.561 61.262 L 385.451 61.262 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 398.141 61.262 L 398.141 57.586 L 400.261 57.586 L 400.261 61.262 L 398.141 61.262 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 398.141 105.475 L 398.141 101.798 L 400.261 101.798 L 400.261 105.475 L 398.141 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 80.611 L 451.141 80.611 L 451.141 82.449 L 449.031 82.449 L 449.031 80.611 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 76.935 L 451.141 76.935 L 451.141 78.87 L 449.031 78.87 L 449.031 76.935 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 84.287 L 451.141 84.287 L 451.141 86.126 L 449.031 86.126 L 449.031 84.287 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 73.258 L 451.141 73.258 L 451.141 75.097 L 449.031 75.097 L 449.031 73.258 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 87.964 L 451.141 87.964 L 451.141 89.802 L 449.031 89.802 L 449.031 87.964 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 69.582 L 451.141 69.582 L 451.141 71.42 L 449.031 71.42 L 449.031 69.582 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 91.64 L 451.141 91.64 L 451.141 93.478 L 449.031 93.478 L 449.031 91.64 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 80.611 L 438.451 80.611 L 438.451 82.449 L 436.331 82.449 L 436.331 80.611 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 76.935 L 438.451 76.935 L 438.451 78.87 L 436.331 78.87 L 436.331 76.935 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 84.287 L 438.451 84.287 L 438.451 86.126 L 436.331 86.126 L 436.331 84.287 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 73.258 L 438.451 73.258 L 438.451 75.097 L 436.331 75.097 L 436.331 73.258 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 87.964 L 438.451 87.964 L 438.451 89.802 L 436.331 89.802 L 436.331 87.964 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 69.582 L 438.451 69.582 L 438.451 71.42 L 436.331 71.42 L 436.331 69.582 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 91.64 L 438.451 91.64 L 438.451 93.478 L 436.331 93.478 L 436.331 91.64 Z"/>
<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">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"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 350 L 775 350 L 775 347.558 L 760.743 342.884 L 732.114 342.884 L 717.857 347.558 L 717.857 350 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 770.133 334.023 L 770.133 337.512 L 756.391 337.512 L 756.391 334.023 L 770.133 334.023 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 347.558 L 775 347.558"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 675 285.361 L 703.571 285.361 L 703.571 350 L 675 350 L 675 285.361 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 287.463 L 701.169 287.463 L 701.169 350 L 677.317 350 L 677.317 287.463 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 290.616 L 701.169 290.616 L 701.169 297.898 L 677.317 297.898 L 677.317 290.616 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 297.898 L 701.169 297.898 L 701.169 305.181 L 677.317 305.181 L 677.317 297.898 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 293.694 L 698.767 293.694 L 698.767 294.745 L 679.72 294.745 L 679.72 293.694 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 300 L 698.767 300 L 698.767 303.078 L 679.72 303.078 L 679.72 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 275 L 698.767 275 L 703.571 285.361 L 675 285.361 L 679.72 275 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 695.163 300 L 701.169 300 L 701.169 303.078 L 695.163 303.078 L 695.163 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 300 L 698.767 300 L 698.767 303.078 L 697.566 303.078 L 697.566 300 Z"/>
<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 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"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 350 L 775 350 L 775 347.558 L 760.743 342.884 L 732.114 342.884 L 717.857 347.558 L 717.857 350 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 770.133 334.023 L 770.133 337.512 L 756.391 337.512 L 756.391 334.023 L 770.133 334.023 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 347.558 L 775 347.558"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 675 285.361 L 703.571 285.361 L 703.571 350 L 675 350 L 675 285.361 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 287.463 L 701.169 287.463 L 701.169 350 L 677.317 350 L 677.317 287.463 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 290.616 L 701.169 290.616 L 701.169 297.898 L 677.317 297.898 L 677.317 290.616 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 297.898 L 701.169 297.898 L 701.169 305.181 L 677.317 305.181 L 677.317 297.898 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 293.694 L 698.767 293.694 L 698.767 294.745 L 679.72 294.745 L 679.72 293.694 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 300 L 698.767 300 L 698.767 303.078 L 679.72 303.078 L 679.72 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 275 L 698.767 275 L 703.571 285.361 L 675 285.361 L 679.72 275 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 695.163 300 L 701.169 300 L 701.169 303.078 L 695.163 303.078 L 695.163 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 300 L 698.767 300 L 698.767 303.078 L 697.566 303.078 L 697.566 300 Z"/>
<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="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 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 "/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M71.957,98.984l-1.127,1.127h-1.125v11.261h1.125l1.127,1.126h-4.504 V98.984H71.957z"/>
</g>
<g id="Group_Supports" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M11.148,89.977h49.547v13.514H11.148V89.977z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M4.392,76.463h4.504v27.026H4.392V76.463z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M62.948,76.463h4.278v27.026h-4.278V76.463z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,102.363h5.631v-6.758h-5.631h-0.337l-0.451,0.338 l-0.338,0.339l-0.338,0.563l-0.338,0.563l-0.225,0.563l-0.112,0.563l-0.113,0.45l0.113,0.451l0.112,0.563l0.225,0.563l0.338,0.563 l0.338,0.449l0.338,0.338l0.451,0.338L15.652,102.363z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,102.363h-5.631v-6.758h5.631h0.451l0.338,0.338l0.449,0.339 l0.338,0.563l0.226,0.563l0.226,0.563l0.225,0.563v0.448v0.451l-0.225,0.563l-0.226,0.563l-0.226,0.563l-0.338,0.449l-0.449,0.338 l-0.338,0.338L56.191,102.363z"/>
</g>
<g id="Group_Pipes" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="341.6875" y1="-275.623" x2="346.1914" y2="-275.623" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M56.191,6.871h-4.504v4.504h4.504V6.871z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,11.375V6.871h-4.504v4.504H56.191z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="305.6523" y1="-275.623" x2="310.1572" y2="-275.623" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#SVGID_2_)" d="M20.157,6.871h-4.504v4.504h4.504V6.871z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M20.157,11.375V6.871h-4.504v4.504H20.157z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="323.6699" y1="-283.5059" x2="328.1738" y2="-283.5059" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#SVGID_3_)" stroke="#4C4C4C" stroke-width="0.25" d="M38.174,6.871H33.67v20.27h4.504V6.871z"/>
<path fill="#999999" d="M58.443,6.871V4.619H13.4v2.252H58.443z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="325.9219" y1="-271.0625" x2="325.9219" y2="-273.2832" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#SVGID_4_)" stroke="#4C4C4C" stroke-width="0.25" d="M13.4,6.871h45.043V4.619H13.4V6.871"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="325.9219" y1="-362.064" x2="325.9219" y2="-368.8364" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#SVGID_5_)" stroke="#4C4C4C" stroke-width="0.25" d="M21.283,95.605h29.277v6.758H21.283V95.605z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="322.5439" y1="-355.3496" x2="329.3008" y2="-355.3496" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#SVGID_6_)" stroke="#4C4C4C" stroke-width="0.25" d="M39.301,95.605V78.715h-6.757v16.893l0.112,0.676l0.226,0.563 l0.225,0.563l0.45,0.45l0.563,0.449l0.563,0.338l0.563,0.227l0.675,0.111l0.677-0.111l0.676-0.227l0.563-0.338l0.451-0.449 l0.449-0.45l0.339-0.563l0.112-0.563L39.301,95.605z"/>
</g>
<g id="Group_Column2" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="298.8965" y1="-318.8652" x2="316.9141" y2="-318.8652" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#B2B2B2"/>
<stop offset="0.5" style="stop-color:#E5E5E5"/>
<stop offset="1" style="stop-color:#B2B2B2"/>
</linearGradient>
<path fill="url(#SVGID_7_)" d="M26.914,13.628V94.48H8.896V13.628c0,0,2.204-3.378,9.009-3.378 C25.176,10.25,26.914,13.628,26.914,13.628"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,13.628V94.48H8.896V13.628c0,0,1.972-3.378,9.043-3.378 C25.442,10.25,26.914,13.628,26.914,13.628z"/>
</g>
<g id="Group_Column1" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="334.9316" y1="-318.7939" x2="352.9482" y2="-318.7939" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#B2B2B2"/>
<stop offset="0.5" style="stop-color:#E5E5E5"/>
<stop offset="1" style="stop-color:#B2B2B2"/>
</linearGradient>
<path fill="url(#SVGID_8_)" d="M62.948,13.628V94.48H44.932V13.628c0,0,1.692-3.52,8.67-3.52 C61.661,10.108,62.948,13.628,62.948,13.628z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M62.948,13.628V94.48H44.932V13.628c0,0,1.668-3.52,8.67-3.52 C61.589,10.108,62.948,13.628,62.948,13.628z"/>
</g>
<g id="Group_Boards" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<circle fill="#666666" stroke="#4C4C4C" stroke-width="0.25" cx="31.981" cy="24.325" r="3.941"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M22.409,27.141h27.026v33.783H22.409V27.141z"/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M25.787,31.645h20.27v21.396h-20.27V31.645z"/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M25.787,57.545h20.27v21.17h-20.27V57.545z"/>
<path fill="#7F7F7F" stroke="#4C4C4C" stroke-width="0.25" d="M37.049,60.924h6.756v7.656h-6.756V60.924z"/>
</g>
<g id="Group_Points" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,55.293h3.378v4.504h-3.378V55.293z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,58.671h3.378v4.505h-3.378V58.671z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,58.671h3.378v1.126h-3.378V58.671z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,55.293h3.378v1.126h-3.378V55.293z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,47.41h3.378v4.504h-3.378V47.41z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,47.41h3.378v1.126h-3.378V47.41z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M52.813,55.293h3.379v4.504h-3.379V55.293z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M52.813,55.293h3.379v1.126h-3.379V55.293z"/>
</g>
<g id="Group_Connectors" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,1.917h0.676v43.692h-0.676V1.917z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,45.608h-7.207v-0.45h7.207V45.608z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,44.032h-7.207v-0.676h7.207V44.032z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,41.78h-7.207v-0.676h7.207V41.78z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,2.367H23.085v-0.45h30.179V2.367z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M23.085,2.367h0.45v2.252h-0.45V2.367z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,22.636h-40.54v-0.675h40.54V22.636z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M55.516,22.636h0.676v6.757h-0.676V22.636z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,22.636h0.676v6.757h-0.676V22.636z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M27.364,0.002l1.577,1.464l-2.478,2.478l-1.576-1.577L27.364,0.002z"/>
<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.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 "/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M71.957,98.984l-1.127,1.127h-1.125v11.261h1.125l1.127,1.126h-4.504 V98.984H71.957z"/>
</g>
<g id="group-2" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M11.148,89.977h49.547v13.514H11.148V89.977z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M4.392,76.463h4.504v27.026H4.392V76.463z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M62.948,76.463h4.278v27.026h-4.278V76.463z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,102.363h5.631v-6.758h-5.631h-0.337l-0.451,0.338 l-0.338,0.339l-0.338,0.563l-0.338,0.563l-0.225,0.563l-0.112,0.563l-0.113,0.45l0.113,0.451l0.112,0.563l0.225,0.563l0.338,0.563 l0.338,0.449l0.338,0.338l0.451,0.338L15.652,102.363z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,102.363h-5.631v-6.758h5.631h0.451l0.338,0.338l0.449,0.339 l0.338,0.563l0.226,0.563l0.226,0.563l0.225,0.563v0.448v0.451l-0.225,0.563l-0.226,0.563l-0.226,0.563l-0.338,0.449l-0.449,0.338 l-0.338,0.338L56.191,102.363z"/>
</g>
<g id="group-3" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="gradient-1" gradientUnits="userSpaceOnUse" x1="341.6875" y1="-275.623" x2="346.1914" y2="-275.623" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-1)" d="M56.191,6.871h-4.504v4.504h4.504V6.871z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,11.375V6.871h-4.504v4.504H56.191z"/>
<linearGradient id="gradient-2" gradientUnits="userSpaceOnUse" x1="305.6523" y1="-275.623" x2="310.1572" y2="-275.623" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-2)" d="M20.157,6.871h-4.504v4.504h4.504V6.871z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M20.157,11.375V6.871h-4.504v4.504H20.157z"/>
<linearGradient id="gradient-3" gradientUnits="userSpaceOnUse" x1="323.6699" y1="-283.5059" x2="328.1738" y2="-283.5059" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-3)" stroke="#4C4C4C" stroke-width="0.25" d="M38.174,6.871H33.67v20.27h4.504V6.871z"/>
<path fill="#999999" d="M58.443,6.871V4.619H13.4v2.252H58.443z"/>
<linearGradient id="gradient-4" gradientUnits="userSpaceOnUse" x1="325.9219" y1="-271.0625" x2="325.9219" y2="-273.2832" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-4)" stroke="#4C4C4C" stroke-width="0.25" d="M13.4,6.871h45.043V4.619H13.4V6.871"/>
<linearGradient id="gradient-5" gradientUnits="userSpaceOnUse" x1="325.9219" y1="-362.064" x2="325.9219" y2="-368.8364" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-5)" stroke="#4C4C4C" stroke-width="0.25" d="M21.283,95.605h29.277v6.758H21.283V95.605z"/>
<linearGradient id="gradient-6" gradientUnits="userSpaceOnUse" x1="322.5439" y1="-355.3496" x2="329.3008" y2="-355.3496" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-6)" stroke="#4C4C4C" stroke-width="0.25" d="M39.301,95.605V78.715h-6.757v16.893l0.112,0.676l0.226,0.563 l0.225,0.563l0.45,0.45l0.563,0.449l0.563,0.338l0.563,0.227l0.675,0.111l0.677-0.111l0.676-0.227l0.563-0.338l0.451-0.449 l0.449-0.45l0.339-0.563l0.112-0.563L39.301,95.605z"/>
</g>
<g id="group-4" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="gradient-7" gradientUnits="userSpaceOnUse" x1="298.8965" y1="-318.8652" x2="316.9141" y2="-318.8652" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#B2B2B2"/>
<stop offset="0.5" style="stop-color:#E5E5E5"/>
<stop offset="1" style="stop-color:#B2B2B2"/>
</linearGradient>
<path fill="url(#gradient-7)" d="M26.914,13.628V94.48H8.896V13.628c0,0,2.204-3.378,9.009-3.378 C25.176,10.25,26.914,13.628,26.914,13.628"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,13.628V94.48H8.896V13.628c0,0,1.972-3.378,9.043-3.378 C25.442,10.25,26.914,13.628,26.914,13.628z"/>
</g>
<g id="group-5" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="gradient-8" gradientUnits="userSpaceOnUse" x1="334.9316" y1="-318.7939" x2="352.9482" y2="-318.7939" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#B2B2B2"/>
<stop offset="0.5" style="stop-color:#E5E5E5"/>
<stop offset="1" style="stop-color:#B2B2B2"/>
</linearGradient>
<path fill="url(#gradient-8)" d="M62.948,13.628V94.48H44.932V13.628c0,0,1.692-3.52,8.67-3.52 C61.661,10.108,62.948,13.628,62.948,13.628z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M62.948,13.628V94.48H44.932V13.628c0,0,1.668-3.52,8.67-3.52 C61.589,10.108,62.948,13.628,62.948,13.628z"/>
</g>
<g id="group-6" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<circle fill="#666666" stroke="#4C4C4C" stroke-width="0.25" cx="31.981" cy="24.325" r="3.941"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M22.409,27.141h27.026v33.783H22.409V27.141z"/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M25.787,31.645h20.27v21.396h-20.27V31.645z"/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M25.787,57.545h20.27v21.17h-20.27V57.545z"/>
<path fill="#7F7F7F" stroke="#4C4C4C" stroke-width="0.25" d="M37.049,60.924h6.756v7.656h-6.756V60.924z"/>
</g>
<g id="group-7" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,55.293h3.378v4.504h-3.378V55.293z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,58.671h3.378v4.505h-3.378V58.671z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,58.671h3.378v1.126h-3.378V58.671z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,55.293h3.378v1.126h-3.378V55.293z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,47.41h3.378v4.504h-3.378V47.41z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,47.41h3.378v1.126h-3.378V47.41z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M52.813,55.293h3.379v4.504h-3.379V55.293z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M52.813,55.293h3.379v1.126h-3.379V55.293z"/>
</g>
<g id="group-8" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,1.917h0.676v43.692h-0.676V1.917z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,45.608h-7.207v-0.45h7.207V45.608z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,44.032h-7.207v-0.676h7.207V44.032z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,41.78h-7.207v-0.676h7.207V41.78z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,2.367H23.085v-0.45h30.179V2.367z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M23.085,2.367h0.45v2.252h-0.45V2.367z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,22.636h-40.54v-0.675h40.54V22.636z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M55.516,22.636h0.676v6.757h-0.676V22.636z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,22.636h0.676v6.757h-0.676V22.636z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M27.364,0.002l1.577,1.464l-2.478,2.478l-1.576-1.577L27.364,0.002z"/>
<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.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 "/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M71.957,98.984l-1.127,1.127h-1.125v11.261h1.125l1.127,1.126h-4.504 V98.984H71.957z"/>
</g>
<g id="group-10" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M11.148,89.977h49.547v13.514H11.148V89.977z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M4.392,76.463h4.504v27.026H4.392V76.463z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M62.948,76.463h4.278v27.026h-4.278V76.463z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,102.363h5.631v-6.758h-5.631h-0.337l-0.451,0.338 l-0.338,0.339l-0.338,0.563l-0.338,0.563l-0.225,0.563l-0.112,0.563l-0.113,0.45l0.113,0.451l0.112,0.563l0.225,0.563l0.338,0.563 l0.338,0.449l0.338,0.338l0.451,0.338L15.652,102.363z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,102.363h-5.631v-6.758h5.631h0.451l0.338,0.338l0.449,0.339 l0.338,0.563l0.226,0.563l0.226,0.563l0.225,0.563v0.448v0.451l-0.225,0.563l-0.226,0.563l-0.226,0.563l-0.338,0.449l-0.449,0.338 l-0.338,0.338L56.191,102.363z"/>
</g>
<g id="group-11" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="gradient-9" gradientUnits="userSpaceOnUse" x1="341.6875" y1="-275.623" x2="346.1914" y2="-275.623" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-9)" d="M56.191,6.871h-4.504v4.504h4.504V6.871z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,11.375V6.871h-4.504v4.504H56.191z"/>
<linearGradient id="gradient-10" gradientUnits="userSpaceOnUse" x1="305.6523" y1="-275.623" x2="310.1572" y2="-275.623" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-10)" d="M20.157,6.871h-4.504v4.504h4.504V6.871z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M20.157,11.375V6.871h-4.504v4.504H20.157z"/>
<linearGradient id="gradient-11" gradientUnits="userSpaceOnUse" x1="323.6699" y1="-283.5059" x2="328.1738" y2="-283.5059" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-11)" stroke="#4C4C4C" stroke-width="0.25" d="M38.174,6.871H33.67v20.27h4.504V6.871z"/>
<path fill="#999999" d="M58.443,6.871V4.619H13.4v2.252H58.443z"/>
<linearGradient id="gradient-12" gradientUnits="userSpaceOnUse" x1="325.9219" y1="-271.0625" x2="325.9219" y2="-273.2832" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-12)" stroke="#4C4C4C" stroke-width="0.25" d="M13.4,6.871h45.043V4.619H13.4V6.871"/>
<linearGradient id="gradient-13" gradientUnits="userSpaceOnUse" x1="325.9219" y1="-362.064" x2="325.9219" y2="-368.8364" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-13)" stroke="#4C4C4C" stroke-width="0.25" d="M21.283,95.605h29.277v6.758H21.283V95.605z"/>
<linearGradient id="gradient-14" gradientUnits="userSpaceOnUse" x1="322.5439" y1="-355.3496" x2="329.3008" y2="-355.3496" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.5" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path fill="url(#gradient-14)" stroke="#4C4C4C" stroke-width="0.25" d="M39.301,95.605V78.715h-6.757v16.893l0.112,0.676l0.226,0.563 l0.225,0.563l0.45,0.45l0.563,0.449l0.563,0.338l0.563,0.227l0.675,0.111l0.677-0.111l0.676-0.227l0.563-0.338l0.451-0.449 l0.449-0.45l0.339-0.563l0.112-0.563L39.301,95.605z"/>
</g>
<g id="group-12" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="gradient-15" gradientUnits="userSpaceOnUse" x1="298.8965" y1="-318.8652" x2="316.9141" y2="-318.8652" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#B2B2B2"/>
<stop offset="0.5" style="stop-color:#E5E5E5"/>
<stop offset="1" style="stop-color:#B2B2B2"/>
</linearGradient>
<path fill="url(#gradient-15)" d="M26.914,13.628V94.48H8.896V13.628c0,0,2.204-3.378,9.009-3.378 C25.176,10.25,26.914,13.628,26.914,13.628"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,13.628V94.48H8.896V13.628c0,0,1.972-3.378,9.043-3.378 C25.442,10.25,26.914,13.628,26.914,13.628z"/>
</g>
<g id="group-13" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<linearGradient id="gradient-16" gradientUnits="userSpaceOnUse" x1="334.9316" y1="-318.7939" x2="352.9482" y2="-318.7939" gradientTransform="matrix(1 0 0 -1 -290 -266.5)">
<stop offset="0" style="stop-color:#B2B2B2"/>
<stop offset="0.5" style="stop-color:#E5E5E5"/>
<stop offset="1" style="stop-color:#B2B2B2"/>
</linearGradient>
<path fill="url(#gradient-16)" d="M62.948,13.628V94.48H44.932V13.628c0,0,1.692-3.52,8.67-3.52 C61.661,10.108,62.948,13.628,62.948,13.628z"/>
<path fill="none" stroke="#4C4C4C" stroke-width="0.25" d="M62.948,13.628V94.48H44.932V13.628c0,0,1.668-3.52,8.67-3.52 C61.589,10.108,62.948,13.628,62.948,13.628z"/>
</g>
<g id="group-14" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<circle fill="#666666" stroke="#4C4C4C" stroke-width="0.25" cx="31.981" cy="24.325" r="3.941"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M22.409,27.141h27.026v33.783H22.409V27.141z"/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M25.787,31.645h20.27v21.396h-20.27V31.645z"/>
<path fill="#4C4C4C" stroke="#4C4C4C" stroke-width="0.25" d="M25.787,57.545h20.27v21.17h-20.27V57.545z"/>
<path fill="#7F7F7F" stroke="#4C4C4C" stroke-width="0.25" d="M37.049,60.924h6.756v7.656h-6.756V60.924z"/>
</g>
<g id="group-15" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,55.293h3.378v4.504h-3.378V55.293z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,58.671h3.378v4.505h-3.378V58.671z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,58.671h3.378v1.126h-3.378V58.671z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,55.293h3.378v1.126h-3.378V55.293z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,47.41h3.378v4.504h-3.378V47.41z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M26.914,47.41h3.378v1.126h-3.378V47.41z"/>
<path fill="#FFFFFF" stroke="#4C4C4C" stroke-width="0.25" d="M52.813,55.293h3.379v4.504h-3.379V55.293z"/>
<path fill="#7F0000" stroke="#4C4C4C" stroke-width="0.25" d="M52.813,55.293h3.379v1.126h-3.379V55.293z"/>
</g>
<g id="group-16" transform="matrix(1, 0, 0, 1, 1236.05109, 62.756969)">
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,1.917h0.676v43.692h-0.676V1.917z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,45.608h-7.207v-0.45h7.207V45.608z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,44.032h-7.207v-0.676h7.207V44.032z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,41.78h-7.207v-0.676h7.207V41.78z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M53.264,2.367H23.085v-0.45h30.179V2.367z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M23.085,2.367h0.45v2.252h-0.45V2.367z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M56.191,22.636h-40.54v-0.675h40.54V22.636z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M55.516,22.636h0.676v6.757h-0.676V22.636z"/>
<path fill="#666666" stroke="#4C4C4C" stroke-width="0.25" d="M15.652,22.636h0.676v6.757h-0.676V22.636z"/>
<path fill="#B2B2B2" stroke="#4C4C4C" stroke-width="0.25" d="M27.364,0.002l1.577,1.464l-2.478,2.478l-1.576-1.577L27.364,0.002z"/>
<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>
</svg>

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com" viewBox="0 0 950 500">
<defs>
<bx:grid x="0" y="0" width="25" height="25"/>
</defs>
<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"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 166.356 102.453 L 278.348 74.371 L 278.348 114.973 L 166.356 114.973 L 166.356 102.453 Z"/>
<path style="fill: rgb(204, 204, 204); stroke-width: 1;" d="M 168.486 49.688 L 276.106 49.688 L 276.106 109.249 L 168.486 109.249 L 168.486 49.688 Z"/>
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 222.296 91.9 L 276.106 67.038 L 276.106 109.249 L 222.296 109.249 L 222.296 91.9 Z"/>
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 168.486 92.079 L 222.296 67.038 L 222.296 109.249 L 168.486 109.249 L 168.486 92.079 Z"/>
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 222.296 94.583 L 276.106 69.542 L 276.106 109.249 L 222.296 109.249 L 222.296 94.583 Z"/>
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 168.486 94.583 L 222.296 69.542 L 222.296 109.249 L 168.486 109.249 L 168.486 94.583 Z"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 222.296 98.16 L 276.106 73.298 L 276.106 109.249 L 222.296 109.249 L 222.296 98.16 Z"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 168.486 98.16 L 222.296 73.298 L 222.296 109.249 L 168.486 109.249 L 168.486 98.16 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" 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"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 222.296 49.688 L 276.106 49.688 L 276.106 109.249 L 222.296 109.249 L 222.296 49.688"/>
<path style="fill: rgb(153, 153, 153); stroke-width: 1;" d="M 240.906 110.323 L 259.739 110.323 L 259.739 113.9 L 240.906 113.9 L 240.906 110.323 Z"/>
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 169.607 108.713 L 169.159 108.176 L 169.607 107.64 L 170.504 107.64 L 170.952 108.176 L 170.504 108.713 L 169.607 108.713 Z"/>
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 169.607 68.111 L 169.159 67.575 L 169.607 66.859 L 170.504 66.859 L 170.952 67.575 L 170.504 68.111 L 169.607 68.111 Z"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 168.486 49.688 L 222.296 49.688 L 222.296 109.249 L 168.486 109.249 L 168.486 49.688"/>
<path style="fill: rgb(229, 229, 229); stroke-width: 1;" d="M 229.247 51.119 L 235.749 51.119 L 235.749 59.973 L 229.247 59.973 L 229.247 51.119 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 224.762 51.119 L 226.332 51.119 L 226.332 55.233 L 224.762 55.233 L 224.762 51.119 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 272.519 51.119 L 274.313 51.119 L 274.313 55.233 L 272.519 55.233 L 272.519 51.119 Z"/>
<path style="fill: rgb(51, 51, 51); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 168.486 49.688 L 222.296 49.688 L 222.296 66.501 L 168.486 66.501 L 168.486 49.688 Z"/>
<path style="fill: rgb(229, 229, 229); stroke-width: 1;" d="M 185.526 60.778 L 192.028 60.778 L 192.028 63.103 L 185.526 63.103 L 185.526 60.778 Z"/>
<path style="fill: rgb(178, 178, 178); stroke-width: 1;" d="M 200.324 62.745 L 198.978 61.672 L 198.978 60.152 L 200.324 59.079 L 202.117 59.079 L 203.687 60.152 L 203.687 61.672 L 202.117 62.745 L 200.324 62.745 Z"/>
<path style="fill: rgb(178, 178, 178); stroke-width: 1;" d="M 207.947 62.745 L 206.602 61.672 L 206.602 60.152 L 207.947 59.079 L 209.74 59.079 L 211.086 60.152 L 211.086 61.672 L 209.74 62.745 L 207.947 62.745 Z"/>
<path style="fill: rgb(102, 102, 102); stroke-width: 1;" d="M 176.109 60.778 L 182.611 60.778 L 182.611 63.103 L 176.109 63.103 L 176.109 60.778 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 179.024 54.339 L 179.024 59.079 L 176.782 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 183.06 54.339 L 183.06 59.079 L 180.93 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 187.32 54.339 L 187.32 59.079 L 184.853 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 191.355 54.339 L 191.355 59.079 L 188.889 59.079"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 188.889 59.079 L 188.889 54.339 L 191.355 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 184.853 59.079 L 184.853 54.339 L 187.32 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 180.93 59.079 L 180.93 54.339 L 183.06 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 176.782 59.079 L 176.782 54.339 L 179.024 54.339"/>
<path style="fill: rgb(127, 127, 127); stroke-width: 1;" d="M 197.857 66.859 L 222.296 104.241 L 222.296 94.404 L 204.135 66.859 L 197.857 66.859 Z"/>
<path style="fill: rgb(102, 102, 102); stroke-width: 1;" d="M 204.135 66.859 L 222.296 94.404 L 222.296 84.566 L 210.637 66.859 L 204.135 66.859 Z"/>
<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.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"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 433.101 105.475 L 433.101 57.586 L 441.571 57.586 L 441.571 105.475 L 433.101 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 420.411 105.475 L 420.411 57.586 L 428.871 57.586 L 428.871 105.475 L 420.411 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 407.721 105.475 L 407.721 57.586 L 416.181 57.586 L 416.181 105.475 L 407.721 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 395.021 105.475 L 395.021 57.586 L 403.481 57.586 L 403.481 105.475 L 395.021 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 382.221 105.475 L 382.221 57.586 L 390.791 57.586 L 390.791 105.475 L 382.221 105.475 Z"/>
<path style="fill: rgb(166, 186, 217); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 369.521 105.475 L 369.521 57.586 L 377.991 57.586 L 377.991 105.475 L 369.521 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.641 81.579 L 371.641 76.064 L 375.871 76.064 L 375.871 81.579 L 371.641 81.579 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.531 94.446 L 371.531 88.931 L 375.871 88.931 L 375.871 94.446 L 371.531 94.446 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.641 87.093 L 371.641 83.417 L 375.981 83.417 L 375.981 87.093 L 371.641 87.093 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 371.641 99.96 L 371.641 96.284 L 375.871 96.284 L 375.871 99.96 L 371.641 99.96 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 81.579 L 384.331 76.064 L 388.561 76.064 L 388.561 81.579 L 384.331 81.579 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 94.446 L 384.331 88.931 L 388.561 88.931 L 388.561 94.446 L 384.331 94.446 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 87.093 L 384.331 83.417 L 388.671 83.417 L 388.671 87.093 L 384.331 87.093 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 384.331 99.96 L 384.331 96.284 L 388.561 96.284 L 388.561 99.96 L 384.331 99.96 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.031 81.579 L 397.031 76.064 L 401.371 76.064 L 401.371 81.579 L 397.031 81.579 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.031 94.446 L 397.031 88.931 L 401.261 88.931 L 401.261 94.446 L 397.031 94.446 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.141 87.093 L 397.141 83.417 L 401.371 83.417 L 401.371 87.093 L 397.141 87.093 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 397.031 99.96 L 397.031 96.284 L 401.371 96.284 L 401.371 99.96 L 397.031 99.96 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 385.451 105.475 L 385.451 101.798 L 387.561 101.798 L 387.561 105.475 L 385.451 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 372.751 105.475 L 372.751 101.798 L 374.871 101.798 L 374.871 105.475 L 372.751 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 372.751 61.262 L 372.751 57.586 L 374.871 57.586 L 374.871 61.262 L 372.751 61.262 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 385.451 61.262 L 385.451 57.586 L 387.561 57.586 L 387.561 61.262 L 385.451 61.262 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 398.141 61.262 L 398.141 57.586 L 400.261 57.586 L 400.261 61.262 L 398.141 61.262 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 398.141 105.475 L 398.141 101.798 L 400.261 101.798 L 400.261 105.475 L 398.141 105.475 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 80.611 L 451.141 80.611 L 451.141 82.449 L 449.031 82.449 L 449.031 80.611 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 76.935 L 451.141 76.935 L 451.141 78.87 L 449.031 78.87 L 449.031 76.935 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 84.287 L 451.141 84.287 L 451.141 86.126 L 449.031 86.126 L 449.031 84.287 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 73.258 L 451.141 73.258 L 451.141 75.097 L 449.031 75.097 L 449.031 73.258 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 87.964 L 451.141 87.964 L 451.141 89.802 L 449.031 89.802 L 449.031 87.964 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 69.582 L 451.141 69.582 L 451.141 71.42 L 449.031 71.42 L 449.031 69.582 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 449.031 91.64 L 451.141 91.64 L 451.141 93.478 L 449.031 93.478 L 449.031 91.64 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 80.611 L 438.451 80.611 L 438.451 82.449 L 436.331 82.449 L 436.331 80.611 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 76.935 L 438.451 76.935 L 438.451 78.87 L 436.331 78.87 L 436.331 76.935 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 84.287 L 438.451 84.287 L 438.451 86.126 L 436.331 86.126 L 436.331 84.287 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 73.258 L 438.451 73.258 L 438.451 75.097 L 436.331 75.097 L 436.331 73.258 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 87.964 L 438.451 87.964 L 438.451 89.802 L 436.331 89.802 L 436.331 87.964 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 69.582 L 438.451 69.582 L 438.451 71.42 L 436.331 71.42 L 436.331 69.582 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 436.331 91.64 L 438.451 91.64 L 438.451 93.478 L 436.331 93.478 L 436.331 91.64 Z"/>
<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">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"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 166.356 102.453 L 278.348 74.371 L 278.348 114.973 L 166.356 114.973 L 166.356 102.453 Z"/>
<path style="fill: rgb(204, 204, 204); stroke-width: 1;" d="M 168.486 49.688 L 276.106 49.688 L 276.106 109.249 L 168.486 109.249 L 168.486 49.688 Z"/>
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 222.296 91.9 L 276.106 67.038 L 276.106 109.249 L 222.296 109.249 L 222.296 91.9 Z"/>
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 168.486 92.079 L 222.296 67.038 L 222.296 109.249 L 168.486 109.249 L 168.486 92.079 Z"/>
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 222.296 94.583 L 276.106 69.542 L 276.106 109.249 L 222.296 109.249 L 222.296 94.583 Z"/>
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 168.486 94.583 L 222.296 69.542 L 222.296 109.249 L 168.486 109.249 L 168.486 94.583 Z"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 222.296 98.16 L 276.106 73.298 L 276.106 109.249 L 222.296 109.249 L 222.296 98.16 Z"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 168.486 98.16 L 222.296 73.298 L 222.296 109.249 L 168.486 109.249 L 168.486 98.16 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" 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"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 222.296 49.688 L 276.106 49.688 L 276.106 109.249 L 222.296 109.249 L 222.296 49.688"/>
<path style="fill: rgb(153, 153, 153); stroke-width: 1;" d="M 240.906 110.323 L 259.739 110.323 L 259.739 113.9 L 240.906 113.9 L 240.906 110.323 Z"/>
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 169.607 108.713 L 169.159 108.176 L 169.607 107.64 L 170.504 107.64 L 170.952 108.176 L 170.504 108.713 L 169.607 108.713 Z"/>
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 169.607 68.111 L 169.159 67.575 L 169.607 66.859 L 170.504 66.859 L 170.952 67.575 L 170.504 68.111 L 169.607 68.111 Z"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 168.486 49.688 L 222.296 49.688 L 222.296 109.249 L 168.486 109.249 L 168.486 49.688"/>
<path style="fill: rgb(229, 229, 229); stroke-width: 1;" d="M 229.247 51.119 L 235.749 51.119 L 235.749 59.973 L 229.247 59.973 L 229.247 51.119 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 224.762 51.119 L 226.332 51.119 L 226.332 55.233 L 224.762 55.233 L 224.762 51.119 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 272.519 51.119 L 274.313 51.119 L 274.313 55.233 L 272.519 55.233 L 272.519 51.119 Z"/>
<path style="fill: rgb(51, 51, 51); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 168.486 49.688 L 222.296 49.688 L 222.296 66.501 L 168.486 66.501 L 168.486 49.688 Z"/>
<path style="fill: rgb(229, 229, 229); stroke-width: 1;" d="M 185.526 60.778 L 192.028 60.778 L 192.028 63.103 L 185.526 63.103 L 185.526 60.778 Z"/>
<path style="fill: rgb(178, 178, 178); stroke-width: 1;" d="M 200.324 62.745 L 198.978 61.672 L 198.978 60.152 L 200.324 59.079 L 202.117 59.079 L 203.687 60.152 L 203.687 61.672 L 202.117 62.745 L 200.324 62.745 Z"/>
<path style="fill: rgb(178, 178, 178); stroke-width: 1;" d="M 207.947 62.745 L 206.602 61.672 L 206.602 60.152 L 207.947 59.079 L 209.74 59.079 L 211.086 60.152 L 211.086 61.672 L 209.74 62.745 L 207.947 62.745 Z"/>
<path style="fill: rgb(102, 102, 102); stroke-width: 1;" d="M 176.109 60.778 L 182.611 60.778 L 182.611 63.103 L 176.109 63.103 L 176.109 60.778 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 179.024 54.339 L 179.024 59.079 L 176.782 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 183.06 54.339 L 183.06 59.079 L 180.93 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 187.32 54.339 L 187.32 59.079 L 184.853 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 191.355 54.339 L 191.355 59.079 L 188.889 59.079"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 188.889 59.079 L 188.889 54.339 L 191.355 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 184.853 59.079 L 184.853 54.339 L 187.32 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 180.93 59.079 L 180.93 54.339 L 183.06 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 176.782 59.079 L 176.782 54.339 L 179.024 54.339"/>
<path style="fill: rgb(127, 127, 127); stroke-width: 1;" d="M 197.857 66.859 L 222.296 104.241 L 222.296 94.404 L 204.135 66.859 L 197.857 66.859 Z"/>
<path style="fill: rgb(102, 102, 102); stroke-width: 1;" d="M 204.135 66.859 L 222.296 94.404 L 222.296 84.566 L 210.637 66.859 L 204.135 66.859 Z"/>
<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.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"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 166.356 102.453 L 278.348 74.371 L 278.348 114.973 L 166.356 114.973 L 166.356 102.453 Z"/>
<path style="fill: rgb(204, 204, 204); stroke-width: 1;" d="M 168.486 49.688 L 276.106 49.688 L 276.106 109.249 L 168.486 109.249 L 168.486 49.688 Z"/>
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 222.296 91.9 L 276.106 67.038 L 276.106 109.249 L 222.296 109.249 L 222.296 91.9 Z"/>
<path style="fill: rgb(199, 199, 199); stroke-width: 1;" d="M 168.486 92.079 L 222.296 67.038 L 222.296 109.249 L 168.486 109.249 L 168.486 92.079 Z"/>
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 222.296 94.583 L 276.106 69.542 L 276.106 109.249 L 222.296 109.249 L 222.296 94.583 Z"/>
<path style="fill: rgb(194, 194, 194); stroke-width: 1;" d="M 168.486 94.583 L 222.296 69.542 L 222.296 109.249 L 168.486 109.249 L 168.486 94.583 Z"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 222.296 98.16 L 276.106 73.298 L 276.106 109.249 L 222.296 109.249 L 222.296 98.16 Z"/>
<path style="fill: rgb(189, 189, 189); stroke-width: 1;" d="M 168.486 98.16 L 222.296 73.298 L 222.296 109.249 L 168.486 109.249 L 168.486 98.16 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" 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"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 222.296 49.688 L 276.106 49.688 L 276.106 109.249 L 222.296 109.249 L 222.296 49.688"/>
<path style="fill: rgb(153, 153, 153); stroke-width: 1;" d="M 240.906 110.323 L 259.739 110.323 L 259.739 113.9 L 240.906 113.9 L 240.906 110.323 Z"/>
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 169.607 108.713 L 169.159 108.176 L 169.607 107.64 L 170.504 107.64 L 170.952 108.176 L 170.504 108.713 L 169.607 108.713 Z"/>
<path style="fill: rgb(76, 76, 76); stroke-width: 1;" d="M 169.607 68.111 L 169.159 67.575 L 169.607 66.859 L 170.504 66.859 L 170.952 67.575 L 170.504 68.111 L 169.607 68.111 Z"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 168.486 49.688 L 222.296 49.688 L 222.296 109.249 L 168.486 109.249 L 168.486 49.688"/>
<path style="fill: rgb(229, 229, 229); stroke-width: 1;" d="M 229.247 51.119 L 235.749 51.119 L 235.749 59.973 L 229.247 59.973 L 229.247 51.119 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 224.762 51.119 L 226.332 51.119 L 226.332 55.233 L 224.762 55.233 L 224.762 51.119 Z"/>
<path style="fill: rgb(0, 0, 0); stroke-width: 1;" d="M 272.519 51.119 L 274.313 51.119 L 274.313 55.233 L 272.519 55.233 L 272.519 51.119 Z"/>
<path style="fill: rgb(51, 51, 51); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 168.486 49.688 L 222.296 49.688 L 222.296 66.501 L 168.486 66.501 L 168.486 49.688 Z"/>
<path style="fill: rgb(229, 229, 229); stroke-width: 1;" d="M 185.526 60.778 L 192.028 60.778 L 192.028 63.103 L 185.526 63.103 L 185.526 60.778 Z"/>
<path style="fill: rgb(178, 178, 178); stroke-width: 1;" d="M 200.324 62.745 L 198.978 61.672 L 198.978 60.152 L 200.324 59.079 L 202.117 59.079 L 203.687 60.152 L 203.687 61.672 L 202.117 62.745 L 200.324 62.745 Z"/>
<path style="fill: rgb(178, 178, 178); stroke-width: 1;" d="M 207.947 62.745 L 206.602 61.672 L 206.602 60.152 L 207.947 59.079 L 209.74 59.079 L 211.086 60.152 L 211.086 61.672 L 209.74 62.745 L 207.947 62.745 Z"/>
<path style="fill: rgb(102, 102, 102); stroke-width: 1;" d="M 176.109 60.778 L 182.611 60.778 L 182.611 63.103 L 176.109 63.103 L 176.109 60.778 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 179.024 54.339 L 179.024 59.079 L 176.782 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 183.06 54.339 L 183.06 59.079 L 180.93 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 187.32 54.339 L 187.32 59.079 L 184.853 59.079"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 191.355 54.339 L 191.355 59.079 L 188.889 59.079"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 188.889 59.079 L 188.889 54.339 L 191.355 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 184.853 59.079 L 184.853 54.339 L 187.32 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 180.93 59.079 L 180.93 54.339 L 183.06 54.339"/>
<path style="fill: none; stroke: rgb(127, 127, 127); stroke-width: 2;" d="M 176.782 59.079 L 176.782 54.339 L 179.024 54.339"/>
<path style="fill: rgb(127, 127, 127); stroke-width: 1;" d="M 197.857 66.859 L 222.296 104.241 L 222.296 94.404 L 204.135 66.859 L 197.857 66.859 Z"/>
<path style="fill: rgb(102, 102, 102); stroke-width: 1;" d="M 204.135 66.859 L 222.296 94.404 L 222.296 84.566 L 210.637 66.859 L 204.135 66.859 Z"/>
<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 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"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 350 L 775 350 L 775 347.558 L 760.743 342.884 L 732.114 342.884 L 717.857 347.558 L 717.857 350 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 770.133 334.023 L 770.133 337.512 L 756.391 337.512 L 756.391 334.023 L 770.133 334.023 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 347.558 L 775 347.558"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 675 285.361 L 703.571 285.361 L 703.571 350 L 675 350 L 675 285.361 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 287.463 L 701.169 287.463 L 701.169 350 L 677.317 350 L 677.317 287.463 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 290.616 L 701.169 290.616 L 701.169 297.898 L 677.317 297.898 L 677.317 290.616 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 297.898 L 701.169 297.898 L 701.169 305.181 L 677.317 305.181 L 677.317 297.898 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 293.694 L 698.767 293.694 L 698.767 294.745 L 679.72 294.745 L 679.72 293.694 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 300 L 698.767 300 L 698.767 303.078 L 679.72 303.078 L 679.72 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 275 L 698.767 275 L 703.571 285.361 L 675 285.361 L 679.72 275 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 695.163 300 L 701.169 300 L 701.169 303.078 L 695.163 303.078 L 695.163 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 300 L 698.767 300 L 698.767 303.078 L 697.566 303.078 L 697.566 300 Z"/>
<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 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"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 350 L 775 350 L 775 347.558 L 760.743 342.884 L 732.114 342.884 L 717.857 347.558 L 717.857 350 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 770.133 334.023 L 770.133 337.512 L 756.391 337.512 L 756.391 334.023 L 770.133 334.023 Z"/>
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 717.857 347.558 L 775 347.558"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 675 285.361 L 703.571 285.361 L 703.571 350 L 675 350 L 675 285.361 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 287.463 L 701.169 287.463 L 701.169 350 L 677.317 350 L 677.317 287.463 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 290.616 L 701.169 290.616 L 701.169 297.898 L 677.317 297.898 L 677.317 290.616 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 677.317 297.898 L 701.169 297.898 L 701.169 305.181 L 677.317 305.181 L 677.317 297.898 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 293.694 L 698.767 293.694 L 698.767 294.745 L 679.72 294.745 L 679.72 293.694 Z"/>
<path style="fill: rgb(0, 0, 0); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 300 L 698.767 300 L 698.767 303.078 L 679.72 303.078 L 679.72 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 679.72 275 L 698.767 275 L 703.571 285.361 L 675 285.361 L 679.72 275 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 695.163 300 L 701.169 300 L 701.169 303.078 L 695.163 303.078 L 695.163 300 Z"/>
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 697.566 300 L 698.767 300 L 698.767 303.078 L 697.566 303.078 L 697.566 300 Z"/>
<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="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 625 75 L 625 114.125 L 625 264.125 L 625 450"/>
</svg>

After

Width:  |  Height:  |  Size: 45 KiB

566
src/assets/svg/test-new.svg Normal file
View File

@@ -0,0 +1,566 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 2750 1600" version="1.1" id="svg2113" xmlns="http://www.w3.org/2000/svg"
xmlns:bx="https://boxy-svg.com">
<defs id="defs1583">
<bx:grid x="0" y="0" width="62.847" height="59.308" />
</defs>
<rect width="2765.268" height="1601.316" style="fill: rgb(249, 249, 249); stroke: rgb(0, 0, 0);" id="rect1585" />
<g transform="matrix(3.756041, 0, 0, 3.411999, -325.08066, -171.136964)" style="" id="g1595">
<rect x="111.721" y="167.133" width="2.541" height="6.598" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1587" />
<rect x="111.373" y="178.442" width="2.889" height="6.598" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1589" />
<rect x="111.373" y="190.204" width="2.889" height="6.598" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1591" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
d="M 105.737 163.995 L 103.281 166.267 L 103.337 197.271 L 105.513 200 L 109.364 200 L 111.373 197.271 C 111.373 197.271 111.3 166.386 111.3 166.355 C 111.3 166.325 109.158 163.986 109.158 163.986 L 105.737 163.995 Z"
id="path1593" />
</g>
<rect x="221.266" y="4276.899" height="719.302"
style="fill: rgb(216, 216, 216); stroke: rgb(255, 230, 0); transform-box: fill-box; transform-origin: 50% 50%;"
transform="matrix(0, -1, 1, 0, 241.54927, -4187.271127)" width="1.854" id="rect1597" />
<g style="" transform="matrix(1.967086, 0, 0, 2.764776, 8.509805, 20.443167)" id="g1605">
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1;"
d="M 160.097 163.649 L 200 148.321 L 200 163.649 L 160.097 148.321 L 160.097 163.649 Z" id="path1599" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1; transform-origin: 180.051px 148.792px;"
d="M 180.051 155.918 L 180.051 141.666" id="path1601" />
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1;"
d="M 180.091 141.868 L 163.816 141.868 L 163.902 140.59 L 164.165 139.38 L 164.515 138.17 L 165.127 137.028 L 165.827 135.952 L 166.614 134.944 L 167.578 133.934 L 168.627 133.061 L 169.764 132.255 L 170.99 131.582 L 172.39 130.909 L 173.79 130.439 L 175.277 129.968 L 176.853 129.699 L 178.428 129.497 L 180.091 129.431 L 181.754 129.497 L 183.415 129.699 L 184.904 129.968 L 186.478 130.439 L 187.879 130.909 L 189.191 131.582 L 190.416 132.255 L 191.642 133.061 L 192.692 133.934 L 193.567 134.944 L 194.441 135.952 L 195.054 137.028 L 195.666 138.17 L 196.017 139.38 L 196.279 140.59 L 196.366 141.868 L 180.091 141.868 Z"
id="path1603" />
</g>
<rect x="570.504" y="312.334" width="1.617" height="134.41"
style="fill: rgb(216, 216, 216); stroke: rgb(255, 230, 0); transform-origin: 571.311px 379.538px;" id="rect1607" />
<rect x="192.153" y="622.531" width="170.94" height="200.351" style="fill: rgb(179, 179, 179); stroke: rgb(0, 0, 0);"
id="rect1609" />
<rect x="363.093" y="636.243" width="11.348" height="175.002" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1611" />
<rect x="1311.745" y="222.133" width="24.158" height="66.668"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%;"
transform="matrix(0, 1, -1, 0, -916.048411, 468.548218)" id="rect1613" />
<g transform="matrix(1.967086, 0, 0, 2.255241, -84.857842, 158.144456)" id="g1627">
<rect x="-270.583" y="233.554" width="2.468" height="4.532" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1615" />
<rect x="-271.043" y="248.421" width="2.928" height="4.29" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1617" />
<rect x="207.97" y="-262.356" width="2.928" height="4.551" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 479.012726, 525.711979)" id="rect1619" />
<path style="fill: rgb(5, 121, 40); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%;"
d="M 274.287 273.087 L 271.043 270.353 L 271.117 233.051 L 273.991 229.767 L 279.077 229.767 L 281.731 233.051 C 281.731 233.051 281.634 270.21 281.634 270.248 C 281.634 270.284 278.805 273.098 278.805 273.098 L 274.287 273.087 Z"
transform="matrix(-1, 0, 0, -1, 0.000001, 0.000002)" id="path1621" />
<rect x="270.583" y="-241.384" width="2.468" height="4.451" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 541.166016, 482.768005)" id="rect1623" />
<rect x="-270.583" y="255.823" width="2.468" height="4.658" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1625" />
</g>
<rect x="1814.407" y="219.287" width="36.797" height="68.004"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1832.81px 253.29px;"
transform="matrix(0, 1, -1, 0, -1263.114954, 471.648948)" id="rect1629" />
<g transform="matrix(-1.967086, 0, 0, 2.255241, 1061.308724, 158.144456)" style="" id="g1643">
<rect x="-270.583" y="233.554" width="2.468" height="4.532" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1631" />
<rect x="-271.043" y="248.421" width="2.928" height="4.29" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1633" />
<rect x="207.97" y="-262.356" width="2.928" height="4.551" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 479.012726, 525.711979)" id="rect1635" />
<path style="fill: rgb(5, 121, 40); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%;"
d="M 274.287 273.087 L 271.043 270.353 L 271.117 233.051 L 273.991 229.767 L 279.077 229.767 L 281.731 233.051 C 281.731 233.051 281.634 270.21 281.634 270.248 C 281.634 270.284 278.805 273.098 278.805 273.098 L 274.287 273.087 Z"
transform="matrix(-1, 0, 0, -1, 0.000001, 0.000002)" id="path1637" />
<rect x="270.583" y="-241.384" width="2.468" height="4.451" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 541.166016, 482.768005)" id="rect1639" />
<rect x="-270.583" y="255.823" width="2.468" height="4.658" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1641" />
</g>
<rect x="603.693" y="580.559" width="11.348" height="284.474" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1645" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%;"
d="M 507.186 740.424 L 550.252 704.131 L 722.03 703.268 L 765.747 740.642 L 507.186 740.424 Z" id="path1647"
transform="matrix(0, 0.872229, -1.146488, 0, -0.000028, 0.000006)" />
<rect x="657.992" y="580.559" width="34.149" height="284.474" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1649" />
<rect x="671.676" y="142.765" width="12.37" height="42.847"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 677.862px 164.189px;"
transform="matrix(0, 1, -1, 0, -41.394006, 438.822517)" id="rect1651" />
<rect x="671.676" y="142.765" width="12.37" height="42.849"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 677.862px 164.191px;"
transform="matrix(0, 1, -1, 0, -41.395654, 676.71634)" id="rect1653" />
<rect x="671.676" y="142.759" width="12.37" height="42.847"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 677.862px 164.183px;"
transform="matrix(0, 1, -1, 0, -41.393823, 469.979671)" id="rect1655" />
<rect x="671.676" y="142.763" width="12.37" height="42.849"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 677.862px 164.189px;"
transform="matrix(0, 1, -1, 0, -41.396143, 640.873796)" id="rect1657" />
<rect x="692.141" y="609.194" width="11.348" height="225.524" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1659" />
<rect x="703.489" y="627.978" width="78.52" height="190.076" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1661" />
<rect x="734.874" y="627.978" width="11.348" height="190.076" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1663" />
<rect x="782.009" y="580.559" width="84.791" height="284.474" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1665" />
<rect x="912.958" y="653.978" width="34.351" height="142.639" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1667" />
<rect x="387.88" y="481.524" width="3.04" height="170.655" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(0.998593, -0.053021, 0, 1.001409, 560.055851, 178.939058)" id="rect1669" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%;"
d="M 726.028 743.604 L 808.32 701.986 L 970.629 701.986 L 1052.174 743.604 L 726.028 743.604 Z" id="path1671"
transform="matrix(0, 0.872229, -1.146488, 0, -0.00006, -0.000073)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 966.433px 728.04px;"
d="M 851.71 741.93 L 909.604 714.15 L 1023.79 714.15 L 1081.159 741.93 L 851.71 741.93 Z" id="path1673"
transform="matrix(0, 0.872229, -1.146488, 0, 0.00001, 0.000013)" />
<rect x="780.851" y="481.524" width="6.12" height="170.655" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(0.998593, -0.053021, 0, 1.001409, 202.605928, 199.545717)" id="rect1675" />
<rect x="989.142" y="656.234" width="44.023" height="142.639" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1677" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1040.14px 723.043px;"
d="M 839.576 716.183 L 884.529 729.902 L 1200.198 729.902 L 1240.694 716.272 L 839.576 716.183 Z" id="path1679"
transform="matrix(0, 0.872229, -1.146488, 0, -0.000087, -0.000004)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
d="M 1048.001 548.108 L 1048.304 897.975 L 1207.093 897.975 L 1218.978 875.774 L 1219.181 569.45 L 1207.954 548.801 L 1048.001 548.108 Z"
id="path1681" />
<rect x="1219.18" y="568.827" width="27.547" height="308.201" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1683" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1250.61px 722.928px;"
d="M 1073.93 726.31 L 1113.529 719.546 L 1391.606 719.546 L 1427.277 726.267 L 1073.93 726.31 Z" id="path1685"
transform="matrix(0, 0.872229, -1.146488, 0, 0.000091, -0.000014)" />
<rect x="1254.482" y="596.467" width="44.499" height="254.908" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1687" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1475.41px 727.407px;"
d="M 1256.467 722.549 L 1278.178 732.178 L 1672.628 732.254 L 1694.355 722.901 L 1256.467 722.549 Z" id="path1689"
transform="matrix(0, 0.872229, -1.146488, 0, 0.000073, 0.000005)" />
<rect x="1298.981" y="568.827" width="44.499" height="308.201" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1691" />
<rect x="1343.481" y="596.824" width="44.499" height="254.908" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1693" />
<rect x="1387.98" y="596.824" width="21.872" height="254.908" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1695" />
<rect x="1409.852" y="596.824" width="44.499" height="254.908" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1697" />
<rect x="1454.351" y="520.549" width="15.503" height="409.931" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1699" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1486.54px 729.878px;"
d="M 1285.741 725.021 L 1305.656 734.65 L 1667.405 734.725 L 1687.333 725.373 L 1285.741 725.021 Z" id="path1701"
transform="matrix(0, 0.872229, -1.146488, 0, -0.000073, 0.000112)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1497.66px 730.53px;"
d="M 1312.27 725.673 L 1330.659 735.302 L 1664.657 735.377 L 1683.056 726.025 L 1312.27 725.673 Z" id="path1703"
transform="matrix(0, 0.872229, -1.146488, 0, 0.000015, -0.000034)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1508.79px 733.956px;"
d="M 1344.755 729.099 L 1361.021 738.727 L 1656.546 738.803 L 1672.82 729.45 L 1344.755 729.099 Z" id="path1705"
transform="matrix(0, 0.872229, -1.146488, 0, -0.000137, 0.000068)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1519.91px 734.718px;"
d="M 1368.907 729.861 L 1383.883 739.49 L 1655.938 739.565 L 1670.927 730.213 L 1368.907 729.861 Z" id="path1707"
transform="matrix(0, 0.872229, -1.146488, 0, -0.000023, -0.000055)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1531.04px 734.75px;"
d="M 1388.217 729.893 L 1402.375 739.521 L 1659.692 739.597 L 1673.869 730.244 L 1388.217 729.893 Z" id="path1709"
transform="matrix(0, 0.872229, -1.146488, 0, 0.000068, -0.000003)" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-origin: 1542.17px 732.158px;"
d="M 1413.447 727.301 L 1426.21 736.93 L 1658.11 737.005 L 1670.886 727.653 L 1413.447 727.301 Z" id="path1711"
transform="matrix(0, 0.872229, -1.146488, 0, -0.000157, 0.000035)" />
<rect x="1547.735" y="619.886" width="16.773" height="224.545" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1713" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
d="M 1565.938 502.426 C 1565.938 502.426 1562.4376824661815 892.9090808121027 1566.214 945.552 C 1567.0379405282195 957.0379606625416 1565.9094864891053 963.619303438939 1569.212 966.433 C 1571.519042488712 968.3985687994298 1577.3044475621036 968.2986812007803 1579.505 966.259 C 1582.6326889892484 963.3599605027395 1580.896216996098 956.9246936747566 1581.431 945.552 C 1583.9015586930873 893.0131066227198 1585.3790228328503 546.5920914640369 1581.978 501.716 C 1581.3657807394668 493.6378397282225 1582.3293586890359 489.67728117870035 1579.793 487.501 C 1577.6385435938726 485.6524038423454 1571.744195211586 485.6529690725045 1569.416 487.501 C 1566.5866798051243 489.74680447459815 1565.938 502.426 1565.938 502.426 C 1565.9379999999999 502.42599999999993 1565.938 502.426 1565.938 502.426 C 1565.938 502.426 1565.9380000000003 502.4260000000001 1565.938 502.426"
id="path1715"
bx:d="M 1565.938 502.426 R 1566.214 945.552 R 1569.212 966.433 R 1579.505 966.259 R 1581.431 945.552 R 1581.978 501.716 R 1579.793 487.501 R 1569.416 487.501 R 1565.938 502.426 R 1565.938 502.426 Z 1@8154597a" />
<path style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); transform-box: fill-box; transform-origin: 50% 50%;"
d="M 1549.808 751.776 L 1677.314 751.035 C 1677.314 751.035 1677.314 726.268 1677.314 725.991 C 1677.314 725.714 1663.065 700.76 1663.065 700.76 L 1564.013 701.59 L 1549.107 726.268 L 1549.808 751.776 Z"
id="path1717" transform="matrix(0, 0.872229, -1.146488, 0, 0.000076, -0.000036)" />
<rect x="1632.876" y="655.365" width="9.58" height="142.788" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1719" />
<rect x="1660.461" y="596.755" width="5.046" height="48.404" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1721" transform="matrix(1, 0, 0, 1, -18.004511, 103.828065)" />
<rect x="1647.502" y="676.325" width="8.445" height="101.391" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1723" />
<rect x="1673.951" y="577.366" width="4.198" height="91.421" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1725" transform="matrix(1, 0, 0, 1, -18.004511, 103.828065)" />
<rect x="1660.144" y="684.807" width="85.36" height="79.267" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1727" />
<rect x="1795.977" y="604.057" width="14.617" height="26.594" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -19.971598, 106.083306)" id="rect1729" />
<rect x="1749.438" y="661.186" width="24.897" height="132.31" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1731" />
<rect x="1757.53" y="559.76" width="10.489" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -19.971598, 106.083306)" id="rect1733" />
<rect x="1763.434" y="611.146" width="10.487" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -25.872856, 106.083306)" id="rect1735" />
<rect x="1763.432" y="661.737" width="10.487" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -25.872856, 106.083306)" id="rect1737" />
<rect x="1365.579" y="186.044" width="1.963" height="36.402" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, 380.50336, 492.679508)" id="rect1739" />
<rect x="1689.88" y="573.855" width="1.395" height="35.82" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, 56.772358, 158.144456)" id="rect1741" />
<rect x="1797.053" y="559.491" width="10.489" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -21.938683, 106.083306)" id="rect1743" />
<rect x="1800.989" y="610.877" width="10.487" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -25.872856, 106.083306)" id="rect1745" />
<rect x="1793.121" y="661.469" width="10.487" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -18.004511, 106.083306)" id="rect1747" />
<rect x="1791.424" y="672.34" width="7.064" height="236.318" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1749" />
<rect x="1798.487" y="655.365" width="131.944" height="264.986"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);" id="rect1751" />
<rect x="1803.02" y="661.186" width="122.717" height="253.381" style="fill: rgb(246, 246, 246); stroke: rgb(0, 0, 0);"
id="rect1753" />
<g style="" transform="matrix(1.018862, 0, 0, 0.560739, 848.629096, 547.548161)" id="g1771">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1755" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1757" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1759" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1761" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1763" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1765" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1767" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1769" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.522625, 848.629096, 533.266483)" id="g1789">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1773" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1775" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1777" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1779" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1781" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1783" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1785" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1787" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.576848, 848.629096, 569.471135)" id="g1807">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1791" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1793" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1795" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1797" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1799" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1801" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1803" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1805" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.580201, 848.629096, 593.583928)" id="g1825">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1809" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1811" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1813" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1815" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1817" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1819" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1821" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1823" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.450487, 848.629096, 651.557073)" id="g1843">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1827" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1829" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1831" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1833" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1835" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1837" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1839" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1841" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.459332, 848.629096, 669.753301)" id="g1861">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1845" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1847" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1849" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1851" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1853" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1855" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1857" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1859" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.522625, 848.629096, 675.022405)" id="g1879">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1863" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1865" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1867" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1869" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1871" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1873" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1875" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1877" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.522625, 848.629096, 698.643987)" id="g1897">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1881" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1883" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1885" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1887" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1889" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1891" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1893" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1895" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.522625, 848.629096, 722.26563)" id="g1915">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1899" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1901" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1903" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1905" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1907" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1909" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1911" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1913" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.522625, 848.629096, 745.887152)" id="g1933">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1917" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1919" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1921" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1923" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1925" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1927" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1929" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1931" />
</g>
<g style="" transform="matrix(1.018862, 0, 0, 0.39464, 848.629096, 800.136481)" id="g1951">
<path style="fill: rgb(230, 230, 230); stroke: rgb(76, 76, 76); stroke-width: 2;"
d="M 989.672 289.959 L 989.672 244.761 L 1009.612 244.761 L 1009.612 289.959 L 989.672 289.959 Z" id="path1935" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 250.366 L 1009.612 250.366"
id="path1937" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 256.03 L 1009.612 256.03"
id="path1939" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 261.635 L 1009.612 261.635"
id="path1941" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 267.3 L 1009.612 267.3"
id="path1943" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 272.965 L 1009.612 272.965"
id="path1945" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 278.629 L 1009.612 278.629"
id="path1947" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 2;" d="M 989.672 284.234 L 1009.612 284.234"
id="path1949" />
</g>
<rect x="1816.162" y="699.155" width="19.366" height="49.631" style="fill: rgb(242, 189, 189); stroke: rgb(0, 0, 0);"
id="rect1953" />
<rect x="1888.417" y="699.155" width="19.366" height="49.631" style="fill: rgb(242, 189, 189); stroke: rgb(0, 0, 0);"
id="rect1955" />
<rect x="1785.603" y="716.96" width="126.859" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1957" />
<rect x="1930.432" y="670.354" width="7.064" height="236.318" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1959" />
<rect x="-1907.783" y="834.718" width="19.366" height="49.631" style="fill: rgb(242, 189, 189); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1961" />
<rect x="-1853.532" y="730.89" width="19.366" height="49.631" style="fill: rgb(242, 189, 189); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, -18.004396, 103.828089)" id="rect1963" />
<rect x="1937.985" y="839.138" width="100.302" height="40.159" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1965" />
<rect x="1937.985" y="846.571" width="24.897" height="24.625" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1967" />
<rect x="-1962.883" y="852.523" width="152.247" height="12.88" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 0, 0)" id="rect1969" />
<rect x="1988.046" y="823.358" width="18.559" height="74.071" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1971" />
<rect x="987.703" y="358.288" width="5.256" height="7.21" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, 994.049751, 467.679142)" id="rect1973" />
<rect x="2070.573" y="748.65" width="5.254" height="7.21" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -88.819611, 106.083306)" id="rect1975" />
<rect x="866.734" y="341.306" width="5.254" height="7.21" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, 1115.019173, 541.748722)" id="rect1977" />
<rect x="2038.287" y="839.138" width="38.832" height="40.159" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1979" />
<rect x="2077.119" y="665.843" width="20.987" height="357.686" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1981" />
<rect x="987.703" y="358.288" width="5.256" height="7.21" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, 1018.901741, 467.679142)" id="rect1983" />
<rect x="2136.735" y="748.65" width="5.254" height="7.21" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, -130.128419, 106.083306)" id="rect1985" />
<rect x="866.734" y="341.306" width="5.254" height="7.21" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(1, 0, 0, 1, 1139.873544, 541.748722)" id="rect1987" />
<rect x="2098.104" y="637.371" width="391.487" height="411.061"
style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);" id="rect1989" />
<rect x="2509.225" y="839.136" width="38.832" height="40.159" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1991" />
<rect x="180.154" y="635.837" width="11.348" height="175.002" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1993" />
<rect x="2488.238" y="665.843" width="20.987" height="357.686" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
id="rect1995" />
<ellipse style="fill: rgb(16, 255, 40); stroke: rgb(0, 0, 0);" cx="2568.167" cy="859.043" rx="26.011" ry="30.315"
id="ellipse1997" />
<rect x="2750.419" y="-736.219" width="38.832" height="40.159" style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);"
transform="matrix(-1, 0, 0, 1, 5482.833562, 1576.26583)" id="rect1999" />
<rect x="2612.182" y="751.661" width="61.845" height="7.808" style="fill: rgb(16, 255, 40); stroke: rgb(0, 0, 0);"
id="rect2001" transform="matrix(1, 0, 0, 1, -18.004511, 103.828065)" />
<ellipse style="fill: rgb(16, 255, 40); stroke: rgb(0, 0, 0);" cx="2675.44" cy="859.952" rx="26.011" ry="30.315"
id="ellipse2003" />
<text
style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-weight: bold; font-size: 14px;"
x="108.414" y="257.057" id="text2017"
transform="matrix(1.967086, 0, 0, 2.255241, -18.004511, 103.828065)">STARTER</text>
<text
style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-weight: bold; font-size: 14px;"
x="1086.976" y="257.057" id="text2019"
transform="matrix(1.967086, 0, 0, 2.255241, -18.004511, 103.828065)">GENERATOR</text>
<g style="" transform="matrix(1.967086, 0, 0, 2.764776, 508.468418, 20.443167)" id="start">
<path style="stroke: rgb(76, 76, 76); stroke-width: 1; fill: rgb(114, 182, 33);"
d="M 160.097 163.649 L 200 148.321 L 200 163.649 L 160.097 148.321 L 160.097 163.649 Z" id="path2021" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1; transform-origin: 180.051px 148.792px;"
d="M 180.051 155.918 L 180.051 141.666" id="path2023" />
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1;"
d="M 180.091 141.868 L 163.816 141.868 L 163.902 140.59 L 164.165 139.38 L 164.515 138.17 L 165.127 137.028 L 165.827 135.952 L 166.614 134.944 L 167.578 133.934 L 168.627 133.061 L 169.764 132.255 L 170.99 131.582 L 172.39 130.909 L 173.79 130.439 L 175.277 129.968 L 176.853 129.699 L 178.428 129.497 L 180.091 129.431 L 181.754 129.497 L 183.415 129.699 L 184.904 129.968 L 186.478 130.439 L 187.879 130.909 L 189.191 131.582 L 190.416 132.255 L 191.642 133.061 L 192.692 133.934 L 193.567 134.944 L 194.441 135.952 L 195.054 137.028 L 195.666 138.17 L 196.017 139.38 L 196.279 140.59 L 196.366 141.868 L 180.091 141.868 Z"
id="path2025" />
</g>
<rect x="221.413" y="1002.801" width="1.854" height="168.654"
style="fill: rgb(216, 216, 216); stroke: rgb(255, 230, 0); transform-origin: 222.34px 1087.13px;"
transform="matrix(0, -1, 1, 0, 763.873214, -637.849971)" id="rect2029" />
<rect x="374.641" y="101.049" width="0.825" height="198.326"
style="fill: rgb(216, 216, 216); stroke: rgb(255, 230, 0); transform-origin: 375.053px 200.208px;"
transform="matrix(0, 1, -1, 0, 294.61756, 111.712623)" id="rect2031" />
<g transform="matrix(1.967086, 0, 0, 2.255241, -488.110508, 103.828065)" id="g2039">
<path style="fill: rgb(192, 192, 192); stroke: rgb(76, 76, 76); stroke-width: 1;"
d="M 567.451 100 L 600 85.62 L 600 100 L 567.451 85.62 L 567.451 100 Z" id="path2033" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1;" d="M 583.725 92.747 L 583.725 77.736"
id="path2035" />
<path style="fill: rgb(192, 192, 192); stroke: rgb(76, 76, 76); stroke-width: 1;"
d="M 570.306 68.59 L 597.145 68.59 L 597.145 77.736 L 570.306 77.736 L 570.306 68.59 Z" id="path2037" />
</g>
<rect x="767.213" y="177.924" width="1.617" height="134.41"
style="fill: rgb(216, 216, 216); stroke: rgb(255, 230, 0); transform-origin: 768.019px 245.128px;" id="rect2041" />
<rect x="1070.54" y="448.35" height="97.503"
style="fill: rgb(216, 216, 216); stroke: rgb(255, 230, 0); transform-origin: 1071.58px 497.101px;" width="2.089"
id="rect2043" />
<line style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0);" x1="724.999" y1="710.607" x2="416.261" y2="944.343"
id="line2045" />
<rect x="276.022" y="952.397" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2047" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="173.639"
y="385.601" id="val_pt008a" transform="matrix(1.967086, 0, 0, 2.255241, -60.004517, 120.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="158.322"
y="487.153" id="text2051" transform="matrix(1.967086, 0, 0, 2.255241, -52.444386, 79.824853)">01-PT008-A</text>
<rect x="279.22" y="1190.531" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2053" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="171.889"
y="502.901" id="val_zt002" transform="matrix(1.967086, 0, 0, 2.255241, -54.735848, 94.476006)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="159.616"
y="369.076" id="text2057" transform="matrix(1.967086, 0, 0, 2.255241, -44.004513, 105.828065)">01-ZT002</text>
<rect x="522.842" y="951.928" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2059" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="277.994"
y="384.55" id="text2061" transform="matrix(1.967086, 0, 0, 2.255241, -19.693392, 121.658036)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="261.191"
y="368.446" id="text2063" transform="matrix(1.967086, 0, 0, 2.255241, -3.615977, 109.752755)">01-TE014-A</text>
<rect x="524.88" y="1071.852" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2065" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="276.954"
y="443.949" id="text2067" transform="matrix(1.967086, 0, 0, 2.255241, -13.004511, 107.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="260.151"
y="427.845" id="text2069" transform="matrix(1.967086, 0, 0, 2.255241, -5.004511, 98.828065)">01-TE014-B</text>
<rect x="761.776" y="952.548" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2071" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="380.973"
y="384.641" id="text2073" transform="matrix(1.967086, 0, 0, 2.255241, 18.995489, 121.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="364.17"
y="368.537" id="text2075" transform="matrix(1.967086, 0, 0, 2.255241, 37.810299, 111.378892)">01-TE015-A</text>
<rect x="761.73" y="1070.507" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2077" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="379.933"
y="444.04" id="text2079" transform="matrix(1.967086, 0, 0, 2.255241, 20.995489, 106.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="363.13"
y="427.936" id="text2081" transform="matrix(1.967086, 0, 0, 2.255241, 43.995491, 98.828065)">01-TE015-B</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="263.902"
y="487.153" id="text2083" transform="matrix(1.967086, 0, 0, 2.255241, -13.004511, 83.828065)">01-PT008-B</text>
<rect x="523.636" y="1188.88" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2085" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="277.469"
y="502.901" id="text2087" transform="matrix(1.967086, 0, 0, 2.255241, -16.004511, 92.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="366.542"
y="487.153" id="text2089" transform="matrix(1.967086, 0, 0, 2.255241, 37.144352, 81.927483)">01-PT008-C</text>
<rect x="763.687" y="1188.982" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2091" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="380.109"
y="502.901" id="text2093" transform="matrix(1.967086, 0, 0, 2.255241, 19.144352, 91.927483)">###.##</text>
<rect x="1065.115" y="713.167" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2095" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="564.157"
y="282.044" id="text2097" transform="matrix(1.967086, 0, 0, 2.255241, -36.004513, 115.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="554.354"
y="265.94" id="text2099" transform="matrix(1.967086, 0, 0, 2.255241, -32.004513, 95.828065)">01-KT001</text>
<rect x="1519.433" y="431.199" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2101" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="786.983"
y="157.016" id="text2103" transform="matrix(1.967086, 0, 0, 2.255241, -22.004511, 114.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="770.18"
y="140.912" id="text2105" transform="matrix(1.967086, 0, 0, 2.255241, -2.004511, 91.828065)">01-PDT007</text>
<rect x="1517.328" y="300.54" width="131" height="51" style="fill: rgb(255, 255, 255); stroke: rgb(0, 0, 0);"
id="rect2107" />
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 16px;" x="785.777"
y="104.795" id="text2109" transform="matrix(1.967086, 0, 0, 2.255241, -22.004511, 101.828065)">###.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 17px;" x="774.974"
y="88.691" id="text2111" transform="matrix(1.967086, 0, 0, 2.255241, -12.112564, 88.3145)">01-TE019</text>
<g style="" transform="matrix(1.967086, 0, 0, 2.764776, 509.086395, 21.011166)" id="stop">
<path style="stroke: rgb(76, 76, 76); stroke-width: 1; fill: rgb(224, 38, 38);"
d="M 160.097 163.649 L 200 148.321 L 200 163.649 L 160.097 148.321 L 160.097 163.649 Z" id="path-1" />
<path style="fill: none; stroke: rgb(76, 76, 76); stroke-width: 1; transform-origin: 180.051px 148.792px;"
d="M 180.051 155.918 L 180.051 141.666" id="path-2" />
<path style="fill: rgb(255, 255, 255); stroke: rgb(76, 76, 76); stroke-width: 1;"
d="M 180.091 141.868 L 163.816 141.868 L 163.902 140.59 L 164.165 139.38 L 164.515 138.17 L 165.127 137.028 L 165.827 135.952 L 166.614 134.944 L 167.578 133.934 L 168.627 133.061 L 169.764 132.255 L 170.99 131.582 L 172.39 130.909 L 173.79 130.439 L 175.277 129.968 L 176.853 129.699 L 178.428 129.497 L 180.091 129.431 L 181.754 129.497 L 183.415 129.699 L 184.904 129.968 L 186.478 130.439 L 187.879 130.909 L 189.191 131.582 L 190.416 132.255 L 191.642 133.061 L 192.692 133.934 L 193.567 134.944 L 194.441 135.952 L 195.054 137.028 L 195.666 138.17 L 196.017 139.38 L 196.279 140.59 L 196.366 141.868 L 180.091 141.868 Z"
id="path-3" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,64 @@
import React from "react";
import { Button, ConfigProvider } from 'antd';
import propTypes from 'prop-types';
const BasicButton = ({
// color,
text,
size,
block,
clickTheButton
}) => {
return (
<>
<ConfigProvider
theme={{
token: {
// colorBgContainer: '#23A55A',
colorText: 'white',
colorBgContainer: 'purple',
// Seed Token
// colorPrimary: '#23A55A',
// // colorPrimary: `${color}`,
// borderRadius: 8,
// // Alias Token
// // colorBgContainer: '#f6ffed',
// // colorBgContainer: {color},
},
components: {
Button: {
defaultBg: '#23A55A',
defaultColor: 'white',
}
},
}}
>
<Button
type=""
block={block}
size={size}
onClick={() => clickTheButton(block)}
// style={{
// background: "#23A55A",
// borderColor: "#23A55A",
// color: "white",
// }}
>
{text}
</Button>
</ConfigProvider>
</>
);
}
BasicButton.propTypes = {
// color: propTypes.string,
text: propTypes.string,
size: propTypes.string,
block: propTypes.bool,
clickTheButton: propTypes.any
}
export default BasicButton;

View File

@@ -0,0 +1,21 @@
import { theme } from "antd";
import React from "react";
// import packageJson from "../../../package.json";
const BasicInput = () => {
const {
token: { colorPrimary },
} = theme.useToken();
return (
<div
data-testid="versionContainer"
className="cursor-default fixed top-1 right-1 z-20 m-1"
style={{ color: colorPrimary }}
>
</div>
);
};
export default BasicInput;

View File

@@ -0,0 +1,58 @@
import { Layout, theme } from "antd";
import React from 'react'
import propTypes from 'prop-types';
const { Header } = Layout;
const navbarClass =
"text-white text-h5 flex flex-col whitespace-nowrap overflow-hidden text-ellipsis";
const styles = {
navbarTitleFullSize: navbarClass,
navbarTitle: navbarClass + " max-w-[calc(100vw-200px)]",
};
const NavBar = ({ fullSize }) => {
const {
token: { colorPrimary },
} = theme.useToken();
console.log("import.meta", import.meta)
return (
<Header
data-testid="navbarContainer"
className="fixed z-10 flex w-full drop-shadow-md"
style={{
backgroundColor: colorPrimary,
paddingInline: 0,
}}
>
<div className="flex h-full w-full items-center gap-4 pl-[5%]">
<a href="/">
<div
data-testid="navbarLogo"
className="h-12 w-48 bg-white text-center"
>
LOGO
</div>
</a>
<div
data-testid="navbarTitle"
className={fullSize ? styles.navbarTitleFullSize : styles.navbarTitle}
>
<div className="text-[2.9vw] font-bold leading-8 sm:text-h5">
{import.meta.env.VITE_PROJECT_NAME}
</div>
<div className="pb-1 text-[2vw] font-bold uppercase leading-3 sm:text-small">
{import.meta.env.VITE_PROJECT_DESCRIPTION}
</div>
</div>
</div>
</Header>
);
};
NavBar.propTypes = {
fullSize: propTypes.any,
}
export default NavBar;

View File

@@ -0,0 +1,20 @@
import { theme } from "antd";
import React from "react";
import packageJson from "../../../package.json";
const Version = () => {
const {
token: { colorPrimary },
} = theme.useToken();
return (
<div
data-testid="versionContainer"
className="cursor-default fixed top-1 right-1 z-20 m-1"
style={{ color: colorPrimary }}
>
v{packageJson.version}
</div>
);
};
export default Version;

View File

@@ -0,0 +1,175 @@
import axios from 'axios';
import Swal from 'sweetalert2';
const baseURL = import.meta.env.VITE_API_SERVER;
const instance = axios.create({
baseURL,
withCredentials: true,
});
// axios khusus refresh
const refreshApi = axios.create({
baseURL,
withCredentials: true,
});
instance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
console.error('🚨 Response Error Interceptor:', {
status: error.response?.status,
url: originalRequest.url,
message: error.response?.data?.message,
hasRetried: originalRequest._retry,
});
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
// 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');
// update token di header
instance.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
// console.log('🔁 Retrying original request...');
return instance(originalRequest);
} catch (refreshError) {
console.error(
'❌ Refresh token gagal:',
refreshError.response?.data || refreshError.message
);
localStorage.clear();
window.location.href = '/signin';
}
}
return Promise.reject(error);
}
);
async function ApiRequest({ method = 'GET', params = {}, prefix = '/', token = true } = {}) {
const isFormData = params instanceof FormData;
const request = {
method,
url: prefix,
data: params,
headers: {
'Accept-Language': 'en_US',
...(isFormData ? {} : { 'Content-Type': 'application/json' }),
},
};
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}`);
}
if (token && rawToken) {
const cleanToken = rawToken.replace(/"/g, '');
request.headers['Authorization'] = `Bearer ${cleanToken}`;
// 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 });
try {
const response = await instance(request);
// 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;
const message = error?.response?.data?.message || error.message || 'Something Wrong';
console.error('❌ API Error:', {
url: prefix,
status,
message,
fullError: error?.response?.data,
});
if (status !== 401) {
await cekError(status, message);
}
return { ...error.response, error: true };
}
}
async function cekError(status, message = '') {
if (status === 403) {
await Swal.fire({
icon: 'warning',
title: 'Forbidden',
text: message,
});
} else if (status >= 500) {
await Swal.fire({
icon: 'error',
title: 'Server Error',
text: message,
});
} else {
await Swal.fire({
icon: 'warning',
title: 'Peringatan',
text: message,
});
}
}
const SendRequest = async (queryParams) => {
try {
const response = await ApiRequest(queryParams);
// If ApiRequest returned error flag, return error structure
if (response.error) {
const errorMsg = response.data?.message || response.statusText || 'Request failed';
// Return consistent error structure instead of empty array
return {
statusCode: response.status || 500,
message: errorMsg,
data: null,
error: true,
};
}
return response || { statusCode: 200, data: [], message: 'Success' };
} catch (error) {
console.error('❌ SendRequest catch error:', error);
// Don't show Swal here, let the calling code handle it
// This allows better error handling in each API call
return {
statusCode: 500,
message: error.message || 'Something went wrong',
data: null,
error: true,
};
}
};
export { ApiRequest, SendRequest };

View File

@@ -0,0 +1,112 @@
import React from 'react';
import { Card, Button, Row, Col, Typography, Space, Tag } from 'antd';
import { EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
const { Text } = Typography;
const CardList = ({
data,
column,
header,
showPreviewModal,
showEditModal,
showDeleteDialog,
cardColor,
fieldColor,
}) => {
const getCardStyle = (color) => {
const colorStyle = color ?? '#F3EDEA'; // Orange color
return {
border: `2px solid ${colorStyle}`,
borderRadius: '8px',
textAlign: 'center', // Center text
};
};
const getTitleStyle = (color) => {
const backgroundColor = color ?? '#FCF2ED';
return {
backgroundColor,
color: '#fff',
padding: '2px 8px',
borderRadius: '4px',
display: 'inline-block', // ganti inline-block → block
width: 'fit-content', // biar lebarnya tetap menyesuaikan teks
};
};
return (
<Row gutter={[16, 16]} style={{ marginTop: '16px', justifyContent: 'left' }}>
{data.map((item) => (
<Col xs={24} sm={24} md={12} lg={6} key={item.device_id}>
<Card
title={
<div
style={{
display: 'flex',
justifyContent: 'space-between', // kiri & kanan
alignItems: 'center',
}}
>
<span
style={getTitleStyle(fieldColor ? item[fieldColor] : cardColor)}
>
{item[header]}
</span>
</div>
}
style={getCardStyle(fieldColor ? item[fieldColor] : cardColor)}
actions={[
showPreviewModal && (
<EyeOutlined
style={{ color: '#1890ff' }}
key="preview"
onClick={() => showPreviewModal(item)}
/>
),
showEditModal && (
<EditOutlined
style={{ color: '#faad14' }}
key="edit"
onClick={() => showEditModal(item)}
/>
),
showDeleteDialog && (
<DeleteOutlined
style={{ color: '#ff1818' }}
key="delete"
onClick={() => showDeleteDialog(item)}
/>
),
].filter(Boolean)} // <== Hapus elemen yang undefined
>
<div style={{ textAlign: 'left' }}>
{column.map((itemCard, index) => (
<React.Fragment key={index}>
{!itemCard.hidden &&
itemCard.title !== 'No' &&
itemCard.title !== 'Action' && (
<p style={{ margin: '8px 0' }}>
<Text strong>{itemCard.title}:</Text>{' '}
{itemCard.render
? itemCard.render(
item[itemCard.dataIndex],
item,
index
)
: item[itemCard.dataIndex] ||
item[itemCard.key] ||
'-'}
</p>
)}
</React.Fragment>
))}
</div>
</Card>
</Col>
))}
</Row>
);
};
export default CardList;

View File

@@ -0,0 +1,7 @@
let filterData = [];
export const setFilterData = (data) => {
filterData = data;
};
export const getFilterData = () => filterData;

View File

@@ -0,0 +1,48 @@
import { useState, useEffect } from 'react';
import { Typography } from 'antd';
const { Title, Text } = Typography;
const JamRealtimeAntd = () => {
const [waktu, setWaktu] = useState(new Date());
useEffect(() => {
const interval = setInterval(() => {
setWaktu(new Date());
}, 1000);
return () => clearInterval(interval);
}, []);
// Format custom manual untuk konsistensi
const formatWaktuLengkap = (date) => {
const hari = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
const bulan = [
'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni',
'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'
];
const namaHari = hari[date.getDay()];
const tanggal = date.getDate().toString().padStart(2, '0');
const namaBulan = bulan[date.getMonth()];
const tahun = date.getFullYear();
const jam = date.getHours().toString().padStart(2, '0');
const menit = date.getMinutes().toString().padStart(2, '0');
const detik = date.getSeconds().toString().padStart(2, '0');
return `${namaHari}, ${tanggal} ${namaBulan} ${tahun} ${jam}:${menit}:${detik}`;
};
return (
<Text style={{
fontSize: '25px',
// fontWeight: 'bold',
color: '#1BAA56'
}}>
{formatWaktuLengkap(waktu)}
</Text>
);
};
export default JamRealtimeAntd;

View File

@@ -0,0 +1,24 @@
import { Empty, Col, Row, Typography } from "antd";
const {Text} = Typography;
const EmptyData = ({
titleButton,
titlePositionButton
})=>{
return(
<Empty
description={
<Col xs={24} sm={24} md={24} lg={24} xl={24}>
<Row justify="center" align="middle" style={{ height: "100%" }}>
<Text style={{fontSize:'22px', fontWeight:'bold'}}>Data Kosong</Text>
</Row>
<Row justify="center" align="middle" style={{ height: "100%"}}>
<Text style={{width:'20%', fontSize:'20px'}}>Untuk menampilkan data silahkan klik tombol <Text strong style={{fontSize:'20px'}}>{titleButton}</Text> {titlePositionButton}</Text>
</Row>
</Col>
}
/>
);
};
export default EmptyData;

View File

@@ -0,0 +1,192 @@
const formatIDR = (value) => {
if (!value) return '';
return new Intl.NumberFormat('id-ID', {
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}).format(value);
};
const formatCurrencyUSD = (value) => {
if (!value) return '';
const numericValue = value.replace(/[^0-9.]/g, ''); // Hanya angka dan titik
const parts = numericValue.split('.'); // Pisahkan bagian desimal
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); // Tambahkan koma
return `${parts.join('.')}`; // Gabungkan kembali dengan simbol $
};
const formatCurrencyIDR = (value) => {
if (!value) return '';
const numericValue = value.replace(/[^0-9]/g, '');
return numericValue.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
};
const toApiNumberFormatter = (value) => {
if (!value) return '';
const formattedValue = value.replace(/[.,]/g, ''); // Hapus semua titik
return Number(formattedValue);
};
const toAppDateFormatter = (value) => {
const date = new Date(value);
const months = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const day = date.getUTCDate().toString().padStart(2, '0');
const month = months[date.getUTCMonth()];
const year = date.getUTCFullYear();
const formattedDate = `${day} ${month} ${year}`;
return formattedDate;
};
const toAppDateFormatterTwoDigit = (value) => {
const date = new Date(value);
// Pastikan validitas tanggal
if (isNaN(date.getTime())) {
return 'Invalid Date'; // Handle nilai tidak valid
}
const day = date.getUTCDate().toString().padStart(2, '0');
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 ke bulan karena bulan dimulai dari 0
const year = date.getUTCFullYear();
const formattedDate = `${day}-${month}-${year}`;
return formattedDate;
};
const toApiDateFormatter = (value) => {
const parts = value.split('-');
if (parts.length === 3) {
const day = parts[0];
const month = parts[1];
const year = parts[2];
return `${year}-${month}-${day}`;
}
return '';
};
const toAppDateTimezoneFormatter = (value) => {
const jakartaTimezone = 'Asia/Jakarta';
const date = new Date(value);
const formatterDay = new Intl.DateTimeFormat('en-US', {
timeZone: jakartaTimezone,
day: '2-digit',
});
const formatterMonth = new Intl.DateTimeFormat('en-US', {
timeZone: jakartaTimezone,
month: 'short',
});
const formatterYear = new Intl.DateTimeFormat('en-US', {
timeZone: jakartaTimezone,
year: 'numeric',
});
const day = formatterDay.format(date);
const month = formatterMonth.format(date);
const year = formatterYear.format(date);
return `${day} ${month} ${year}`;
};
const toApiDateTimezoneFormatter = (value) => {
const jakartaTimezone = 'Asia/Jakarta';
const date = new Date(value);
const formatterDay = new Intl.DateTimeFormat('en-US', {
timeZone: jakartaTimezone,
day: '2-digit',
});
const formatterMonth = new Intl.DateTimeFormat('en-US', {
timeZone: jakartaTimezone,
month: '2-digit',
});
const formatterYear = new Intl.DateTimeFormat('en-US', {
timeZone: jakartaTimezone,
year: 'numeric',
});
const day = formatterDay.format(date);
const month = formatterMonth.format(date);
const year = formatterYear.format(date);
return `${year}-${month}-${day}`;
};
import { message } from 'antd';
// cryptoHelper.js
import CryptoJS from 'crypto-js';
const secretKey = `${import.meta.env.VITE_KEY_SESSION}`; // Ganti dengan kunci rahasia kamu
// Fungsi untuk mengenkripsi data
const encryptData = (data) => {
try {
const ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();
return ciphertext;
} catch (error) {
console.error('Encrypt Error:', error);
return null;
}
};
// Fungsi untuk mendekripsi data
const decryptData = (ciphertext) => {
try {
const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);
const decrypted = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
if (decrypted?.error) {
decrypted.error = false;
}
return decrypted;
} catch (error) {
// console.error('Decrypt Error:', error);
return { error: true, message: `Decrypt Error: ${error}` };
}
};
const getSessionData = () => {
try {
const ciphertext = localStorage.getItem('session');
if (!ciphertext) {
return {
error: true,
};
}
const result = decryptData(ciphertext);
return result;
} catch (error) {
// console.error('Decrypt Error:', error);
return { error: true, message: error };
}
};
export {
formatIDR,
formatCurrencyUSD,
formatCurrencyIDR,
toApiNumberFormatter,
toAppDateFormatter,
toApiDateFormatter,
toAppDateTimezoneFormatter,
toAppDateFormatterTwoDigit,
toApiDateTimezoneFormatter,
encryptData,
getSessionData,
decryptData,
};

View File

@@ -0,0 +1,23 @@
const toBase64 = (url) =>
fetch(url)
.then((res) => res.blob())
.then(
(blob) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
})
);
// Fungsi utama
const kopReportPdf = async (logo, title) => {
const images = await toBase64(logo);
return {
images,
title,
};
};
export { kopReportPdf };

View File

@@ -0,0 +1,101 @@
// mqttService.js
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'
];
const options = {
keepalive: 30,
clientId: 'react_mqtt_' + Math.random().toString(16).substr(2, 8),
protocolId: 'MQTT',
protocolVersion: 4,
clean: true,
reconnectPeriod: 1000,
connectTimeout: 30 * 1000,
username: `${import.meta.env.VITE_MQTT_USERNAME ?? ''}`, // jika ada
password: `${import.meta.env.VITE_MQTT_PASSWORD ?? ''}`, // jika ada
};
const client = mqtt.connect(mqttUrl, options);
// Track connection status
let isConnected = false;
client.on('connect', () => {
console.log('MQTT Connected');
isConnected = true;
// Subscribe default topic
client.subscribe(topics, (err) => {
if (err) console.error('Subscribe error:', err);
else console.log(`Subscribed to topics: ${topics.join(', ')}`);
});
});
client.on('error', (err) => {
console.error('Connection error: ', err);
client.end();
});
client.on('close', () => {
console.log('MQTT Disconnected');
isConnected = false;
});
/**
* Publish message to MQTT
* @param {string} topic
* @param {string} message
*/
const publishMessage = (topic, message) => {
if (client && isConnected && message.trim() !== '') {
client.publish(topic, message);
} else {
console.warn('MQTT not connected or message empty');
}
};
/**
* Listen to incoming messages
* @param {function} callback - Function(topic, message)
*/
const listenMessage = (callback) => {
client.on('message', (topic, message) => {
callback(topic, message.toString());
});
};
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) {
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;
}
}
});
}
});
};
export { publishMessage, listenMessage, setValSvg };

View File

@@ -0,0 +1,109 @@
import { Typography } from 'antd';
import { useSearchParams } from 'react-router-dom';
import ImgPIU from '../../assets/freepik/LOGOPIU.png';
const { Title, Text } = Typography;
function QrPermit() {
const [searchParams] = useSearchParams();
const selectedRole = searchParams.get('role');
const selectedName = searchParams.get('name');
const selectedTime = searchParams.get('time');
const formattedTime = selectedTime
? new Date(selectedTime).toLocaleString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
})
: '-';
const userApproval = {
role: ['Performing Authority', 'Permit Control', 'Site Authority', 'Area Authority'],
roleCode: ['PA', 'PC', 'SA', 'AA'],
};
const filteredRoles = userApproval.role.filter((role, index) => {
const code = userApproval.roleCode[index];
return !selectedRole || selectedRole === code;
});
const isMobile = window.innerWidth <= 768;
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fafafa',
textAlign: 'center',
minHeight: '100vh',
padding: isMobile ? '1rem' : '3rem',
boxSizing: 'border-box',
}}
>
<img
src={ImgPIU}
alt="Logo PIU"
style={{
width: isMobile ? '100%' : '100%',
maxWidth: isMobile ? '300px' : '30%',
height: 'auto',
marginBottom: isMobile ? '1.5rem' : '2vh',
marginTop: isMobile ? '-1rem' : '-75px',
}}
/>
{filteredRoles.map((role, index) => (
<div key={index} style={{ width: '100%' }}>
<Title
strong
level={1}
style={{
marginTop: isMobile ? '-2rem' : '-75px',
fontWeight: 600,
color: '#004D80',
textAlign: 'center',
fontSize: isMobile ? '6vw' : '2.5rem',
}}
>
Validasi Dokumen <br /> Pupuk Indonesia Utilitas
</Title>
<Title
level={2}
style={{
marginTop: isMobile ? '1rem' : '-5px',
fontWeight: 600,
color: '#141414',
textAlign: 'center',
fontSize: isMobile ? '6vw' : '2.5rem',
}}
>
{role}
</Title>
<div
style={{
fontSize: isMobile ? '4.5vw' : '25px',
lineHeight: isMobile ? 1.5 : 1.8,
marginTop: isMobile ? '1rem' : '1.5rem',
}}
>
<Text strong style={{ fontSize: isMobile ? '4.5vw' : 25 }}>
Nama:
</Text>{' '}
{selectedName ?? '-'}
<br />
<Text strong style={{ fontSize: isMobile ? '4.5vw' : 25 }}>
{formattedTime}
</Text>
</div>
</div>
))}
</div>
);
}
export default QrPermit;

View File

@@ -0,0 +1,25 @@
import axios from 'axios';
const RegistrationRequest = async ({ method, prefix, params, headers = {} }) => {
const baseURL = `${import.meta.env.VITE_API_SERVER}`;
try {
const response = await axios({
method: method,
url: `${baseURL}/${prefix}`,
data: params,
headers: {
'Accept-Language': 'en_US',
...headers,
},
withCredentials: true,
});
return response.data || {};
} catch (error) {
console.error(`Error saat ${prefix}:`, error.response?.data || error.message);
throw error.response?.data || { message: 'Terjadi kesalahan pada server' };
}
};
export default RegistrationRequest;

View File

@@ -0,0 +1,499 @@
import React, { useState } from 'react';
import {
Button,
Modal,
Divider,
Card,
Tag,
ConfigProvider,
Typography,
message,
Input,
Radio,
} from 'antd';
import { getStatusHistory, approvalPermit } from '../../api/status-history';
import { NotifAlert, NotifOk, NotifConfirmDialog } from './ToastNotif';
import { getSessionData } from './Formatter';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);
const { Text } = Typography;
const { TextArea } = Input;
const StatusButton = (props) => {
const {
color,
name,
style,
canApprove = true,
canReject = true,
refreshData = (e) => {},
} = props;
const session = getSessionData();
const isVendor = session?.user?.role_id == `${import.meta.env.VITE_ROLE_VENDOR}`;
const [isModalVisible, setIsModalVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [historyData, setHistoryData] = useState([]);
const [showConfirmModal, setShowConfirmModal] = useState(false);
const [showPermitSelesai, setShowPermitSelesai] = useState(false);
const [actionType, setActionType] = useState(null);
const [deskripsi, setDeskripsi] = useState('');
const [closeType, setCloseType] = useState('1');
const pengajuanPermitSelesai = 4;
const permitSelesai = 7;
const fetchHistory = async () => {
const permitId = props.permitId;
const id = parseInt(permitId);
if (!permitId || isNaN(id)) {
console.error('Permit ID tidak valid:', permitId);
message.error('Permit ID tidak valid atau kosong');
return;
}
try {
const res = await getStatusHistory(id);
const mapped =
res?.data?.data?.map((item) => ({
name: item.name,
color: item.status_permit_color,
text: item.status_permit_name,
deskripsi: item.deskripsi,
date: item.created_at,
closed: item.close_type !== null ? item.close_type_name : null,
})) ?? [];
setHistoryData(mapped);
} catch (err) {
console.error('API ERROR:', err);
message.error('Gagal mengambil riwayat status dari server');
}
};
const showModal = () => {
fetchHistory();
setIsModalVisible(true);
};
const handleCancel = () => {
setIsModalVisible(false);
};
const handleSelesai = () => {
setShowPermitSelesai(true);
};
const handleApprove = () => {
setActionType('approve');
setShowConfirmModal(true);
};
const handleReject = () => {
setActionType('reject');
setShowConfirmModal(true);
};
const submitSelesai = async () => {
const payload = {
status_permit: true,
close_type: closeType,
};
try {
setConfirmLoading(true);
const response = await approvalPermit(props.permitId, payload);
if (response?.status === 200) {
NotifOk({
icon: 'success',
title: 'Pengajuan Selesai',
message: `Permit berhasil diajukan sebagai ${
closeType === '1' ? 'selesai' : 'belum selesai'
}.`,
});
setIsModalVisible(false);
setShowPermitSelesai(false);
setCloseType('');
setTimeout(() => {
refreshData();
}, 500);
} else {
throw new Error(response?.data?.message || 'Proses gagal');
}
} catch (err) {
console.error('Error saat mengajukan permit:', err);
NotifAlert({
icon: 'error',
title: 'Gagal',
message: err.message || 'Terjadi kesalahan saat memproses permit.',
});
} finally {
setConfirmLoading(false);
setShowPermitSelesai(false);
setCloseType('');
}
};
const submitApproval = async () => {
const payload = {
status_permit: actionType === 'approve' ? true : false,
deskripsi: deskripsi.trim(),
};
try {
setConfirmLoading(true);
const response = await approvalPermit(props.permitId, payload);
if (response?.status === 200) {
NotifOk({
icon: 'success',
title: actionType === 'approve' ? 'Disetujui' : 'Ditolak',
message:
actionType === 'approve'
? 'Permit berhasil disetujui.'
: 'Permit berhasil ditolak.',
});
setIsModalVisible(false);
setShowConfirmModal(false);
setDeskripsi('');
setTimeout(() => {
refreshData();
}, 500);
} else {
throw new Error(response?.data?.message || 'Proses gagal');
}
} catch (err) {
console.error('Error saat menyetujui permit:', err);
NotifAlert({
icon: 'error',
title: 'Gagal',
message: err.message || 'Terjadi kesalahan saat memproses permit.',
});
} finally {
setConfirmLoading(false);
setShowConfirmModal(false);
setDeskripsi('');
}
};
return (
<>
<Button
size="middle"
onClick={showModal}
style={{
backgroundColor: '#fff',
color: color,
borderColor: color,
borderRadius: '8px',
padding: '5px 16px',
fontWeight: 500,
...style?.button,
}}
>
{name || 'N/A'}
</Button>
<Modal
title={
<Tag
style={{
backgroundColor: '#fff',
color: color || '#999',
border: `1px solid ${color || '#ddd'}`,
borderRadius: 8,
padding: '4px 12px',
fontSize: 16,
display: 'inline-block',
}}
>
{name ?? 'Belum ada status'}
</Tag>
}
open={isModalVisible}
onCancel={handleCancel}
footer={[
<>
<ConfigProvider
theme={{
token: { colorBgContainer: '#E9F6EF' },
components: {
Button: {
defaultBg: 'white',
defaultColor: '#23A55A',
defaultBorderColor: '#23A55A',
defaultHoverColor: '#23A55A',
defaultHoverBorderColor: '#23A55A',
},
},
}}
>
<Button onClick={handleCancel}>Batal</Button>
</ConfigProvider>
{props.status_permit === pengajuanPermitSelesai &&
historyData.length >= 0 &&
isVendor && (
<>
<ConfigProvider
theme={{
token: { colorBgContainer: '#23a55ade' },
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#23a55a',
},
},
}}
>
<Button loading={confirmLoading} onClick={handleSelesai}>
Selesai
</Button>
</ConfigProvider>
</>
)}
{props.status_permit !== 0 &&
props.status_permit !== pengajuanPermitSelesai &&
props.status_permit !== permitSelesai &&
historyData.length >= 0 && (
<>
{canReject && (
<ConfigProvider
theme={{
token: { colorBgContainer: '#FF4D4Fde' },
components: {
Button: {
defaultBg: '#FF4D4F',
defaultColor: '#FFFFFF',
defaultBorderColor: '#FF4D4F',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#FF4D4F',
},
},
}}
>
<Button onClick={handleReject}>Reject</Button>
</ConfigProvider>
)}
{canApprove && (
<ConfigProvider
theme={{
token: { colorBgContainer: '#23a55ade' },
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#23a55a',
},
},
}}
>
<Button
loading={confirmLoading}
onClick={handleApprove}
>
Approve
</Button>
</ConfigProvider>
)}
</>
)}
</>,
]}
>
<Divider style={{ margin: '16px 0', borderTop: '2px solid #D9D9D9' }} />
{historyData.length > 0 ? (
[...historyData]
.sort((a, b) => new Date(b.date) - new Date(a.date))
.map((item, index) => (
<Card
key={index}
style={{
marginBottom: 16,
color: item.color,
backgroundColor: '#FFFFFF',
border: `1.5px solid ${item.color}`,
borderRadius: 8,
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: 8,
}}
>
<Tag
style={{
backgroundColor: '#FFFFFF',
color: item.color,
border: `1.5px solid ${item.color}`,
fontSize: 13,
padding: '4px 10px',
borderRadius: 6,
fontWeight: '600',
}}
>
{item.text}
</Tag>
{item.date != null && (
<Text type="secondary" style={{ fontSize: 12 }}>
{dayjs.utc(item.date).format('YYYY-MM-DD HH:mm:ss')}
</Text>
)}
</div>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 4,
}}
>
<div style={{ fontSize: 13, color: '#333' }}>{item.name}</div>
{item.closed && (
<Tag
style={{
backgroundColor: '#f9f9f9',
color: '#000',
border: '1px dashed #999',
fontSize: 12,
fontStyle: 'italic',
marginRight: 0,
}}
>
Closed: {item.closed}
</Tag>
)}
</div>
{item.deskripsi && (
<p style={{ fontSize: 12, color: '#333', margin: 0 }}>
{item.deskripsi}
</p>
)}
</Card>
))
) : (
<Text type="secondary">Belum ada riwayat status.</Text>
)}
</Modal>
<Modal
open={showConfirmModal}
title={actionType === 'approve' ? 'Konfirmasi Persetujuan' : 'Konfirmasi Penolakan'}
onCancel={() => {
setShowConfirmModal(false);
setDeskripsi('');
}}
confirmLoading={confirmLoading}
footer={[
<Button
key="cancel"
onClick={() => {
setShowConfirmModal(false);
setDeskripsi('');
}}
>
Batal
</Button>,
<ConfigProvider
key="action"
theme={{
token: {
colorBgContainer:
actionType === 'approve' ? '#23a55ade' : '#FF4D4Fde',
},
components: {
Button: {
defaultBg: actionType === 'approve' ? '#23a55a' : '#FF4D4F',
defaultColor: '#FFFFFF',
defaultBorderColor:
actionType === 'approve' ? '#23a55a' : '#FF4D4F',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor:
actionType === 'approve' ? '#23a55a' : '#FF4D4F',
},
},
}}
>
<Button key="submit" loading={confirmLoading} onClick={submitApproval}>
{actionType === 'approve' ? 'Approve' : 'Reject'}
</Button>
</ConfigProvider>,
]}
>
<p>Silakan isi deskripsi:</p>
<TextArea
rows={4}
value={deskripsi}
onChange={(e) => setDeskripsi(e.target.value)}
placeholder="Contoh: Disetujui karena dokumen lengkap atau ditolak karena dokumen tidak lengkap."
/>
</Modal>
<Modal
open={showPermitSelesai}
title={'Konfirmasi Pengajuan Selesai'}
onCancel={() => {
setShowPermitSelesai(false);
setCloseType('');
}}
confirmLoading={confirmLoading}
footer={[
<Button
key="cancel"
onClick={() => {
setShowPermitSelesai(false);
setCloseType('');
}}
>
Batal
</Button>,
<ConfigProvider
key="action"
theme={{
token: { colorBgContainer: '#23a55ade' },
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#23a55a',
},
},
}}
>
<Button key="submit" loading={confirmLoading} onClick={submitSelesai}>
Ajukan Permit Selesai
</Button>
</ConfigProvider>,
]}
>
<p>Status Permit saat ini :</p>
<Radio.Group onChange={(e) => setCloseType(e.target.value)} value={closeType}>
<Radio value="0">Belum Selesai</Radio>
<Radio value="1">Selesai</Radio>
</Radio.Group>
</Modal>
</>
);
};
export default StatusButton;

View File

@@ -0,0 +1,294 @@
import React, { useState } from 'react';
import { Button, Modal, Divider, Card, Tag, ConfigProvider, Typography } from 'antd';
import { NotifAlert, NotifOk, NotifConfirmDialog } from './ToastNotif';
import { approvalUser } from '../../api/user-admin';
import { toAppDateFormatter } from './Formatter';
const { Text } = Typography;
const StatusUserButton = ({ color, name, data, readOnly, style }) => {
const [isModalVisible, setIsModalVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const showModal = () => {
setIsModalVisible(true);
};
const handleCancel = () => {
setIsModalVisible(false);
};
const statusColor = data?.warna || color || '#999';
const statusName = data?.status_name || name || 'N/A';
const userCreated = data?.user_add_name || 'Pengguna tidak dikenal';
const userUpdated = data?.user_upd_name || 'Pengguna tidak dikenal';
const handleApprove = async () => {
setConfirmLoading(true);
try {
const payload = {
approve_user: true,
};
const response = await approvalUser(data?.id_register, payload);
if (response?.data?.statusCode === 200) {
NotifOk({
icon: 'success',
title: 'Berhasil',
message: 'User berhasil di-approve.',
});
setIsModalVisible(false);
} else {
NotifAlert({
icon: 'error',
title: 'Gagal',
message: response?.data?.message || 'Gagal approve user.',
});
}
} catch (err) {
console.error('Error saat approve user:', err);
NotifAlert({
icon: 'error',
title: 'Error',
message: 'Terjadi kesalahan pada server.',
});
} finally {
setConfirmLoading(false);
}
};
const handleReject = async () => {
setConfirmLoading(true);
NotifConfirmDialog({
icon: 'question',
title: 'Konfirmasi Penolakan',
message: 'Apakah kamu yakin ingin menolak permintaan ini?',
confirmButtonText: 'Reject',
onConfirm: async () => {
try {
const payload = {
approve_user: false,
};
const response = await approvalUser(data.id_register, payload);
if (response?.data?.statusCode === 200) {
NotifOk({
icon: 'success',
title: 'Ditolak',
message: 'User berhasil ditolak.',
});
setIsModalVisible(false);
} else {
NotifAlert({
icon: 'error',
title: 'Gagal',
message: response?.message || 'Gagal reject user.',
});
}
} catch (err) {
NotifAlert({
icon: 'error',
title: 'Error',
message: 'Terjadi kesalahan pada server.',
});
} finally {
setConfirmLoading(false);
}
},
onCancel: () => {
},
});
};
return (
<>
<Button
size="middle"
onClick={showModal}
style={{
backgroundColor: '#fff',
color: statusColor,
borderColor: statusColor,
borderRadius: '8px',
padding: '4px 16px',
fontWeight: 500,
...style?.button,
}}
>
{statusName}
</Button>
<Modal
title={
<Tag
style={{
backgroundColor: '#fff',
color: statusColor,
border: `1px solid ${statusColor}`,
borderRadius: 8,
padding: '4px 12px',
fontSize: 16,
display: 'inline-block',
}}
>
{statusName}
</Tag>
}
open={isModalVisible}
onCancel={handleCancel}
footer={[
<>
<ConfigProvider
theme={{
token: { colorBgContainer: '#E9F6EF' },
components: {
Button: {
defaultBg: 'white',
defaultColor: '#23A55A',
defaultBorderColor: '#23A55A',
defaultHoverColor: '#23A55A',
defaultHoverBorderColor: '#23A55A',
},
},
}}
>
<Button onClick={handleCancel}>Batal</Button>
</ConfigProvider>
{data?.status_register === 1 && (
<>
<ConfigProvider
theme={{
token: {
colorBgContainer: '#FF4D4Fde',
},
components: {
Button: {
defaultBg: '#FF4D4F',
defaultColor: '#FFFFFF',
defaultBorderColor: '#FF4D4F',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#FF4D4F',
},
},
}}
>
<Button onClick={handleReject}>Reject</Button>
</ConfigProvider>
<ConfigProvider
theme={{
token: {
colorBgContainer: '#23a55ade',
},
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#23a55a',
},
},
}}
>
<Button loading={confirmLoading} onClick={handleApprove}>
Approve
</Button>
</ConfigProvider>
</>
)}
</>,
]}
>
<Divider style={{ margin: '16px 0', borderTop: '2px solid #D9D9D9' }} />
{data ? (
<>
{data.updated_at !== data.created_at && (
<Card
style={{
marginBottom: 16,
color: '#FF6E35',
backgroundColor: '#FFFFFF',
border: `1.5px solid #FF6E35`,
borderRadius: 8,
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: 8,
}}
>
<Tag
style={{
backgroundColor: '#FFFFFF',
color: '#FF6E35',
border: `1.5px solid #FF6E35`,
fontSize: 13,
padding: '4px 10px',
borderRadius: 6,
fontWeight: '500',
}}
>
Updated at
</Tag>
<Text
type="secondary"
style={{ fontSize: 12, fontWeight: '500' }}
>
{toAppDateFormatter(data.updated_at)}
</Text>
</div>
<div style={{ fontSize: 13, color: '#333' }}>
Diubah terakhir oleh <b>{userUpdated}</b>
</div>
</Card>
)}
<Card
style={{
marginBottom: 16,
color: '#3498DB',
backgroundColor: '#FFFFFF',
border: `1.5px solid #3498DB`,
borderRadius: 8,
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: 8,
}}
>
<Tag
style={{
backgroundColor: '#FFFFFF',
color: '#3498DB',
border: `1.5px solid #3498DB`,
fontSize: 13,
padding: '4px 10px',
borderRadius: 6,
fontWeight: '500',
}}
>
Created at
</Tag>
<Text type="secondary" style={{ fontSize: 12, fontWeight: '500' }}>
{toAppDateFormatter(data.created_at)}
</Text>
</div>
<div style={{ fontSize: 13, color: '#333' }}>
Dibuat oleh <b>{userCreated}</b>
</div>
</Card>
</>
) : (
<Text type="secondary">Belum ada riwayat status.</Text>
)}
</Modal>
</>
);
};
export default StatusUserButton;

View File

@@ -0,0 +1,217 @@
import React, { memo, useState, useEffect, useRef } from 'react';
import { Table, Pagination, Row, Col, Card, Grid, Button, Typography, Tag, Segmented } from 'antd';
import { MacCommandOutlined, TableOutlined } from '@ant-design/icons';
import CardList from './CardList';
const { Text } = Typography;
const TableList = memo(function TableList({
getData,
queryParams,
columns,
triger,
mobile,
rowSelection = null,
header = 'name',
showPreviewModal,
showEditModal,
showDeleteDialog,
cardColor,
fieldColor,
firstLoad = true,
columnDynamic = false,
cardComponent, // New prop for custom card component
onStockUpdate, // Prop to pass to card component
onGetData, // Callback to execute when data is received
}) {
const [gridLoading, setGridLoading] = useState(false);
const [data, setData] = useState([]);
const [pagination, setPagination] = useState({
current_page: 1,
current_limit: 10,
total_limit: 0,
total_page: 1,
});
const [columnsDynamic, setColumnsDynamic] = useState(columns);
const [viewMode, setViewMode] = useState('table');
const { useBreakpoint } = Grid;
const [renderCount, setRenderCount] = useState(firstLoad ? 1 : 0);
useEffect(() => {
if (renderCount < 1) {
setRenderCount(renderCount + 1);
return;
} else {
filter(1, pagination.current_limit);
}
}, [triger]);
const filter = async (currentPage, pageSize) => {
setGridLoading(true);
const paging = {
page: Number(currentPage),
limit: Number(pageSize),
};
const param = new URLSearchParams({ ...paging, ...queryParams });
const resData = await getData(param);
if (columnDynamic && resData) {
const columnsApi = resData[columnDynamic] ?? '';
// Pisahkan string menjadi array kolom
const colArray = columnsApi.split(',').map((c) => c.trim());
// Kolom default datetime di awal
const defaultColumns = [
{
title: 'No',
key: 'no',
width: '5%',
align: 'center',
render: (_, __, index) => index + 1,
},
{
title: 'Datetime',
dataIndex: 'datetime',
key: 'datetime',
width: '15%',
// render: (value) => dayjs(value).format('YYYY-MM-DD HH:mm:ss'),
},
];
// Buat kolom numerik dengan format 4 angka di belakang koma
const numericColumns = colArray.map((colName) => ({
title: colName,
dataIndex: colName,
key: colName,
align: 'right',
width: 'auto',
render: (value) => {
if (typeof value === 'number') {
return value.toFixed(4);
}
return value ?? '-';
},
}));
// Gabungkan default + API columns
setColumnsDynamic([...defaultColumns, ...numericColumns]);
}
const fetchedData = resData?.data ?? [];
// Panggil callback jika disediakan
if (onGetData && typeof onGetData === 'function') {
onGetData(fetchedData);
}
setData(fetchedData);
const pagingData = resData?.paging;
if (pagingData) {
setPagination((prev) => ({
...prev,
current_page: pagingData.current_page || 1,
current_limit: pagingData.current_limit || 10,
total_limit: pagingData.total_limit || 0,
total_page: pagingData.total_page || 1,
}));
}
setGridLoading(false);
if (resData) {
setTimeout(() => {
setGridLoading(false);
}, 900);
} else {
setGridLoading(false);
return;
}
};
const handlePaginationChange = (page, pageSize) => {
setPagination((prev) => ({
...prev,
current: page,
limit: pageSize,
}));
filter(page, pageSize);
};
const screens = useBreakpoint();
const isMobile = !screens.md; // kalau kurang dari md (768px) dianggap mobile
// Use the custom card component if provided, otherwise default to CardList
const CardViewComponent = cardComponent || CardList;
return (
<div>
<Segmented
options={[
{ value: 'table', icon: <TableOutlined /> },
{ value: 'card', icon: <MacCommandOutlined /> },
]}
value={viewMode}
onChange={setViewMode}
/>
{(isMobile && mobile) || viewMode === 'card' ? (
<CardViewComponent
cardColor={cardColor}
fieldColor={fieldColor}
data={data}
column={columnsDynamic}
header={header}
showPreviewModal={showPreviewModal}
showEditModal={showEditModal}
showDeleteDialog={showDeleteDialog}
onStockUpdate={onStockUpdate}
/>
) : (
<Row gutter={24} style={{ marginTop: '16px' }}>
<Table
rowSelection={rowSelection || null}
columns={columnsDynamic}
dataSource={data.map((item, index) => ({ ...item, key: index }))}
pagination={false}
loading={gridLoading}
scroll={{ y: 520 }}
size="small"
/>
</Row>
)}
{/* PAGINATION */}
<Row justify="space-between" align="middle">
<Col>
<div>
Menampilkan {pagination.current_limit} data halaman{' '}
{pagination.current_page} dari total {pagination.total_limit} data
</div>
</Col>
<Col>
<Pagination
showSizeChanger
onChange={handlePaginationChange}
onShowSizeChange={handlePaginationChange}
current={pagination.current_page}
pageSize={pagination.current_limit}
total={pagination.total_limit}
/>
</Col>
</Row>
</div>
);
});
export default TableList;

View File

@@ -0,0 +1,70 @@
import Swal from 'sweetalert2';
const NotifAlert = ({ icon, title, message }) => {
Swal.fire({
icon: icon,
title: title,
text: message,
showConfirmButton: false,
position: 'center',
timer: 2000,
});
};
const NotifOk = ({ icon, title, message }) => {
Swal.fire({
icon: icon,
title: title,
text: message,
html: message.replace(/\n/g, '<br/>'),
});
};
const NotifConfirmDialog = ({
icon,
title,
message,
onConfirm,
onCancel,
confirmButtonText = 'Hapus',
}) => {
Swal.fire({
icon: icon,
title: title,
text: message,
showCancelButton: true,
cancelButtonColor: '#23A55A',
cancelButtonText: 'Batal',
confirmButtonColor: '#d33000',
confirmButtonText: confirmButtonText,
reverseButtons: true,
}).then((result) => {
if (result.isConfirmed) {
onConfirm();
} else if (result.dismiss) {
onCancel();
}
});
};
const QuestionConfirmSubmit = ({ icon, title, message, onConfirm, onCancel }) => {
Swal.fire({
icon: icon,
title: title,
text: message,
showCancelButton: true,
cancelButtonColor: '#23A55A',
cancelButtonText: 'Batal',
confirmButtonColor: '#d33000',
confirmButtonText: 'Proses',
reverseButtons: true,
}).then((result) => {
if (result.isConfirmed) {
onConfirm();
} else if (result.dismiss) {
onCancel();
}
});
};
export { NotifAlert, NotifOk, NotifConfirmDialog, QuestionConfirmSubmit };

View File

@@ -0,0 +1,81 @@
import { Row, Col, Button, ConfigProvider, Divider, Typography } from "antd";
import { ArrowLeftOutlined, SearchOutlined } from '@ant-design/icons';
const {Text} = Typography;
const HeaderReport = ({
title,
loadingPilihDataStep1,
handleSelectData,
step
})=>{
return(
<>
<Row style={{ justifyContent: "space-between" }}>
<Col>
<Row>
<Text style={{fontSize:'18px'}} strong>{title}</Text>
<div style={{width:'20px'}}></div>
<div style={{
width:'95px',
border:'1px solid #e9f6ef',
borderRadius:'5px',
backgroundColor:'#e9f6ef',
color:'#23a55a',
padding:'3px',
fontSize:'16px',
fontWeight:'bold'
}}>
{step}
</div>
</Row>
</Col>
<Col>
<ConfigProvider
theme={{
token: {
colorBgContainer: "#eff0f5",
},
components: {
Button: {
defaultBg: "white",
defaultColor: "#000000",
defaultBorderColor: "#000000",
defaultHoverColor: "#000000",
defaultHoverBorderColor: "#000000",
defaultHoverColor: "#000000",
},
},
}}
>
<Button icon={<ArrowLeftOutlined />}>Batal</Button>
</ConfigProvider>
</Col>
</Row>
<Divider/>
<Row style={{ justifyContent: "space-between" }}>
<Col>
<ConfigProvider
theme={{
token: {
colorBgContainer: "#209652",
},
components: {
Button: {
defaultBg: "#23a55a",
defaultColor: "#FFFFFF",
defaultBorderColor: "#23a55a",
defaultHoverColor: "#FFFFFF",
defaultHoverBorderColor: "#209652",
},
},
}}
>
<Button loading={loadingPilihDataStep1} onClick={handleSelectData}><SearchOutlined /> Pilih Data</Button>
</ConfigProvider>
</Col>
</Row>
</>
);
};
export default HeaderReport;

View File

@@ -0,0 +1,28 @@
import React, { memo } from 'react'
import './loading.css'
const Loading = memo(function Loading() {
return(
<div className='mask'>
<div className="main">
<div className="loader">
<p className="text">
<span className="letter letter1">L</span>
<span className="letter letter2">o</span>
<span className="letter letter3">a</span>
<span className="letter letter4">d</span>
<span className="letter letter5">i</span>
<span className="letter letter6">n</span>
<span className="letter letter7">g</span>
<span className="letter letter8">.</span>
<span className="letter letter9">.</span>
<span className="letter letter10">.</span>
</p>
</div>
</div>
</div>
);
})
export default Loading

View File

@@ -0,0 +1,80 @@
.mask {
/* background-color: rgba(0, 0, 0, .6); */
background-color: rgba(255, 255, 255, .6);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
}
.main {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
text {
font-weight: bolder;
}
@keyframes letter {
0% {
font-size: 30px;
}
50% {
font-size: 40px;
}
100% {
font-size: 30px;
}
}
.letter {
animation: letter 1s infinite;
color: #fff;
}
.letter1 {
animation-delay: 0s;
}
.letter2 {
animation-delay: -0.9s;
}
.letter3 {
animation-delay: -0.8s;
}
.letter4 {
animation-delay: -0.7s;
}
.letter5 {
animation-delay: -0.6s;
}
.letter6 {
animation-delay: -0.5s;
}
.letter7 {
animation-delay: -0.4s;
}
.letter8 {
animation-delay: -0.3s;
}
.letter9 {
animation-delay: -0.2s;
}
.letter10 {
animation-delay: -0.1s;
}

View File

@@ -0,0 +1,42 @@
import { createContext, useContext, useState, useEffect } from "react";
import { SendRequest } from "../utils/api";
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
// fetch user info saat mount
useEffect(() => {
const fetchUser = async () => {
try {
const res = await SendRequest({ prefix: "/auth/me", method: "GET" });
setUser(res);
} catch (err) {
setUser(null);
} finally {
setLoading(false);
}
};
fetchUser();
}, []);
const login = (accessToken) => {
localStorage.setItem("token", accessToken);
};
const logout = () => {
localStorage.clear();
setUser(null);
window.location.href = "/signin";
};
return (
<AuthContext.Provider value={{ user, setUser, login, logout, loading }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);

84
src/index.css Normal file
View File

@@ -0,0 +1,84 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
/* color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424; */
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin: 0;
height: 100vh;
}
html body {
margin: 0;
height: 100vh;
}
/* Custom green Sidebar Menu Styles */
.custom-green-menu.ant-menu-dark .ant-menu-item-selected {
background-color: rgba(255, 255, 255, 0.2) !important;
color: white !important;
}
.custom-green-menu.ant-menu-dark .ant-menu-item-selected::after {
border-right-color: white !important;
}
.custom-green-menu.ant-menu-dark .ant-menu-item:hover,
.custom-green-menu.ant-menu-dark .ant-menu-submenu-title:hover {
background-color: rgba(255, 255, 255, 0.15) !important;
color: white !important;
}
.custom-green-menu.ant-menu-dark .ant-menu-submenu-selected > .ant-menu-submenu-title {
color: white !important;
}
.custom-green-menu.ant-menu-dark.ant-menu-inline .ant-menu-sub {
background: rgba(0, 0, 0, 0.2) !important;
}
.custom-green-menu.ant-menu-dark .ant-menu-item,
.custom-green-menu.ant-menu-dark .ant-menu-submenu-title {
color: rgba(255, 255, 255, 0.9) !important;
}
.custom-green-menu.ant-menu-dark .ant-menu-item-active,
.custom-green-menu.ant-menu-dark .ant-menu-submenu-active > .ant-menu-submenu-title {
color: white !important;
}
/*start styling for scrollbar menu */
.custom-menu-scrollbar::-webkit-scrollbar {
width: 8px;
}
.custom-menu-scrollbar::-webkit-scrollbar-track {
background: transparent;
border-radius: 10px;
margin: 5px 0;
}
.custom-menu-scrollbar::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #1BAA56 0%, rgb(5, 75, 34) 100%);
border-radius: 10px;
border: 2px solid rgba(255, 255, 255, 0.3);
}
.custom-menu-scrollbar::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, #2bc56d 0%, rgb(8, 94, 43) 100%);
}
.custom-menu-scrollbar {
scrollbar-width: thin;
scrollbar-color: #1BAA56 transparent;
}
/* Hilangkan panah atas/bawah dengan important */
.custom-menu-scrollbar::-webkit-scrollbar-button {
display: none !important;
width: 0 !important;
height: 0 !important;
}
/*end styling for scrollbar menu */

View File

@@ -0,0 +1,15 @@
import React, { createContext, useContext, useState } from 'react';
const BreadcrumbContext = createContext();
export const BreadcrumbProvider = ({ children }) => {
const [breadcrumbItems, setBreadcrumbItems] = useState([]);
return (
<BreadcrumbContext.Provider value={{ breadcrumbItems, setBreadcrumbItems }}>
{children}
</BreadcrumbContext.Provider>
);
};
export const useBreadcrumb = () => useContext(BreadcrumbContext);

View File

@@ -0,0 +1,18 @@
import React from 'react'
import { Layout } from 'antd'
import Link from 'antd/es/typography/Link';
const { Footer } = Layout;
const LayoutFooter = () => {
return (
<Footer
style={{
textAlign: 'center',
}}
>
{/* SYPIU GGCP */}
</Footer>
)
}
export default LayoutFooter

170
src/layout/LayoutHeader.jsx Normal file
View File

@@ -0,0 +1,170 @@
import React from 'react';
import { Layout, Typography, Breadcrumb, Button, theme } from 'antd';
import { UserOutlined } from '@ant-design/icons';
import handleLogOut from '../Utils/Auth/Logout';
import { useBreadcrumb } from './LayoutBreadcrumb';
import { decryptData } from '../components/Global/Formatter';
import { useNavigate } from 'react-router-dom';
import DateRealTime from '../components/Global/DateRealTime';
const { Link, Text } = Typography;
const { Header } = Layout;
const LayoutHeader = () => {
const { breadcrumbItems } = useBreadcrumb();
const navigate = useNavigate();
// Ambil token warna dari theme Ant Design
const { token } = theme.useToken() || {};
const colorBgContainer = token?.colorBgContainer || '#fff';
const colorBorder = token?.colorBorder || '#d9d9d9';
const colorText = token?.colorText || '#1BAA56';
// Ambil data user dari localStorage
let userData = null;
const sessionData = localStorage.getItem('session');
if (sessionData) {
userData = decryptData(sessionData);
} else {
const userRaw = localStorage.getItem('user');
if (userRaw) {
try {
// bungkus biar konsisten { user: {...} }
userData = { user: JSON.parse(userRaw) };
} catch (e) {
console.error('Gagal parse user dari localStorage:', e);
}
}
}
// console.log('User data di header:', userData?.user);
// Role handling
let roleName = userData?.user?.role_name || 'Guest';
const userName = userData?.user?.name || userData?.user?.username || userData?.user?.user_name || 'User';
// Override jika Super Admin
if (
userData?.user?.is_sa === true ||
userData?.user?.is_sa === 'true' ||
userData?.user?.is_sa === 1
) {
roleName = 'Super Admin';
}
return (
<>
<Header
style={{
background: colorBgContainer,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexWrap: 'wrap',
rowGap: 10,
paddingTop: 15,
paddingBottom: 20,
paddingLeft: 24,
paddingRight: 24,
// minHeight: 100,
boxSizing: 'border-box',
boxShadow: '5px 0 10px rgba(0, 0, 0, 0.4)'
}}
>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
gap: 12,
}}
>
<Text
style={{
color: '#1BAA56',
fontSize: 26,
fontWeight: 'bold',
whiteSpace: 'nowrap',
}}
>
{/* Login AS {roleName} */}
CALL OF DUTY
</Text>
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
gap: 12,
}}
>
{/* <Text
style={{
color: '#000000',
fontSize: 20,
fontWeight: 'bold',
whiteSpace: 'nowrap',
}}
> */}
{/* Login AS {roleName} */}
{/* Kamis, 04 November 2025 16:35:00 */}
{/* </Text> */}
<DateRealTime/>
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
gap: 10,
}}
>
<Button
style={{
display: 'flex',
alignItems: 'center',
background: '#f5f5f5',
border: `1px solid ${colorBorder}`,
borderRadius: 6,
padding: '4px 12px',
}}
>
<UserOutlined style={{ fontSize: 16, color: colorText }} />
<Text style={{ marginLeft: 8, color: colorText }} strong>
{userName} @ {roleName}
</Text>
</Button>
<Link
onClick={() => {
handleLogOut(navigate);
}}
aria-label="Log out from the application"
style={{
color: colorText,
whiteSpace: 'nowrap',
}}
>
Logout
</Link>
</div>
</Header>
<div style={{ width: '100%', maxWidth: '50%', textAlign: 'left' }}>
<Breadcrumb
style={{
marginLeft: '20px',
marginTop: '20px',
marginBottom: '10px',
}}
items={breadcrumbItems || []}
/>
</div>
</>
);
};
export default LayoutHeader;

69
src/layout/LayoutLogo.jsx Normal file
View File

@@ -0,0 +1,69 @@
import { Image } from 'antd';
import logoPiu from '../assets/freepik/LOGOPIU.png';
import React from 'react';
const LayoutLogo = () => {
return (
<div
style={{
margin: '1rem auto',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
padding: '1rem',
borderRadius: '1rem',
}}
>
<div
style={{
background:
'radial-gradient(circle at center, rgba(255,255,255,0.95), rgba(220,220,220,0.5))',
borderRadius: '50%',
width: 160,
height: 160,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
boxShadow: '0 6px 20px rgba(0, 0, 0, 0.2)',
position: 'relative',
overflow: 'hidden',
}}
>
{/* Ring sebelum logo utama */}
<div
style={{
border: '5px solid #ffffffff',
borderRadius: '50%',
width: 160,
height: 160,
position: 'absolute',
zIndex: 1,
}}
/>
<div
style={{
borderRadius: '10px',
padding: '4px',
mixBlendMode: 'normal',
opacity: 1,
zIndex: 2,
}}
>
<Image
src={logoPiu}
alt="logo"
width={140}
height={100}
preview={false}
style={{
filter: 'drop-shadow(0 0 3px rgba(0, 0, 0, 0.2))',
}}
/>
</div>
</div>
</div>
);
};
export default LayoutLogo;

429
src/layout/LayoutMenu.jsx Normal file
View File

@@ -0,0 +1,429 @@
import React, { useState, useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Menu, Typography, Image } from 'antd';
import { getSessionData } from '../components/Global/Formatter';
import {
HomeOutlined,
DatabaseOutlined,
SettingOutlined,
UserOutlined,
AntDesignOutlined,
ShoppingCartOutlined,
ShoppingOutlined,
HistoryOutlined,
DollarOutlined,
RollbackOutlined,
ProductOutlined,
TagOutlined,
AppstoreOutlined,
MobileOutlined,
WarningOutlined,
LineChartOutlined,
FileTextOutlined,
BellOutlined,
AlertOutlined,
SafetyOutlined,
TeamOutlined,
ClockCircleOutlined,
CalendarOutlined,
DesktopOutlined,
NodeExpandOutlined,
GroupOutlined,
SlidersOutlined,
SnippetsOutlined,
ContactsOutlined,
ToolOutlined,
} from '@ant-design/icons';
const { Text } = Typography;
const allItems = [
{
key: 'home',
icon: <HomeOutlined style={{ fontSize: '19px' }} />,
label: (
<Link to="/dashboard/home" className="fontMenus">
Home
</Link>
),
},
{
key: 'dashboard-svg',
icon: <GroupOutlined style={{ fontSize: '19px' }} />,
label: 'Dashboard',
children: [
{
key: 'dashboard-svg-compressor',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: 'Compressor',
children: [
{
key: 'dashboard-svg-compressor-overview',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/overview-compressor">Overview</Link>,
},
{
key: 'dashboard-svg-compressor-compressor-a',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/compressor-a">Compressor A</Link>,
},
{
key: 'dashboard-svg-compressor-compressor-b',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/compressor-b">Compressor B</Link>,
},
{
key: 'dashboard-svg-compressor-compressor-c',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/compressor-c">Compressor C</Link>,
},
],
},
{
key: 'dashboard-svg-airdryer',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: 'Air Dryer',
children: [
{
key: 'dashboard-svg-airdryer-overview',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/overview-airdryer">Overview</Link>,
},
{
key: 'dashboard-svg-airdryer-airdryer-a',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/airdryer-a">Air Dryer A</Link>,
},
{
key: 'dashboard-svg-airdryer-airdryer-b',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/airdryer-b">Air Dryer B</Link>,
},
{
key: 'dashboard-svg-airdryer-airdryer-c',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/airdryer-c">Air Dryer C</Link>,
},
],
},
],
},
{
key: 'master',
icon: <DatabaseOutlined style={{ fontSize: '19px' }} />,
label: 'Master',
children: [
{
key: 'master-plant-sub-section',
icon: <ProductOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/plant-sub-section">Plant Sub Section</Link>,
},
{
key: 'master-brand-device',
icon: <AntDesignOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/brand-device">Brand Device</Link>,
},
{
key: 'master-device',
icon: <MobileOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/device">Device</Link>,
},
{
key: 'master-unit',
icon: <AppstoreOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/unit">Unit</Link>,
},
{
key: 'master-tag',
icon: <TagOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/tag">Tag</Link>,
},
{
key: 'master-status',
icon: <SafetyOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/status">Status</Link>,
},
{
key: 'master-sparepart',
icon: <ToolOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/sparepart">Sparepart</Link>,
},
// {
// key: 'master-shift',
// icon: <ClockCircleOutlined style={{ fontSize: '19px' }} />,
// label: <Link to="/master/shift">Shift</Link>,
// },
],
},
{
key: 'report',
icon: <SnippetsOutlined style={{ fontSize: '19px' }} />,
label: 'Report',
children: [
{
key: 'report-trending',
icon: <LineChartOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/report/trending">Trending</Link>,
},
{
key: 'report-report',
icon: <FileTextOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/report/report">Report</Link>,
},
],
},
{
key: 'history',
icon: <HistoryOutlined style={{ fontSize: '19px' }} />,
label: 'History',
children: [
{
key: 'history-alarm',
icon: <AlertOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/history/alarm">Alarm</Link>,
},
{
key: 'history-event',
icon: <SlidersOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/history/event">Event</Link>,
},
],
},
{
key: 'contact',
icon: <ContactsOutlined style={{ fontSize: '19px' }} />,
label: (
<Link to="/contact" className="fontMenus">
Contact
</Link>
),
},
{
key: 'notification',
icon: <BellOutlined style={{ fontSize: '19px' }} />,
label: (
<Link to="/notification" className="fontMenus">
Notification
</Link>
),
},
{
key: 'role',
icon: <SafetyOutlined style={{ fontSize: '19px' }} />,
label: (
<Link to="/role" className="fontMenus">
Role
</Link>
),
},
{
key: 'user',
icon: <UserOutlined style={{ fontSize: '19px' }} />,
label: (
<Link to="/user" className="fontMenus">
User
</Link>
),
},
// {
// key: 'jadwal-shift',
// icon: <CalendarOutlined style={{ fontSize: '19px' }} />,
// label: (
// <Link to="/jadwal-shift" className="fontMenus">
// Jadwal Shift
// </Link>
// ),
// },
];
const LayoutMenu = () => {
const location = useLocation();
const [stateOpenKeys, setStateOpenKeys] = useState(['home']);
const [selectedKeys, setSelectedKeys] = useState(['home']);
// Function to get menu key from current path
const getMenuKeyFromPath = (pathname) => {
// Remove leading slash and split path
const pathParts = pathname.replace(/^\//, '').split('/');
// Handle different route patterns
if (pathname === '/dashboard/home') return 'home';
if (pathname === '/user') return 'user';
if (pathname === '/role') return 'role';
if (pathname === '/notification') return 'notification';
if (pathname === '/jadwal-shift') return 'jadwal-shift';
if (pathname === '/contact') return 'contact';
// Handle master routes
if (pathname.startsWith('/master/')) {
const subPath = pathParts[1];
// Convert kebab-case to the actual menu keys
const masterKeyMap = {
'plant-sub-section': 'master-plant-sub-section',
'brand-device': 'master-brand-device',
device: 'master-device',
unit: 'master-unit',
tag: 'master-tag',
status: 'master-status',
sparepart: 'master-sparepart',
shift: 'master-shift',
};
return masterKeyMap[subPath] || `master-${subPath}`;
}
// Handle dashboard svg routes
if (pathname.startsWith('/dashboard-svg/')) {
const subPath = pathParts[1];
// Map specific routes to their menu keys
if (subPath === 'overview-compressor') return 'dashboard-svg-compressor-overview';
if (subPath === 'compressor-a') return 'dashboard-svg-compressor-compressor-a';
if (subPath === 'compressor-b') return 'dashboard-svg-compressor-compressor-b';
if (subPath === 'compressor-c') return 'dashboard-svg-compressor-compressor-c';
if (subPath === 'overview-airdryer') return 'dashboard-svg-airdryer-overview';
if (subPath === 'airdryer-a') return 'dashboard-svg-airdryer-airdryer-a';
if (subPath === 'airdryer-b') return 'dashboard-svg-airdryer-airdryer-b';
if (subPath === 'airdryer-c') return 'dashboard-svg-airdryer-airdryer-c';
return `dashboard-svg-${subPath}`;
}
// Handle report routes
if (pathname.startsWith('/report/')) {
const subPath = pathParts[1];
const reportKeyMap = {
trending: 'report-trending',
report: 'report-report',
};
return reportKeyMap[subPath] || `report-${subPath}`;
}
// Handle history routes
if (pathname.startsWith('/history/')) {
const subPath = pathParts[1];
const historyKeyMap = {
alarm: 'history-alarm',
event: 'history-event',
};
return historyKeyMap[subPath] || `history-${subPath}`;
}
return 'home'; // default
};
// Function to get parent keys from menu key
const getParentKeys = (key) => {
const parentKeys = [];
if (key.startsWith('dashboard-svg-compressor-')) {
parentKeys.push('dashboard-svg', 'dashboard-svg-compressor');
} else if (key.startsWith('dashboard-svg-airdryer-')) {
parentKeys.push('dashboard-svg', 'dashboard-svg-airdryer');
} else if (key.startsWith('dashboard-svg-')) {
parentKeys.push('dashboard-svg');
} else if (key.startsWith('master-')) {
parentKeys.push('master');
} else if (key.startsWith('report-')) {
parentKeys.push('report');
} else if (key.startsWith('history-')) {
parentKeys.push('history');
}
return parentKeys;
};
// Update selected and open keys when route changes
useEffect(() => {
const currentKey = getMenuKeyFromPath(location.pathname);
setSelectedKeys([currentKey]);
const parentKeys = getParentKeys(currentKey);
// Always keep the parent menus open when a child is selected
if (parentKeys.length > 0) {
setStateOpenKeys(parentKeys);
} else {
setStateOpenKeys([]);
}
}, [location.pathname]);
const getLevelKeys = (items1) => {
const key = {};
const func = (items2, level = 1) => {
items2.forEach((item) => {
if (item.key) {
key[item.key] = level;
}
if (item.children) {
func(item.children, level + 1);
}
});
};
func(items1);
return key;
};
const levelKeys = getLevelKeys(allItems);
const onOpenChange = (openKeys) => {
const currentOpenKey = openKeys.find((key) => stateOpenKeys.indexOf(key) === -1);
// If clicking on a menu that was previously closed
if (currentOpenKey !== undefined) {
const repeatIndex = openKeys
.filter((key) => key !== currentOpenKey)
.findIndex((key) => levelKeys[key] === levelKeys[currentOpenKey]);
setStateOpenKeys(
openKeys
.filter((_, index) => index !== repeatIndex)
.filter((key) => levelKeys[key] <= levelKeys[currentOpenKey])
);
} else {
// If clicking on a menu that was previously open, close only that menu
// but keep other parent menus open if they have active children
const currentKey = getMenuKeyFromPath(location.pathname);
const necessaryParentKeys = getParentKeys(currentKey);
// Filter out only the menus that are necessary to keep open
const filteredOpenKeys = openKeys.filter((key) => necessaryParentKeys.includes(key));
setStateOpenKeys(filteredOpenKeys);
}
};
const session = getSessionData();
const isAdmin = session?.user?.user_id;
const karyawan = () => {
return allItems
.filter((item) => item.key !== 'setting')
.map((item) => {
if (item.key === 'master') {
return {
...item,
};
}
return item;
});
};
const items = isAdmin === 1 ? allItems : karyawan();
return (
<Menu
mode="inline"
items={items}
selectedKeys={selectedKeys}
openKeys={stateOpenKeys}
onOpenChange={onOpenChange}
style={{
background: 'transparent',
color: 'white',
border: 'none',
}}
theme="dark"
className="custom-green-menu"
/>
);
};
export default LayoutMenu;

View File

@@ -0,0 +1,55 @@
import React from 'react';
import { Layout } from 'antd';
import LayoutLogo from './LayoutLogo';
import LayoutMenu from './LayoutMenu';
const { Sider } = Layout;
const LayoutSidebar = () => {
return (
<Sider
width={255}
breakpoint="lg"
collapsedWidth="0"
onBreakpoint={(broken) => {
// console.log(broken);
}}
onCollapse={(collapsed, type) => {
// console.log(collapsed, type);
}}
style={{
background: 'linear-gradient(180deg, #1BAA56 0%,rgb(5, 75, 34) 100%)',
// overflow: 'auto',
height: '100vh',
position: 'fixed',
left: 0,
top: 0,
bottom: 0,
borderTopRightRadius: '30px',
borderBottomRightRadius: '30px',
boxShadow: '5px 0 10px rgba(0, 0, 0, 0.4)',
zIndex: 9999
}}
>
<div style={{
display: 'flex',
flexDirection: 'column',
height: '100vh',
overflow: 'hidden'
}}>
{/* Logo section - fixed height */}
<div style={{flexShrink: 0,minHeight: '64px'}}>
<LayoutLogo />
</div>
{/* Menu section - scrollable */}
<div style={{flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column'}}>
<div className="custom-menu-scrollbar" style={{flex: 1, overflowY: 'auto', overflowX: 'hidden', backgroundColor: 'transparent'}}>
<LayoutMenu />
</div>
</div>
</div>
</Sider>
);
};
export default LayoutSidebar;

51
src/layout/MainLayout.jsx Normal file
View File

@@ -0,0 +1,51 @@
import React, { useState, useEffect } from 'react';
import { Layout, theme, Grid } from 'antd';
import LayoutFooter from './LayoutFooter';
import LayoutHeader from './LayoutHeader';
import LayoutSidebar from './LayoutSidebar';
const { Content } = Layout;
const { useBreakpoint } = Grid;
const MainLayout = ({ children }) => {
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
const screens = useBreakpoint();
const isDesktop = screens.lg;
return (
<Layout style={{ height: '100vh' }}>
<LayoutSidebar />
<Layout
style={{
marginLeft: isDesktop ? '250px' : '0',
overflow: 'auto',
}}
>
<LayoutHeader />
<Content
style={{
margin: '0 10px',
flex: '1 0 auto',
padding: '8px 8px',
}}
>
{/* <div
style={{
padding: 24,
minHeight: '100%',
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
> */}
{children}
{/* </div> */}
</Content>
{/* <LayoutFooter /> */}
</Layout>
</Layout>
);
};
export default MainLayout;

14
src/main.jsx Normal file
View File

@@ -0,0 +1,14 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import './App.css'
import { BreadcrumbProvider } from './layout/LayoutBreadcrumb.jsx';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BreadcrumbProvider>
<App />
</BreadcrumbProvider>
</React.StrictMode>,
)

181
src/pages/auth/SignIn.jsx Normal file
View File

@@ -0,0 +1,181 @@
import React, { useEffect, useState } from 'react';
import { Flex, Input, Form, Button, Card, Space, Image } from 'antd';
import { useNavigate } from 'react-router-dom';
import { NotifAlert } from '../../components/Global/ToastNotif';
import { SendRequest } from '../../components/Global/ApiRequest';
import bg_cod from 'assets/bg-cod-1.jpg';
import logo from 'assets/freepik/LOGOPIU.png';
const SignIn = () => {
const [form] = Form.useForm();
const [captchaSvg, setCaptchaSvg] = useState('');
const [captchaText, setCaptchaText] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const defaultSignIn = {
identifier: 'superadmin@cod.com',
password: '@Superadmin123',
captcha: '',
};
const moveToSignUp = () => {
navigate('/signup');
};
// ambil captcha
const fetchCaptcha = async () => {
try {
const res = await SendRequest({
method: 'get',
prefix: 'auth/generate-captcha',
token: false,
});
setCaptchaSvg(res.data?.data?.svg || '');
setCaptchaText(res.data?.data?.text || '');
} catch (err) {
console.error('Error fetching captcha:', err);
}
};
useEffect(() => {
fetchCaptcha();
}, []);
const handleOnSubmit = async (values) => {
setLoading(true);
try {
const res = await SendRequest({
method: 'post',
prefix: 'auth/login',
params: {
identifier: values.identifier,
password: values.password,
captcha: values.captcha,
captchaText: captchaText,
},
withCredentials: true,
});
const user = res?.data?.data?.user || res?.user;
const accessToken = res?.data?.data?.accessToken || res?.tokens?.accessToken;
if (user && accessToken) {
localStorage.setItem('token', accessToken);
localStorage.setItem('user', JSON.stringify(user));
NotifAlert({
icon: 'success',
title: 'Login Berhasil',
message: res?.message || 'Selamat datang!',
});
navigate('/dashboard/home');
}
} catch (err) {
// hanya handle invalid captcha disini
if (err?.response?.data?.message?.toLowerCase().includes('captcha')) {
NotifAlert({
icon: 'warning',
title: 'Peringatan',
message: 'Invalid captcha',
});
fetchCaptcha();
} else {
NotifAlert({
icon: 'error',
title: 'Login Gagal',
message: err?.message || 'Terjadi kesalahan',
});
fetchCaptcha();
}
} finally {
setLoading(false);
}
};
return (
<Flex
align="center"
justify="center"
style={{
height: '100vh',
backgroundImage: `url(${bg_cod})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
>
<Card style={{ boxShadow: '0px 4px 8px rgba(0,0,0,0.1)' }}>
<Flex align="center" justify="center">
<Image src={logo} height={150} width={220} preview={false} alt="logo" />
</Flex>
<br />
<Form
form={form}
layout="vertical"
style={{ width: '250px' }}
onFinish={handleOnSubmit}
initialValues={defaultSignIn}
>
<Form.Item
label="Email / Username"
name="identifier"
rules={[
{
required: true,
message: 'Email / Username tidak boleh kosong',
},
]}
>
<Input placeholder="Email / Username" size="large" />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[{ required: true, message: 'Password tidak boleh kosong' }]}
>
<Input.Password placeholder="Password" size="large" />
</Form.Item>
<div
style={{ textAlign: 'center' }}
dangerouslySetInnerHTML={{ __html: captchaSvg }}
/>
<Form.Item
label="CAPTCHA"
name="captcha"
rules={[{ required: true, message: 'Silahkan masukkan CAPTCHA' }]}
>
<Input placeholder="Masukkan CAPTCHA" size="large" />
</Form.Item>
<Form.Item>
<Space direction="vertical" style={{ width: '100%' }}>
<Button
type="primary"
htmlType="submit"
loading={loading}
style={{ width: '100%' }}
>
Sign In
</Button>
</Space>
</Form.Item>
</Form>
<Button
type="primary"
htmlType="submit"
style={{ width: '100%' }}
onClick={() => moveToSignUp()}
>
Registration
</Button>
</Card>
</Flex>
);
};
export default SignIn;

201
src/pages/auth/Signup.jsx Normal file
View File

@@ -0,0 +1,201 @@
import React, { useState } from 'react';
import { Flex, Input, Form, Button, Card, Space, Image, Row, Col } from 'antd';
import { useNavigate } from 'react-router-dom';
import bg_cod from 'assets/bg_cod.jpg';
import logo from 'assets/freepik/LOGOPIU.png';
import { register } from '../../api/auth';
import { NotifOk, NotifAlert } from '../../components/Global/ToastNotif';
const SignUp = () => {
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const navigate = useNavigate();
const [isRegistered, setIsRegistered] = useState(false);
const moveToSignin = () => {
navigate('/signin');
};
const handleSignUp = async (values) => {
const { user_fullname, user_name, user_email, user_phone, user_password, confirmPassword } =
values;
// Validasi confirm password
if (user_password !== confirmPassword) {
NotifAlert({
icon: 'error',
title: 'Password Tidak Sama',
message: 'Password dan confirm password harus sama',
});
form.resetFields(['password', 'confirmPassword']);
return;
}
// Validasi nomor telepon Indonesia
const phoneRegex = /^(?:\+62|62|0)8[1-9][0-9]{6,11}$/;
if (!phoneRegex.test(user_phone)) {
NotifAlert({
icon: 'error',
title: 'Format Telepon Salah',
message: 'Nomor telepon tidak valid (harus nomor Indonesia)',
});
form.resetFields(['user_phone']);
return;
}
// Validasi password kompleks
const passwordErrors = [];
if (user_password.length < 8) passwordErrors.push('Minimal 8 karakter');
if (!/[A-Z]/.test(user_password)) passwordErrors.push('Harus ada huruf kapital');
if (!/[0-9]/.test(user_password)) passwordErrors.push('Harus ada angka');
if (!/[!@#$%^&*(),.?":{}|<>]/.test(user_password))
passwordErrors.push('Harus ada karakter spesial');
if (passwordErrors.length) {
NotifAlert({
icon: 'error',
title: 'Password Tidak Valid',
message: passwordErrors.join(', '),
});
form.resetFields(['user_password', 'confirmPassword']);
return;
}
setLoading(true);
try {
const res = await register({
user_fullname,
user_name,
user_email,
user_phone,
user_password,
});
NotifOk({
icon: 'success',
title: 'Registrasi Berhasil',
message: res?.data?.message || 'Berhasil menambahkan user.',
});
form.resetFields();
setIsRegistered(true);
// navigate('/signin');
} catch (err) {
console.error('Register error:', err);
const errorMessage = err?.response?.data?.message || err.message || 'Terjadi kesalahan';
NotifAlert({
icon: 'error',
title: 'Registrasi Gagal',
message: errorMessage || 'Terjadi kesalahan',
});
if (errorMessage.toLowerCase().includes('already')) {
form.resetFields();
}
} finally {
setLoading(false);
}
};
return (
<Flex
align="center"
justify="center"
style={{
minHeight: '100vh',
backgroundImage: `url(${bg_cod})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
padding: '20px',
}}
>
<Card
style={{
width: '100%',
maxWidth: 450,
borderRadius: '12px',
boxShadow: '0 8px 16px rgba(0, 0, 0, 0.1)',
padding: '10px',
textAlign: 'center',
}}
>
<Image src={logo} height={150} width={220} preview={false} alt="logo" />
<h2 style={{ marginBottom: '20px', color: '#1a3c34' }}>Registration</h2>
<Form form={form} onFinish={handleSignUp} layout="vertical">
<Row gutter={16}>
<Col span={12}>
<Form.Item
label="Full Name"
name="user_fullname"
rules={[{ required: true }]}
>
<Input placeholder="Full Name" size="large" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Name" name="user_name" rules={[{ required: true }]}>
<Input placeholder="Name" size="large" />
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item
label="Email"
name="user_email"
rules={[
{
required: true,
type: 'email',
message: 'Please input a valid email!',
},
]}
>
<Input placeholder="Email" size="large" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Phone" name="user_phone" rules={[{ required: true }]}>
<Input placeholder="Phone" size="large" />
</Form.Item>
</Col>
</Row>
<Form.Item label="Password" name="user_password" rules={[{ required: true }]}>
<Input.Password placeholder="Password" size="large" />
</Form.Item>
<Form.Item
label="Confirm Password"
name="confirmPassword"
rules={[{ required: true }]}
>
<Input.Password placeholder="Confirm Password" size="large" />
</Form.Item>
<Form.Item>
<Space direction="vertical" style={{ width: '100%' }}>
<Button
type="primary"
htmlType="submit"
loading={loading}
style={{ width: '100%' }}
>
Sign Up
</Button>
</Space>
</Form.Item>
</Form>
<Button type="primary" style={{ width: '100%' }} onClick={moveToSignin}>
Sign In
</Button>
</Card>
</Flex>
);
};
export default SignUp;

11
src/pages/blank/Blank.jsx Normal file
View File

@@ -0,0 +1,11 @@
import React from 'react'
const Blank = () => {
return (
<div>
Hi From BlankPage
</div>
)
}
export default Blank

View File

@@ -0,0 +1,85 @@
import { Button, Typography } from 'antd';
import { Link } from 'react-router-dom';
import ImgRobot from '../../assets/freepik/404.png';
const { Title, Paragraph, Text } = Typography;
const NotFound = () => {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fafafa',
padding: '5vh 16px',
textAlign: 'center',
minHeight: '100vh',
}}
>
<Title
level={2}
style={{
fontWeight: 800,
marginBottom: 12,
fontSize: 'clamp(28px, 5vw, 42px)',
color: '#1f1f1f',
}}
>
Oops... You seem lost.
</Title>
<Paragraph
style={{
fontSize: 'clamp(14px, 2vw, 18px)',
maxWidth: '90%',
color: '#595959',
marginBottom: '3vh',
}}
>
We couldn't find the page you were looking for. Let us take you back to the main
page.
</Paragraph>
<img
src={ImgRobot}
alt="404 Not Found"
style={{
maxWidth: '90%',
width: '480px',
marginBottom: '4vh',
}}
/>
<Link to="/">
<Button
type="default"
size="large"
style={{
backgroundColor: '#2f2f2f',
color: '#fff',
border: 'none',
padding: '10px 20px',
}}
>
Go back
</Button>
</Link>
<Text type="secondary" style={{ fontSize: '12px', marginTop: '5vh' }}>
Illustration by{' '}
<a
href="https://www.freepik.com"
target="_blank"
rel="noopener noreferrer"
style={{ color: '#1890ff' }}
>
Freepik
</a>
</Text>
</div>
);
};
export default NotFound;

View File

@@ -0,0 +1,49 @@
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} />;
}

View File

@@ -0,0 +1,58 @@
import { Button, Spin, Typography } from 'antd';
import { Link } from 'react-router-dom';
import ImgPIU from '../../assets/freepik/LOGOPIU.png';
const { Title, Paragraph, Text } = Typography;
const Waiting = () => {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fafafa',
padding: '5vh 16px',
textAlign: 'center',
minHeight: '100vh',
}}
>
<img
src={ImgPIU}
alt="Loading"
style={{
maxWidth: '30%',
// width: '400px',
marginBottom: '4vh',
}}
/>
<Spin size="large" style={{ marginBottom: '4vh' }} />
<Title
level={2}
style={{
fontWeight: 800,
marginBottom: 12,
fontSize: 'clamp(28px, 5vw, 42px)',
color: '#1f1f1f',
}}
>
Please wait...
</Title>
<Paragraph
style={{
fontSize: 'clamp(14px, 2vw, 18px)',
maxWidth: '90%',
color: '#595959',
marginBottom: '3vh',
}}
>
We are loading your content. This wont take long.
</Paragraph>
</div>
);
};
export default Waiting;

View File

@@ -0,0 +1,72 @@
import React, { memo, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import ListContact from './component/ListContact';
import DetailContact from './component/DetailContact';
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
import { Typography } from 'antd';
const { Text } = Typography;
const IndexContact = memo(function IndexContact() {
const navigate = useNavigate();
const { setBreadcrumbItems } = useBreadcrumb();
const [actionMode, setActionMode] = useState('list');
const [selectedData, setSelectedData] = useState(null);
const [readOnly, setReadOnly] = useState(false);
const [showModal, setShowModal] = useState(false);
const [contactType, setContactType] = useState('operator');
const setMode = (param) => {
setShowModal(param !== 'list');
setReadOnly(param === 'preview');
setActionMode(param);
};
const handleContactSaved = (contactData, actionMode) => {
setLastSavedContact({ contactData, actionMode });
// Clear after processing
setTimeout(() => setLastSavedContact(null), 100);
};
const [lastSavedContact, setLastSavedContact] = useState(null);
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
setBreadcrumbItems([
{ title: <Text strong style={{ fontSize: '14px' }}> Contact</Text> },
]);
} else {
navigate('/signin');
}
}, [navigate, setBreadcrumbItems]);
return (
<React.Fragment>
<ListContact
actionMode={actionMode}
setActionMode={setMode}
selectedData={selectedData}
setSelectedData={setSelectedData}
readOnly={readOnly}
lastSavedContact={lastSavedContact}
setContactType={setContactType}
/>
<DetailContact
setActionMode={setMode}
selectedData={selectedData}
setSelectedData={setSelectedData}
readOnly={readOnly}
showModal={showModal}
actionMode={actionMode}
onContactSaved={handleContactSaved}
contactType={contactType}
/>
</React.Fragment>
);
});
export default IndexContact;

View File

@@ -0,0 +1,272 @@
import React, { memo, useEffect, useState } from 'react';
import { Modal, Input, Button, Switch, ConfigProvider, Typography, Divider, Select } from 'antd';
import { NotifAlert, NotifOk } from '../../../components/Global/ToastNotif';
import { validateRun } from '../../../Utils/validate';
import { createContact, updateContact } from '../../../api/contact';
const { Text } = Typography;
const DetailContact = memo(function DetailContact(props) {
const [confirmLoading, setConfirmLoading] = useState(false);
const defaultData = {
id: '',
name: '',
phone: '',
is_active: true,
};
const [formData, setFormData] = useState(defaultData);
const handleInputChange = (e) => {
const { name, value } = e.target;
// Validasi untuk field phone - hanya angka yang diperbolehkan
if (name === 'phone') {
const cleanedValue = value.replace(/[^0-9+\-\s()]/g, '');
setFormData((prev) => ({
...prev,
[name]: cleanedValue,
}));
} else {
setFormData((prev) => ({
...prev,
[name]: value,
}));
}
};
const handleStatusToggle = (checked) => {
setFormData({
...formData,
is_active: checked,
});
};
const handleSave = async () => {
setConfirmLoading(true);
// Validation rules
const validationRules = [
{ field: 'name', label: 'Contact Name', required: true },
{ field: 'phone', label: 'Phone', required: true },
];
if (
validateRun(formData, validationRules, (errorMessages) => {
NotifOk({ icon: 'warning', title: 'Peringatan', message: errorMessages });
setConfirmLoading(false);
})
)
return;
// Custom validation untuk name - minimal 3 karakter
if (formData.name && formData.name.length < 3) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Nama contact minimal 3 karakter',
});
setConfirmLoading(false);
return;
}
// Custom validation untuk phone - Indonesian phone format
const phoneRegex = /^(?:\+62|0)8\d{7,10}$/;
if (formData.phone && !phoneRegex.test(formData.phone.replace(/[\s\-\(\)]/g, ''))) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Nomor telepon harus format Indonesia (+628XXXXXXXXX atau 08XXXXXXXXX)',
});
setConfirmLoading(false);
return;
}
try {
const contactData = {
contact_name: formData.name,
contact_phone: formData.phone.replace(/[\s\-\(\)]/g, ''), // Clean phone number
is_active: formData.is_active,
};
let response;
if (props.actionMode === 'edit') {
response = await updateContact(
props.selectedData.contact_id || props.selectedData.id,
contactData
);
} else {
response = await createContact(contactData);
}
NotifAlert({
icon: 'success',
title: 'Berhasil',
message: `Data Contact "${formData.name}" berhasil ${
props.actionMode === 'add' ? 'ditambahkan' : 'diperbarui'
}.`,
});
props.onContactSaved?.(response.data, props.actionMode);
handleCancel();
} catch (error) {
console.error('Save failed:', error);
NotifAlert({
icon: 'error',
title: 'Error',
message: error.response?.data?.message || 'Terjadi kesalahan saat menyimpan data.',
});
} finally {
setConfirmLoading(false);
}
};
const handleCancel = () => {
props.setActionMode('list');
props.setSelectedData(null);
};
useEffect(() => {
if (props.showModal) {
if (props.actionMode === 'edit' && props.selectedData) {
setFormData({
name: props.selectedData.contact_name || props.selectedData.name,
phone: props.selectedData.contact_phone || props.selectedData.phone,
is_active:
props.selectedData.is_active || props.selectedData.status === 'active',
});
} else if (props.actionMode === 'add') {
setFormData({
name: '',
phone: '',
is_active: true,
});
}
}
}, [props.showModal, props.actionMode, props.selectedData]);
return (
<Modal
title={`${
props.actionMode === 'add'
? 'Tambah'
: props.actionMode === 'edit'
? 'Edit'
: 'Detail'
} Kontak`}
open={props.showModal}
onCancel={handleCancel}
footer={[
<React.Fragment key="modal-footer">
<ConfigProvider
theme={{
components: {
Button: {
defaultBg: 'white',
defaultColor: '#23A55A',
defaultBorderColor: '#23A55A',
},
},
}}
>
<Button onClick={handleCancel}>{props.readOnly ? 'Tutup' : 'Batal'}</Button>
</ConfigProvider>
<ConfigProvider
theme={{
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
},
},
}}
>
{!props.readOnly && (
<Button loading={confirmLoading} onClick={handleSave}>
Simpan
</Button>
)}
</ConfigProvider>
</React.Fragment>,
]}
>
<div style={{ padding: '8px 0' }}>
{/* Status field only show in add mode*/}
{props.actionMode === 'add' && (
<>
<div>
<div>
<Text strong>Status</Text>
</div>
<div
style={{ display: 'flex', alignItems: 'center', marginTop: '8px' }}
>
<div style={{ marginRight: '8px' }}>
<Switch
disabled={props.readOnly}
style={{
backgroundColor: formData.is_active
? '#23A55A'
: '#bfbfbf',
}}
checked={formData.is_active}
onChange={handleStatusToggle}
/>
</div>
<div>
<Text>{formData.is_active ? 'Active' : 'Inactive'}</Text>
</div>
</div>
</div>
<Divider style={{ margin: '12px 0' }} />
</>
)}
<div style={{ marginBottom: 12 }}>
<Text strong>Name</Text>
<Text style={{ color: 'red' }}> *</Text>
<Input
name="name"
value={formData.name}
onChange={handleInputChange}
placeholder="Enter Name"
readOnly={props.readOnly}
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Phone</Text>
<Text style={{ color: 'red' }}> *</Text>
<Input
name="phone"
value={formData.phone}
onChange={handleInputChange}
placeholder="Enter Phone Number"
readOnly={props.readOnly}
maxLength={15}
style={{ color: formData.is_active ? '#000000' : '#ff4d4f' }}
/>
</div>
{/* Contact Type */}
{/* <div style={{ marginBottom: 12 }}>
<Text strong>Contact Type</Text>
<Text style={{ color: 'red' }}> *</Text>
<Select
value={formData.contact_type || undefined}
onChange={handleContactTypeChange}
placeholder="Select Contact Type"
disabled={props.readOnly}
style={{ width: '100%' }}
>
<Select.Option value="operator">Operator</Select.Option>
<Select.Option value="gudang">Gudang</Select.Option>
</Select>
</div> */}
</div>
</Modal>
);
});
export default DetailContact;

View File

@@ -0,0 +1,487 @@
import React, { memo, useState, useEffect } from 'react';
import { Button, Row, Col, Input, Tabs, Space, ConfigProvider, Card, Tag, Switch } from 'antd';
import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
SearchOutlined,
UserOutlined,
PhoneOutlined,
} from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import { NotifAlert, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
import { getAllContact, deleteContact, updateContact } from '../../../api/contact';
const ContactCard = memo(function ContactCard({
contact,
showEditModal,
showDeleteModal,
onStatusToggle,
}) {
const handleStatusToggle = async (checked) => {
try {
const updatedContact = {
contact_name: contact.contact_name || contact.name,
contact_phone: contact.contact_phone || contact.phone,
is_active: checked,
contact_type: contact.contact_type,
};
await updateContact(contact.contact_id || contact.id, updatedContact);
NotifAlert({
icon: 'success',
title: 'Berhasil',
message: `Status "${contact.contact_name || contact.name}" berhasil diperbarui.`,
});
// Refresh contacts list
onStatusToggle && onStatusToggle();
} catch (error) {
console.error('Error updating contact status:', error);
NotifAlert({
icon: 'error',
title: 'Error',
message: 'Gagal memperbarui status kontak',
});
}
};
return (
<Col xs={24} sm={12} md={8} lg={6}>
<div
className="contact-card"
style={{
marginBottom: 16,
borderRadius: 8,
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
height: '100%',
padding: '16px',
backgroundColor: '#f5f5f5',
border: '1px solid #e8e8e8',
transition: 'all 0.3s ease',
cursor: 'pointer',
}}
onMouseEnter={(e) => {
e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
}}
>
<div
style={{
height: '100%',
display: 'flex',
flexDirection: 'column',
position: 'relative',
}}
>
{/* Type Badge - Top Left */}
{/* <div style={{ position: 'absolute', top: 0, left: 0, zIndex: 1 }}>
<Tag
color={
contact.contact_type === 'operator'
? 'blue'
: contact.contact_type === 'gudang'
? 'orange'
: 'default'
}
style={{ fontSize: '11px' }}
>
{contact.contact_type === 'operator' ? 'Operator' : contact.contact_type === 'gudang' ? 'Gudang' : 'Unknown'}
</Tag>
</div> */}
{/* Status Slider - Top Right */}
<div
style={{
position: 'absolute',
top: 0,
right: 0,
zIndex: 1,
padding: '4px 8px',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
<Switch
checked={contact.status === 'active'}
onChange={handleStatusToggle}
style={{
backgroundColor:
contact.status === 'active' ? '#52c41a' : '#d9d9d9',
}}
/>
<span
style={{
fontSize: '12px',
color: contact.status === 'active' ? '#52c41a' : '#ff4d4f',
fontWeight: 500,
}}
>
{contact.status === 'active' ? 'Active' : 'Inactive'}
</span>
</div>
</div>
{/* Main Content */}
<div
style={{
display: 'flex',
alignItems: 'center',
gap: 12,
flex: 1,
paddingTop: '28px',
}}
>
<div
className="avatar"
style={{
width: 55,
height: 55,
borderRadius: '50%',
backgroundColor:
contact.status === 'active' ? '#52c41a' : '#ff4d4f',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}}
>
<UserOutlined style={{ color: 'white', fontSize: '25px' }} />
</div>
<div style={{ flex: 1, minWidth: 0 }}>
<div
style={{
fontWeight: 600,
fontSize: '16px',
marginBottom: '4px',
color: '#262626',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{contact.contact_name || contact.name}
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
fontSize: '14px',
}}
>
<PhoneOutlined style={{ marginRight: 6, color: '#1890ff' }} />
<span
style={{
color: contact.status === 'active' ? '#262626' : '#262626',
}}
>
{contact.contact_phone || contact.phone}
</span>
</div>
</div>
</div>
{/* Edit and Delete Buttons - Bottom Right */}
<div
style={{
display: 'flex',
justifyContent: 'flex-end',
gap: '8px',
marginTop: '8px',
}}
>
<Space>
<Button
type="default"
size="small"
style={{
backgroundColor: '#fff7e6',
borderColor: '#faad14',
color: '#faad14',
padding: '2px 6px',
fontSize: '11px',
height: '24px',
}}
icon={
<EditOutlined style={{ color: '#faad14', fontSize: '11px' }} />
}
onClick={(e) => {
e.stopPropagation();
showEditModal(contact);
}}
>
Edit info
</Button>
<Button
type="default"
danger
size="small"
style={{
backgroundColor: '#fff1f0',
borderColor: 'red',
padding: '2px 6px',
fontSize: '11px',
height: '24px',
}}
icon={<DeleteOutlined style={{ fontSize: '11px' }} />}
onClick={(e) => {
e.stopPropagation();
showDeleteModal(contact);
}}
>
Delete
</Button>
</Space>
</div>
</div>
</div>
</Col>
);
});
const ListContact = memo(function ListContact(props) {
const [activeTab, setActiveTab] = useState('all');
const [filteredContacts, setFilteredContacts] = useState([]);
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
// Default filter object matching plantSection pattern
const defaultFilter = { criteria: '' };
const [formDataFilter, setFormDataFilter] = useState(defaultFilter);
// Fetch contacts from API
const fetchContacts = async () => {
setLoading(true);
try {
// Build search parameters matching database pattern
const searchParams = { ...formDataFilter };
// Add specific filters if not "all"
if (activeTab !== 'all') {
if (activeTab === 'operator') {
searchParams.code = 'operator';
} else if (activeTab === 'gudang') {
searchParams.code = 'gudang';
}
}
const queryParams = new URLSearchParams();
Object.entries(searchParams).forEach(([key, value]) => {
if (value !== '' && value !== null && value !== undefined) {
queryParams.append(key, value);
}
});
const response = await getAllContact(queryParams);
setFilteredContacts(response.data || []);
} catch (error) {
console.error('Error fetching contacts:', error);
NotifAlert({
icon: 'error',
title: 'Error',
message: 'Gagal memuat data kontak',
});
} finally {
setLoading(false);
}
};
// Fetch contacts on component mount
useEffect(() => {
const token = localStorage.getItem('token');
if (!token) {
navigate('/signin');
return;
}
fetchContacts();
}, []);
// Refetch when filters change
useEffect(() => {
fetchContacts();
}, [formDataFilter, activeTab]);
// Listen for saved contact data
useEffect(() => {
if (props.lastSavedContact) {
fetchContacts();
}
}, [props.lastSavedContact]);
const getFilteredContacts = () => {
return filteredContacts;
};
const showEditModal = (param) => {
props.setSelectedData(param);
props.setActionMode('edit');
};
const showAddModal = () => {
props.setSelectedData(null);
props.setActionMode('add');
props.setContactType?.(activeTab);
};
const showDeleteModal = (contact) => {
NotifConfirmDialog({
icon: 'question',
title: 'Konfirmasi Hapus',
message: `Kontak "${contact.contact_name || contact.name}" akan dihapus?`,
onConfirm: () => handleDelete(contact),
onCancel: () => props.setSelectedData(null),
});
};
const handleDelete = async (contact) => {
try {
await deleteContact(contact.contact_id || contact.id);
NotifAlert({
icon: 'success',
title: 'Berhasil',
message: `Kontak "${contact.contact_name || contact.name}" berhasil dihapus.`,
});
// Refetch contacts after deletion
fetchContacts();
} catch (error) {
console.error('Error deleting contact:', error);
NotifAlert({
icon: 'error',
title: 'Error',
message: 'Gagal menghapus kontak',
});
}
};
return (
<React.Fragment>
<Card>
<Row>
<Col xs={24}>
<Row justify="space-between" align="middle" gutter={[8, 8]}>
<Col xs={24} sm={24} md={12} lg={12}>
<Input.Search
placeholder="Search by name..."
value={formDataFilter.criteria}
onChange={(e) => {
const value = e.target.value;
setFormDataFilter({ criteria: value });
if (value === '') {
setFormDataFilter(defaultFilter);
}
}}
onSearch={(value) => setFormDataFilter({ criteria: value })}
allowClear={{
clearIcon: (
<span onClick={() => setFormDataFilter(defaultFilter)}>
</span>
),
}}
enterButton={
<Button
type="primary"
icon={<SearchOutlined />}
style={{
backgroundColor: '#23A55A',
borderColor: '#23A55A',
}}
>
Search
</Button>
}
size="large"
/>
</Col>
<Col>
<Space wrap size="small">
<ConfigProvider
theme={{
components: {
Button: {
defaultBg: 'white',
defaultColor: '#23A55A',
defaultBorderColor: '#23A55A',
},
},
}}
>
<Button
icon={<PlusOutlined />}
onClick={() => showAddModal()}
size="large"
>
Add Contact
</Button>
</ConfigProvider>
</Space>
</Col>
</Row>
</Col>
<Col xs={24} style={{ marginTop: '16px' }}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '16px',
}}
>
{/* Tabs */}
{/* <Tabs
activeKey={activeTab}
onChange={setActiveTab}
size="large"
items={[
{
key: 'all',
label: 'All',
},
{
key: 'operator',
label: 'Operator',
},
{
key: 'gudang',
label: 'Gudang',
},
]}
/> */}
</div>
{getFilteredContacts().length === 0 ? (
<div style={{ textAlign: 'center', padding: '40px' }}>
<span style={{ color: '#8c8c8c' }}>
{loading ? 'Loading contacts...' : 'No contacts found'}
</span>
</div>
) : (
<Row gutter={[16, 16]}>
{getFilteredContacts().map((contact) => (
<ContactCard
key={contact.contact_id || contact.id}
contact={{
...contact,
id: contact.contact_id || contact.id,
name: contact.contact_name || contact.name,
phone: contact.contact_phone || contact.phone,
status: contact.is_active ? 'active' : 'inactive',
}}
showEditModal={showEditModal}
showDeleteModal={showDeleteModal}
onStatusToggle={fetchContacts}
/>
))}
</Row>
)}
</Col>
</Row>
</Card>
</React.Fragment>
);
});
export default ListContact;

View File

@@ -0,0 +1,38 @@
import React, { memo, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
import { Typography } from 'antd';
import ListHistoryAlarm from './component/ListHistoryAlarm';
const { Text } = Typography;
const IndexHistoryAlarm = memo(function IndexHistoryAlarm() {
const navigate = useNavigate();
const { setBreadcrumbItems } = useBreadcrumb();
const [selectedData, setSelectedData] = useState(null);
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
setBreadcrumbItems([
{
title: (
<Text strong style={{ fontSize: '14px' }}>
History Event
</Text>
),
},
]);
} else {
navigate('/signin');
}
}, [navigate, setBreadcrumbItems]);
return (
<React.Fragment>
<ListHistoryAlarm selectedData={selectedData} setSelectedData={setSelectedData} />
</React.Fragment>
);
});
export default IndexHistoryAlarm;

View File

@@ -0,0 +1,158 @@
import React, { memo, useState, useEffect } from 'react';
import { Button, Row, Col, Card, Input } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import TableList from '../../../../components/Global/TableList';
import { getAllHistoryAlarm } from '../../../../api/history-value';
const ListHistoryAlarm = memo(function ListHistoryAlarm(props) {
const columns = [
{
title: 'No',
key: 'no',
width: '5%',
align: 'center',
render: (_, __, index) => index + 1,
},
{
title: 'Datetime',
dataIndex: 'datetime',
key: 'datetime',
width: '15%',
// render: (_, record) => toAppDateTimezoneFormatter(record.datetime),
},
{
title: 'Tag Name',
dataIndex: 'tag_name',
key: 'tag_name',
width: '40%',
},
{
title: 'Value',
dataIndex: 'new_val',
key: 'new_val',
width: '10%',
render: (_, record) => Number(record.new_val).toFixed(4),
},
{
title: 'Threshold',
dataIndex: 'threshold',
key: 'threshold',
width: '10%',
render: (_, record) => {
switch (record.status) {
case 1:
return (
<span>
{record.lim_low} : {record.lim_high}
</span>
);
case 2:
return <span>{`< ${record.lim_low_crash}`}</span>;
case 3:
return (
<span>
{record.lim_low_crash} : {record.lim_low}
</span>
);
case 4:
return (
<span>
{record.lim_high} : {record.lim_high_crash}
</span>
);
case 5:
return <span>{`> ${record.lim_high_crash}`}</span>;
default:
return <span>Undefined</span>;
}
},
},
{
title: 'Condition',
dataIndex: 'condition',
key: 'condition',
width: '20%',
render: (_, record) => (
<Button type="text" style={{ backgroundColor: record.status_color, width: '100%' }}>
{record.condition}
</Button>
),
},
{
title: 'Stat',
dataIndex: 'status',
key: 'status',
width: '5%',
},
];
const [trigerFilter, setTrigerFilter] = useState(false);
const defaultFilter = { criteria: '' };
const [formDataFilter, setFormDataFilter] = useState(defaultFilter);
const [searchValue, setSearchValue] = useState('');
const handleSearch = () => {
setFormDataFilter({ criteria: searchValue });
setTrigerFilter((prev) => !prev);
};
const handleSearchClear = () => {
setSearchValue('');
setFormDataFilter({ criteria: '' });
setTrigerFilter((prev) => !prev);
};
return (
<React.Fragment>
<Card>
<Row>
<Col xs={24}>
<Row justify="space-between" align="middle" gutter={[8, 8]}>
<Col xs={24} sm={24} md={12} lg={12}>
<Input.Search
placeholder="Search ..."
value={searchValue}
onChange={(e) => {
const value = e.target.value;
setSearchValue(value);
if (value === '') {
handleSearchClear();
}
}}
onSearch={handleSearch}
allowClear={{
clearIcon: <span onClick={handleSearchClear}></span>,
}}
enterButton={
<Button
type="primary"
icon={<SearchOutlined />}
style={{
backgroundColor: '#23A55A',
borderColor: '#23A55A',
}}
>
Search
</Button>
}
size="large"
/>
</Col>
</Row>
</Col>
<Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: '16px' }}>
<TableList
getData={getAllHistoryAlarm}
queryParams={formDataFilter}
columns={columns}
triger={trigerFilter}
/>
</Col>
</Row>
</Card>
</React.Fragment>
);
});
export default ListHistoryAlarm;

View File

@@ -0,0 +1,38 @@
import React, { memo, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
import { Typography } from 'antd';
import ListHistoryEvent from './component/ListHistoryEvent';
const { Text } = Typography;
const IndexHistoryEvent = memo(function IndexHistoryEvent() {
const navigate = useNavigate();
const { setBreadcrumbItems } = useBreadcrumb();
const [selectedData, setSelectedData] = useState(null);
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
setBreadcrumbItems([
{
title: (
<Text strong style={{ fontSize: '14px' }}>
History Event
</Text>
),
},
]);
} else {
navigate('/signin');
}
}, [navigate, setBreadcrumbItems]);
return (
<React.Fragment>
<ListHistoryEvent selectedData={selectedData} setSelectedData={setSelectedData} />
</React.Fragment>
);
});
export default IndexHistoryEvent;

View File

@@ -0,0 +1,117 @@
import React, { memo, useState, useEffect } from 'react';
import { Button, Row, Col, Card, Input } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import TableList from '../../../../components/Global/TableList';
import { getAllHistoryEvent } from '../../../../api/history-value';
const ListHistoryEvent = memo(function ListHistoryEvent(props) {
const columns = [
{
title: 'No',
key: 'no',
width: '5%',
align: 'center',
render: (_, __, index) => index + 1,
},
{
title: 'Datetime',
dataIndex: 'datetime',
key: 'datetime',
width: '15%',
// render: (_, record) => toAppDateTimezoneFormatter(record.datetime),
},
{
title: 'Tag Name',
dataIndex: 'tagname',
key: 'tagname',
width: '40%',
},
{
title: 'Description',
dataIndex: 'description',
key: 'description',
width: '20%',
render: (_, record) => (
<Button type="text" style={{ backgroundColor: record.status_color, width: '100%' }}>
{record.description}
</Button>
),
},
{
title: 'Stat',
dataIndex: 'status',
key: 'status',
width: '5%',
},
];
const [trigerFilter, setTrigerFilter] = useState(false);
const defaultFilter = { criteria: '' };
const [formDataFilter, setFormDataFilter] = useState(defaultFilter);
const [searchValue, setSearchValue] = useState('');
const handleSearch = () => {
setFormDataFilter({ criteria: searchValue });
setTrigerFilter((prev) => !prev);
};
const handleSearchClear = () => {
setSearchValue('');
setFormDataFilter({ criteria: '' });
setTrigerFilter((prev) => !prev);
};
return (
<React.Fragment>
<Card>
<Row>
<Col xs={24}>
<Row justify="space-between" align="middle" gutter={[8, 8]}>
<Col xs={24} sm={24} md={12} lg={12}>
<Input.Search
placeholder="Search ..."
value={searchValue}
onChange={(e) => {
const value = e.target.value;
setSearchValue(value);
if (value === '') {
handleSearchClear();
}
}}
onSearch={handleSearch}
allowClear={{
clearIcon: <span onClick={handleSearchClear}></span>,
}}
enterButton={
<Button
type="primary"
icon={<SearchOutlined />}
style={{
backgroundColor: '#23A55A',
borderColor: '#23A55A',
}}
>
Search
</Button>
}
size="large"
/>
</Col>
</Row>
</Col>
<Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: '16px' }}>
<TableList
getData={getAllHistoryEvent}
queryParams={formDataFilter}
columns={columns}
triger={trigerFilter}
/>
</Col>
</Row>
</Card>
</React.Fragment>
);
});
export default ListHistoryEvent;

47
src/pages/home/Home.jsx Normal file
View File

@@ -0,0 +1,47 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
const { Text } = Typography;
const Home = () => {
const { setBreadcrumbItems } = useBreadcrumb();
const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 768);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => {
setBreadcrumbItems([
{
title: (
<Text strong style={{ fontSize: '14px' }}>
Dashboard
</Text>
),
},
{
title: (
<Text strong style={{ fontSize: '14px' }}>
Home
</Text>
),
},
]);
}, []);
return (
<Card>
<Flex align="center" justify="center">
<Text strong style={{ fontSize: '30px' }}>
Welcome to Call Of Duty App
</Text>
</Flex>
</Card>
);
};
export default Home;

Some files were not shown because too many files have changed in this diff Show More