textbox component
This commit is contained in:
parent
4206a8cbf7
commit
b542e0bd0c
|
@ -0,0 +1,62 @@
|
||||||
|
package textbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
ui "github.com/gizak/termui/v3"
|
||||||
|
"github.com/sqshq/sampler/component"
|
||||||
|
"github.com/sqshq/sampler/config"
|
||||||
|
"github.com/sqshq/sampler/console"
|
||||||
|
"github.com/sqshq/sampler/data"
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TextBox struct {
|
||||||
|
*ui.Block
|
||||||
|
*data.Consumer
|
||||||
|
alert *data.Alert
|
||||||
|
text string
|
||||||
|
border bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTextBox(c config.TextBoxConfig, palette console.Palette) *TextBox {
|
||||||
|
|
||||||
|
box := TextBox{
|
||||||
|
Block: component.NewBlock(c.Title, *c.Border, palette),
|
||||||
|
Consumer: data.NewConsumer(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case sample := <-box.SampleChannel:
|
||||||
|
box.text = sample.Value
|
||||||
|
case alert := <-box.AlertChannel:
|
||||||
|
box.alert = alert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &box
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TextBox) Draw(buffer *ui.Buffer) {
|
||||||
|
|
||||||
|
t.Block.Draw(buffer)
|
||||||
|
|
||||||
|
cells := ui.ParseStyles(t.text, ui.Theme.Paragraph.Text)
|
||||||
|
cells = ui.WrapCells(cells, uint(t.Inner.Dx()))
|
||||||
|
|
||||||
|
rows := ui.SplitCells(cells, '\n')
|
||||||
|
|
||||||
|
for y, row := range rows {
|
||||||
|
if y+t.Inner.Min.Y >= t.Inner.Max.Y {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
row = ui.TrimCells(row, t.Inner.Dx())
|
||||||
|
for _, cx := range ui.BuildCellWithXArray(row) {
|
||||||
|
x, cell := cx.X, cx.Cell
|
||||||
|
buffer.SetCell(cell, image.Pt(x, y+1).Add(t.Inner.Min))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component.RenderAlert(t.alert, t.Rectangle, buffer)
|
||||||
|
}
|
48
config.yml
48
config.yml
|
@ -27,30 +27,30 @@ runcharts:
|
||||||
scale: 0
|
scale: 0
|
||||||
items:
|
items:
|
||||||
- label: ACTIVE
|
- label: ACTIVE
|
||||||
init: ${mongoconnection}
|
init: $mongoconnection
|
||||||
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
|
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
|
||||||
- label: INACTIVE
|
- label: INACTIVE
|
||||||
init: ${mongoconnection}
|
init: $mongoconnection
|
||||||
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
|
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
|
||||||
barcharts:
|
barcharts:
|
||||||
- title: EVENTS BY STATUS
|
- title: EVENTS BY STATUS
|
||||||
position: [[0, 17], [27, 12]]
|
position: [[0, 17], [28, 12]]
|
||||||
rate-ms: 300
|
rate-ms: 300
|
||||||
scale: 0
|
scale: 0
|
||||||
items:
|
items:
|
||||||
- label: NEW
|
- label: NEW
|
||||||
init: ${mongoconnection}
|
init: $mongoconnection
|
||||||
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
|
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
|
||||||
- label: TRIGGERED
|
- label: TRIGGERED
|
||||||
init: ${mongoconnection}
|
init: $mongoconnection
|
||||||
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
|
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
|
||||||
- label: IN_PROCESS
|
- label: IN_PROCESS
|
||||||
sample: echo 0
|
sample: echo 0
|
||||||
- label: FAILED
|
- label: FAILED
|
||||||
init: ${mongoconnection}
|
init: $mongoconnection
|
||||||
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
|
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
|
||||||
- label: FINISHED
|
- label: FINISHED
|
||||||
init: ${mongoconnection}
|
init: $mongoconnection
|
||||||
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
|
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
|
||||||
gauges:
|
gauges:
|
||||||
- title: YEAR PROGRESS
|
- title: YEAR PROGRESS
|
||||||
|
@ -91,6 +91,31 @@ gauges:
|
||||||
sample: echo 60
|
sample: echo 60
|
||||||
min:
|
min:
|
||||||
sample: echo 0
|
sample: echo 0
|
||||||
|
sparklines:
|
||||||
|
- title: CPU usage
|
||||||
|
position: [[28, 22], [24, 7]]
|
||||||
|
scale: 0
|
||||||
|
sample: ps -A -o %cpu | awk '{s+=$1} END {print s}'
|
||||||
|
- title: Memory pages free
|
||||||
|
position: [[28, 17], [24, 5]]
|
||||||
|
scale: 0
|
||||||
|
sample: memory_pressure | grep 'Pages free' | awk '{print $3}'
|
||||||
|
textboxes:
|
||||||
|
- title: Local weather
|
||||||
|
position: [[0, 30], [13, 7]]
|
||||||
|
rate-ms: 10000
|
||||||
|
sample: curl wttr.in?0ATQF
|
||||||
|
border: false
|
||||||
|
- title: New York weather
|
||||||
|
position: [[8, 30], [13, 7]]
|
||||||
|
rate-ms: 10000
|
||||||
|
sample: curl wttr.in/newyork?0ATQF
|
||||||
|
border: false
|
||||||
|
- title: San Francisco weather
|
||||||
|
position: [[17, 30], [13, 7]]
|
||||||
|
rate-ms: 10000
|
||||||
|
sample: curl wttr.in/sanfrancisco?0ATQF
|
||||||
|
border: false
|
||||||
asciiboxes:
|
asciiboxes:
|
||||||
- title: LOCAL TIME
|
- title: LOCAL TIME
|
||||||
position: [[53, 17], [27, 5]]
|
position: [[53, 17], [27, 5]]
|
||||||
|
@ -99,12 +124,3 @@ asciiboxes:
|
||||||
position: [[53, 22], [27, 7]]
|
position: [[53, 22], [27, 7]]
|
||||||
sample: env TZ=UTC date +%r
|
sample: env TZ=UTC date +%r
|
||||||
font: 3d
|
font: 3d
|
||||||
sparklines:
|
|
||||||
- title: CPU usage
|
|
||||||
position: [[27, 22], [25, 7]]
|
|
||||||
scale: 0
|
|
||||||
sample: ps -A -o %cpu | awk '{s+=$1} END {print s}'
|
|
||||||
- title: Memory pages free
|
|
||||||
position: [[27, 17], [25, 5]]
|
|
||||||
scale: 0
|
|
||||||
sample: memory_pressure | grep 'Pages free' | awk '{print $3}'
|
|
||||||
|
|
|
@ -70,9 +70,16 @@ type BarChartConfig struct {
|
||||||
type AsciiBoxConfig struct {
|
type AsciiBoxConfig struct {
|
||||||
ComponentConfig `yaml:",inline"`
|
ComponentConfig `yaml:",inline"`
|
||||||
Item `yaml:",inline"`
|
Item `yaml:",inline"`
|
||||||
|
Border *bool `yaml:"border,omitempty"`
|
||||||
Font *console.AsciiFont `yaml:"font,omitempty"`
|
Font *console.AsciiFont `yaml:"font,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TextBoxConfig struct {
|
||||||
|
ComponentConfig `yaml:",inline"`
|
||||||
|
Item `yaml:",inline"`
|
||||||
|
Border *bool `yaml:"border,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type RunChartConfig struct {
|
type RunChartConfig struct {
|
||||||
ComponentConfig `yaml:",inline"`
|
ComponentConfig `yaml:",inline"`
|
||||||
Legend *LegendConfig `yaml:"legend,omitempty"`
|
Legend *LegendConfig `yaml:"legend,omitempty"`
|
||||||
|
|
|
@ -16,8 +16,9 @@ type Config struct {
|
||||||
RunCharts []RunChartConfig `yaml:"runcharts,omitempty"`
|
RunCharts []RunChartConfig `yaml:"runcharts,omitempty"`
|
||||||
BarCharts []BarChartConfig `yaml:"barcharts,omitempty"`
|
BarCharts []BarChartConfig `yaml:"barcharts,omitempty"`
|
||||||
Gauges []GaugeConfig `yaml:"gauges,omitempty"`
|
Gauges []GaugeConfig `yaml:"gauges,omitempty"`
|
||||||
AsciiBoxes []AsciiBoxConfig `yaml:"asciiboxes,omitempty"`
|
|
||||||
SparkLines []SparkLineConfig `yaml:"sparklines,omitempty"`
|
SparkLines []SparkLineConfig `yaml:"sparklines,omitempty"`
|
||||||
|
TextBoxes []TextBoxConfig `yaml:"textboxes,omitempty"`
|
||||||
|
AsciiBoxes []AsciiBoxConfig `yaml:"asciiboxes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load() (Config, Options) {
|
func Load() (Config, Options) {
|
||||||
|
@ -66,16 +67,22 @@ func (c *Config) findComponent(componentType ComponentType, componentTitle strin
|
||||||
return &c.Gauges[i].ComponentConfig
|
return &c.Gauges[i].ComponentConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case TypeSparkLine:
|
||||||
|
for i, component := range c.SparkLines {
|
||||||
|
if component.Title == componentTitle {
|
||||||
|
return &c.SparkLines[i].ComponentConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
case TypeAsciiBox:
|
case TypeAsciiBox:
|
||||||
for i, component := range c.AsciiBoxes {
|
for i, component := range c.AsciiBoxes {
|
||||||
if component.Title == componentTitle {
|
if component.Title == componentTitle {
|
||||||
return &c.AsciiBoxes[i].ComponentConfig
|
return &c.AsciiBoxes[i].ComponentConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case TypeSparkLine:
|
case TypeTextBox:
|
||||||
for i, component := range c.SparkLines {
|
for i, component := range c.TextBoxes {
|
||||||
if component.Title == componentTitle {
|
if component.Title == componentTitle {
|
||||||
return &c.SparkLines[i].ComponentConfig
|
return &c.TextBoxes[i].ComponentConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,27 @@ func (c *Config) setDefaultValues() {
|
||||||
}
|
}
|
||||||
c.AsciiBoxes[i] = box
|
c.AsciiBoxes[i] = box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, box := range c.TextBoxes {
|
||||||
|
|
||||||
|
setDefaultTriggersValues(box.Triggers)
|
||||||
|
box.ComponentConfig.Type = TypeTextBox
|
||||||
|
|
||||||
|
if box.RateMs == nil {
|
||||||
|
r := defaultRateMs
|
||||||
|
box.RateMs = &r
|
||||||
|
}
|
||||||
|
if box.Label == nil {
|
||||||
|
label := string(i)
|
||||||
|
box.Label = &label
|
||||||
|
}
|
||||||
|
if box.Border == nil {
|
||||||
|
border := true
|
||||||
|
box.Border = &border
|
||||||
|
}
|
||||||
|
|
||||||
|
c.TextBoxes[i] = box
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setDefaultTriggersValues(triggers []TriggerConfig) {
|
func setDefaultTriggersValues(triggers []TriggerConfig) {
|
||||||
|
|
16
main.go
16
main.go
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/sqshq/sampler/component/layout"
|
"github.com/sqshq/sampler/component/layout"
|
||||||
"github.com/sqshq/sampler/component/runchart"
|
"github.com/sqshq/sampler/component/runchart"
|
||||||
"github.com/sqshq/sampler/component/sparkline"
|
"github.com/sqshq/sampler/component/sparkline"
|
||||||
|
"github.com/sqshq/sampler/component/textbox"
|
||||||
"github.com/sqshq/sampler/config"
|
"github.com/sqshq/sampler/config"
|
||||||
"github.com/sqshq/sampler/console"
|
"github.com/sqshq/sampler/console"
|
||||||
"github.com/sqshq/sampler/data"
|
"github.com/sqshq/sampler/data"
|
||||||
|
@ -58,11 +59,6 @@ func main() {
|
||||||
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)
|
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cfg.AsciiBoxes {
|
|
||||||
cpt := asciibox.NewAsciiBox(c, palette)
|
|
||||||
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range cfg.BarCharts {
|
for _, c := range cfg.BarCharts {
|
||||||
cpt := barchart.NewBarChart(c, palette)
|
cpt := barchart.NewBarChart(c, palette)
|
||||||
starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers)
|
starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers)
|
||||||
|
@ -73,6 +69,16 @@ func main() {
|
||||||
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Cur, c.Min, c.Max}, c.Triggers)
|
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Cur, c.Min, c.Max}, c.Triggers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, c := range cfg.AsciiBoxes {
|
||||||
|
cpt := asciibox.NewAsciiBox(c, palette)
|
||||||
|
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cfg.TextBoxes {
|
||||||
|
cpt := textbox.NewTextBox(c, palette)
|
||||||
|
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)
|
||||||
|
}
|
||||||
|
|
||||||
handler := event.NewHandler(lout, opt)
|
handler := event.NewHandler(lout, opt)
|
||||||
handler.HandleEvents()
|
handler.HandleEvents()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue