adds kaneo board
This commit is contained in:
@@ -0,0 +1,102 @@
|
|||||||
|
package kaneo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ArinDash/config"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const apiBaseURL = "https://board.arindy.de/api"
|
||||||
|
|
||||||
|
type configFile struct {
|
||||||
|
Board boardConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type boardConfig struct {
|
||||||
|
ApiKey string
|
||||||
|
ProjectId string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoardData struct {
|
||||||
|
Data Board `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Column struct {
|
||||||
|
Position int `json:"position"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Tasks []Task `json:"tasks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Task struct {
|
||||||
|
Position int `json:"position"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Priority string `json:"priority"`
|
||||||
|
DueDate time.Time `json:"dueDate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Board struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Columns []Column `json:"columns"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchBoard() Board {
|
||||||
|
cfg := &configFile{}
|
||||||
|
config.LoadConfig(cfg)
|
||||||
|
client := &http.Client{}
|
||||||
|
if cfg.Board.ApiKey == "" {
|
||||||
|
return Board{
|
||||||
|
Status: "No API key provided",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cfg.Board.ProjectId == "" {
|
||||||
|
return Board{
|
||||||
|
Status: "No ProjectId provided",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", apiBaseURL+"/task/tasks/"+cfg.Board.ProjectId, nil)
|
||||||
|
if err != nil {
|
||||||
|
return Board{
|
||||||
|
Status: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", "Bearer "+cfg.Board.ApiKey)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return Board{
|
||||||
|
Status: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return Board{
|
||||||
|
Status: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boardData := BoardData{}
|
||||||
|
board := Board{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(respBody, &boardData)
|
||||||
|
if err != nil {
|
||||||
|
board = Board{
|
||||||
|
Status: err.Error(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
board = boardData.Data
|
||||||
|
board.Status = "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
return board
|
||||||
|
}
|
||||||
@@ -23,6 +23,10 @@ gebietsCode = "000000000000"
|
|||||||
ApiKey = "ApiKey"
|
ApiKey = "ApiKey"
|
||||||
Sources = "comma,sepparated,sources,from,newsapi"
|
Sources = "comma,sepparated,sources,from,newsapi"
|
||||||
|
|
||||||
|
[board]
|
||||||
|
ApiKey = "ApiKey"
|
||||||
|
ProjectId = "ProjectId"
|
||||||
|
|
||||||
[[calendar.ics]]
|
[[calendar.ics]]
|
||||||
Icon = ""
|
Icon = ""
|
||||||
Url = "https://url.to.ics"
|
Url = "https://url.to.ics"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func initWidgets(ctx context.Context, term *tcell.Terminal) {
|
|||||||
widgets.New("Weather", widgets.Weather()),
|
widgets.New("Weather", widgets.Weather()),
|
||||||
widgets.New("ChangeTitle", widgets.TextInput(titleUpdate, textinput.Label("Update Title: "), textinput.PlaceHolder("New Title"))),
|
widgets.New("ChangeTitle", widgets.TextInput(titleUpdate, textinput.Label("Update Title: "), textinput.PlaceHolder("New Title"))),
|
||||||
widgets.New("Wifi", widgets.WifiQRCode()),
|
widgets.New("Wifi", widgets.WifiQRCode()),
|
||||||
widgets.New("NetworkDevices", widgets.NetworkDevices()),
|
/*widgets.New("NetworkDevices", widgets.NetworkDevices()),*/
|
||||||
widgets.New("Docker", widgets.DockerList()),
|
widgets.New("Docker", widgets.DockerList()),
|
||||||
widgets.New("HTTPProber", widgets.HTTPProber()),
|
widgets.New("HTTPProber", widgets.HTTPProber()),
|
||||||
widgets.New("PiHole", widgets.PiholeStats()),
|
widgets.New("PiHole", widgets.PiholeStats()),
|
||||||
@@ -48,6 +48,7 @@ func initWidgets(ctx context.Context, term *tcell.Terminal) {
|
|||||||
widgets.New("NinaWarnings", widgets.NinaWarnings()),
|
widgets.New("NinaWarnings", widgets.NinaWarnings()),
|
||||||
widgets.New("News", widgets.News()),
|
widgets.New("News", widgets.News()),
|
||||||
widgets.New("Zukitchi", widgets.Zukitchi()),
|
widgets.New("Zukitchi", widgets.Zukitchi()),
|
||||||
|
widgets.New("Board", widgets.Board()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +215,7 @@ func layout() []container.Option {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
grid.RowHeightFixed(85,
|
grid.RowHeightFixed(85,
|
||||||
grid.Widget(widgets.Get["empty"],
|
grid.Widget(widgets.Get["Board"],
|
||||||
container.Border(linestyle.Light),
|
container.Border(linestyle.Light),
|
||||||
container.BorderColor(cell.ColorWhite),
|
container.BorderColor(cell.ColorWhite),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
package widgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ArinDash/apis/kaneo"
|
||||||
|
"ArinDash/util"
|
||||||
|
"context"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mum4k/termdash/cell"
|
||||||
|
"github.com/mum4k/termdash/terminal/terminalapi"
|
||||||
|
"github.com/mum4k/termdash/widgetapi"
|
||||||
|
"github.com/mum4k/termdash/widgets/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BoardOptions struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func Board() BoardOptions {
|
||||||
|
widgetOptions["BoardOptions"] = createBoard
|
||||||
|
return BoardOptions{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBoard(ctx context.Context, _ terminalapi.Terminal, _ interface{}) widgetapi.Widget {
|
||||||
|
widget := util.PanicOnErrorWithResult(NewBoardText())
|
||||||
|
go util.Periodic(ctx, 1*time.Minute, func() error {
|
||||||
|
widget.Reset()
|
||||||
|
widget.board = kaneo.FetchBoard()
|
||||||
|
if widget.board.Status != "ok" {
|
||||||
|
if err := widget.Write("Error:"+widget.board.Status, text.WriteCellOpts(cell.FgColor(cell.ColorRed))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(widget.board.Columns, func(i, j int) bool {
|
||||||
|
return widget.board.Columns[i].Position < widget.board.Columns[j].Position
|
||||||
|
})
|
||||||
|
|
||||||
|
colWidth := 70 / len(widget.board.Columns)
|
||||||
|
|
||||||
|
if err := widget.Write("┌"+strings.Repeat(strings.Repeat("─", colWidth)+"┬", len(widget.board.Columns)-1)+strings.Repeat("─", colWidth)+"┐\n", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := widget.Write("│", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for i, column := range widget.board.Columns {
|
||||||
|
if i != 0 {
|
||||||
|
if err := widget.Write("│", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name := column.Name
|
||||||
|
if len(name) > colWidth {
|
||||||
|
name = name[0:colWidth-2] + ".."
|
||||||
|
}
|
||||||
|
if len(name) < colWidth {
|
||||||
|
name = name + strings.Repeat(" ", colWidth-len(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := widget.Write(name, text.WriteCellOpts(cell.FgColor(cell.ColorGreen))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := widget.Write("│\n", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writeMiddle(widget, colWidth, widget.board.Columns); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range 4 {
|
||||||
|
if i != 0 {
|
||||||
|
if err := writeMiddle(widget, colWidth, widget.board.Columns); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := widget.Write("│", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for j, column := range widget.board.Columns {
|
||||||
|
sort.Slice(column.Tasks, func(i, j int) bool {
|
||||||
|
return column.Tasks[i].Position < column.Tasks[j].Position
|
||||||
|
})
|
||||||
|
|
||||||
|
if j != 0 {
|
||||||
|
if err := widget.Write("│", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(column.Tasks) > i {
|
||||||
|
title := column.Tasks[i].Title
|
||||||
|
if len(title) > colWidth {
|
||||||
|
title = title[0:colWidth-2] + ".."
|
||||||
|
}
|
||||||
|
if len(title) < colWidth {
|
||||||
|
title = title + strings.Repeat(" ", colWidth-len(title))
|
||||||
|
}
|
||||||
|
if err := widget.Write(title, text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := widget.Write(strings.Repeat(" ", colWidth), text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := widget.Write("│\n", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writeBottom(widget, colWidth, widget.board.Columns); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return widget
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeMiddle(widget *BoardText, colWidth int, columns []kaneo.Column) error {
|
||||||
|
if err := widget.Write("├"+strings.Repeat(strings.Repeat("─", colWidth)+"┼", len(columns)-1)+strings.Repeat("─", colWidth)+"┤\n", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeBottom(widget *BoardText, colWidth int, columns []kaneo.Column) error {
|
||||||
|
if err := widget.Write("└"+strings.Repeat(strings.Repeat("─", colWidth)+"┴", len(columns)-1)+strings.Repeat("─", colWidth)+"┘\n", text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoardText struct {
|
||||||
|
*text.Text
|
||||||
|
Selected int
|
||||||
|
board kaneo.Board
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBoardText(opts ...text.Option) (*BoardText, error) {
|
||||||
|
t, err := text.New(opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &BoardText{Text: t}, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user