mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
37
modules/bamboohr/calendar.go
Normal file
37
modules/bamboohr/calendar.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package bamboohr
|
||||
|
||||
type Calendar struct {
|
||||
Items []Item `xml:"item"`
|
||||
}
|
||||
|
||||
/* -------------------- Public Functions -------------------- */
|
||||
|
||||
func (calendar *Calendar) Holidays() []Item {
|
||||
return calendar.filteredItems("holiday")
|
||||
}
|
||||
|
||||
func (calendar *Calendar) ItemsByType(itemType string) []Item {
|
||||
if itemType == "timeOff" {
|
||||
return calendar.TimeOffs()
|
||||
}
|
||||
|
||||
return calendar.Holidays()
|
||||
}
|
||||
|
||||
func (calendar *Calendar) TimeOffs() []Item {
|
||||
return calendar.filteredItems("timeOff")
|
||||
}
|
||||
|
||||
/* -------------------- Private Functions -------------------- */
|
||||
|
||||
func (calendar *Calendar) filteredItems(itemType string) []Item {
|
||||
items := []Item{}
|
||||
|
||||
for _, item := range calendar.Items {
|
||||
if item.Type == itemType {
|
||||
items = append(items, item)
|
||||
}
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
61
modules/bamboohr/client.go
Normal file
61
modules/bamboohr/client.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package bamboohr
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A Client represents the data required to connect to the BambooHR API
|
||||
type Client struct {
|
||||
apiBase string
|
||||
apiKey string
|
||||
subdomain string
|
||||
}
|
||||
|
||||
// NewClient creates and returns a new BambooHR client
|
||||
func NewClient(url string, apiKey string, subdomain string) *Client {
|
||||
client := Client{
|
||||
apiBase: url,
|
||||
apiKey: apiKey,
|
||||
subdomain: subdomain,
|
||||
}
|
||||
|
||||
return &client
|
||||
}
|
||||
|
||||
/* -------------------- Public Functions -------------------- */
|
||||
|
||||
// Away returns a string representation of the people who are out of the office during the defined period
|
||||
func (client *Client) Away(itemType, startDate, endDate string) []Item {
|
||||
calendar, err := client.away(startDate, endDate)
|
||||
if err != nil {
|
||||
return []Item{}
|
||||
}
|
||||
|
||||
items := calendar.ItemsByType(itemType)
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
/* -------------------- Private Functions -------------------- */
|
||||
|
||||
// away is the private interface for retrieving structural data about who will be out of the office
|
||||
// This method does the actual communication with BambooHR and returns the raw Go
|
||||
// data structures used by the public interface
|
||||
func (client *Client) away(startDate, endDate string) (cal Calendar, err error) {
|
||||
apiURL := fmt.Sprintf(
|
||||
"%s/%s/v1/time_off/whos_out?start=%s&end=%s",
|
||||
client.apiBase,
|
||||
client.subdomain,
|
||||
startDate,
|
||||
endDate,
|
||||
)
|
||||
|
||||
data, err := Request(client.apiKey, apiURL)
|
||||
if err != nil {
|
||||
return cal, err
|
||||
}
|
||||
err = xml.Unmarshal(data, &cal)
|
||||
|
||||
return
|
||||
}
|
||||
10
modules/bamboohr/employee.go
Normal file
10
modules/bamboohr/employee.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package bamboohr
|
||||
|
||||
/*
|
||||
* Note: this currently implements the minimum number of fields to fulfill the Away functionality.
|
||||
* Undoubtedly there are more fields than this to an employee
|
||||
*/
|
||||
type Employee struct {
|
||||
ID int `xml:"id,attr"`
|
||||
Name string `xml:",chardata"`
|
||||
}
|
||||
42
modules/bamboohr/item.go
Normal file
42
modules/bamboohr/item.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package bamboohr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
//"time"
|
||||
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
Employee Employee `xml:"employee"`
|
||||
End string `xml:"end"`
|
||||
Holiday string `xml:"holiday"`
|
||||
Start string `xml:"start"`
|
||||
Type string `xml:"type,attr"`
|
||||
}
|
||||
|
||||
func (item *Item) String() string {
|
||||
return fmt.Sprintf("Item: %s, %s, %s, %s", item.Type, item.Employee.Name, item.Start, item.End)
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func (item *Item) IsOneDay() bool {
|
||||
return item.Start == item.End
|
||||
}
|
||||
|
||||
func (item *Item) Name() string {
|
||||
if (item.Employee != Employee{}) {
|
||||
return item.Employee.Name
|
||||
}
|
||||
|
||||
return item.Holiday
|
||||
}
|
||||
|
||||
func (item *Item) PrettyStart() string {
|
||||
return wtf.PrettyDate(item.Start)
|
||||
}
|
||||
|
||||
func (item *Item) PrettyEnd() string {
|
||||
return wtf.PrettyDate(item.End)
|
||||
}
|
||||
39
modules/bamboohr/request.go
Normal file
39
modules/bamboohr/request.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package bamboohr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Request(apiKey string, apiURL string) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", apiURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.SetBasicAuth(apiKey, "x")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ParseBody(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, err
|
||||
}
|
||||
|
||||
func ParseBody(resp *http.Response) ([]byte, error) {
|
||||
var buffer bytes.Buffer
|
||||
_, err := buffer.ReadFrom(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
73
modules/bamboohr/widget.go
Normal file
73
modules/bamboohr/widget.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package bamboohr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
}
|
||||
|
||||
func NewWidget(app *tview.Application) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, "BambooHR", "bamboohr", false),
|
||||
}
|
||||
|
||||
return &widget
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
apiKey := wtf.Config.UString(
|
||||
"wtf.mods.bamboohr.apiKey",
|
||||
os.Getenv("WTF_BAMBOO_HR_TOKEN"),
|
||||
)
|
||||
|
||||
subdomain := wtf.Config.UString(
|
||||
"wtf.mods.bamboohr.subdomain",
|
||||
os.Getenv("WTF_BAMBOO_HR_SUBDOMAIN"),
|
||||
)
|
||||
|
||||
client := NewClient("https://api.bamboohr.com/api/gateway.php", apiKey, subdomain)
|
||||
todayItems := client.Away(
|
||||
"timeOff",
|
||||
wtf.Now().Format(wtf.DateFormat),
|
||||
wtf.Now().Format(wtf.DateFormat),
|
||||
)
|
||||
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.Name))
|
||||
|
||||
widget.View.SetText(widget.contentFrom(todayItems))
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) contentFrom(items []Item) string {
|
||||
if len(items) == 0 {
|
||||
return fmt.Sprintf("\n\n\n\n\n\n\n\n%s", wtf.CenterText("[grey]no one[white]", 50))
|
||||
}
|
||||
|
||||
str := ""
|
||||
for _, item := range items {
|
||||
str = str + widget.format(item)
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) format(item Item) string {
|
||||
var str string
|
||||
|
||||
if item.IsOneDay() {
|
||||
str = fmt.Sprintf(" [green]%s[white]\n %s\n\n", item.Name(), item.PrettyEnd())
|
||||
} else {
|
||||
str = fmt.Sprintf(" [green]%s[white]\n %s - %s\n\n", item.Name(), item.PrettyStart(), item.PrettyEnd())
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
Reference in New Issue
Block a user