opensignalbox-interface 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. opensignalbox/interface/__init__.py +42 -0
  2. opensignalbox/interface/adapters/__init__.py +3 -0
  3. opensignalbox/interface/adapters/base.py +148 -0
  4. opensignalbox/interface/adapters/controller.py +286 -0
  5. opensignalbox/interface/adapters/modbus/__init__.py +3 -0
  6. opensignalbox/interface/adapters/modbus/adapter.py +485 -0
  7. opensignalbox/interface/assets/favicon.ico +0 -0
  8. opensignalbox/interface/interfaces/__init__.py +3 -0
  9. opensignalbox/interface/interfaces/base.py +170 -0
  10. opensignalbox/interface/interfaces/basicio/__init__.py +3 -0
  11. opensignalbox/interface/interfaces/basicio/connections.py +239 -0
  12. opensignalbox/interface/interfaces/basicio/handler.py +1096 -0
  13. opensignalbox/interface/interfaces/basicio/models.py +165 -0
  14. opensignalbox/interface/interfaces/bell/__init__.py +3 -0
  15. opensignalbox/interface/interfaces/bell/connections.py +279 -0
  16. opensignalbox/interface/interfaces/bell/handler.py +802 -0
  17. opensignalbox/interface/interfaces/bell/models.py +103 -0
  18. opensignalbox/interface/interfaces/controller.py +467 -0
  19. opensignalbox/interface/main.py +187 -0
  20. opensignalbox/interface/models.py +155 -0
  21. opensignalbox/interface/routes/__init__.py +4 -0
  22. opensignalbox/interface/routes/adapters.py +119 -0
  23. opensignalbox/interface/routes/interfaces.py +104 -0
  24. opensignalbox/interface/routes.py +204 -0
  25. opensignalbox/interface/utils.py +29 -0
  26. opensignalbox/interface/version.py +5 -0
  27. opensignalbox/interface/web_ui/.gitignore +24 -0
  28. opensignalbox/interface/web_ui/README.md +5 -0
  29. opensignalbox/interface/web_ui/WEB_UI_REFACTORING.md +136 -0
  30. opensignalbox/interface/web_ui/components.json +17 -0
  31. opensignalbox/interface/web_ui/dist/assets/index-DhsEc6uo.css +2020 -0
  32. opensignalbox/interface/web_ui/dist/assets/index-t__5JZjf.js +39056 -0
  33. opensignalbox/interface/web_ui/dist/assets/index-t__5JZjf.js.map +1 -0
  34. opensignalbox/interface/web_ui/dist/index.html +14 -0
  35. opensignalbox/interface/web_ui/index.html +13 -0
  36. opensignalbox/interface/web_ui/package-lock.json +3710 -0
  37. opensignalbox/interface/web_ui/package.json +39 -0
  38. opensignalbox/interface/web_ui/src/App.vue +32 -0
  39. opensignalbox/interface/web_ui/src/assets/favicon.ico +0 -0
  40. opensignalbox/interface/web_ui/src/assets/index.css +83 -0
  41. opensignalbox/interface/web_ui/src/components/SharedVariablePicker.vue +112 -0
  42. opensignalbox/interface/web_ui/src/components/adapters/AdapterList.vue +183 -0
  43. opensignalbox/interface/web_ui/src/components/adapters/types.ts +35 -0
  44. opensignalbox/interface/web_ui/src/components/interfaces/InterfaceList.vue +200 -0
  45. opensignalbox/interface/web_ui/src/components/ui/badge/Badge.vue +16 -0
  46. opensignalbox/interface/web_ui/src/components/ui/badge/index.ts +25 -0
  47. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/Breadcrumb.vue +13 -0
  48. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +22 -0
  49. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbItem.vue +16 -0
  50. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbLink.vue +19 -0
  51. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbList.vue +16 -0
  52. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbPage.vue +19 -0
  53. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +21 -0
  54. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/index.ts +7 -0
  55. opensignalbox/interface/web_ui/src/components/ui/button/Button.vue +26 -0
  56. opensignalbox/interface/web_ui/src/components/ui/button/index.ts +35 -0
  57. opensignalbox/interface/web_ui/src/components/ui/card/Card.vue +21 -0
  58. opensignalbox/interface/web_ui/src/components/ui/card/CardContent.vue +14 -0
  59. opensignalbox/interface/web_ui/src/components/ui/card/CardDescription.vue +14 -0
  60. opensignalbox/interface/web_ui/src/components/ui/card/CardFooter.vue +14 -0
  61. opensignalbox/interface/web_ui/src/components/ui/card/CardHeader.vue +14 -0
  62. opensignalbox/interface/web_ui/src/components/ui/card/CardTitle.vue +18 -0
  63. opensignalbox/interface/web_ui/src/components/ui/card/index.ts +6 -0
  64. opensignalbox/interface/web_ui/src/components/ui/checkbox/Checkbox.vue +33 -0
  65. opensignalbox/interface/web_ui/src/components/ui/checkbox/index.ts +1 -0
  66. opensignalbox/interface/web_ui/src/components/ui/collapsible/Collapsible.vue +15 -0
  67. opensignalbox/interface/web_ui/src/components/ui/collapsible/CollapsibleContent.vue +11 -0
  68. opensignalbox/interface/web_ui/src/components/ui/collapsible/CollapsibleTrigger.vue +11 -0
  69. opensignalbox/interface/web_ui/src/components/ui/collapsible/index.ts +3 -0
  70. opensignalbox/interface/web_ui/src/components/ui/command/Command.vue +30 -0
  71. opensignalbox/interface/web_ui/src/components/ui/command/CommandDialog.vue +21 -0
  72. opensignalbox/interface/web_ui/src/components/ui/command/CommandEmpty.vue +20 -0
  73. opensignalbox/interface/web_ui/src/components/ui/command/CommandGroup.vue +29 -0
  74. opensignalbox/interface/web_ui/src/components/ui/command/CommandInput.vue +33 -0
  75. opensignalbox/interface/web_ui/src/components/ui/command/CommandItem.vue +26 -0
  76. opensignalbox/interface/web_ui/src/components/ui/command/CommandList.vue +27 -0
  77. opensignalbox/interface/web_ui/src/components/ui/command/CommandSeparator.vue +23 -0
  78. opensignalbox/interface/web_ui/src/components/ui/command/CommandShortcut.vue +14 -0
  79. opensignalbox/interface/web_ui/src/components/ui/command/index.ts +9 -0
  80. opensignalbox/interface/web_ui/src/components/ui/dialog/Dialog.vue +14 -0
  81. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogClose.vue +11 -0
  82. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogContent.vue +50 -0
  83. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogDescription.vue +24 -0
  84. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogFooter.vue +19 -0
  85. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogHeader.vue +16 -0
  86. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  87. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogTitle.vue +29 -0
  88. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogTrigger.vue +11 -0
  89. opensignalbox/interface/web_ui/src/components/ui/dialog/index.ts +9 -0
  90. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
  91. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  92. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuContent.vue +38 -0
  93. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
  94. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
  95. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
  96. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
  97. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
  98. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
  99. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  100. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  101. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  102. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
  103. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
  104. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/index.ts +16 -0
  105. opensignalbox/interface/web_ui/src/components/ui/form/FormControl.vue +16 -0
  106. opensignalbox/interface/web_ui/src/components/ui/form/FormDescription.vue +20 -0
  107. opensignalbox/interface/web_ui/src/components/ui/form/FormItem.vue +19 -0
  108. opensignalbox/interface/web_ui/src/components/ui/form/FormLabel.vue +23 -0
  109. opensignalbox/interface/web_ui/src/components/ui/form/FormMessage.vue +16 -0
  110. opensignalbox/interface/web_ui/src/components/ui/form/index.ts +7 -0
  111. opensignalbox/interface/web_ui/src/components/ui/form/injectionKeys.ts +4 -0
  112. opensignalbox/interface/web_ui/src/components/ui/form/useFormField.ts +30 -0
  113. opensignalbox/interface/web_ui/src/components/ui/input/Input.vue +24 -0
  114. opensignalbox/interface/web_ui/src/components/ui/input/index.ts +1 -0
  115. opensignalbox/interface/web_ui/src/components/ui/label/Label.vue +27 -0
  116. opensignalbox/interface/web_ui/src/components/ui/label/index.ts +1 -0
  117. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberField.vue +23 -0
  118. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldContent.vue +14 -0
  119. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldDecrement.vue +25 -0
  120. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldIncrement.vue +25 -0
  121. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldInput.vue +16 -0
  122. opensignalbox/interface/web_ui/src/components/ui/number-field/index.ts +5 -0
  123. opensignalbox/interface/web_ui/src/components/ui/popover/Popover.vue +15 -0
  124. opensignalbox/interface/web_ui/src/components/ui/popover/PopoverContent.vue +48 -0
  125. opensignalbox/interface/web_ui/src/components/ui/popover/PopoverTrigger.vue +11 -0
  126. opensignalbox/interface/web_ui/src/components/ui/popover/index.ts +3 -0
  127. opensignalbox/interface/web_ui/src/components/ui/radio-group/RadioGroup.vue +25 -0
  128. opensignalbox/interface/web_ui/src/components/ui/radio-group/RadioGroupItem.vue +39 -0
  129. opensignalbox/interface/web_ui/src/components/ui/radio-group/index.ts +2 -0
  130. opensignalbox/interface/web_ui/src/components/ui/scroll-area/ScrollArea.vue +29 -0
  131. opensignalbox/interface/web_ui/src/components/ui/scroll-area/ScrollBar.vue +30 -0
  132. opensignalbox/interface/web_ui/src/components/ui/scroll-area/index.ts +2 -0
  133. opensignalbox/interface/web_ui/src/components/ui/select/Select.vue +15 -0
  134. opensignalbox/interface/web_ui/src/components/ui/select/SelectContent.vue +53 -0
  135. opensignalbox/interface/web_ui/src/components/ui/select/SelectGroup.vue +19 -0
  136. opensignalbox/interface/web_ui/src/components/ui/select/SelectItem.vue +44 -0
  137. opensignalbox/interface/web_ui/src/components/ui/select/SelectItemText.vue +11 -0
  138. opensignalbox/interface/web_ui/src/components/ui/select/SelectLabel.vue +13 -0
  139. opensignalbox/interface/web_ui/src/components/ui/select/SelectScrollDownButton.vue +24 -0
  140. opensignalbox/interface/web_ui/src/components/ui/select/SelectScrollUpButton.vue +24 -0
  141. opensignalbox/interface/web_ui/src/components/ui/select/SelectSeparator.vue +17 -0
  142. opensignalbox/interface/web_ui/src/components/ui/select/SelectTrigger.vue +31 -0
  143. opensignalbox/interface/web_ui/src/components/ui/select/SelectValue.vue +11 -0
  144. opensignalbox/interface/web_ui/src/components/ui/select/index.ts +11 -0
  145. opensignalbox/interface/web_ui/src/components/ui/separator/Separator.vue +35 -0
  146. opensignalbox/interface/web_ui/src/components/ui/separator/index.ts +1 -0
  147. opensignalbox/interface/web_ui/src/components/ui/sheet/Sheet.vue +14 -0
  148. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetClose.vue +11 -0
  149. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetContent.vue +56 -0
  150. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetDescription.vue +22 -0
  151. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetFooter.vue +19 -0
  152. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetHeader.vue +16 -0
  153. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetTitle.vue +22 -0
  154. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetTrigger.vue +11 -0
  155. opensignalbox/interface/web_ui/src/components/ui/sheet/index.ts +31 -0
  156. opensignalbox/interface/web_ui/src/components/ui/table/Table.vue +16 -0
  157. opensignalbox/interface/web_ui/src/components/ui/table/TableBody.vue +14 -0
  158. opensignalbox/interface/web_ui/src/components/ui/table/TableCaption.vue +14 -0
  159. opensignalbox/interface/web_ui/src/components/ui/table/TableCell.vue +21 -0
  160. opensignalbox/interface/web_ui/src/components/ui/table/TableEmpty.vue +37 -0
  161. opensignalbox/interface/web_ui/src/components/ui/table/TableFooter.vue +14 -0
  162. opensignalbox/interface/web_ui/src/components/ui/table/TableHead.vue +14 -0
  163. opensignalbox/interface/web_ui/src/components/ui/table/TableHeader.vue +14 -0
  164. opensignalbox/interface/web_ui/src/components/ui/table/TableRow.vue +14 -0
  165. opensignalbox/interface/web_ui/src/components/ui/table/index.ts +9 -0
  166. opensignalbox/interface/web_ui/src/components/ui/tabs/Tabs.vue +15 -0
  167. opensignalbox/interface/web_ui/src/components/ui/tabs/TabsContent.vue +22 -0
  168. opensignalbox/interface/web_ui/src/components/ui/tabs/TabsList.vue +25 -0
  169. opensignalbox/interface/web_ui/src/components/ui/tabs/TabsTrigger.vue +29 -0
  170. opensignalbox/interface/web_ui/src/components/ui/tabs/index.ts +4 -0
  171. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInput.vue +22 -0
  172. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputInput.vue +19 -0
  173. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputItem.vue +22 -0
  174. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
  175. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
  176. opensignalbox/interface/web_ui/src/components/ui/tags-input/index.ts +5 -0
  177. opensignalbox/interface/web_ui/src/components/ui/textarea/Textarea.vue +24 -0
  178. opensignalbox/interface/web_ui/src/components/ui/textarea/index.ts +1 -0
  179. opensignalbox/interface/web_ui/src/components/ui/tooltip/Tooltip.vue +14 -0
  180. opensignalbox/interface/web_ui/src/components/ui/tooltip/TooltipContent.vue +31 -0
  181. opensignalbox/interface/web_ui/src/components/ui/tooltip/TooltipProvider.vue +11 -0
  182. opensignalbox/interface/web_ui/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
  183. opensignalbox/interface/web_ui/src/components/ui/tooltip/index.ts +4 -0
  184. opensignalbox/interface/web_ui/src/libs/utils.ts +6 -0
  185. opensignalbox/interface/web_ui/src/main.ts +141 -0
  186. opensignalbox/interface/web_ui/src/views/Overview.vue +11 -0
  187. opensignalbox/interface/web_ui/src/views/Settings.vue +6 -0
  188. opensignalbox/interface/web_ui/src/views/SleafordEast.vue +205 -0
  189. opensignalbox/interface/web_ui/src/views/adapters/modbus/ModbusAdapterEdit.vue +343 -0
  190. opensignalbox/interface/web_ui/src/views/adapters/modbus/ModbusAdapterView.vue +270 -0
  191. opensignalbox/interface/web_ui/src/views/interfaces/InterfaceCreate.vue +0 -0
  192. opensignalbox/interface/web_ui/src/views/interfaces/basicio/BasicIOInterfaceEdit.vue +795 -0
  193. opensignalbox/interface/web_ui/src/views/interfaces/basicio/BasicIOInterfaceView.vue +648 -0
  194. opensignalbox/interface/web_ui/src/views/interfaces/bell/BellInterfaceEdit.vue +790 -0
  195. opensignalbox/interface/web_ui/src/views/interfaces/bell/BellInterfaceView.vue +437 -0
  196. opensignalbox/interface/web_ui/src/vite-env.d.ts +1 -0
  197. opensignalbox/interface/web_ui/tailwind.config.js +94 -0
  198. opensignalbox/interface/web_ui/tsconfig.app.json +27 -0
  199. opensignalbox/interface/web_ui/tsconfig.json +30 -0
  200. opensignalbox/interface/web_ui/tsconfig.node.json +12 -0
  201. opensignalbox/interface/web_ui/tsconfig.tsbuildinfo +1 -0
  202. opensignalbox/interface/web_ui/vite.config.d.ts +2 -0
  203. opensignalbox/interface/web_ui/vite.config.js +60 -0
  204. opensignalbox/interface/web_ui/vite.config.ts +62 -0
  205. opensignalbox_interface-0.1.0.dist-info/METADATA +49 -0
  206. opensignalbox_interface-0.1.0.dist-info/RECORD +209 -0
  207. opensignalbox_interface-0.1.0.dist-info/WHEEL +4 -0
  208. opensignalbox_interface-0.1.0.dist-info/entry_points.txt +2 -0
  209. opensignalbox_interface-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,270 @@
1
+ <script setup lang="ts">
2
+ import { onMounted, computed } from 'vue'
3
+ import { useRoute, useRouter } from 'vue-router'
4
+ import { useQuery } from '@tanstack/vue-query'
5
+ import { ChevronLeft, Pencil, Trash2 } from 'lucide-vue-next'
6
+
7
+ import { Badge } from '@/components/ui/badge'
8
+ import { Button } from '@/components/ui/button'
9
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
10
+ import { Label } from '@/components/ui/label'
11
+ import axios from 'axios'
12
+
13
+ const route = useRoute()
14
+ const router = useRouter()
15
+
16
+ const adapterQuery = useQuery({
17
+ queryKey: ['adapter', route.params.name],
18
+ queryFn: async () => {
19
+ const url = location.origin + `/api/adapters/modbus/${route.params.name}`
20
+ const response = await fetch(url)
21
+
22
+ if (!response.ok) {
23
+ throw new Error(`HTTP error! status: ${response.status}`)
24
+ }
25
+
26
+ return response.json()
27
+ },
28
+ enabled: computed(() => Boolean(route.params.name)),
29
+ refetchInterval: 1000, // Refresh every 1 second
30
+ })
31
+
32
+ async function deleteAdapter() {
33
+ if (!adapterQuery.data?.value || !confirm('Are you sure you want to delete this adapter?')) {
34
+ return
35
+ }
36
+
37
+ try {
38
+ const response = await fetch(`${location.origin}/api/adapters/modbus/${route.params.name}`, {
39
+ method: 'DELETE'
40
+ })
41
+
42
+ if (!response.ok) {
43
+ throw new Error(`HTTP error! status: ${response.status}`)
44
+ }
45
+
46
+ router.push('/')
47
+ } catch (error) {
48
+ console.error('Failed to delete adapter:', error)
49
+ alert('Failed to delete adapter')
50
+ }
51
+ }
52
+
53
+ function editAdapter() {
54
+ router.push(`/adapters/edit/modbus/${route.params.name}`)
55
+ }
56
+
57
+ async function connectAdapter() {
58
+ try {
59
+ await axios.put(`${location.origin}/api/adapters/${route.params.name}/connect`)
60
+ } catch (error) {
61
+ console.error('Failed to connect adapter:', error)
62
+ alert('Failed to connect adapter')
63
+ }
64
+ }
65
+
66
+ async function disconnectAdapter() {
67
+ try {
68
+ await axios.put(`${location.origin}/api/adapters/${route.params.name}/disconnect`)
69
+ } catch (error) {
70
+ console.error('Failed to disconnect adapter:', error)
71
+ alert('Failed to disconnect adapter')
72
+ }
73
+ }
74
+
75
+ async function enableAdapter() {
76
+ try {
77
+ await axios.put(`${location.origin}/api/adapters/${route.params.name}/enable`)
78
+ } catch (error) {
79
+ console.error('Failed to enable adapter:', error)
80
+ alert('Failed to enable adapter')
81
+ }
82
+ }
83
+
84
+ async function disableAdapter() {
85
+ try {
86
+ await axios.put(`${location.origin}/api/adapters/${route.params.name}/disable`)
87
+ } catch (error) {
88
+ console.error('Failed to disable adapter:', error)
89
+ alert('Failed to disable adapter')
90
+ }
91
+ }
92
+
93
+ onMounted(() => {
94
+ if (!route.params.name) {
95
+ router.push('/')
96
+ }
97
+ })
98
+ </script>
99
+
100
+ <template>
101
+ <div class="w-full">
102
+ <p v-if="adapterQuery.isLoading.value">Loading..</p>
103
+ <div v-else-if="adapterQuery.data?.value" class="space-y-6">
104
+ <!-- Header -->
105
+ <div class="flex items-center gap-4">
106
+ <Button type="button" variant="outline" size="icon" class="h-7 w-7" @click.prevent="$router.back()">
107
+ <ChevronLeft class="h-4 w-4" />
108
+ <span class="sr-only">Back</span>
109
+ </Button>
110
+ <h1 class="flex-1 shrink-0 whitespace-nowrap text-xl font-semibold tracking-tight sm:grow-0">
111
+ {{ adapterQuery.data.value.userName || adapterQuery.data.value.systemName }}
112
+ </h1>
113
+ <div class="flex items-center gap-2 ml-auto">
114
+ <Button type="button" variant="outline" size="sm" @click="editAdapter">
115
+ <Pencil class="h-4 w-4 mr-2" />
116
+ Edit
117
+ </Button>
118
+ <Button type="button" variant="destructive" size="sm" @click="deleteAdapter">
119
+ <Trash2 class="h-4 w-4 mr-2" />
120
+ Delete
121
+ </Button>
122
+ </div>
123
+ </div>
124
+
125
+ <!-- Main content grid -->
126
+ <div class="grid auto-rows-max items-start gap-4 md:gap-8 lg:grid-cols-2">
127
+ <!-- Live Status Card -->
128
+ <Card class="col-span-2 md:col-span-1">
129
+ <CardHeader>
130
+ <CardTitle>Live Status</CardTitle>
131
+ <CardDescription>
132
+ Current interface status and controls. Click to toggle.
133
+ </CardDescription>
134
+ </CardHeader>
135
+ <CardContent>
136
+ <div class="flex flex-col lg:flex-row gap-6">
137
+ <!-- Status Indicators -->
138
+ <div class="flex flex-col gap-4 flex-1">
139
+ <div class="grid grid-cols-2 gap-4">
140
+ <!-- Connection Status -->
141
+ <div class="flex flex-col items-center p-4 border rounded-lg">
142
+ <h4 class="font-medium text-sm text-muted-foreground mb-2">Connection</h4>
143
+ <Badge variant="outline" :class="{
144
+ 'bg-green-100 text-green-800 border-green-300': adapterQuery.data.value.isConnected,
145
+ 'bg-red-100 text-red-800 border-red-300': !adapterQuery.data.value.isConnected
146
+ }">
147
+ {{ adapterQuery.data.value.isConnected ? 'Connected' : 'Disconnected' }}
148
+ </Badge>
149
+ <Button
150
+ type="button"
151
+ variant="default"
152
+ :disabled="!adapterQuery.data.value.enabled"
153
+ size="sm"
154
+ class="w-full mt-2"
155
+ v-if="!adapterQuery.data.value.isConnected"
156
+ @click="connectAdapter"
157
+ >
158
+ {{ adapterQuery.data.value.enabled ? 'Connect' : 'Enable to Connect' }}
159
+ </Button>
160
+ <Button
161
+ type="button"
162
+ variant="outline"
163
+ size="sm"
164
+ class="w-full mt-2"
165
+ v-if="adapterQuery.data.value.isConnected"
166
+ @click="disconnectAdapter"
167
+ >
168
+ Disconnect
169
+ </Button>
170
+ </div>
171
+
172
+ <!-- Enabled Status -->
173
+ <div class="flex flex-col items-center p-4 border rounded-lg">
174
+ <h4 class="font-medium text-sm text-muted-foreground mb-2">State</h4>
175
+ <Badge variant="outline" :class="{
176
+ 'bg-green-100 text-green-800 border-green-300': adapterQuery.data.value.enabled,
177
+ 'bg-red-100 text-red-800 border-red-300': !adapterQuery.data.value.enabled
178
+ }">
179
+ {{ adapterQuery.data.value.enabled ? 'Enabled' : 'Disabled' }}
180
+ </Badge>
181
+ <Button
182
+ type="button"
183
+ variant="default"
184
+ size="sm"
185
+ class="w-full mt-2"
186
+ v-if="!adapterQuery.data.value.enabled"
187
+ @click="enableAdapter"
188
+ >
189
+ Enable
190
+ </Button>
191
+ <Button
192
+ type="button"
193
+ variant="destructive"
194
+ size="sm"
195
+ class="w-full mt-2"
196
+ v-if="adapterQuery.data.value.enabled"
197
+ @click="disableAdapter"
198
+ >
199
+ Disable
200
+ </Button>
201
+ </div>
202
+
203
+ </div>
204
+
205
+ <!-- Error Message Display -->
206
+ <div v-if="adapterQuery.data.value.error" class="p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
207
+ <h5 class="font-medium text-yellow-800 mb-1">Error Details:</h5>
208
+ <p class="text-sm text-yellow-700">{{ adapterQuery.data.value.error }}</p>
209
+ </div>
210
+ <div v-else class="p-3 bg-green-50 border border-green-200 rounded-lg">
211
+ <h5 class="font-medium text-green-800 mb-1">No Errors</h5>
212
+ <p class="text-sm text-green-700">The interface is functioning normally.</p>
213
+ </div>
214
+ </div>
215
+
216
+ </div>
217
+ </CardContent>
218
+ </Card>
219
+ <!-- General Details -->
220
+ <Card>
221
+ <CardHeader>
222
+ <CardTitle>General Details</CardTitle>
223
+ <CardDescription>
224
+ Basic adapter information
225
+ </CardDescription>
226
+ </CardHeader>
227
+ <CardContent>
228
+ <div class="grid gap-4">
229
+ <div class="grid gap-2">
230
+ <Label>System Name</Label>
231
+ <div class="text-sm">{{ adapterQuery.data.value.systemName }}</div>
232
+ </div>
233
+ <div class="grid gap-2">
234
+ <Label>User Name</Label>
235
+ <div class="text-sm">{{ adapterQuery.data.value.userName || 'Not set' }}</div>
236
+ </div>
237
+ <div class="grid gap-2">
238
+ <Label>Description</Label>
239
+ <div class="text-sm">{{ adapterQuery.data.value.description || 'No description' }}</div>
240
+ </div>
241
+ <div class="grid gap-2">
242
+ <Label>Enabled?</Label>
243
+ <div class="text-sm">{{ adapterQuery.data.value.enabled ? 'Yes' : 'No' }}</div>
244
+ </div>
245
+ <div class="grid gap-2">
246
+ <Label>Connection Type</Label>
247
+ <div class="text-sm">{{ adapterQuery.data.value.isNetwork ? 'Network (TCP)' : 'Serial (RTU)' }}</div>
248
+ </div>
249
+ <div class="grid gap-2">
250
+ <Label>{{ adapterQuery.data.value.isNetwork ? 'IP Address' : 'Serial Port' }}</Label>
251
+ <div class="text-sm">{{ adapterQuery.data.value.isNetwork ? adapterQuery.data.value.address : adapterQuery.data.value.serialPort }}</div>
252
+ </div>
253
+ <div v-if="adapterQuery.data.value.isNetwork" class="grid gap-2">
254
+ <Label>TCP Port</Label>
255
+ <div class="text-sm">{{ adapterQuery.data.value.networkPort }}</div>
256
+ </div>
257
+ <div class="grid gap-2">
258
+ <Label>Baud Rate</Label>
259
+ <div class="text-sm">{{ adapterQuery.data.value.baud }}</div>
260
+ </div>
261
+ </div>
262
+ </CardContent>
263
+ </Card>
264
+ </div>
265
+ </div>
266
+ <div v-else-if="adapterQuery.isError.value" class="text-center text-destructive">
267
+ Failed to load adapter: {{ adapterQuery.error?.value?.message }}
268
+ </div>
269
+ </div>
270
+ </template>