first
This commit is contained in:
55
DCIManager6/dci6-support-reader/createViews.go
Normal file
55
DCIManager6/dci6-support-reader/createViews.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func (a *App) buildUI() {
|
||||
a.statusLabel = widget.NewLabel("Готов к работе")
|
||||
a.statusLabel.TextStyle = fyne.TextStyle{Bold: true}
|
||||
|
||||
a.fileInfo = widget.NewLabel("Файл не выбран")
|
||||
a.version = widget.NewLabel("2603-01.8")
|
||||
a.progressBar = widget.NewProgressBar()
|
||||
a.progressBar.Hide()
|
||||
|
||||
a.serverTab = container.NewAppTabs()
|
||||
a.platformTab = container.NewAppTabs()
|
||||
|
||||
// a.contentArea = container.NewHBox()
|
||||
|
||||
uploadBtnServer := widget.NewButton("🖥 server", a.onUploadServer)
|
||||
// uploadBtnServer.Importance = widget.HighImportance
|
||||
uploadBtnPlatform := widget.NewButton("🖧 platform", a.onUploadPlatform)
|
||||
|
||||
// Панель инструментов
|
||||
toolbar := container.NewHBox(
|
||||
uploadBtnServer,
|
||||
uploadBtnPlatform,
|
||||
widget.NewSeparator(),
|
||||
a.progressBar,
|
||||
)
|
||||
|
||||
// Основной контент
|
||||
mainContent := container.NewBorder(
|
||||
container.NewHBox(
|
||||
toolbar,
|
||||
widget.NewSeparator(),
|
||||
a.statusLabel,
|
||||
),
|
||||
container.NewHBox(
|
||||
widget.NewSeparator(),
|
||||
a.fileInfo,
|
||||
a.version,
|
||||
),
|
||||
nil, nil,
|
||||
container.NewAppTabs(
|
||||
container.NewTabItem("Server", a.serverTab),
|
||||
container.NewTabItem("Platform", a.platformTab),
|
||||
),
|
||||
)
|
||||
|
||||
a.window.SetContent(mainContent)
|
||||
}
|
||||
BIN
DCIManager6/dci6-support-reader/dci6-support-reader
Executable file
BIN
DCIManager6/dci6-support-reader/dci6-support-reader
Executable file
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/dci6-support-reader.png
Normal file
BIN
DCIManager6/dci6-support-reader/dci6-support-reader.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 590 B |
BIN
DCIManager6/dci6-support-reader/fyne-cross/bin/linux-amd64/dci6-support-reader
Executable file
BIN
DCIManager6/dci6-support-reader/fyne-cross/bin/linux-amd64/dci6-support-reader
Executable file
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/fyne-cross/bin/windows-386/ts_dci6_reader.exe
Executable file
BIN
DCIManager6/dci6-support-reader/fyne-cross/bin/windows-386/ts_dci6_reader.exe
Executable file
Binary file not shown.
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/fyne-cross/bin/windows-arm64/ts_dci6_reader.exe
Executable file
BIN
DCIManager6/dci6-support-reader/fyne-cross/bin/windows-arm64/ts_dci6_reader.exe
Executable file
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/linux-amd64/dci6-support-reader.tar.xz
vendored
Normal file
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/linux-amd64/dci6-support-reader.tar.xz
vendored
Normal file
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/windows-386/ts_dci6_reader.exe.zip
vendored
Normal file
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/windows-386/ts_dci6_reader.exe.zip
vendored
Normal file
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/windows-amd64/dci6-support-reader.zip
vendored
Normal file
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/windows-amd64/dci6-support-reader.zip
vendored
Normal file
Binary file not shown.
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/windows-arm64/ts_dci6_reader.exe.zip
vendored
Normal file
BIN
DCIManager6/dci6-support-reader/fyne-cross/dist/windows-arm64/ts_dci6_reader.exe.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 590 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 590 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
39
DCIManager6/dci6-support-reader/go.mod
Normal file
39
DCIManager6/dci6-support-reader/go.mod
Normal file
@@ -0,0 +1,39 @@
|
||||
module dci6-support-reader
|
||||
|
||||
go 1.24.4
|
||||
|
||||
require (
|
||||
fyne.io/fyne v1.4.3 // indirect
|
||||
fyne.io/fyne/v2 v2.7.1 // indirect
|
||||
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fredbi/uri v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fyne-io/gl-js v0.2.0 // indirect
|
||||
github.com/fyne-io/glfw-js v0.3.0 // indirect
|
||||
github.com/fyne-io/image v0.1.1 // indirect
|
||||
github.com/fyne-io/oksvg v0.2.0 // indirect
|
||||
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
|
||||
github.com/go-text/render v0.2.0 // indirect
|
||||
github.com/go-text/typesetting v0.2.1 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/hack-pad/go-indexeddb v0.3.2 // indirect
|
||||
github.com/hack-pad/safejs v0.1.0 // indirect
|
||||
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rymdport/portal v0.4.2 // indirect
|
||||
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
|
||||
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
github.com/yuin/goldmark v1.7.8 // indirect
|
||||
golang.org/x/image v0.24.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
119
DCIManager6/dci6-support-reader/go.sum
Normal file
119
DCIManager6/dci6-support-reader/go.sum
Normal file
@@ -0,0 +1,119 @@
|
||||
fyne.io/fyne v1.4.3 h1:356CnXCiYrrfaLGsB7qLK3c6ktzyh8WR05v/2RBu51I=
|
||||
fyne.io/fyne v1.4.3/go.mod h1:8kiPBNSDmuplxs9WnKCkaWYqbcXFy0DeAzwa6PBO9Z8=
|
||||
fyne.io/fyne/v2 v2.7.1 h1:ja7rNHWWEooha4XBIZNnPP8tVFwmTfwMJdpZmLxm2Zc=
|
||||
fyne.io/fyne/v2 v2.7.1/go.mod h1:xClVlrhxl7D+LT+BWYmcrW4Nf+dJTvkhnPgji7spAwE=
|
||||
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 h1:eA5/u2XRd8OUkoMqEv3IBlFYSruNlXD8bRHDiqm0VNI=
|
||||
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
|
||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko=
|
||||
github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs=
|
||||
github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI=
|
||||
github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk=
|
||||
github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk=
|
||||
github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
|
||||
github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
|
||||
github.com/fyne-io/mobile v0.1.2/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY=
|
||||
github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8=
|
||||
github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI=
|
||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA=
|
||||
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
|
||||
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
|
||||
github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
|
||||
github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
|
||||
github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
||||
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
||||
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
||||
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
||||
github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
|
||||
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
|
||||
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
||||
github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU=
|
||||
github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
|
||||
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
|
||||
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
|
||||
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
|
||||
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
|
||||
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
55
DCIManager6/dci6-support-reader/main.go
Normal file
55
DCIManager6/dci6-support-reader/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
app fyne.App
|
||||
window fyne.Window
|
||||
serverContent []byte
|
||||
platformContent []byte
|
||||
fileName string
|
||||
filePath string
|
||||
fileSize int64
|
||||
|
||||
// Виджеты, которые часто обновляем
|
||||
statusLabel *widget.Label
|
||||
fileInfo *widget.Label
|
||||
version *widget.Label
|
||||
progressBar *widget.ProgressBar
|
||||
contentArea *fyne.Container
|
||||
serverTab *container.AppTabs
|
||||
platformTab *container.AppTabs
|
||||
}
|
||||
|
||||
var iconData = []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x04, 0x03, 0x00, 0x00, 0x00, 0x81, 0x54, 0x67, 0xc7, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0x93, 0xd6, 0xff, 0x90, 0xd5, 0xff, 0x91, 0xd5, 0xff, 0x92, 0xd6, 0xff, 0xae, 0xe0, 0xff, 0xf2, 0xfa, 0xff, 0xfb, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xef, 0xff, 0xd9, 0xf0, 0xff, 0xd1, 0xed, 0xff, 0xfc, 0xfe, 0xff, 0xa0, 0xdb, 0xff, 0xa7, 0xde, 0xff, 0xc0, 0xe7, 0xff, 0x52, 0x19, 0x63, 0x47, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x88, 0x05, 0x1d, 0x48, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x37, 0x5c, 0x00, 0x00, 0x37, 0x5c, 0x01, 0xcb, 0xc7, 0xa4, 0xb9, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xea, 0x02, 0x0e, 0x09, 0x10, 0x08, 0xaa, 0xdc, 0x17, 0xfb, 0x00, 0x00, 0x00, 0xe2, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x6d, 0x92, 0xbd, 0x0d, 0xc2, 0x30, 0x10, 0x85, 0x1f, 0x47, 0x45, 0x87, 0xa3, 0x0c, 0xe0, 0x38, 0x80, 0x04, 0x08, 0x84, 0xb2, 0x41, 0x50, 0x26, 0x40, 0x62, 0x01, 0x0a, 0x60, 0x02, 0x68, 0xa8, 0x11, 0x25, 0x62, 0x04, 0x46, 0x60, 0x09, 0x7a, 0x7a, 0x1a, 0x16, 0x81, 0x3b, 0xe3, 0x38, 0xc8, 0xe6, 0x2b, 0x2c, 0xbf, 0x17, 0xfb, 0x7c, 0x3f, 0x41, 0x4b, 0x31, 0xb9, 0xd2, 0xa4, 0x0a, 0xd9, 0x75, 0x21, 0xab, 0x21, 0x31, 0xb4, 0x91, 0xbd, 0x35, 0x34, 0x34, 0x40, 0x20, 0x67, 0xa4, 0x6a, 0x06, 0x4b, 0x5b, 0x95, 0xd6, 0xd0, 0x06, 0x30, 0x0c, 0xaf, 0x24, 0x46, 0xca, 0xdf, 0x72, 0x39, 0x5c, 0xf0, 0xa6, 0xb4, 0x27, 0x60, 0xa3, 0x71, 0x6c, 0xd0, 0xf7, 0x0a, 0x55, 0x0e, 0x2d, 0x46, 0x92, 0xa3, 0xbf, 0x74, 0x2c, 0x50, 0x64, 0x48, 0x80, 0xcd, 0xde, 0xb1, 0x03, 0x32, 0xce, 0x80, 0x4e, 0x1e, 0x16, 0x28, 0xd0, 0x69, 0x8c, 0x33, 0x72, 0x28, 0x3d, 0x6a, 0x8c, 0x2b, 0xf1, 0x2b, 0xf8, 0x35, 0x58, 0x1a, 0x8c, 0xef, 0x75, 0xd0, 0xc3, 0x8d, 0x25, 0x30, 0x59, 0x7a, 0x1e, 0xb6, 0xa6, 0x5e, 0xe5, 0x99, 0xb3, 0x34, 0x98, 0xbe, 0x3d, 0x2f, 0x96, 0x0a, 0xc3, 0x26, 0xe8, 0x85, 0x65, 0xf4, 0x6c, 0x94, 0x58, 0x94, 0x3a, 0x17, 0xb7, 0xad, 0xf5, 0x51, 0x8a, 0xe3, 0xf2, 0x07, 0x6b, 0xc7, 0x4a, 0xca, 0x97, 0x06, 0x3d, 0x1d, 0xda, 0x75, 0x2c, 0x68, 0xe1, 0x9f, 0x26, 0x07, 0x63, 0x88, 0x07, 0x15, 0x8d, 0x32, 0x18, 0x76, 0xf8, 0x3b, 0x7c, 0x00, 0x1a, 0xb4, 0x74, 0x9d, 0x66, 0xa4, 0x3d, 0x9a, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x32, 0x36, 0x2d, 0x30, 0x32, 0x2d, 0x31, 0x34, 0x54, 0x30, 0x38, 0x3a, 0x33, 0x32, 0x3a, 0x33, 0x35, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x42, 0xed, 0xf0, 0x52, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x32, 0x36, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x34, 0x54, 0x31, 0x34, 0x3a, 0x33, 0x39, 0x3a, 0x31, 0x35, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x2d, 0x96, 0x6a, 0x40, 0x00, 0x00, 0x00, 0x28, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x00, 0x32, 0x30, 0x32, 0x36, 0x2d, 0x30, 0x32, 0x2d, 0x31, 0x34, 0x54, 0x30, 0x39, 0x3a, 0x31, 0x36, 0x3a, 0x30, 0x38, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x07, 0xec, 0xcf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}
|
||||
|
||||
func NewApp() *App {
|
||||
a := &App{
|
||||
app: app.NewWithID("com.ispsystem.dci6-support-reader"),
|
||||
}
|
||||
a.window = a.app.NewWindow("ISPSystem Техподдержка DCImanager6")
|
||||
// icon, err := fyne.LoadResourceFromPath("./dci6-support-reader.jpg")
|
||||
// if err != nil {
|
||||
// log.Printf("Загрузка иконки: %s", err)
|
||||
// }
|
||||
|
||||
icon := fyne.NewStaticResource("dci6-support-reader.png", iconData)
|
||||
a.window.SetIcon(icon)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *App) Run() {
|
||||
a.buildUI()
|
||||
a.window.Resize(fyne.NewSize(1200, 600))
|
||||
a.window.ShowAndRun()
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := NewApp()
|
||||
app.Run()
|
||||
}
|
||||
235
DCIManager6/dci6-support-reader/misc.go
Normal file
235
DCIManager6/dci6-support-reader/misc.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// Вспомогательные методы
|
||||
func (a *App) showError(title, message string) {
|
||||
dialog.ShowError(fmt.Errorf(message), a.window)
|
||||
a.statusLabel.SetText("❌ " + title)
|
||||
}
|
||||
|
||||
func (a *App) showSuccess(title, message string) {
|
||||
dialog.ShowInformation(title, message, a.window)
|
||||
}
|
||||
|
||||
func (a *App) detectMimeType() string {
|
||||
ext := strings.ToLower(filepath.Ext(a.fileName))
|
||||
|
||||
mimeTypes := map[string]string{
|
||||
".txt": "text/plain",
|
||||
".pdf": "application/pdf",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".png": "image/png",
|
||||
".zip": "application/zip",
|
||||
".doc": "application/msword",
|
||||
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
}
|
||||
|
||||
if mime, ok := mimeTypes[ext]; ok {
|
||||
return mime
|
||||
}
|
||||
return "application/octet-stream"
|
||||
}
|
||||
|
||||
// // Это делал DeepSeek оно криво, но работает. Оставлю это так, потому что всё равно планирую не использовать больше fyne
|
||||
type JournalEntryWidget struct {
|
||||
widget.BaseWidget
|
||||
event journalctlEntry
|
||||
label *widget.Label
|
||||
}
|
||||
|
||||
func NewJournalEntryWidget(event journalctlEntry) *JournalEntryWidget {
|
||||
j := &JournalEntryWidget{
|
||||
event: event,
|
||||
}
|
||||
j.ExtendBaseWidget(j)
|
||||
return j
|
||||
}
|
||||
|
||||
func (j *JournalEntryWidget) CreateRenderer() fyne.WidgetRenderer {
|
||||
j.label = widget.NewLabel(j.formatEventText())
|
||||
j.label.Wrapping = fyne.TextWrapBreak
|
||||
j.label.Selectable = true
|
||||
|
||||
return widget.NewSimpleRenderer(j.label)
|
||||
}
|
||||
|
||||
func (j *JournalEntryWidget) formatEventText() string {
|
||||
return fmt.Sprintf("%s :: %s :: %s :: %s :: %s",
|
||||
j.event.Timestamp, j.event.CommandLine, j.event.CommandName,
|
||||
j.event.SyslogIdentifier, j.event.Message)
|
||||
}
|
||||
|
||||
func (j *JournalEntryWidget) UpdateEvent(event journalctlEntry) {
|
||||
j.event = event
|
||||
if j.label != nil {
|
||||
j.label.SetText(j.formatEventText())
|
||||
}
|
||||
j.Refresh()
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// func (a *App) isTextFile() bool {
|
||||
// ext := strings.ToLower(filepath.Ext(a.fileName))
|
||||
// textExts := []string{".txt", ".csv", ".json", ".xml", ".yaml", ".yml", ".md", ".go", ".py", ".js"}
|
||||
|
||||
// for _, textExt := range textExts {
|
||||
// if ext == textExt {
|
||||
// return true
|
||||
// }
|
||||
// }ц=
|
||||
|
||||
// // Проверяем содержимое (простейшая проверка)
|
||||
// if len(a.fileContent) == 0 {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// // Если файл содержит null-байты, это скорее бинарный файл
|
||||
// for _, b := range a.fileContent {
|
||||
// if b == 0 {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
|
||||
// return true
|
||||
// }
|
||||
|
||||
// type TextStats struct {
|
||||
// lines int
|
||||
// words int
|
||||
// chars int
|
||||
// bytes int
|
||||
// }
|
||||
|
||||
// func (a *App) calculateTextStats() TextStats {
|
||||
// if len(a.fileContent) == 0 {
|
||||
// return TextStats{}
|
||||
// }
|
||||
|
||||
// content := string(a.fileContent)
|
||||
// stats := TextStats{
|
||||
// bytes: len(a.fileContent),
|
||||
// chars: len(content),
|
||||
// lines: strings.Count(content, "\n") + 1,
|
||||
// words: len(strings.Fields(content)),
|
||||
// }
|
||||
|
||||
// return stats
|
||||
// }
|
||||
|
||||
// Это делал DeepSeek оно криво, но работает. Оставлю это так, потому что всё равно планирую не использовать больше fyne
|
||||
// Кастомный виджет для элемента списка с динамической высотой
|
||||
type JournalListItem struct {
|
||||
widget.BaseWidget
|
||||
event journalctlEntry
|
||||
label *widget.Label
|
||||
}
|
||||
|
||||
func NewJournalListItem(event journalctlEntry) *JournalListItem {
|
||||
j := &JournalListItem{
|
||||
event: event,
|
||||
}
|
||||
j.ExtendBaseWidget(j)
|
||||
return j
|
||||
}
|
||||
|
||||
func (j *JournalListItem) CreateRenderer() fyne.WidgetRenderer {
|
||||
j.label = widget.NewLabel(j.formatText())
|
||||
j.label.Wrapping = fyne.TextWrapBreak
|
||||
j.label.Selectable = true
|
||||
|
||||
return &journalListItemRenderer{
|
||||
item: j,
|
||||
label: j.label,
|
||||
}
|
||||
}
|
||||
|
||||
func (j *JournalListItem) formatText() string {
|
||||
return fmt.Sprintf("%s :: %s :: %s :: %s :: %s",
|
||||
j.event.Timestamp, j.event.CommandLine, j.event.CommandName,
|
||||
j.event.SyslogIdentifier, j.event.Message)
|
||||
}
|
||||
|
||||
func (j *JournalListItem) Update(event journalctlEntry) {
|
||||
j.event = event
|
||||
if j.label != nil {
|
||||
j.label.SetText(j.formatText())
|
||||
}
|
||||
j.Refresh()
|
||||
}
|
||||
|
||||
type journalListItemRenderer struct {
|
||||
item *JournalListItem
|
||||
label *widget.Label
|
||||
}
|
||||
|
||||
func (r *journalListItemRenderer) Layout(size fyne.Size) {
|
||||
// Рассчитываем высоту label на основе его содержимого
|
||||
minSize := r.label.MinSize()
|
||||
labelHeight := minSize.Height
|
||||
|
||||
// Если высота label больше 50, используем её, иначе минимальную
|
||||
height := labelHeight
|
||||
if height < 50 {
|
||||
height = 50
|
||||
}
|
||||
|
||||
r.label.Resize(fyne.NewSize(size.Width, height))
|
||||
r.label.Move(fyne.NewPos(0, 0))
|
||||
}
|
||||
|
||||
func (r *journalListItemRenderer) MinSize() fyne.Size {
|
||||
minSize := r.label.MinSize()
|
||||
if minSize.Height < 50 {
|
||||
minSize.Height = 50
|
||||
}
|
||||
return minSize
|
||||
}
|
||||
|
||||
func (r *journalListItemRenderer) Refresh() {
|
||||
r.label.Refresh()
|
||||
}
|
||||
|
||||
func (r *journalListItemRenderer) Objects() []fyne.CanvasObject {
|
||||
return []fyne.CanvasObject{r.label}
|
||||
}
|
||||
|
||||
func (r *journalListItemRenderer) Destroy() {}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// Вспомогательные функции
|
||||
func formatFileSize(bytes int64) string {
|
||||
const unit = 1024
|
||||
if bytes < unit {
|
||||
return fmt.Sprintf("%d Б", bytes)
|
||||
}
|
||||
div, exp := int64(unit), 0
|
||||
for n := bytes / unit; n >= unit; n /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
return fmt.Sprintf("%.1f %cБ", float64(bytes)/float64(div), "КМГТП"[exp])
|
||||
}
|
||||
74
DCIManager6/dci6-support-reader/networkTab.go
Normal file
74
DCIManager6/dci6-support-reader/networkTab.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func createNetworkTab(server outputStruct) *container.AppTabs {
|
||||
etcHostsList := widget.NewList(
|
||||
func() int {
|
||||
return len(server.NetworkConfig.EtcHosts)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("etc hosts"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
hbox := obj.(*fyne.Container)
|
||||
line := server.NetworkConfig.EtcHosts[id]
|
||||
lineLabel := hbox.Objects[0].(*widget.Label)
|
||||
lineLabel.SetText(line)
|
||||
},
|
||||
)
|
||||
|
||||
netInterfacesList := widget.NewList(
|
||||
//TODO тут всё может упасть. В NetInterfaces лежит структура, в которой есть список ip адресов
|
||||
// обычно их не очень много, но в крайних случаях их может быть 100500 на сетевом интерфейсе
|
||||
// и гуй этому не обрадуется. Пока фигачим всё одной строкой
|
||||
func() int {
|
||||
return len(server.NetworkConfig.NetInterfaces)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("интерфейс"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
hbox := obj.(*fyne.Container)
|
||||
iface := server.NetworkConfig.NetInterfaces[id]
|
||||
ifaceLabel := hbox.Objects[0].(*widget.Label)
|
||||
|
||||
ifaceLabel.SetText(fmt.Sprintf("%s, флаги: %s, мак: %s, ip: %s, index: %s, MTU: %s", iface.Device, iface.Flags, iface.HwAddr, iface.IpAddr, iface.Index, iface.MTU))
|
||||
},
|
||||
)
|
||||
|
||||
networkManagerConnList := widget.NewList(
|
||||
func() int {
|
||||
return len(server.NetworkConfig.NetworkManagerConn)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("соединение"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
hbox := obj.(*fyne.Container)
|
||||
conn := server.NetworkConfig.NetworkManagerConn[id]
|
||||
connLabel := hbox.Objects[0].(*widget.Label)
|
||||
connLabel.SetText(conn)
|
||||
},
|
||||
)
|
||||
networkAppTabs := container.NewAppTabs()
|
||||
networkAppTabs.Append(container.NewTabItem("etc/hosts", container.NewScroll(etcHostsList)))
|
||||
networkAppTabs.Append(container.NewTabItem("Список сетевых интерфейсов", container.NewScroll(netInterfacesList)))
|
||||
networkAppTabs.Append(container.NewTabItem("nmcli c s", container.NewScroll(networkManagerConnList)))
|
||||
networkAppTabs.Append(container.NewTabItem("NetworkManager", widget.NewLabel(fmt.Sprintf("Включен: %s", server.NetworkConfig.NetworkManager))))
|
||||
networkAppTabs.Append(container.NewTabItem("Networking", widget.NewLabel(fmt.Sprintf("Включен: %s", server.NetworkConfig.Networking))))
|
||||
|
||||
return networkAppTabs
|
||||
}
|
||||
9
DCIManager6/dci6-support-reader/notes.md
Normal file
9
DCIManager6/dci6-support-reader/notes.md
Normal file
@@ -0,0 +1,9 @@
|
||||
### Упаковка с помощью fyne-cross
|
||||
используется docker, так что он должен быть установлен и настроен.
|
||||
|
||||
fyne-cross windows -icon ./dci6-support-reader.png -name dci6-support-reader -app-id com.ispsystem.dci6-suppor-reader
|
||||
|
||||
fyne-cross linux -icon ./dci6-support-reader.png -name dci6-support-reader -app-id com.ispsystem.dci6-suppor-reader
|
||||
|
||||
прочитать содержимое png в байтах, что бы засунуть сразу в переменную для иконки
|
||||
xxd -i ./dci6-support-reader.png | head -n -1 | tail -n +2 | sed 's/ /, /g' | tr -d '\n' | sed 's/^/var iconData = []byte{/;s/$/}/'
|
||||
43
DCIManager6/dci6-support-reader/outputStruct.go
Normal file
43
DCIManager6/dci6-support-reader/outputStruct.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
type outputStruct struct {
|
||||
BiosInfo biosInfo `json:"bios_info"`
|
||||
OperatingSystem operatingSystem `json:"operating_system"`
|
||||
InstalledPackages []installedPackage `json:"installed_packages"`
|
||||
FsInformations []fsInfo `json:"fs_informations"`
|
||||
LoadAverage loadAverage `json:"load_average"`
|
||||
Cpus []cpu `json:"cpu"`
|
||||
Ram ram `json:"ram"`
|
||||
Uptime uptime `json:"uptime"`
|
||||
TimeService timeService `json:"time_service"`
|
||||
Firewalls firewalls `json:"firewalls"`
|
||||
NetworkConfig networkConfig `json:"network_config"`
|
||||
InternetRequired []internetResource `json:"internet_required"`
|
||||
SecSetALSE secSetALSE `json:"security_settings_alse"`
|
||||
SecSetUbuntu secSetUbuntu `json:"security_settings_ubuntu"`
|
||||
SecSetAlma secSetAlma `json:"security_settings_alma"`
|
||||
DockerPsA []dockerPs `json:"docker_ps_a"`
|
||||
DockerStats []dockerStats `json:"docker_stats"`
|
||||
DockerSupervisor []dockerSupervisor `json:"docker_supervisor"`
|
||||
JournalctlEntries []journalctlEntry `json:"journalctl_entries"`
|
||||
NftRuleset nftRuleset `json:"nft_rulest"`
|
||||
RootHistory []rootHistoryCommand `json:"root_history_command"`
|
||||
}
|
||||
|
||||
type platformStruct struct {
|
||||
// IspSettings []ispSetting `json:"isp_settings"`
|
||||
DciLocations []dciLocation `json:"dci_locations"` //+
|
||||
DciLocationDockerComposes []dciLocationDockerCompose `json:"dci_location_dockercomposes"` //+
|
||||
TaskManagerTask []taskManagerTask `json:"task_manager_task"` //+
|
||||
HwByLocations []hwByLocation `json:"hw_by_locations"` //+
|
||||
InstalledPlugin []installedPlugin `json:"installed_plugin"` //+
|
||||
Users users `json:"users"` //+
|
||||
Ldaps []ldap `json:"ldaps"` //+
|
||||
Repos []repo `json:"repos"` //+
|
||||
OsTemplates []osTemplate `json:"os_template"` //+
|
||||
RealIP realIP `json:"real_ip"` //+
|
||||
BackupTasks []backupTask `json:"backup_tasks"` //+
|
||||
CopiedFiles copiedFiles `json:"copied_files"` //+
|
||||
License license `json:"license"`
|
||||
// ShowProcesslist []processlist `json:"show_processlist"`
|
||||
}
|
||||
133
DCIManager6/dci6-support-reader/platformStruct.go
Normal file
133
DCIManager6/dci6-support-reader/platformStruct.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package main
|
||||
|
||||
// type ispSetting struct {
|
||||
// // select name, value from isp_settings;
|
||||
// Name string `json:"name"`
|
||||
// Value string `json:"value"`
|
||||
// }
|
||||
|
||||
type dciLocation struct {
|
||||
// select id,status,status_info,name,ssh_address,ssh_port,ssh_user,setup_info,params_dhcp,params_redis,params_nginx,params_netflow,settings,is_main,proxy_params,userspace,patch from dci_1.dci_location;
|
||||
Id int `json:"id"`
|
||||
Status string `json:"status"`
|
||||
StatusInfo string `json:"status_info"`
|
||||
Name string `json:"name"`
|
||||
SshAddress string `json:"ssh_address"`
|
||||
SshPort int `json:"ssh_port"`
|
||||
SshUser string `json:"ssh_user"`
|
||||
SetupInfo string `json:"setup_info"`
|
||||
ParamsDhcp string `json:"params_dhcp"`
|
||||
ParamsRedis string `json:"params_redis"`
|
||||
ParamsNginx string `json:"params_nginx"`
|
||||
ParamsNetflow string `json:"params_netflow"`
|
||||
Settings string `json:"settings"`
|
||||
IsMain int `json:"is_main"`
|
||||
ProxyParams string `json:"proxy_params"`
|
||||
Userspace int `json:"userspace"`
|
||||
Patch string `json:"patch"`
|
||||
}
|
||||
|
||||
type dciLocationDockerCompose struct {
|
||||
// select id,name,docker_compose from dci_1.dci_location;
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DockerCompose string `json:"docker_compose"`
|
||||
}
|
||||
|
||||
type taskManagerTask struct {
|
||||
// select id,name,status,registration_time from auth.taskmgr_task where status != 'complete' and registration_time >= NOW() - INTERVAL 1 MONTH;
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
RegistrationTime string `json:"registration_time"`
|
||||
RequestInfo string `json:"request_info"`
|
||||
Output string `json:"output"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type hwByLocation struct {
|
||||
// SELECT
|
||||
// (SELECT COUNT(id) from dci_server WHERE location = 2) as server,
|
||||
// (SELECT COUNT(id) from dci_switch WHERE location = 2) as switch,
|
||||
// (SELECT count(id) from dci_pdu WHERE location = 2) as pdu,
|
||||
// (SELECT COUNT(id) from dci_ups WHERE location = 2) as ups,
|
||||
// (SELECT COUNT(id) from dci_server WHERE location = 2) +
|
||||
// (SELECT COUNT(id) from dci_switch WHERE location = 2) +
|
||||
// (SELECT count(id) from dci_pdu WHERE location = 2) +
|
||||
// (SELECT COUNT(id) from dci_ups WHERE location = 2) as total_location_2;
|
||||
Location int `json:"location"`
|
||||
Server int `json:"server"`
|
||||
Switch int `json:"switch"`
|
||||
Pdu int `json:"pdu"`
|
||||
Ups int `json:"ups"`
|
||||
}
|
||||
|
||||
type installedPlugin struct {
|
||||
// select name,status,version,current_version from ps_plugin;
|
||||
Name string `json:"name"`
|
||||
Status string `json:"string"`
|
||||
Version string `json:"version"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
}
|
||||
|
||||
type users struct {
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type ldap struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LastSync string `json:"last_sync"`
|
||||
}
|
||||
|
||||
type repo struct {
|
||||
// SELECT id,name,url FROM dci_repo
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
type osTemplate struct {
|
||||
// SELECT id,name,filename,macro,metainfo,directory_name,repository,size from dci_os_template where repo != 1 /* репозиторий ispsystem*/
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Filename string `json:"filename"`
|
||||
Macro string `json:"macro"`
|
||||
Metainfo string `json:"metainfo"`
|
||||
DirectoryName string `json:"directory_name"`
|
||||
Repository int `json:"repository"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
// type processlist struct {
|
||||
// // SELECT * FROM information_schema.processlist WHERE COMMAND != 'Sleep' AND TIME > 0 ORDER BY TIME DESC;
|
||||
// Id int `json:"id"`
|
||||
// User string `json:"user"`
|
||||
// Host string `json:"host"`
|
||||
// Db string `json:"db"`
|
||||
// Command string `json:"command"`
|
||||
// Time int `json:"time"`
|
||||
// State string `json:"state"`
|
||||
// Info string `json:"info"`
|
||||
// }
|
||||
|
||||
type realIP struct {
|
||||
// SELECT name, value FROM auth.isp_settings WHERE name = "trusted_servers"
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type backupTask struct {
|
||||
// SELECT id,enabled,cron_expression,limit_count,limit_size_mib FROM backup_task
|
||||
Id int `json:"id"`
|
||||
Enabled int `json:"enabled"`
|
||||
CronExpression string `json:"cron_expression"`
|
||||
LimitCount int `json:"limit_count"`
|
||||
LimitSizeMib int `json:"limit_size_mib"`
|
||||
}
|
||||
|
||||
type copiedFiles struct {
|
||||
FileNames []string `json:"file_names"`
|
||||
Config string `json:"config"`
|
||||
PlatformDockerCompose string `json:"platform_docker_compose"`
|
||||
InstallLog string `json:"install_log"`
|
||||
}
|
||||
533
DCIManager6/dci6-support-reader/platformTabs.go
Normal file
533
DCIManager6/dci6-support-reader/platformTabs.go
Normal file
@@ -0,0 +1,533 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func createLocationTab(platform platformStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск Локаций ...")
|
||||
|
||||
filteredEntries := platform.DciLocations
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewEntry(),
|
||||
widget.NewEntry(),
|
||||
widget.NewEntry(),
|
||||
widget.NewEntry(),
|
||||
widget.NewEntry(),
|
||||
widget.NewEntry(),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
|
||||
entryOne := box.Objects[0].(*widget.Entry)
|
||||
entryTwo := box.Objects[1].(*widget.Entry)
|
||||
entryThree := box.Objects[2].(*widget.Entry)
|
||||
entryFour := box.Objects[3].(*widget.Entry)
|
||||
entryFive := box.Objects[4].(*widget.Entry)
|
||||
entrySix := box.Objects[5].(*widget.Entry)
|
||||
|
||||
entryOne.AlwaysShowValidationError = true
|
||||
entryOne.SetText(fmt.Sprintf("%d Имя: %s Главная локация: %d Статус: %s (%s)", e.Id, e.Name, e.IsMain, e.Status, e.StatusInfo))
|
||||
entryTwo.SetText(fmt.Sprintf("SSH: %s@%s:%d", e.SshUser, e.SshAddress, e.SshPort))
|
||||
entryThree.SetText(fmt.Sprintf("%s Userspace: %d", e.SetupInfo, e.Userspace))
|
||||
entryFour.SetText(fmt.Sprintf("Настройки: %s", e.Settings))
|
||||
entryFive.SetText(fmt.Sprintf("Патч: %s", e.Patch))
|
||||
entrySix.SetText(fmt.Sprintf("DHCP: %s Redis: %s Nginx: %s Netflow: %s Proxy: %s", e.ParamsDhcp, e.ParamsRedis, e.ParamsNginx, e.ParamsNetflow, e.ProxyParams))
|
||||
entryOne.TextStyle.Bold = true
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEntries = platform.DciLocations
|
||||
} else {
|
||||
filtered := []dciLocation{}
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range platform.DciLocations {
|
||||
if strings.Contains(strings.ToLower(elem.Name), lText) || strings.Contains(strings.ToLower(elem.SshAddress), lText) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
locationsTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return locationsTab
|
||||
}
|
||||
|
||||
// func createLocationComposeTab(platform platformStruct) *fyne.Container {
|
||||
// // строка поиска
|
||||
// searchEntry := widget.NewEntry()
|
||||
// searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
// // переменная с которой будем работать дальше при фильтрации, с пустым условием фильтрации равна всему списку
|
||||
// filteredEntries := platform.DciLocationDockerComposes
|
||||
// // создаём список, котрый будет отображаться в табе
|
||||
// list := widget.NewList(
|
||||
// // состоит из трёх функций, которые постоянно дургаются, когда скролишь список
|
||||
// // первая возвращает длину списка, что даёт возможность получить id элемента
|
||||
// func() int {
|
||||
// return len(filteredEntries)
|
||||
// },
|
||||
// // вторая работает шаблоном показывая из каких элементов список будет состоять
|
||||
// func() fyne.CanvasObject {
|
||||
// return container.NewVBox(
|
||||
// widget.NewLabel("имя"),
|
||||
// widget.NewMultiLineEntry(),
|
||||
// )
|
||||
// },
|
||||
// // третья функция формирует собственно список с данными
|
||||
// func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
// box := obj.(*fyne.Container)
|
||||
// e := filteredEntries[id]
|
||||
// nameLabel := box.Objects[0].(*widget.Label)
|
||||
// composeEntry := box.Objects[1].(*widget.Entry)
|
||||
|
||||
// nameLabel.SetText(fmt.Sprintf("%d %s", e.Id, e.Name))
|
||||
// nameLabel.TextStyle.Bold = true
|
||||
// composeEntry.SetText(e.DockerCompose)
|
||||
// },
|
||||
// )
|
||||
// // дальше формируем поисковую логику, которая вызывается при изменении строки
|
||||
// searchEntry.OnChanged = func(text string) {
|
||||
// if text == "" {
|
||||
// filteredEntries = platform.DciLocationDockerComposes
|
||||
// } else {
|
||||
// filtered := []dciLocationDockerCompose{}
|
||||
// lText := strings.ToLower(text)
|
||||
// for _, elem := range platform.DciLocationDockerComposes {
|
||||
// if strings.Contains(strings.ToLower(elem.Name), lText) || strings.Contains(strings.ToLower(elem.DockerCompose), lText) {
|
||||
// filtered = append(filtered, elem)
|
||||
// }
|
||||
// }
|
||||
// filteredEntries = filtered
|
||||
// }
|
||||
// list.Refresh()
|
||||
// }
|
||||
// locationsTab := container.NewBorder(
|
||||
// container.NewVBox(
|
||||
// searchEntry,
|
||||
// widget.NewSeparator(),
|
||||
// ), nil, nil, nil,
|
||||
// container.NewScroll(list),
|
||||
// )
|
||||
// return locationsTab
|
||||
// }
|
||||
|
||||
func createTaskManagerFailedTab(platform platformStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск задач ...")
|
||||
|
||||
filteredEntries := platform.TaskManagerTask
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("id name status"),
|
||||
widget.NewLabel("time"),
|
||||
widget.NewEntry(),
|
||||
widget.NewLabel("output"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
idLabel := box.Objects[0].(*widget.Label)
|
||||
nameLabel := box.Objects[1].(*widget.Label)
|
||||
statusLabel := box.Objects[2].(*widget.Entry)
|
||||
timeLabel := box.Objects[3].(*widget.Label)
|
||||
|
||||
idLabel.SetText(fmt.Sprintf("%d %s %s", e.Id, e.Name, e.Status))
|
||||
idLabel.TextStyle.Bold = true
|
||||
nameLabel.SetText(e.RegistrationTime)
|
||||
statusLabel.SetText(e.RequestInfo)
|
||||
timeLabel.SetText(e.Output)
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEntries = platform.TaskManagerTask
|
||||
} else {
|
||||
filtered := []taskManagerTask{}
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range platform.TaskManagerTask {
|
||||
if strings.Contains(strings.ToLower(elem.Name), lText) || strings.Contains(strings.ToLower(elem.Status), lText) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
taskFailedTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return taskFailedTab
|
||||
}
|
||||
|
||||
func createHwByLocationsTab(platform platformStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск по локациям ...")
|
||||
|
||||
filteredEntries := platform.HwByLocations
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("loc"),
|
||||
widget.NewLabel("serv"),
|
||||
widget.NewLabel("switch"),
|
||||
widget.NewLabel("pdu"),
|
||||
widget.NewLabel("ups"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
loc := box.Objects[0].(*widget.Label)
|
||||
serv := box.Objects[1].(*widget.Label)
|
||||
sw := box.Objects[2].(*widget.Label)
|
||||
pdu := box.Objects[3].(*widget.Label)
|
||||
ups := box.Objects[4].(*widget.Label)
|
||||
|
||||
loc.SetText(fmt.Sprintf("Локация: %d", e.Location))
|
||||
loc.TextStyle.Bold = true
|
||||
serv.SetText(fmt.Sprintf("Серверов: %d", e.Server))
|
||||
sw.SetText(fmt.Sprintf("Коммутаторов: %d", e.Switch))
|
||||
pdu.SetText(fmt.Sprintf("PDU: %d", e.Pdu))
|
||||
ups.SetText(fmt.Sprintf("UPS: %d", e.Ups))
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEntries = platform.HwByLocations
|
||||
} else {
|
||||
filtered := []hwByLocation{}
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range platform.HwByLocations {
|
||||
if strings.Contains(strconv.Itoa(elem.Location), lText) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createInstalledPluginTab(platform platformStruct) *fyne.Container {
|
||||
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(platform.InstalledPlugin)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("name"),
|
||||
widget.NewLabel("status"),
|
||||
widget.NewLabel("version"),
|
||||
widget.NewLabel("Curver"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := platform.InstalledPlugin[id]
|
||||
|
||||
nameLabel := box.Objects[0].(*widget.Label)
|
||||
statLabel := box.Objects[1].(*widget.Label)
|
||||
verLabel := box.Objects[2].(*widget.Label)
|
||||
curverLabel := box.Objects[3].(*widget.Label)
|
||||
|
||||
nameLabel.SetText(e.Name)
|
||||
nameLabel.TextStyle.Bold = true
|
||||
statLabel.SetText(e.Status)
|
||||
verLabel.SetText(e.Version)
|
||||
curverLabel.SetText(e.CurrentVersion)
|
||||
},
|
||||
)
|
||||
list.Refresh()
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createLdapTab(platform platformStruct) *fyne.Container {
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(platform.Ldaps)
|
||||
},
|
||||
// Id int `json:"id"`
|
||||
// Name string `json:"name"`
|
||||
// LastSync string `json:"last_sync"`
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("ldap"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := platform.Ldaps[id]
|
||||
|
||||
ldapLabel := box.Objects[0].(*widget.Label)
|
||||
ldapLabel.SetText(fmt.Sprintf("%d %s Синхронизация: %s", e.Id, e.Name, e.LastSync))
|
||||
},
|
||||
)
|
||||
list.Refresh()
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createRepoTab(platform platformStruct) *fyne.Container {
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(platform.Repos)
|
||||
},
|
||||
// Id int `json:"id"`
|
||||
// Name string `json:"name"`
|
||||
// Url string `json:"url"`
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("id"),
|
||||
widget.NewLabel("name"),
|
||||
widget.NewLabel("url"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := platform.Repos[id]
|
||||
|
||||
idLabel := box.Objects[0].(*widget.Label)
|
||||
nameLabel := box.Objects[1].(*widget.Label)
|
||||
urlLabel := box.Objects[2].(*widget.Label)
|
||||
|
||||
idLabel.SetText(fmt.Sprintf("%d", e.Id))
|
||||
nameLabel.SetText(e.Name)
|
||||
urlLabel.SetText(e.Url)
|
||||
},
|
||||
)
|
||||
list.Refresh()
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createOsTemplateTab(platform platformStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
filteredEntries := platform.OsTemplates
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
// Id int `json:"id"`
|
||||
// Name string `json:"name"`
|
||||
// Filename string `json:"filename"`
|
||||
// Macro string `json:"macro"`
|
||||
// Metainfo string `json:"metainfo"`
|
||||
// DirectoryName string `json:"directory_name"`
|
||||
// Repository int `json:"repository"`
|
||||
// Size int `json:"size"`
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("id-name-filename-directoryname-size"),
|
||||
widget.NewLabel("macro-metainfo-reposiztory"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
labelFirst := box.Objects[0].(*widget.Label)
|
||||
labelSecond := box.Objects[1].(*widget.Label)
|
||||
|
||||
labelFirst.SetText(fmt.Sprintf("%d %s %s %s размер: %d", e.Id, e.Name, e.Filename, e.DirectoryName, e.Size))
|
||||
labelFirst.Selectable = true
|
||||
labelSecond.SetText(fmt.Sprintf("макросы: %s мета: %s репозиторий: %d", e.Macro, e.Metainfo, e.Repository))
|
||||
labelSecond.Selectable = true
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(textRaw string) {
|
||||
if textRaw == "" {
|
||||
filteredEntries = platform.OsTemplates
|
||||
} else {
|
||||
filtered := []osTemplate{}
|
||||
text := strings.ToLower(textRaw)
|
||||
for _, elem := range platform.OsTemplates {
|
||||
if strings.Contains(strings.ToLower(elem.Name), text) || strings.Contains(strings.ToLower(elem.Filename), text) || strings.Contains(strings.ToLower(elem.Metainfo), text) || strings.Contains(strings.ToLower(elem.DirectoryName), text) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
osTemplTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return osTemplTab
|
||||
}
|
||||
|
||||
func createBackupTasksTab(platform platformStruct) *fyne.Container {
|
||||
// Id int `json:"id"`
|
||||
// Enabled int `json:"enabled"`
|
||||
// CronExpression string `json:"cron_expression"`
|
||||
// LimitCount int `json:"limit_count"`
|
||||
// LimitSizeMib int `json:"limit_size_mib"`
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(platform.BackupTasks)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("id"),
|
||||
widget.NewLabel("enabled"),
|
||||
widget.NewLabel("cron"),
|
||||
widget.NewLabel("count"),
|
||||
widget.NewLabel("size"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := platform.BackupTasks[id]
|
||||
|
||||
label0 := box.Objects[0].(*widget.Label)
|
||||
label1 := box.Objects[1].(*widget.Label)
|
||||
label2 := box.Objects[2].(*widget.Label)
|
||||
label3 := box.Objects[3].(*widget.Label)
|
||||
label4 := box.Objects[4].(*widget.Label)
|
||||
|
||||
label0.SetText(strconv.Itoa(e.Id))
|
||||
label1.SetText(fmt.Sprintf("включено: %d", e.Enabled))
|
||||
label2.SetText(e.CronExpression)
|
||||
label3.SetText(fmt.Sprintf("количество копий: %d", e.LimitCount))
|
||||
label4.SetText(fmt.Sprintf("размер: %d", e.LimitSizeMib))
|
||||
},
|
||||
)
|
||||
list.Refresh()
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createCopiedFileListTab(platform platformStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
filteredEntries := platform.CopiedFiles.FileNames
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("fileName"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
fileName := box.Objects[0].(*widget.Label)
|
||||
|
||||
fileName.SetText(e)
|
||||
fileName.Selectable = true
|
||||
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEntries = platform.CopiedFiles.FileNames
|
||||
} else {
|
||||
var filtered []string
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range platform.CopiedFiles.FileNames {
|
||||
if strings.Contains(strings.ToLower(elem), lText) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createLicenseTab(platform platformStruct) *fyne.Container {
|
||||
licCheck := widget.NewMultiLineEntry()
|
||||
licCheck.SetText(platform.License.LicenseCheck)
|
||||
licInfo := widget.NewMultiLineEntry()
|
||||
licInfo.SetText(platform.License.LicenseInfo)
|
||||
licInfo.MultiLine = true
|
||||
licInfo.SetMinRowsVisible(20)
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
licCheck,
|
||||
licInfo,
|
||||
), nil, nil, nil,
|
||||
)
|
||||
return tab
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package main
|
||||
|
||||
type license struct {
|
||||
LicenseCheck string `json:"license_check"`
|
||||
LicenseInfo string `json:"license_info"`
|
||||
}
|
||||
264
DCIManager6/dci6-support-reader/processedFile.go
Normal file
264
DCIManager6/dci6-support-reader/processedFile.go
Normal file
@@ -0,0 +1,264 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/storage"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// Очистка вкладок server
|
||||
func (a *App) clearServerTabs() {
|
||||
// Удаляем все вкладки, кроме первой (если она нужна)
|
||||
items := a.serverTab.Items
|
||||
if len(items) > 0 {
|
||||
// Удаляем все вкладки после первой (если первая - это какая-то базовая)
|
||||
// Или удаляем все, если нужно полностью очистить
|
||||
for i := len(items) - 1; i >= 0; i-- {
|
||||
a.serverTab.RemoveIndex(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Очистка вкладок platform
|
||||
func (a *App) clearPlatformTabs() {
|
||||
items := a.platformTab.Items
|
||||
if len(items) > 0 {
|
||||
for i := len(items) - 1; i >= 0; i-- {
|
||||
a.platformTab.RemoveIndex(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление UI после загрузки
|
||||
func (a *App) updateUIAfterUpload(uiFunc string) {
|
||||
// Обновляем статус
|
||||
a.statusLabel.SetText("✅ Файл загружен")
|
||||
a.statusLabel.TextStyle = fyne.TextStyle{Bold: true, Italic: true}
|
||||
a.statusLabel.Refresh()
|
||||
|
||||
// Обновляем информацию о файле
|
||||
fileInfoText := fmt.Sprintf("📄 %s | 📦 %s | 🕒 %s",
|
||||
a.fileName,
|
||||
formatFileSize(a.fileSize),
|
||||
time.Now().Format("15:04:05"))
|
||||
a.fileInfo.SetText(fileInfoText)
|
||||
|
||||
if uiFunc == "server" {
|
||||
a.updateServer()
|
||||
}
|
||||
if uiFunc == "platform" {
|
||||
a.updatePlatform()
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление содержимого server
|
||||
func (a *App) updateServer() {
|
||||
a.clearServerTabs()
|
||||
var server outputStruct
|
||||
err := json.Unmarshal(a.serverContent, &server)
|
||||
if err != nil {
|
||||
log.Printf("Unmarshall server: %s", err)
|
||||
}
|
||||
|
||||
a.serverTab.Append(container.NewTabItem("БИОС", widget.NewLabel(server.BiosInfo.Name)))
|
||||
if server.OperatingSystem.AstraLicense == "" || server.OperatingSystem.AstraVersion == "" {
|
||||
a.serverTab.Append(container.NewTabItem("ОС", widget.NewLabel(server.OperatingSystem.OsRelease)))
|
||||
} else {
|
||||
a.serverTab.Append(container.NewTabItem("ОС", widget.NewLabel(fmt.Sprintf("Версия: %s, Версия ALSE: %s, Уровень защиты ALSE: %s", server.OperatingSystem.OsRelease, server.OperatingSystem.AstraLicense, server.OperatingSystem.AstraVersion))))
|
||||
}
|
||||
|
||||
installedPkgsTab := createInstalledPkgsTab(server)
|
||||
a.serverTab.Append(container.NewTabItem("Пакеты", installedPkgsTab))
|
||||
fsInfoTab := createFsInfoTab(server)
|
||||
a.serverTab.Append(container.NewTabItem("ФС", fsInfoTab))
|
||||
a.serverTab.Append(container.NewTabItem("LA", widget.NewLabel(fmt.Sprintf("Средняя загрузка: 15м %s\n, \t5м %s\n, \t1м %s\n, Процессы %s", server.LoadAverage.FifteenMin, server.LoadAverage.FiveMin, server.LoadAverage.OneMin, server.LoadAverage.Processes))))
|
||||
cpuTab := createCpuTab(server)
|
||||
a.serverTab.Append(container.NewTabItem("ЦП", cpuTab))
|
||||
a.serverTab.Append(container.NewTabItem("ОЗУ", widget.NewLabel(fmt.Sprintf("Доступно: %s\nСвободно: %s\nВсего: %s", server.Ram.MemAvailable, server.Ram.MemFree, server.Ram.MemTotal))))
|
||||
a.serverTab.Append(container.NewTabItem("Uptime", widget.NewLabel(server.Uptime.WorkSeconds)))
|
||||
a.serverTab.Append(container.NewTabItem("Фаерволы", createFirewallTab(server)))
|
||||
a.serverTab.Append(container.NewTabItem("Время", widget.NewLabel(fmt.Sprintf("Служба времени\t\t\t%s, \nВремя синхронизировано\t%s", server.TimeService.TimeService, server.TimeService.TimeSync))))
|
||||
a.serverTab.Append(container.NewTabItem("Сеть", createNetworkTab(server)))
|
||||
// a.serverTab.Append(container.NewTabItem("Интеренет", widget.NewLabel(fmt.Sprintf("docker-registry.ispsystem.com :: %d\ndownload.ispsystem.com :: %d\nlicense6.ispsystem.com :: %d\nmetricreport.ispsystem.net :: %d\ndownload.docker.com :: %d", server.InternetRequired.IspRegistry, server.InternetRequired.IspDownload, server.InternetRequired.IspLicense, server.InternetRequired.IspMetric, server.InternetRequired.DockerDownload))))
|
||||
a.serverTab.Append(container.NewTabItem("Интернет", createInternetRequiredTab(server)))
|
||||
a.serverTab.Append(container.NewTabItem("Сесюрити", createSecSetTab(server)))
|
||||
a.serverTab.Append(container.NewTabItem("Docker", createDockerTab(server)))
|
||||
a.serverTab.Append(container.NewTabItem("Jrnlctl", createJournalTab(server)))
|
||||
a.serverTab.Append(container.NewTabItem("root history", createRootHistoryTab(server)))
|
||||
}
|
||||
|
||||
func (a *App) updatePlatform() {
|
||||
a.clearPlatformTabs()
|
||||
var platform platformStruct
|
||||
err := json.Unmarshal(a.platformContent, &platform)
|
||||
if err != nil {
|
||||
log.Printf("Unmarshall platform: %s", err)
|
||||
}
|
||||
a.platformTab.Append(container.NewTabItem("Лицензия", createLicenseTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Локации", createLocationTab(platform)))
|
||||
// a.platformTab.Append(container.NewTabItem("Compose Локация", createLocationComposeTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Имена файлов", createCopiedFileListTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Taskmgr", createTaskManagerFailedTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Оборудование", createHwByLocationsTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Плагины", createInstalledPluginTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Пользователи", widget.NewLabel(fmt.Sprintf("Количество пользователей: %d", platform.Users.Count))))
|
||||
a.platformTab.Append(container.NewTabItem("LDAP", createLdapTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Репозитории", createRepoTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Шаблоны ОС", createOsTemplateTab(platform)))
|
||||
a.platformTab.Append(container.NewTabItem("Real ip", widget.NewLabel(fmt.Sprintf("%s : %s", platform.RealIP.Name, platform.RealIP.Value))))
|
||||
a.platformTab.Append(container.NewTabItem("Бэкап", createBackupTasksTab(platform)))
|
||||
}
|
||||
|
||||
func (a *App) onUploadServer() {
|
||||
a.statusLabel.SetText("Выбор файла...")
|
||||
|
||||
// Фильтр json файлов
|
||||
jsonFilter := storage.NewExtensionFileFilter([]string{".json"})
|
||||
|
||||
// Создаем диалог выбора файла
|
||||
fileDialog := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
|
||||
if err != nil {
|
||||
a.showError("Ошибка", fmt.Sprintf("Не удалось открыть диалог: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
if reader == nil {
|
||||
a.statusLabel.SetText("Отменено")
|
||||
return
|
||||
}
|
||||
|
||||
defer reader.Close()
|
||||
|
||||
// Получаем информацию о файле
|
||||
fileURI := reader.URI()
|
||||
a.filePath = fileURI.Path()
|
||||
a.fileName = fileURI.Name()
|
||||
|
||||
// Читаем файл
|
||||
content, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
a.showError("Ошибка чтения", fmt.Sprintf("Не удалось прочитать файл: %v", err))
|
||||
a.progressBar.Hide()
|
||||
return
|
||||
}
|
||||
|
||||
// Сохраняем данные
|
||||
a.serverContent = content
|
||||
a.fileSize = int64(len(content))
|
||||
|
||||
// Завершаем прогресс
|
||||
a.progressBar.SetValue(1.0)
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
a.progressBar.Hide()
|
||||
|
||||
// Обновляем UI
|
||||
a.updateUIAfterUpload("server")
|
||||
|
||||
// Показываем уведомление
|
||||
a.showSuccess("Файл загружен",
|
||||
fmt.Sprintf("Файл '%s' успешно загружен", a.fileName))
|
||||
|
||||
}, a.window)
|
||||
|
||||
fileDialog.SetFilter(jsonFilter)
|
||||
// Альтернативный способ установки начальной директории
|
||||
// Используем домашнюю директорию пользователя
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err == nil {
|
||||
// Пытаемся использовать Downloads
|
||||
downloadsPath := filepath.Join(homeDir, "Downloads")
|
||||
if _, err := os.Stat(downloadsPath); err == nil {
|
||||
// Создаем URI из пути
|
||||
uri := storage.NewFileURI(downloadsPath)
|
||||
listableURI, err := storage.ListerForURI(uri)
|
||||
if err == nil {
|
||||
fileDialog.SetLocation(listableURI)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Показываем диалог
|
||||
fileDialog.Show()
|
||||
}
|
||||
|
||||
func (a *App) onUploadPlatform() {
|
||||
a.statusLabel.SetText("Выбор файла...")
|
||||
|
||||
// Фильтр json файлов
|
||||
jsonFilter := storage.NewExtensionFileFilter([]string{".json"})
|
||||
|
||||
// Создаем диалог выбора файла
|
||||
fileDialog := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
|
||||
if err != nil {
|
||||
a.showError("Ошибка", fmt.Sprintf("Не удалось открыть диалог: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
if reader == nil {
|
||||
a.statusLabel.SetText("Отменено")
|
||||
return
|
||||
}
|
||||
|
||||
defer reader.Close()
|
||||
|
||||
// Получаем информацию о файле
|
||||
fileURI := reader.URI()
|
||||
a.filePath = fileURI.Path()
|
||||
a.fileName = fileURI.Name()
|
||||
|
||||
// Читаем файл
|
||||
content, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
a.showError("Ошибка чтения", fmt.Sprintf("Не удалось прочитать файл: %v", err))
|
||||
a.progressBar.Hide()
|
||||
return
|
||||
}
|
||||
|
||||
// Сохраняем данные
|
||||
a.platformContent = content
|
||||
a.fileSize = int64(len(content))
|
||||
|
||||
// Завершаем прогресс
|
||||
a.progressBar.SetValue(1.0)
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
a.progressBar.Hide()
|
||||
|
||||
// Обновляем UI
|
||||
a.updateUIAfterUpload("platform")
|
||||
|
||||
// Показываем уведомление
|
||||
a.showSuccess("Файл загружен",
|
||||
fmt.Sprintf("Файл '%s' успешно загружен", a.fileName))
|
||||
|
||||
}, a.window)
|
||||
|
||||
fileDialog.SetFilter(jsonFilter)
|
||||
// Альтернативный способ установки начальной директории
|
||||
// Используем домашнюю директорию пользователя
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err == nil {
|
||||
// Пытаемся использовать Downloads
|
||||
downloadsPath := filepath.Join(homeDir, "Downloads")
|
||||
if _, err := os.Stat(downloadsPath); err == nil {
|
||||
// Создаем URI из пути
|
||||
uri := storage.NewFileURI(downloadsPath)
|
||||
listableURI, err := storage.ListerForURI(uri)
|
||||
if err == nil {
|
||||
fileDialog.SetLocation(listableURI)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Показываем диалог
|
||||
fileDialog.Show()
|
||||
}
|
||||
248
DCIManager6/dci6-support-reader/server_docker_tab.go
Normal file
248
DCIManager6/dci6-support-reader/server_docker_tab.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func createDockerTab(server outputStruct) *container.AppTabs {
|
||||
dockerTabs := container.NewAppTabs()
|
||||
dockerTabs.Append(container.NewTabItem("docker ps", createDockerPsTab(server)))
|
||||
dockerTabs.Append(container.NewTabItem("docker stats", createDockerStats(server)))
|
||||
dockerTabs.Append(container.NewTabItem("supervisor status", createDockerSupervisorTab(server)))
|
||||
return dockerTabs
|
||||
}
|
||||
|
||||
// type dockerStats struct {
|
||||
// BlockIO string `json:"BlockIO"`
|
||||
// CPUPerc string `json:"CPUPerc"`
|
||||
// Container string `json:"Container"`
|
||||
// ID string `json:"ID"`
|
||||
// MemPerc string `json:"MemPerc"`
|
||||
// MemUsage string `json:"MemUsage"`
|
||||
// Name string `json:"Name"`
|
||||
// NetIO string `json:"NetIO"`
|
||||
// PIDs string `json:"PIDs"`
|
||||
// }
|
||||
|
||||
func shortId(id string) string {
|
||||
if len(id) > 12 {
|
||||
return id[:12]
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func parsePercent(percent string) float64 {
|
||||
var val float64
|
||||
fmt.Sscanf(percent, "%f%%", &val)
|
||||
return val
|
||||
}
|
||||
|
||||
func createDockerStats(server outputStruct) *fyne.Container {
|
||||
// Заголовки таблицы
|
||||
headers := []string{"CONTAINER", "NAME", "CPU %", "MEM %", "MEM USAGE", "NET I/O", "BLOCK I/O", "PIDs"}
|
||||
// Данные
|
||||
stats := server.DockerStats
|
||||
// Создаю таблицу
|
||||
table := widget.NewTable(
|
||||
func() (rows int, cols int) {
|
||||
return len(stats) + 1, len(headers)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
label := widget.NewLabel("Template")
|
||||
label.Selectable = true
|
||||
label.Alignment = fyne.TextAlignCenter
|
||||
return label
|
||||
},
|
||||
func(id widget.TableCellID, obj fyne.CanvasObject) {
|
||||
label := obj.(*widget.Label)
|
||||
|
||||
// Заголовки
|
||||
if id.Row == 0 {
|
||||
label.SetText(headers[id.Col])
|
||||
label.TextStyle.Bold = true
|
||||
label.Alignment = fyne.TextAlignCenter
|
||||
}
|
||||
// Данные
|
||||
row := id.Row - 1
|
||||
// if row < len(stats) {
|
||||
if len(stats) > 0 && row >= 0 && row < len(stats) {
|
||||
switch id.Col {
|
||||
case 0:
|
||||
// label.SetText(shortId(stats[row].Container))
|
||||
label.SetText(stats[row].Container)
|
||||
case 1:
|
||||
label.SetText(stats[row].Name)
|
||||
case 2:
|
||||
label.SetText(stats[row].CPUPerc)
|
||||
case 3:
|
||||
label.SetText(stats[row].MemPerc)
|
||||
if memPercent := parsePercent(stats[row].MemPerc); memPercent > 50 {
|
||||
label.Importance = widget.HighImportance
|
||||
}
|
||||
case 4:
|
||||
label.SetText(stats[row].MemUsage)
|
||||
case 5:
|
||||
label.SetText(stats[row].NetIO)
|
||||
case 6:
|
||||
label.SetText(stats[row].BlockIO)
|
||||
case 7:
|
||||
label.SetText(stats[row].PIDs)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
//Размер колонок
|
||||
table.SetColumnWidth(0, 100)
|
||||
table.SetColumnWidth(1, 150)
|
||||
table.SetColumnWidth(2, 70)
|
||||
table.SetColumnWidth(3, 70)
|
||||
table.SetColumnWidth(4, 140)
|
||||
table.SetColumnWidth(5, 140)
|
||||
table.SetColumnWidth(6, 140)
|
||||
table.SetColumnWidth(7, 50)
|
||||
|
||||
table.Refresh()
|
||||
|
||||
tab := container.NewBorder(
|
||||
widget.NewSeparator(),
|
||||
nil, nil, nil,
|
||||
container.NewScroll(table),
|
||||
)
|
||||
|
||||
return tab
|
||||
}
|
||||
|
||||
func createDockerPsTab(server outputStruct) *fyne.Container {
|
||||
searchDockerEntry := widget.NewEntry()
|
||||
searchDockerEntry.SetPlaceHolder("Поиск контейнеров ...")
|
||||
|
||||
filteredDockers := server.DockerPsA
|
||||
|
||||
// type dockerPs struct {
|
||||
// Id string `json:"id"`
|
||||
// Image string `json:"image"`
|
||||
// Names []string `json:"names"`
|
||||
// Created int64 `json:"running_for"`
|
||||
// State string `json:"state"`
|
||||
// Status string `json:"status"`
|
||||
// }
|
||||
|
||||
dockerList := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredDockers)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("id"),
|
||||
widget.NewLabel("image"),
|
||||
widget.NewLabel("names"),
|
||||
widget.NewLabel("created"),
|
||||
widget.NewLabel("state"),
|
||||
widget.NewLabel("status"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
hbox := obj.(*fyne.Container)
|
||||
dock := filteredDockers[id]
|
||||
|
||||
idLabel := hbox.Objects[0].(*widget.Label)
|
||||
imageLabel := hbox.Objects[1].(*widget.Label)
|
||||
namesLabel := hbox.Objects[2].(*widget.Label)
|
||||
createdLabel := hbox.Objects[3].(*widget.Label)
|
||||
stateLabel := hbox.Objects[4].(*widget.Label)
|
||||
statusLabel := hbox.Objects[5].(*widget.Label)
|
||||
|
||||
idLabel.SetText(dock.Id)
|
||||
imageLabel.SetText(dock.Image)
|
||||
namesLabel.SetText(fmt.Sprintf("%s", dock.Names))
|
||||
createdLabel.SetText(strconv.Itoa(int(dock.Created)))
|
||||
stateLabel.SetText(dock.State)
|
||||
statusLabel.SetText(dock.Status)
|
||||
},
|
||||
)
|
||||
|
||||
searchDockerEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredDockers = server.DockerPsA
|
||||
} else {
|
||||
filtered := []dockerPs{}
|
||||
lowerText := strings.ToLower(text)
|
||||
for _, d := range server.DockerPsA {
|
||||
if strings.Contains(strings.ToLower(d.Image), lowerText) || strings.Contains(strings.ToLower(d.State), lowerText) || strings.Contains(strings.ToLower(fmt.Sprintf("%s", d.Names)), lowerText) || strings.Contains(strings.ToLower(d.Status), lowerText) {
|
||||
filtered = append(filtered, d)
|
||||
}
|
||||
}
|
||||
filteredDockers = filtered
|
||||
}
|
||||
dockerList.Refresh()
|
||||
}
|
||||
dockerTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchDockerEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(dockerList),
|
||||
)
|
||||
return dockerTab
|
||||
}
|
||||
|
||||
func createDockerSupervisorTab(server outputStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
filtered := server.DockerSupervisor
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filtered)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
entry := widget.NewMultiLineEntry()
|
||||
entry.SetMinRowsVisible(10)
|
||||
entry.Wrapping = fyne.TextWrapWord
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("container_name"),
|
||||
entry,
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filtered[id]
|
||||
containerName := box.Objects[0].(*widget.Label)
|
||||
containerName.SetText(e.Name)
|
||||
containerName.TextStyle.Bold = true
|
||||
containerName.Selectable = true
|
||||
supervisorStatus := box.Objects[1].(*widget.Entry)
|
||||
supervisorStatus.SetText(e.SupStatus)
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filtered = server.DockerSupervisor
|
||||
} else {
|
||||
var f []dockerSupervisor
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range server.DockerSupervisor {
|
||||
if strings.Contains(strings.ToLower(elem.Name), lText) {
|
||||
f = append(f, elem)
|
||||
}
|
||||
}
|
||||
filtered = f
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
113
DCIManager6/dci6-support-reader/server_firewall_tab.go
Normal file
113
DCIManager6/dci6-support-reader/server_firewall_tab.go
Normal file
@@ -0,0 +1,113 @@
|
||||
// добавить генерацию файлов с правилами в архив, добавить номера строк, что бы хоть как то ориентироваться и в жопу это
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// widget.NewLabel(fmt.Sprintf("UFW\t%s\nNftables\t%s\nFirewalld\t%s\nIptables\t%s", server.Firewalls.Ufw, server.Firewalls.Nftables, server.Firewalls.Firewalld, server.Firewalls.Iptables))
|
||||
|
||||
func createFirewallTab(server outputStruct) *container.AppTabs {
|
||||
firewallTabs := container.NewAppTabs()
|
||||
firewallTabs.Append(container.NewTabItem("список фаерволов", createFirewallListTab(server)))
|
||||
firewallTabs.Append(container.NewTabItem("nft list ruleset", createNftListRuleset(server)))
|
||||
return firewallTabs
|
||||
}
|
||||
|
||||
func createFirewallListTab(server outputStruct) *fyne.Container {
|
||||
firewalls := ""
|
||||
if server.Firewalls.Firewalld != "" {
|
||||
firewalls = firewalls + "firewalld"
|
||||
}
|
||||
if server.Firewalls.Nftables != "" {
|
||||
firewalls = firewalls + ", nftables"
|
||||
}
|
||||
if server.Firewalls.Ufw != "" {
|
||||
firewalls = firewalls + ", ufw"
|
||||
}
|
||||
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
widget.NewSeparator(),
|
||||
widget.NewLabel(fmt.Sprintf("Активные службы фаерволов: %s", firewalls)),
|
||||
), nil, nil, nil,
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createNftListRuleset(server outputStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
filteredEntries := server.NftRuleset.Lines
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("fileName"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
fileName := box.Objects[0].(*widget.Label)
|
||||
|
||||
fileName.SetText(e)
|
||||
fileName.Selectable = true
|
||||
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEntries = server.NftRuleset.Lines
|
||||
} else {
|
||||
var filtered []string
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range server.NftRuleset.Lines {
|
||||
if strings.Contains(strings.ToLower(elem), lText) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
// searchEntry.OnChanged = func(text string) {
|
||||
// if text == "" {
|
||||
// // Если поиск пустой - сбрасываем выделение
|
||||
// list.UnselectAll()
|
||||
// return
|
||||
// }
|
||||
|
||||
// lText := strings.ToLower(text)
|
||||
|
||||
// // Ищем первое вхождение
|
||||
// for index, elem := range server.NftRuleset.Lines {
|
||||
// if strings.Contains(strings.ToLower(elem), lText) {
|
||||
// // Выделяем найденный элемент
|
||||
// list.Select(index)
|
||||
// // Прокручиваем к нему
|
||||
// list.ScrollTo(index)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Если ничего не найдено - сбрасываем выделение
|
||||
// list.UnselectAll()
|
||||
// }
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
8
DCIManager6/dci6-support-reader/server_nft_struct.go
Normal file
8
DCIManager6/dci6-support-reader/server_nft_struct.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
// я расчитываю в дальнейшем вернуться к этому. Json структура nftables непростая, поэтому я или разгадаю сам как её анмаршалить, или сопру из одной из двух библиотек на гитхабе. Или вообще их заиспользую.
|
||||
// пока что просто построчно выведу правила nft list ruleset
|
||||
|
||||
type nftRuleset struct {
|
||||
Lines []string `json:"lines"`
|
||||
}
|
||||
162
DCIManager6/dci6-support-reader/server_struct.go
Normal file
162
DCIManager6/dci6-support-reader/server_struct.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
type biosInfo struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type operatingSystem struct {
|
||||
OsRelease string `json:"os_name"`
|
||||
AstraVersion string `json:"astra_version"`
|
||||
AstraLicense string `json:"astra_license"`
|
||||
}
|
||||
|
||||
type installedPackage struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type fsInfo struct {
|
||||
MountPointDevice string `json:"mount_point_devices"`
|
||||
MountPointOsPath string `json:"mount_point_os_path"`
|
||||
MountPointSize uint64 `json:"mount_point_size"`
|
||||
MountPointFree uint64 `json:"mount_point_free"`
|
||||
}
|
||||
|
||||
type loadAverage struct {
|
||||
OneMin string `json:"la_onemin"`
|
||||
FiveMin string `json:"la_fivemin"`
|
||||
FifteenMin string `json:"la_fifteenmin"`
|
||||
Processes string `json:"la_processes"`
|
||||
}
|
||||
|
||||
type cpu struct {
|
||||
VendorId string `json:"vendor_id"`
|
||||
CpuFamily string `json:"cpu_family"`
|
||||
Model string `json:"model"`
|
||||
ModelName string `json:"model_name"`
|
||||
Stepping string `json:"stepping"`
|
||||
Microcode string `json:"microcode"`
|
||||
CpuMhz string `json:"cpu_mhz"`
|
||||
CacheSize string `json:"cache_size"`
|
||||
PhysicalId string `json:"phusical_id"`
|
||||
CpuCores string `json:"cpu_cores"`
|
||||
Flags string `json:"flags"`
|
||||
Bugs string `json:"bugs"`
|
||||
Bogomips string `json:"bogomips"`
|
||||
TlbSize string `json:"tlb_size"`
|
||||
ClflushSize string `json:"clflush_size"`
|
||||
CacheAlignment string `json:"cache_alignment"`
|
||||
AddressSize string `json:"address_size"`
|
||||
PowerManagement string `json:"power_management"`
|
||||
}
|
||||
|
||||
type ram struct {
|
||||
MemTotal string `json:"mem_total"`
|
||||
MemFree string `json:"mem_free"`
|
||||
MemAvailable string `json:"mem_available"`
|
||||
}
|
||||
|
||||
type uptime struct {
|
||||
WorkSeconds string `json:"work_seconds"`
|
||||
}
|
||||
|
||||
type timeService struct {
|
||||
TimeService string `json:"time_service"`
|
||||
TimeSync string `json:"time_sync"`
|
||||
}
|
||||
|
||||
type journalctlEntry struct {
|
||||
Timestamp string `json:"__REALTIME_TIMESTAMP"`
|
||||
CommandLine string `json:"_CMDLINE"`
|
||||
CommandName string `json:"_COMM"`
|
||||
SyslogIdentifier string `json:"SYSLOG_IDENTIFIER"`
|
||||
Message string `json:"MESSAGE"`
|
||||
}
|
||||
|
||||
type firewalls struct {
|
||||
Ufw string `json:"ufw"`
|
||||
Nftables string `json:"nftables"`
|
||||
Iptables string `json:"iptables"`
|
||||
Firewalld string `json:"firewalld"`
|
||||
}
|
||||
|
||||
type netInterface struct {
|
||||
Device string `json:"device"`
|
||||
Flags string `json:"flags"`
|
||||
HwAddr string `json:"hardware_address"`
|
||||
IpAddr []string `json:"ip_addr"`
|
||||
Index string `json:"index"`
|
||||
MTU string `json:"mtu"`
|
||||
}
|
||||
|
||||
type networkConfig struct {
|
||||
NetInterfaces []netInterface `json:"net_interfaces"`
|
||||
NetworkManager string `json:"networkmanager"`
|
||||
NetworkManagerConn []string `json:"networkmanager_conn"`
|
||||
Networking string `json:"networking"`
|
||||
EtcHosts []string `json:"etc_hosts"`
|
||||
}
|
||||
|
||||
type internetResource struct {
|
||||
Name string `json:"name"`
|
||||
Http string `json:"http"`
|
||||
Https string `json:"https"`
|
||||
IpList string `json:"ip_list"`
|
||||
}
|
||||
|
||||
type secSetALSE struct {
|
||||
Apparmor string `json:"apparmor"`
|
||||
Selinux string `json:"selinux"`
|
||||
Parsec string `json:"parsec"`
|
||||
Mic string `json:"astra_mic"`
|
||||
Mac string `json:"astra_mac"`
|
||||
Digsig string `json:"digsig"`
|
||||
Sudo string `json:"sudo"`
|
||||
Nochmodx string `json:"nochmodx"`
|
||||
Interpret string `json:"interpret"`
|
||||
SudoersAstraAdmin string `json:"sudoers_astraadmin"`
|
||||
SudoersSudo string `json:"sudoers_sudo"`
|
||||
AstraAdmin string `json:"astra-admin"`
|
||||
}
|
||||
|
||||
type secSetUbuntu struct {
|
||||
Apparmor string `json:"apparmor"`
|
||||
}
|
||||
|
||||
type secSetAlma struct {
|
||||
Selinux string `json:"selinux"`
|
||||
}
|
||||
|
||||
type dockerPs struct {
|
||||
Id string `json:"id"`
|
||||
Image string `json:"image"`
|
||||
Names []string `json:"names"`
|
||||
Created int64 `json:"running_for"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
// Health string `json:"health"`
|
||||
}
|
||||
|
||||
type dockerStats struct {
|
||||
BlockIO string `json:"BlockIO"`
|
||||
CPUPerc string `json:"CPUPerc"`
|
||||
Container string `json:"Container"`
|
||||
ID string `json:"ID"`
|
||||
MemPerc string `json:"MemPerc"`
|
||||
MemUsage string `json:"MemUsage"`
|
||||
Name string `json:"Name"`
|
||||
NetIO string `json:"NetIO"`
|
||||
PIDs string `json:"PIDs"`
|
||||
}
|
||||
|
||||
type dockerSupervisor struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SupStatus string `json:"sup_status"`
|
||||
}
|
||||
|
||||
type rootHistoryCommand struct {
|
||||
Id int `json:"id"`
|
||||
ExecutionTime string `json:"excution_time"`
|
||||
Command string `json:"command"`
|
||||
}
|
||||
489
DCIManager6/dci6-support-reader/server_tabs.go
Normal file
489
DCIManager6/dci6-support-reader/server_tabs.go
Normal file
@@ -0,0 +1,489 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func createInstalledPkgsTab(server outputStruct) *fyne.Container {
|
||||
searchPkgEntry := widget.NewEntry()
|
||||
searchPkgEntry.SetPlaceHolder("Поиск пакетов ...")
|
||||
|
||||
filteredPackages := server.InstalledPackages
|
||||
|
||||
installedPackagesList := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredPackages)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("Пакет"),
|
||||
widget.NewLabel("Версия"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
hbox := obj.(*fyne.Container)
|
||||
pkg := filteredPackages[id]
|
||||
|
||||
nameLabel := hbox.Objects[0].(*widget.Label)
|
||||
versionLabel := hbox.Objects[1].(*widget.Label)
|
||||
|
||||
nameLabel.SetText(pkg.Name)
|
||||
versionLabel.SetText(pkg.Version)
|
||||
versionLabel.TextStyle = fyne.TextStyle{Monospace: true}
|
||||
},
|
||||
)
|
||||
|
||||
searchPkgEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredPackages = server.InstalledPackages
|
||||
} else {
|
||||
filtered := []installedPackage{}
|
||||
lowerText := strings.ToLower(text)
|
||||
for _, pkg := range server.InstalledPackages {
|
||||
if strings.Contains(strings.ToLower(pkg.Name), lowerText) ||
|
||||
strings.Contains(strings.ToLower(pkg.Version), lowerText) {
|
||||
filtered = append(filtered, pkg)
|
||||
}
|
||||
}
|
||||
filteredPackages = filtered
|
||||
}
|
||||
installedPackagesList.Refresh()
|
||||
}
|
||||
installedPkgsTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchPkgEntry,
|
||||
widget.NewSeparator(),
|
||||
),
|
||||
nil, nil, nil,
|
||||
container.NewScroll(installedPackagesList),
|
||||
)
|
||||
return installedPkgsTab
|
||||
}
|
||||
|
||||
func createFsInfoTab(server outputStruct) *fyne.Container {
|
||||
searchFsInfoEntry := widget.NewEntry()
|
||||
searchFsInfoEntry.SetPlaceHolder("Поиск монтирований...")
|
||||
|
||||
filteredFs := server.FsInformations
|
||||
|
||||
fsInfoList := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredFs)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabel("Устройство"),
|
||||
widget.NewLabel("Путь монтирования"),
|
||||
widget.NewLabel("Размер"),
|
||||
widget.NewLabel("Свободно"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
hbox := obj.(*fyne.Container)
|
||||
fs := filteredFs[id]
|
||||
|
||||
deviceLabel := hbox.Objects[0].(*widget.Label)
|
||||
pathLabel := hbox.Objects[1].(*widget.Label)
|
||||
sizeLabel := hbox.Objects[2].(*widget.Label)
|
||||
freeLabel := hbox.Objects[3].(*widget.Label)
|
||||
|
||||
deviceLabel.SetText(fs.MountPointDevice)
|
||||
pathLabel.SetText(fs.MountPointOsPath)
|
||||
sizeLabel.SetText(strconv.Itoa(int(fs.MountPointSize)))
|
||||
freeLabel.SetText(strconv.Itoa(int(fs.MountPointFree)))
|
||||
|
||||
freeLabel.TextStyle.Bold = true
|
||||
},
|
||||
)
|
||||
|
||||
searchFsInfoEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredFs = server.FsInformations
|
||||
} else {
|
||||
filtered := []fsInfo{}
|
||||
lowerText := strings.ToLower(text)
|
||||
for _, fs := range server.FsInformations {
|
||||
if strings.Contains(strings.ToLower(fs.MountPointDevice), lowerText) ||
|
||||
strings.Contains(strings.ToLower(fs.MountPointOsPath), lowerText) {
|
||||
filtered = append(filtered, fs)
|
||||
}
|
||||
}
|
||||
filteredFs = filtered
|
||||
}
|
||||
fsInfoList.Refresh()
|
||||
}
|
||||
fsInfoTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchFsInfoEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(fsInfoList),
|
||||
)
|
||||
return fsInfoTab
|
||||
}
|
||||
|
||||
// func createCpuTab(server outputStruct) *fyne.Container {
|
||||
// searchCpuEntry := widget.NewEntry()
|
||||
// searchCpuEntry.SetPlaceHolder("ЦПУ...")
|
||||
// filteredCpu := server.Cpu.Model
|
||||
// cpuList := widget.NewList(
|
||||
// func() int {
|
||||
// return len(filteredCpu)
|
||||
// },
|
||||
// func() fyne.CanvasObject {
|
||||
// return container.NewHBox(
|
||||
// widget.NewLabel("Модель"),
|
||||
// )
|
||||
// },
|
||||
// func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
// hbox := obj.(*fyne.Container)
|
||||
// cpu := filteredCpu[id]
|
||||
|
||||
// modelLabel := hbox.Objects[0].(*widget.Label)
|
||||
// modelLabel.SetText(cpu)
|
||||
// },
|
||||
// )
|
||||
|
||||
// searchCpuEntry.OnChanged = func(text string) {
|
||||
// if text == "" {
|
||||
// filteredCpu = server.Cpu.Model
|
||||
// } else {
|
||||
// filtered := cpu{}
|
||||
// lowerText := strings.ToLower(text)
|
||||
// for _, c := range server.Cpu.Model {
|
||||
// if strings.Contains(strings.ToLower(c), lowerText) {
|
||||
// filtered.Model = append(filtered.Model, c)
|
||||
// }
|
||||
// }
|
||||
// filteredCpu = filtered.Model
|
||||
// }
|
||||
// cpuList.Refresh()
|
||||
// }
|
||||
// cpuTab := container.NewBorder(
|
||||
// container.NewVBox(
|
||||
// searchCpuEntry,
|
||||
// widget.NewSeparator(),
|
||||
// ), nil, nil, nil,
|
||||
// container.NewScroll(cpuList),
|
||||
// )
|
||||
// return cpuTab
|
||||
// }
|
||||
|
||||
func createCpuTab(server outputStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
filteredEntries := server.Cpus
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("VendorID,CpuFamily,Model,ModelName"),
|
||||
widget.NewLabel("Stepping,Microcode,CpuMhz,CacheSize"),
|
||||
widget.NewLabel("PhysicalId,CpuCores,Fpu,FpuException,Wp"),
|
||||
widget.NewLabel("Flags"),
|
||||
widget.NewLabel("Bugs"),
|
||||
widget.NewLabel("Bogomips,TlbSize,ClflushSize"),
|
||||
widget.NewLabel("CacheAlignment,AddressSize,PowerManagement"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
label0 := box.Objects[0].(*widget.Label)
|
||||
label1 := box.Objects[1].(*widget.Label)
|
||||
label2 := box.Objects[2].(*widget.Label)
|
||||
label3 := box.Objects[3].(*widget.Label)
|
||||
label4 := box.Objects[4].(*widget.Label)
|
||||
label5 := box.Objects[5].(*widget.Label)
|
||||
label6 := box.Objects[6].(*widget.Label)
|
||||
|
||||
label0.SetText(fmt.Sprintf("VendorId: %s, CpuFamily: %s, Model: %s, ModelName: %s", e.VendorId, e.CpuFamily, e.Model, e.ModelName))
|
||||
label1.SetText(fmt.Sprintf("Stepping: %s, Microcode: %s, CpuMhz: %s, CacheSize: %s", e.Stepping, e.Microcode, e.CpuMhz, e.CacheSize))
|
||||
label2.SetText(fmt.Sprintf("PhysicalId: %s, CpuCores: %s", e.PhysicalId, e.CpuCores))
|
||||
label3.SetText(fmt.Sprintf("Flags: %s", e.Flags))
|
||||
label4.SetText(fmt.Sprintf("Bugs: %s", e.Bugs))
|
||||
label5.SetText(fmt.Sprintf("Bogomips: %s, TlbSize: %s, ClflushSize: %s", e.Bogomips, e.TlbSize, e.ClflushSize))
|
||||
label6.SetText(fmt.Sprintf("CacheAlignment: %s, AddressSize: %s, PowerManagement: %s", e.CacheAlignment, e.AddressSize, e.PowerManagement))
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(textRaw string) {
|
||||
if textRaw == "" {
|
||||
filteredEntries = server.Cpus
|
||||
} else {
|
||||
filtered := []cpu{}
|
||||
text := strings.ToLower(textRaw)
|
||||
for _, elem := range server.Cpus {
|
||||
if strings.Contains(strings.ToLower(elem.Flags), text) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createInternetRequiredTab(server outputStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
filteredEntries := server.InternetRequired
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
|
||||
return container.NewVBox(
|
||||
// widget.NewCard("Title", "Subtitle", widget.NewLabel("content")),
|
||||
widget.NewLabel("name"),
|
||||
widget.NewLabel("ip_list"),
|
||||
widget.NewLabel("http+https"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
|
||||
label0 := box.Objects[0].(*widget.Label)
|
||||
label1 := box.Objects[1].(*widget.Label)
|
||||
label2 := box.Objects[2].(*widget.Label)
|
||||
|
||||
label0.SetText(e.Name)
|
||||
label0.TextStyle.Bold = true
|
||||
label1.SetText(e.IpList)
|
||||
label1.Selectable = true
|
||||
label2.SetText(fmt.Sprintf("HTTP: %s HTTPS: %s", e.Http, e.Https))
|
||||
label2.Selectable = true
|
||||
// card := box.Objects[0].(*widget.Card)
|
||||
// card.SetTitle(e.Name)
|
||||
// card.SetSubTitle(e.IpList)
|
||||
// card.SetContent(widget.NewLabel(fmt.Sprintf("HTTP: %s HTTPS: %s", e.Http, e.Https)))
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(textRaw string) {
|
||||
if textRaw == "" {
|
||||
filteredEntries = server.InternetRequired
|
||||
} else {
|
||||
filtered := []internetResource{}
|
||||
text := strings.ToLower(textRaw)
|
||||
for _, elem := range server.InternetRequired {
|
||||
if strings.Contains(strings.ToLower(elem.Name), text) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
|
||||
func createSecSetTab(server outputStruct) *widget.Label {
|
||||
if strings.Contains(server.OperatingSystem.OsRelease, "Alma") {
|
||||
return widget.NewLabel(fmt.Sprintf("Selinux :: %s", server.SecSetAlma.Selinux))
|
||||
} else if strings.Contains(server.OperatingSystem.OsRelease, "Ubuntu") {
|
||||
return widget.NewLabel(fmt.Sprintf("Apparmor :: %s", server.SecSetUbuntu.Apparmor))
|
||||
} else {
|
||||
return widget.NewLabel(fmt.Sprintf("Apparmor\t%s\nAstraAdmin\t%s\nDigsig\t%s\nИнтерпретаторы\t%s\nmac\t%s\nmic\t%s\nnochmodx\t%s\nparsec\t%s\nselinux\t%s\nsudo control\t%s\nsudoers astra admin\t%s\nsudoers sudo\t%s", server.SecSetALSE.Apparmor, server.SecSetALSE.AstraAdmin, server.SecSetALSE.Digsig, server.SecSetALSE.Interpret, server.SecSetALSE.Mac, server.SecSetALSE.Mic, server.SecSetALSE.Nochmodx, server.SecSetALSE.Parsec, server.SecSetALSE.Selinux, server.SecSetALSE.Sudo, server.SecSetALSE.SudoersAstraAdmin, server.SecSetALSE.SudoersSudo))
|
||||
}
|
||||
}
|
||||
|
||||
// Это делал DeepSeek оно криво, но работает. Оставлю это так, потому что всё равно планирую не использовать больше fyne
|
||||
func createJournalTab(server outputStruct) *fyne.Container {
|
||||
searchJrlEntry := widget.NewEntry()
|
||||
searchJrlEntry.SetPlaceHolder("Поиск событий ...")
|
||||
|
||||
filteredEvents := server.JournalctlEntries
|
||||
|
||||
// Создаем список
|
||||
journalctlEntriesList := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEvents)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
// Возвращаем кастомный виджет
|
||||
return NewJournalListItem(journalctlEntry{})
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
// Обновляем виджет
|
||||
widget := obj.(*JournalListItem)
|
||||
widget.Update(filteredEvents[id])
|
||||
},
|
||||
)
|
||||
|
||||
searchJrlEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEvents = server.JournalctlEntries
|
||||
} else {
|
||||
filtered := []journalctlEntry{}
|
||||
lowerText := strings.ToLower(text)
|
||||
for _, ev := range server.JournalctlEntries {
|
||||
if strings.Contains(strings.ToLower(ev.CommandLine), lowerText) ||
|
||||
strings.Contains(strings.ToLower(ev.CommandName), lowerText) ||
|
||||
strings.Contains(strings.ToLower(ev.SyslogIdentifier), lowerText) ||
|
||||
strings.Contains(strings.ToLower(ev.Message), lowerText) {
|
||||
filtered = append(filtered, ev)
|
||||
}
|
||||
}
|
||||
filteredEvents = filtered
|
||||
}
|
||||
journalctlEntriesList.Refresh()
|
||||
}
|
||||
|
||||
journalctlEntriesTab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchJrlEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(journalctlEntriesList),
|
||||
)
|
||||
return journalctlEntriesTab
|
||||
}
|
||||
|
||||
// func createJournalTab(server outputStruct) *fyne.Container {
|
||||
// searchJrlEntry := widget.NewEntry()
|
||||
// searchJrlEntry.SetPlaceHolder("Поиск событий ...")
|
||||
|
||||
// filteredEvents := server.JournalctlEntries
|
||||
|
||||
// journalctlEntriesList := widget.NewList(
|
||||
// func() int {
|
||||
// return len(filteredEvents)
|
||||
// },
|
||||
// func() fyne.CanvasObject {
|
||||
// label := widget.NewLabel("entry")
|
||||
// label.Wrapping = fyne.TextWrapBreak
|
||||
// // label.Resize(fyne.Size{Height: 50})
|
||||
// return container.NewVBox(
|
||||
// label,
|
||||
// // widget.NewSeparator(),
|
||||
// )
|
||||
// },
|
||||
// func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
// vbox := obj.(*fyne.Container)
|
||||
// event := filteredEvents[id]
|
||||
|
||||
// eventEntry := vbox.Objects[0].(*widget.Label)
|
||||
|
||||
// eventEntry.SetText(fmt.Sprintf("%s :: %s :: %s :: %s :: %s", event.Timestamp, event.CommandLine, event.CommandName, event.SyslogIdentifier, event.Message))
|
||||
// eventEntry.Selectable = true
|
||||
// eventEntry.Wrapping = fyne.TextWrapBreak
|
||||
// var doubleHeight fyne.Size
|
||||
// doubleHeight.Height = 72.0
|
||||
// if eventEntry.Size().Height >= 36.0 {
|
||||
// eventEntry.Resize(doubleHeight)
|
||||
// }
|
||||
|
||||
// // eventEntry.Truncation = fyne.TextTruncateClip
|
||||
// },
|
||||
// )
|
||||
|
||||
// searchJrlEntry.OnChanged = func(text string) {
|
||||
// if text == "" {
|
||||
// filteredEvents = server.JournalctlEntries
|
||||
// } else {
|
||||
// filtered := []journalctlEntry{}
|
||||
// lowerText := strings.ToLower(text)
|
||||
// for _, ev := range server.JournalctlEntries {
|
||||
// if strings.Contains(strings.ToLower(ev.CommandLine), lowerText) || strings.Contains(strings.ToLower(ev.CommandName), lowerText) || strings.Contains(strings.ToLower(ev.SyslogIdentifier), lowerText) || strings.Contains(strings.ToLower(ev.Message), lowerText) {
|
||||
// filtered = append(filtered, ev)
|
||||
// }
|
||||
// }
|
||||
// filteredEvents = filtered
|
||||
// }
|
||||
// journalctlEntriesList.Refresh()
|
||||
// }
|
||||
// journalctlEntriesTab := container.NewBorder(
|
||||
// container.NewVBox(
|
||||
// searchJrlEntry,
|
||||
// widget.NewSeparator(),
|
||||
// ), nil, nil, nil,
|
||||
// container.NewScroll(journalctlEntriesList),
|
||||
// )
|
||||
// return journalctlEntriesTab
|
||||
// }
|
||||
|
||||
func createRootHistoryTab(server outputStruct) *fyne.Container {
|
||||
searchEntry := widget.NewEntry()
|
||||
searchEntry.SetPlaceHolder("Поиск ...")
|
||||
|
||||
filteredEntries := server.RootHistory
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(filteredEntries)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewVBox(
|
||||
widget.NewLabel("template"),
|
||||
)
|
||||
},
|
||||
func(id widget.ListItemID, obj fyne.CanvasObject) {
|
||||
box := obj.(*fyne.Container)
|
||||
e := filteredEntries[id]
|
||||
fileName := box.Objects[0].(*widget.Label)
|
||||
timeExec := ""
|
||||
if len(e.ExecutionTime) != 0 {
|
||||
timeInt64, err := strconv.ParseInt(e.ExecutionTime, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
timeExec = e.ExecutionTime
|
||||
} else {
|
||||
timeExec = time.Unix(timeInt64, 0).String()
|
||||
}
|
||||
}
|
||||
fileName.SetText(fmt.Sprintf("%d %s %s", e.Id, timeExec, e.Command))
|
||||
fileName.Selectable = true
|
||||
|
||||
},
|
||||
)
|
||||
searchEntry.OnChanged = func(text string) {
|
||||
if text == "" {
|
||||
filteredEntries = server.RootHistory
|
||||
} else {
|
||||
var filtered []rootHistoryCommand
|
||||
lText := strings.ToLower(text)
|
||||
for _, elem := range server.RootHistory {
|
||||
if strings.Contains(strings.ToLower(elem.Command), lText) {
|
||||
filtered = append(filtered, elem)
|
||||
}
|
||||
}
|
||||
filteredEntries = filtered
|
||||
}
|
||||
list.Refresh()
|
||||
}
|
||||
tab := container.NewBorder(
|
||||
container.NewVBox(
|
||||
searchEntry,
|
||||
widget.NewSeparator(),
|
||||
), nil, nil, nil,
|
||||
container.NewScroll(list),
|
||||
)
|
||||
return tab
|
||||
}
|
||||
1
DCIManager6/dci6-support-reader/todo.md
Normal file
1
DCIManager6/dci6-support-reader/todo.md
Normal file
@@ -0,0 +1 @@
|
||||
# 2602-3
|
||||
Reference in New Issue
Block a user