working de/edit/complete funcs
This commit is contained in:
parent
6a4650cfd2
commit
43843c705d
104
caldav.go
104
caldav.go
@ -6,6 +6,7 @@ import (
|
|||||||
webdav "github.com/emersion/go-webdav"
|
webdav "github.com/emersion/go-webdav"
|
||||||
"github.com/emersion/go-webdav/caldav"
|
"github.com/emersion/go-webdav/caldav"
|
||||||
"github.com/emersion/go-ical"
|
"github.com/emersion/go-ical"
|
||||||
|
"github.com/teambition/rrule-go"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -496,10 +497,10 @@ func (m model) UploadTodo(event ical.Event) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m model) DelTodo(delUID string) (err error) {
|
// func (m model) DelTodo(delUID string) (err error) {
|
||||||
// func (m model) DelTodo(todo ical.Event) (err error) {
|
func (m model) DelTodo(todo ical.Event) (err error) {
|
||||||
|
|
||||||
// delUID,err := todo.Props.Get(ical.PropUID).Text()
|
delUID,err := todo.Props.Get(ical.PropUID).Text()
|
||||||
// if err != nil {return}
|
// if err != nil {return}
|
||||||
|
|
||||||
// calendar, err := client.GetCalendarObject(ctx, m.Creds.CalendarPath+delUID+".isc")
|
// calendar, err := client.GetCalendarObject(ctx, m.Creds.CalendarPath+delUID+".isc")
|
||||||
@ -531,24 +532,20 @@ func (m model) DelTodo(delUID string) (err error) {
|
|||||||
// URL: url.Parse(m.Creds.URL + m.Creds.CalendarPath + delUID + ".isc"),
|
// URL: url.Parse(m.Creds.URL + m.Creds.CalendarPath + delUID + ".isc"),
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
parts := strings.Split(m.Creds.URL, "/")
|
parts := strings.Split(m.Creds.URL, "/")
|
||||||
baseURL := parts[0]+"//"+parts[2]
|
baseURL := parts[0]+"//"+parts[2]
|
||||||
// Create request
|
// Create request
|
||||||
req, err := http.NewRequest("DELETE", baseURL + m.Creds.CalendarPath + delUID + ".isc", nil)
|
req, err := http.NewRequest("DELETE", baseURL + m.Creds.CalendarPath + delUID + ".isc", nil)
|
||||||
if err != nil {
|
if err != nil {return}
|
||||||
// fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.SetBasicAuth(m.Creds.Username, m.Creds.Password)
|
req.SetBasicAuth(m.Creds.Username, m.Creds.Password)
|
||||||
|
|
||||||
// Fetch Request
|
// Fetch Request
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {return}
|
||||||
// fmt.Println(err)
|
// resp.Body.Close()
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Read Response Body
|
// Read Response Body
|
||||||
@ -558,22 +555,66 @@ func (m model) DelTodo(delUID string) (err error) {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if resp.Status != "204 No Content" {return errors.New("Can't delete, response status: "+resp.Status+".")}
|
if resp.Status == "204 No Content" {return nil}
|
||||||
|
if resp.Status == "404 Not Found" {
|
||||||
|
// Nextcloud Tasks create differend GUID for Vtodo and path
|
||||||
|
// TODO code fmt - Highway to for-if hell
|
||||||
|
|
||||||
|
for _, calObj := range m.CalObjects {
|
||||||
|
for _, eventComponent:= range (*calObj.Data).Children {
|
||||||
|
event := ical.Event{Component: eventComponent}
|
||||||
|
if event.Name == "VTODO" {
|
||||||
|
// eventUID,_ := (*event).Props["UID"][0].Text()
|
||||||
|
|
||||||
|
eventUID,err := event.Props.Get(ical.PropUID).Text()
|
||||||
|
|
||||||
|
if err != nil {eventUID = ""}
|
||||||
|
if (eventUID == delUID) {
|
||||||
|
//verify that it's indeed that event by comparing Name
|
||||||
|
sum1,err:=todo.Props.Get("SUMMARY").Text()
|
||||||
|
if err != nil {return err}
|
||||||
|
sum2,err:=event.Props.Get("SUMMARY").Text()
|
||||||
|
if err != nil {return err}
|
||||||
|
if sum1==sum2 {
|
||||||
|
req2, err := http.NewRequest("DELETE", baseURL + calObj.Path, nil)
|
||||||
|
if err != nil {return err}
|
||||||
|
req2.SetBasicAuth(m.Creds.Username, m.Creds.Password)
|
||||||
|
|
||||||
|
// Fetch Request
|
||||||
|
resp2, err := client.Do(req2)
|
||||||
|
if err != nil {return err}
|
||||||
|
|
||||||
|
defer resp2.Body.Close()
|
||||||
|
if resp2.Status == "204 No Content" {return nil} else {return errors.New("Can't delete, response status: "+resp2.Status+".")}
|
||||||
|
|
||||||
|
//TODO exit for loop
|
||||||
|
// return errors.New("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// return errors.New("test")
|
||||||
|
}
|
||||||
|
time.Sleep(2*time.Second) //TODO DEBUG RM ME
|
||||||
// Display Results
|
// Display Results
|
||||||
// fmt.Println("response Status : ", resp.Status)
|
// fmt.Println("response Status : ", resp.Status)
|
||||||
// fmt.Println("response Headers : ", resp.Header)
|
// fmt.Println("response Headers : ", resp.Header)
|
||||||
// fmt.Println("response Body : ", string(respBody))
|
// fmt.Println("response Body : ", string(respBody))
|
||||||
|
|
||||||
return nil
|
// return nil
|
||||||
|
return errors.New("Can't delete, response status: "+resp.Status+".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m model) EditTodo(todo ical.Event) (err error) {
|
func (m model) EditTodo(todo ical.Event) (err error) {
|
||||||
//TODO is there proper edit function ???
|
//TODO is there proper edit function ???
|
||||||
uid,err := todo.Props.Get(ical.PropUID).Text()
|
// uid,err := todo.Props.Get(ical.PropUID).Text()
|
||||||
if err != nil {return}
|
// if err != nil {return}
|
||||||
|
|
||||||
err = m.DelTodo(uid)
|
err = m.DelTodo(todo)
|
||||||
if err != nil {return}
|
if err != nil {return}
|
||||||
|
|
||||||
err = m.UploadTodo(todo)
|
err = m.UploadTodo(todo)
|
||||||
@ -590,6 +631,37 @@ func (m model) CompleteTodo(todo ical.Event) (err error) {
|
|||||||
|
|
||||||
//TODO if it repitable - Repeate, otherwise complete it
|
//TODO if it repitable - Repeate, otherwise complete it
|
||||||
|
|
||||||
|
if todo.Props["RRULE"] != nil {
|
||||||
|
var rOptions *rrule.ROption
|
||||||
|
rOptions, err = todo.Props.RecurrenceRule()
|
||||||
|
if err != nil {return}
|
||||||
|
offset := rOptions.Interval
|
||||||
|
var currentDUE time.Time
|
||||||
|
currentDUE,err = todo.Props.DateTime("DUE",nil)
|
||||||
|
if err != nil {return}
|
||||||
|
switch rOptions.Freq {
|
||||||
|
case rrule.DAILY:
|
||||||
|
currentDUE = currentDUE.AddDate(0,0,offset)
|
||||||
|
case rrule.WEEKLY:
|
||||||
|
currentDUE = currentDUE.AddDate(0,0,7*offset)
|
||||||
|
case rrule.MONTHLY:
|
||||||
|
currentDUE = currentDUE.AddDate(0,offset,0)
|
||||||
|
case rrule.YEARLY:
|
||||||
|
currentDUE = currentDUE.AddDate(offset,0,0)
|
||||||
|
case rrule.HOURLY: //TODO didn't debug
|
||||||
|
currentDUE = currentDUE.Add(time.Hour * time.Duration(offset))
|
||||||
|
case rrule.MINUTELY: //TODO didn't debug
|
||||||
|
currentDUE = currentDUE.Add(time.Minute * time.Duration(offset))
|
||||||
|
case rrule.SECONDLY: //TODO didn't debug
|
||||||
|
currentDUE = currentDUE.Add(time.Second * time.Duration(offset))
|
||||||
|
}
|
||||||
|
todo.Props.SetDateTime("DUE",currentDUE)
|
||||||
|
} else {
|
||||||
|
todo.Props.SetText(ical.PropStatus,"COMPLETED")
|
||||||
|
todo.Props.SetText(ical.PropPercentComplete,"100")
|
||||||
|
todo.Props.SetDateTime(ical.PropCompleted,time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
err = m.EditTodo(todo)
|
err = m.EditTodo(todo)
|
||||||
if err != nil {return}
|
if err != nil {return}
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -10,6 +10,7 @@ require (
|
|||||||
github.com/emersion/go-webdav v0.5.0
|
github.com/emersion/go-webdav v0.5.0
|
||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.3.1
|
||||||
github.com/projectdiscovery/goflags v0.1.56
|
github.com/projectdiscovery/goflags v0.1.56
|
||||||
|
github.com/teambition/rrule-go v1.8.2
|
||||||
github.com/zalando/go-keyring v0.2.5
|
github.com/zalando/go-keyring v0.2.5
|
||||||
golang.org/x/term v0.18.0
|
golang.org/x/term v0.18.0
|
||||||
)
|
)
|
||||||
@ -47,7 +48,6 @@ require (
|
|||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
|
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
|
||||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
|
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
|
||||||
github.com/teambition/rrule-go v1.8.2 // indirect
|
|
||||||
github.com/tidwall/gjson v1.14.3 // indirect
|
github.com/tidwall/gjson v1.14.3 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
|
65
main.go
65
main.go
@ -16,12 +16,15 @@ import (
|
|||||||
|
|
||||||
|
|
||||||
// "strconv"
|
// "strconv"
|
||||||
|
// "github.com/charmbracelet/bubbles/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
// var waitGroup sync.WaitGroup
|
// var waitGroup sync.WaitGroup
|
||||||
|
|
||||||
func errHandler(err error, message string) {
|
func errHandler(err error, message string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
//TODO double err!=nil
|
||||||
|
//TODO copy error to clipboard
|
||||||
fmt.Printf("\n\n%s: %s\n", message, err)
|
fmt.Printf("\n\n%s: %s\n", message, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -46,8 +49,13 @@ func main() {
|
|||||||
calendars, err = GetCalendars()
|
calendars, err = GetCalendars()
|
||||||
errHandler(err, "Error getting calendars (incorrect url/login/password)")
|
errHandler(err, "Error getting calendars (incorrect url/login/password)")
|
||||||
|
|
||||||
|
//TODO crushs START
|
||||||
var found bool
|
var found bool
|
||||||
// var calPath string
|
// var calPath string
|
||||||
|
if options.Calendar == "" {
|
||||||
|
m.LoginToCalendar()
|
||||||
|
// m.ActiveWindow = "login"
|
||||||
|
}
|
||||||
if options.Calendar != "" {
|
if options.Calendar != "" {
|
||||||
for _,calendar := range calendars {
|
for _,calendar := range calendars {
|
||||||
if calendar.Name == options.Calendar {
|
if calendar.Name == options.Calendar {
|
||||||
@ -65,59 +73,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fmt.Println(m)
|
||||||
m.LoginToCalendar()
|
m.LoginToCalendar()
|
||||||
m.GatherTodos()
|
m.CalendarToTodo()
|
||||||
|
|
||||||
|
|
||||||
// calendarObjects, err := GetTODOs(calPath)
|
//TODO crushs End
|
||||||
// errHandler(err, "Error getting TODOs")
|
|
||||||
//
|
|
||||||
// today := time.Now() //TODO move to tui and remove it
|
|
||||||
// todayTodos, err := ParseDueDateTODOs(calendarObjects, today)
|
|
||||||
// tomorrow := time.Now().AddDate(0, 0, 1)
|
|
||||||
// tomorrowTodos, err := ParseDueDateTODOs(calendarObjects, tomorrow)
|
|
||||||
// //TODO remove it
|
|
||||||
// fmt.Println("In total we have", len(calendarObjects), "todos")
|
|
||||||
// //TODO remove it
|
|
||||||
// var itemsToday []list.Item
|
|
||||||
// var itemsTomorrow []list.Item
|
|
||||||
// for _, todo := range todayTodos {
|
|
||||||
// itemsToday = append(itemsToday, todo)
|
|
||||||
// }
|
|
||||||
// for _, todo := range tomorrowTodos {
|
|
||||||
// itemsTomorrow = append(itemsTomorrow, todo)
|
|
||||||
// }
|
|
||||||
//TODO remove it
|
|
||||||
m.GatherTodos()
|
|
||||||
|
|
||||||
|
|
||||||
// m.TodayTab = list.New(itemsToday, list.NewDefaultDelegate(), 0, 0)
|
|
||||||
// m.TodayTab.Title = "Today"
|
|
||||||
// m.TomorrowTab = list.New(itemsTomorrow, list.NewDefaultDelegate(), 0, 0)
|
|
||||||
// m.TomorrowTab.Title = "Tomorrow"
|
|
||||||
|
|
||||||
m.LoggedIn = true
|
|
||||||
m.ActiveWindow = "today"
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//TODO go to calendars page
|
|
||||||
// m.LoggedIn = true
|
|
||||||
m.ActiveWindow = "calendarChoose"
|
|
||||||
|
|
||||||
// items := []list.Item{
|
|
||||||
// item("Ramen"),
|
|
||||||
// item("Tomato Soup"),
|
|
||||||
// item("Hamburgers"),
|
|
||||||
// item("Cheeseburgers"),
|
|
||||||
// item("Currywurst"),
|
|
||||||
// item("Okonomiyaki"),
|
|
||||||
// item("Pasta"),
|
|
||||||
// item("Fillet Mignon"),
|
|
||||||
// item("Caviar"),
|
|
||||||
// item("Just Wine"),
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//TODO I'm on a highway to (IfElse) hell!
|
//TODO I'm on a highway to (IfElse) hell!
|
||||||
//TODO probably need to do more careful debug
|
//TODO probably need to do more careful debug
|
||||||
@ -156,8 +119,8 @@ func main() {
|
|||||||
// errHandler(err,"test fail2")
|
// errHandler(err,"test fail2")
|
||||||
//DEBUG stuff
|
//DEBUG stuff
|
||||||
|
|
||||||
|
//TODO if task have alarm - make a notification / play sound...
|
||||||
p := tea.NewProgram(m, tea.WithAltScreen())
|
p := tea.NewProgram(m, tea.WithAltScreen()) //TODO DEBUG bring me back
|
||||||
if _, err := p.Run(); err != nil {
|
if _, err := p.Run(); err != nil {
|
||||||
fmt.Println("Error running program:", err)
|
fmt.Println("Error running program:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -68,7 +68,7 @@ func (options *Options) SanityCheck() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Proxy != "" {os.Setenv("HTTP_PROXY", options.Proxy)}
|
if options.Proxy != "" {os.Setenv("HTTPS_PROXY", options.Proxy)}
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
// "github.com/emersion/go-ical"
|
"github.com/emersion/go-ical"
|
||||||
// "time"
|
// "time"
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
"github.com/charmbracelet/bubbles/key"
|
"github.com/charmbracelet/bubbles/key"
|
||||||
@ -31,11 +31,13 @@ func (m model) newItemDelegate(keys *delegateKeyMap) list.DefaultDelegate {
|
|||||||
|
|
||||||
d.UpdateFunc = func(msg tea.Msg, ml *list.Model) tea.Cmd {
|
d.UpdateFunc = func(msg tea.Msg, ml *list.Model) tea.Cmd {
|
||||||
var title string
|
var title string
|
||||||
var todoUID string
|
// var todoUID string
|
||||||
|
var todoIcal ical.Event
|
||||||
|
|
||||||
if i, ok := ml.SelectedItem().(TODO); ok {
|
if i, ok := ml.SelectedItem().(TODO); ok {
|
||||||
title = i.Title()
|
title = i.Title()
|
||||||
todoUID = i.UID()
|
// todoUID = i.UID()
|
||||||
|
todoIcal = ical.Event(i)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -44,10 +46,17 @@ func (m model) newItemDelegate(keys *delegateKeyMap) list.DefaultDelegate {
|
|||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch {
|
switch {
|
||||||
case key.Matches(msg, keys.choose):
|
case key.Matches(msg, keys.choose):
|
||||||
|
err := m.CompleteTodo(todoIcal)
|
||||||
|
if err != nil {return errHandler_tui(err,"can't complete item")}
|
||||||
|
index := ml.Index()
|
||||||
|
ml.RemoveItem(index)
|
||||||
|
if len(ml.Items()) == 0 {
|
||||||
|
keys.choose.SetEnabled(false)
|
||||||
|
}
|
||||||
return ml.NewStatusMessage(statusMessageStyle("You chose " + title))
|
return ml.NewStatusMessage(statusMessageStyle("You chose " + title))
|
||||||
|
|
||||||
case key.Matches(msg, keys.remove):
|
case key.Matches(msg, keys.remove):
|
||||||
err := m.DelTodo(todoUID)
|
err := m.DelTodo(todoIcal)
|
||||||
if err != nil {return errHandler_tui(err,"can't delete item")}
|
if err != nil {return errHandler_tui(err,"can't delete item")}
|
||||||
index := ml.Index()
|
index := ml.Index()
|
||||||
ml.RemoveItem(index)
|
ml.RemoveItem(index)
|
||||||
|
@ -41,9 +41,10 @@ func (i TODO) FilterValue() string {
|
|||||||
|
|
||||||
func (m *model) GatherTodos() (err error) {
|
func (m *model) GatherTodos() (err error) {
|
||||||
//TODO more modular approach
|
//TODO more modular approach
|
||||||
calendarObjects, err := GetTODOs(m.Creds.CalendarPath)
|
m.CalObjects, err = GetTODOs(m.Creds.CalendarPath)
|
||||||
if err != nil {return}
|
if err != nil {return}
|
||||||
|
|
||||||
|
calendarObjects := m.CalObjects //TODO rm me
|
||||||
// var todayTodos []TODO
|
// var todayTodos []TODO
|
||||||
|
|
||||||
today := time.Now()
|
today := time.Now()
|
||||||
|
Loading…
Reference in New Issue
Block a user