First working version. Can add Projects and Tasks
This commit is contained in:
243
app/tui.go
Normal file
243
app/tui.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/asdine/storm/v3"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/ajaxray/geek-life/model"
|
||||
"github.com/ajaxray/geek-life/repository"
|
||||
repo "github.com/ajaxray/geek-life/repository/storm"
|
||||
"github.com/ajaxray/geek-life/util"
|
||||
)
|
||||
|
||||
var (
|
||||
app *tview.Application
|
||||
newProject, newTask *tview.InputField
|
||||
projectList, taskList *tview.List
|
||||
projectPane, taskPane *tview.Flex
|
||||
statusBar *tview.Pages
|
||||
message *tview.TextView
|
||||
shortcutsPage, messagePage string = "shortcuts", "message"
|
||||
|
||||
db *storm.DB
|
||||
projectRepo repository.ProjectRepository
|
||||
taskRepo repository.TaskRepository
|
||||
|
||||
projects []model.Project
|
||||
currentProject model.Project
|
||||
|
||||
tasks []model.Task
|
||||
currentTask model.Task
|
||||
)
|
||||
|
||||
func main() {
|
||||
app = tview.NewApplication()
|
||||
|
||||
db = util.ConnectStorm()
|
||||
defer db.Close()
|
||||
|
||||
projectRepo = repo.NewProjectRepository(db)
|
||||
taskRepo = repo.NewTaskRepository(db)
|
||||
|
||||
titleText := tview.NewTextView().SetText("[lime::b]Geek-life [::-]- life management for geeks!").SetDynamicColors(true)
|
||||
cloudStatus := tview.NewTextView().SetText("[::d]Cloud Sync: off").SetTextAlign(tview.AlignRight).SetDynamicColors(true)
|
||||
|
||||
prepareStatusBar()
|
||||
|
||||
titleBar := tview.NewFlex().
|
||||
AddItem(titleText, 0, 2, false).
|
||||
AddItem(cloudStatus, 0, 1, false)
|
||||
|
||||
projectPane = makeProjectPane()
|
||||
taskPane = makeTaskPane()
|
||||
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(titleBar, 2, 1, false).
|
||||
AddItem(tview.NewFlex().
|
||||
AddItem(projectPane, 25, 1, true).
|
||||
AddItem(taskPane, 0, 2, false).
|
||||
AddItem(tview.NewBox().SetBorder(true).SetTitle("Details"), 0, 3, false),
|
||||
0, 2, true).
|
||||
AddItem(statusBar, 1, 1, false)
|
||||
|
||||
setKeyboardShortcuts(projectPane, taskPane)
|
||||
|
||||
if err := app.SetRoot(layout, true).EnableMouse(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func makeProjectPane() *tview.Flex {
|
||||
var err error
|
||||
projects, err = projectRepo.GetAll()
|
||||
util.FatalIfError(err, "Could not load Projects")
|
||||
|
||||
projectList = tview.NewList()
|
||||
|
||||
for i := range projects {
|
||||
addProjectToList(i, false)
|
||||
}
|
||||
|
||||
newProject = makeLightTextInput("+[New Project]").
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
project, err := projectRepo.Create(newProject.GetText(), "")
|
||||
if err != nil {
|
||||
showMessage("[red::]Failed to create Project:" + err.Error())
|
||||
} else {
|
||||
showMessage(fmt.Sprintf("[green::]Project %s created. Press n to start adding new tasks.", newProject.GetText()))
|
||||
projects = append(projects, project)
|
||||
addProjectToList(len(projects)-1, true)
|
||||
newProject.SetText("")
|
||||
}
|
||||
case tcell.KeyEsc:
|
||||
app.SetFocus(projectPane)
|
||||
}
|
||||
})
|
||||
|
||||
projectBar := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(projectList, 0, 1, true).
|
||||
AddItem(newProject, 1, 0, false)
|
||||
|
||||
projectBar.SetBorder(true).SetTitle("Projects (p)")
|
||||
|
||||
return projectBar
|
||||
}
|
||||
|
||||
func addProjectToList(i int, selectItem bool) {
|
||||
// To avoid overriding of loop variables - https://www.calhoun.io/gotchas-and-common-mistakes-with-closures-in-go/
|
||||
projectList.AddItem(projects[i].Title, "", 0, func(idx int) func() {
|
||||
return func() { loadProject(idx) }
|
||||
}(i))
|
||||
|
||||
if selectItem {
|
||||
projectList.SetCurrentItem(i)
|
||||
loadProject(i)
|
||||
}
|
||||
}
|
||||
|
||||
func makeTaskPane() *tview.Flex {
|
||||
taskList = tview.NewList().ShowSecondaryText(false)
|
||||
taskList.SetDoneFunc(func() {
|
||||
app.SetFocus(projectPane)
|
||||
})
|
||||
|
||||
newTask = makeLightTextInput("+[New Task]").
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
task, err := taskRepo.Create(currentProject, newTask.GetText(), "", "", time.Now().Unix())
|
||||
if err != nil {
|
||||
showMessage("[red::]Could not create Task:" + err.Error())
|
||||
}
|
||||
|
||||
taskList.AddItem(task.Title, "", 0, nil)
|
||||
newTask.SetText("")
|
||||
case tcell.KeyEsc:
|
||||
app.SetFocus(taskPane)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
taskPane := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(taskList, 0, 1, true).
|
||||
AddItem(newTask, 1, 0, false)
|
||||
|
||||
taskPane.SetBorder(true).SetTitle("Tasks (t)")
|
||||
|
||||
return taskPane
|
||||
}
|
||||
|
||||
func loadProject(idx int) {
|
||||
currentProject = projects[idx]
|
||||
taskList.Clear()
|
||||
app.SetFocus(taskPane)
|
||||
var err error
|
||||
|
||||
if tasks, err = taskRepo.GetAllByProject(currentProject); err != nil && err != storm.ErrNotFound {
|
||||
showMessage("[red::]Error: " + err.Error())
|
||||
}
|
||||
|
||||
for i, task := range tasks {
|
||||
taskList.AddItem(task.Title, "", 0, func(taskidx int) func() {
|
||||
return func() { loadTask(taskidx) }
|
||||
}(i))
|
||||
}
|
||||
}
|
||||
|
||||
func loadTask(idx int) {
|
||||
currentTask = tasks[idx]
|
||||
// taskList.Clear()
|
||||
// app.SetFocus(taskPane)
|
||||
}
|
||||
|
||||
func makeLightTextInput(placeholder string) *tview.InputField {
|
||||
return tview.NewInputField().
|
||||
SetPlaceholder(placeholder).
|
||||
SetPlaceholderTextColor(tcell.ColorLightSlateGray).
|
||||
SetFieldTextColor(tcell.ColorBlack).
|
||||
SetFieldBackgroundColor(tcell.ColorGray)
|
||||
}
|
||||
|
||||
func ignoreKeyEvt() bool {
|
||||
return reflect.TypeOf(app.GetFocus()).String() == "*tview.InputField"
|
||||
}
|
||||
|
||||
func setKeyboardShortcuts(projectPane *tview.Flex, taskPane *tview.Flex) *tview.Application {
|
||||
return app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if ignoreKeyEvt() {
|
||||
return event
|
||||
}
|
||||
switch event.Rune() {
|
||||
case 'p':
|
||||
app.SetFocus(projectPane)
|
||||
case 't':
|
||||
app.SetFocus(taskPane)
|
||||
case 'n':
|
||||
if projectPane.HasFocus() {
|
||||
app.SetFocus(newProject)
|
||||
} else if taskPane.HasFocus() {
|
||||
app.SetFocus(newTask)
|
||||
}
|
||||
}
|
||||
|
||||
return event
|
||||
})
|
||||
}
|
||||
|
||||
func showMessage(text string) {
|
||||
message.SetText(text)
|
||||
statusBar.SwitchToPage(messagePage)
|
||||
|
||||
go func() {
|
||||
app.QueueUpdateDraw(func() {
|
||||
time.Sleep(time.Second * 5)
|
||||
statusBar.SwitchToPage(shortcutsPage)
|
||||
})
|
||||
}()
|
||||
}
|
||||
|
||||
func prepareStatusBar() {
|
||||
statusBar = tview.NewPages()
|
||||
|
||||
message = tview.NewTextView().SetDynamicColors(true).SetText("Loading...")
|
||||
statusBar.AddPage(messagePage, message, true, true)
|
||||
|
||||
statusBar.AddPage(shortcutsPage,
|
||||
tview.NewGrid().
|
||||
SetColumns(0, 0, 0, 0).
|
||||
SetRows(0).
|
||||
AddItem(tview.NewTextView().SetText("Shortcuts: Alt+.(dot)"), 0, 0, 1, 1, 0, 0, false).
|
||||
AddItem(tview.NewTextView().SetText("New Project: n").SetTextAlign(tview.AlignCenter), 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(tview.NewTextView().SetText("New Task: t").SetTextAlign(tview.AlignCenter), 0, 2, 1, 1, 0, 0, false).
|
||||
AddItem(tview.NewTextView().SetText("Quit: Ctrl+C").SetTextAlign(tview.AlignRight), 0, 3, 1, 1, 0, 0, false),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
13
go.mod
Normal file
13
go.mod
Normal file
@@ -0,0 +1,13 @@
|
||||
module github.com/ajaxray/geek-life
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/asdine/storm/v3 v3.2.0
|
||||
github.com/gdamore/tcell v1.3.0
|
||||
github.com/golang/protobuf v1.3.3 // indirect
|
||||
github.com/rivo/tview v0.0.0-20200507165325-823f280c5426
|
||||
github.com/stretchr/testify v1.4.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
)
|
||||
68
go.sum
Normal file
68
go.sum
Normal file
@@ -0,0 +1,68 @@
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
||||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwvZMJY1tzqBvQgpaZiQRuIDD40jM=
|
||||
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM=
|
||||
github.com/asdine/storm/v3 v3.2.0 h1:qFpwwlOyIDVVrAgJliML9fEccRO3PJrJe+KpWK199ho=
|
||||
github.com/asdine/storm/v3 v3.2.0/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
|
||||
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/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
|
||||
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
|
||||
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
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/rivo/tview v0.0.0-20200507165325-823f280c5426 h1:oUJaa48KPBmtgqppKbVqP4QHRa/cdONfQoXcNWRe7wE=
|
||||
github.com/rivo/tview v0.0.0-20200507165325-823f280c5426/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84=
|
||||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20191105084925-a882066a44e0 h1:QPlSTtPE2k6PZPasQUbzuK3p9JbS+vMXYVto8g/yrsg=
|
||||
golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
7
model/project.go
Normal file
7
model/project.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
type Project struct {
|
||||
ID int64 `storm:"id,increment",json:"id"`
|
||||
Title string `storm:"index",json:"title"`
|
||||
UUID string `storm:"unique",json:"uuid,omitempty"`
|
||||
}
|
||||
11
model/task.go
Normal file
11
model/task.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package model
|
||||
|
||||
type Task struct {
|
||||
ID int64 `storm:"id,increment",json:"id"`
|
||||
ProjectID int64 `storm:"index",json:"project_id"`
|
||||
UUID string `storm:"unique",json:"uuid,omitempty"`
|
||||
Title string `json:"text"`
|
||||
Details string `json:"notes"`
|
||||
Completed bool `storm:"index",json:"completed"`
|
||||
DueDate int64 `storm:"index",json:"due_date,omitempty"`
|
||||
}
|
||||
13
repository/project.go
Normal file
13
repository/project.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package repository
|
||||
|
||||
import "github.com/ajaxray/geek-life/model"
|
||||
|
||||
type ProjectRepository interface {
|
||||
GetAll() ([]model.Project, error)
|
||||
GetByID(id int64) (model.Project, error)
|
||||
GetByTitle(title string) (model.Project, error)
|
||||
GetByUUID(UUID string) (model.Project, error)
|
||||
Create(title, UUID string) (model.Project, error)
|
||||
Update(p *model.Project) error
|
||||
Delete(p *model.Project) error
|
||||
}
|
||||
61
repository/storm/project.go
Normal file
61
repository/storm/project.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package storm
|
||||
|
||||
import (
|
||||
"github.com/asdine/storm/v3"
|
||||
|
||||
"github.com/ajaxray/geek-life/model"
|
||||
"github.com/ajaxray/geek-life/repository"
|
||||
)
|
||||
|
||||
type projectRepository struct {
|
||||
DB *storm.DB
|
||||
}
|
||||
|
||||
// NewProjectRepository will create an object that represent the repository.Project interface
|
||||
func NewProjectRepository(db *storm.DB) repository.ProjectRepository {
|
||||
return &projectRepository{db}
|
||||
}
|
||||
|
||||
func (repo *projectRepository) GetAll() ([]model.Project, error) {
|
||||
var projects []model.Project
|
||||
err := repo.DB.All(&projects)
|
||||
|
||||
return projects, err
|
||||
}
|
||||
|
||||
func (repo *projectRepository) GetByID(id int64) (model.Project, error) {
|
||||
return repo.getOneByField("ID", id)
|
||||
}
|
||||
|
||||
func (repo *projectRepository) GetByTitle(title string) (model.Project, error) {
|
||||
return repo.getOneByField("Title", title)
|
||||
}
|
||||
|
||||
func (repo *projectRepository) GetByUUID(UUID string) (model.Project, error) {
|
||||
return repo.getOneByField("CloudId", UUID)
|
||||
}
|
||||
|
||||
func (repo *projectRepository) Create(title, UUID string) (model.Project, error) {
|
||||
project := model.Project{
|
||||
Title: title,
|
||||
UUID: UUID,
|
||||
}
|
||||
|
||||
err := repo.DB.Save(&project)
|
||||
return project, err
|
||||
}
|
||||
|
||||
func (repo *projectRepository) Update(project *model.Project) error {
|
||||
return repo.DB.Save(project)
|
||||
}
|
||||
|
||||
func (repo *projectRepository) Delete(project *model.Project) error {
|
||||
return repo.DB.DeleteStruct(project)
|
||||
}
|
||||
|
||||
func (repo *projectRepository) getOneByField(fieldName string, val interface{}) (model.Project, error) {
|
||||
var project model.Project
|
||||
err := repo.DB.One(fieldName, val, &project)
|
||||
|
||||
return project, err
|
||||
}
|
||||
64
repository/storm/task.go
Normal file
64
repository/storm/task.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package storm
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/asdine/storm/v3"
|
||||
|
||||
"github.com/ajaxray/geek-life/model"
|
||||
"github.com/ajaxray/geek-life/repository"
|
||||
)
|
||||
|
||||
type taskRepository struct {
|
||||
DB *storm.DB
|
||||
}
|
||||
|
||||
// NewTaskRepository will create an object that represent the repository.Task interface
|
||||
func NewTaskRepository(db *storm.DB) repository.TaskRepository {
|
||||
return &taskRepository{db}
|
||||
}
|
||||
|
||||
func (t taskRepository) GetAll() ([]model.Task, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t taskRepository) GetAllByProject(project model.Project) ([]model.Task, error) {
|
||||
var tasks []model.Task
|
||||
//err = db.Find("ProjetID", project.ID, &tasks, storm.Limit(10), storm.Skip(10), storm.Reverse())
|
||||
err := t.DB.Find("ProjectID", project.ID, &tasks)
|
||||
|
||||
return tasks, err
|
||||
}
|
||||
|
||||
func (t taskRepository) GetAllByDate(from, to time.Time) ([]model.Task, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t taskRepository) GetByID(ID string) (model.Task, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t taskRepository) GetByUUID(UUID string) (model.Task, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t taskRepository) Create(project model.Project, title, details, UUID string, dueDate int64) (model.Task, error) {
|
||||
task := model.Task{
|
||||
ProjectID: project.ID,
|
||||
Title: title,
|
||||
Details: details,
|
||||
UUID: UUID,
|
||||
DueDate: dueDate,
|
||||
}
|
||||
|
||||
err := t.DB.Save(&task)
|
||||
return task, err
|
||||
}
|
||||
|
||||
func (t taskRepository) Update(p *model.Task) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t taskRepository) Delete(p *model.Task) error {
|
||||
panic("implement me")
|
||||
}
|
||||
18
repository/task.go
Normal file
18
repository/task.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/ajaxray/geek-life/model"
|
||||
)
|
||||
|
||||
type TaskRepository interface {
|
||||
GetAll() ([]model.Task, error)
|
||||
GetAllByProject(project model.Project) ([]model.Task, error)
|
||||
GetAllByDate(from, to time.Time) ([]model.Task, error)
|
||||
GetByID(ID string) (model.Task, error)
|
||||
GetByUUID(UUID string) (model.Task, error)
|
||||
Create(project model.Project, title, details, UUID string, dueDate int64) (model.Task, error)
|
||||
Update(p *model.Task) error
|
||||
Delete(p *model.Task) error
|
||||
}
|
||||
27
util/array.go
Normal file
27
util/array.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package util
|
||||
|
||||
import "reflect"
|
||||
|
||||
// InArray checks is val exists in a Slice
|
||||
func InArray(val interface{}, array interface{}) bool {
|
||||
return AtArrayPosition(val, array) != -1
|
||||
}
|
||||
|
||||
// AtArrayPosition find the int position of val in a Slice
|
||||
func AtArrayPosition(val interface{}, array interface{}) (index int) {
|
||||
index = -1
|
||||
|
||||
switch reflect.TypeOf(array).Kind() {
|
||||
case reflect.Slice:
|
||||
s := reflect.ValueOf(array)
|
||||
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
|
||||
index = i
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
34
util/env.go
Normal file
34
util/env.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
// "github.com/subosito/gotenv"
|
||||
)
|
||||
|
||||
// func init() {
|
||||
// gotenv.Load()
|
||||
// }
|
||||
|
||||
func GetEnvInt(key string, defaultVal int) int {
|
||||
if v, ok := os.LookupEnv(key); ok {
|
||||
if i, err := strconv.Atoi(v); err == nil {
|
||||
return i
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func GetEnvStr(key, defaultVal string) string {
|
||||
if v, ok := os.LookupEnv(key); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
51
util/util.go
Normal file
51
util/util.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/asdine/storm/v3"
|
||||
)
|
||||
|
||||
// ConnectStorm Create database connection
|
||||
func ConnectStorm() *storm.DB {
|
||||
db, err := storm.Open(GetEnvStr("DB_FILE", "geek-life.db"))
|
||||
FatalIfError(err, "Could not connect Embedded Database File")
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// UnixToTime create time.Time from string timestamp
|
||||
func UnixToTime(timestamp string) time.Time {
|
||||
parts := strings.Split(timestamp, ".")
|
||||
i, err := strconv.ParseInt(parts[0], 10, 64)
|
||||
if LogIfError(err, "Could not parse timestamp : "+timestamp+" (using current time instead)") {
|
||||
return time.Unix(i, 0)
|
||||
}
|
||||
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// LogIfError logs the error and returns true on Error. think as IfError
|
||||
func LogIfError(err error, msgOrPattern string, args ...interface{}) bool {
|
||||
if err != nil {
|
||||
message := fmt.Sprintf(msgOrPattern, args...)
|
||||
log.Printf("%s: %w\n", message, err)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// FatalIfError logs the error and Exit program on Error
|
||||
func FatalIfError(err error, msgOrPattern string, args ...interface{}) {
|
||||
message := fmt.Sprintf(msgOrPattern, args...)
|
||||
|
||||
if LogIfError(err, message) {
|
||||
log.Fatal("FATAL ERROR: Exiting program! - ", message, "\n")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user