Skip to content
This repository has been archived by the owner on Sep 25, 2023. It is now read-only.

Commit

Permalink
Pre-release (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-alvarenga authored Sep 17, 2022
2 parents d6188df + d694c6e commit 9b87ce1
Show file tree
Hide file tree
Showing 20 changed files with 905 additions and 43 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ jobs:
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }}

- name: Copy static files
uses: actions/upload-artifact@v3
with:
name: DashboardUI
path: static/*
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.yaml
*.db
*.db
to-go
File renamed without changes.
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ Simply download the binary corresponding to your machine, move it to a directory

Robust and easy to use, _To go_ supports the following option:

- `to-go help`: Adds a task based of on the users input
- `to-go add`: Adds a task based of on the users input"
- `to-go remove`: Adds a task based of on the users input
- `to-go edit`: Edits a task chosen by you
- `to-go update`: Updates the status of a task chosen by you
- `to-go finish`: Updates the status of a task chosen by you to 'done'
- `to-go list`: Lists all the tasks, including ther titles, priorities, statuses and dates
- `to-go help`: Shows helpful information on the options available
- `to-go add`: Adds a task based of on the users input
- `to-go remove`: Removes a task selected by the user
- `to-go edit`: Edits a task selected by the user
- `to-go update`: Updates the status of a task selected by the user
- `to-go finish`: Updates the status of a task selected by the user to 'done'
- `to-go list`: Lists all the tasks, displaying their titles, priorities, statuses and dates
- `to-go describe`: Displays all the info pertaining to a task chosen by you
- `to-go dashboard`: Spins up a lightweight `http` server to a port of your choice ([see more](#customization)), with a interactive UI being served on the `/`;

# Customization

Expand All @@ -26,7 +27,9 @@ _To go_ offers a few values for you to play around and change to whatever you th
// to_go.cfg.yaml

useUnicode: true
OpenBrowser: true
storage: sqlite
dashboardPort: "8080"
colors:
priority:
high: red
Expand All @@ -47,8 +50,12 @@ colors:
| Option | Description | Values |
| ------ | ------------| --------------- |
| `useUnicode` | Whether or not to use unicode characters to represent the task status | `true` or `false`
| `storage` | Determines the way _To go_ stores data | Anything other than `sqlite` will defaults to using `YAML` files for persistency
| `colors` | Defines the colors to be used in the output | Change the value of its properties to one of [these colors](#colors) |
| `OpenBrowser` | Whether or not your system's default internet browser should be opened on the Dashboard UI when the `dashboard` option is ran | `true` or `false` |
| `storage` | Determines the way _To go_ stores data | Anything other than `sqlite` will defaults to using `YAML` files for persistency |
| `dashboardPort` | To which port the Dashboard's `http` server should listen | A string value with any number; Defaults to "8080" if not provided or otherwise invalid |
| `colors` | Defines the colors to be used in the output | The value of its properties should be one of [these colors](#colors)* |

(*) Changing the `reset` value does not apply any changes on behavior, and the field will return to its original value after executing _To go_ again.

## Colors

Expand Down
19 changes: 11 additions & 8 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,12 @@ func Entrypoint(args []string) bool {
}

switch option {
case clihelper.List:
return cliopts.ListOption()

case clihelper.Describe:
return cliopts.DescribeOption()

case clihelper.Add:
return cliopts.AddOption()

case clihelper.Remove:
return cliopts.RemoveOption()

case clihelper.Edit:
return cliopts.EditOption()

Expand All @@ -68,8 +65,14 @@ func Entrypoint(args []string) bool {
case clihelper.Finish:
return cliopts.FinishOption()

case clihelper.Remove:
return cliopts.RemoveOption()
case clihelper.List:
return cliopts.ListOption()

case clihelper.Describe:
return cliopts.DescribeOption()

case clihelper.Dashboard:
return cliopts.DashboardOption()

default:
break
Expand Down
34 changes: 18 additions & 16 deletions cli/clihelper/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,56 @@ import "fmt"

const (
Executable string = "to-go"
Help string = "help"
Add string = "add"
Remove string = "remove"
Edit string = "edit"
Update string = "update"
Remove string = "remove"
Finish string = "finish"
Help string = "help"
List string = "list"
Describe string = "describe"
Dashboard string = "dashboard"
)

var CLIOptions map[string]string = map[string]string{
"add": Add,
"edit": Edit,
"update": Update,
"remove": Remove,
"finish": Finish,
"help": Help,
"list": List,
"describe": Describe,
"help": Help,
"add": Add,
"remove": Remove,
"edit": Edit,
"update": Update,
"finish": Finish,
"list": List,
"describe": Describe,
"dashboard": Dashboard,
}

var CLIOptionsDescription map[string][2]string = map[string][2]string{
"help": {
"Adds a task based of on the users input",
"Shows helpful information on the options available",
fmt.Sprintf("%s %s", Executable, Help),
},
"add": {
"Adds a task based of on the users input",
fmt.Sprintf("%s %s", Executable, Add),
},
"remove": {
"Adds a task based of on the users input",
"Removes a task selected by the user",
fmt.Sprintf("%s %s", Executable, Remove),
},
"edit": {
"Edits a task chosen by you",
"Edits a task selected by the user",
fmt.Sprintf("%s %s", Executable, Edit),
},
"update": {
"Updates the status of a task chosen by you",
"Updates the status of a task selected by the user",
fmt.Sprintf("%s %s", Executable, Update),
},
"finish": {
"Updates the status of a task chosen by you to 'done'",
"Updates the status of a task selected by the user to 'done'",
fmt.Sprintf("%s %s", Executable, Finish),
},
"list": {
"Lists all the tasks, including ther titles, priorities, statuses and dates",
"Lists all the tasks, displaying their titles, priorities, statuses and dates",
fmt.Sprintf("%s %s", Executable, List),
},
"describe": {
Expand Down
12 changes: 12 additions & 0 deletions cli/cliopts/dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cliopts

import (
"github.com/leo-alvarenga/to-go/ng"
"github.com/leo-alvarenga/to-go/ng/ngops"
)

func DashboardOption() bool {
ngops.Dashboard(ng.Config)

return false
}
180 changes: 180 additions & 0 deletions ng/ngops/dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package ngops

import (
"encoding/json"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"

"github.com/leo-alvarenga/to-go/ng"
"github.com/leo-alvarenga/to-go/shared/cfg"
"github.com/leo-alvarenga/to-go/shared/task"
)

func openBrowser(port string) error {
var cmd string
var args []string

switch runtime.GOOS {
case "windows":
cmd = "cmd"
args = []string{"/c", "start"}
case "darwin":
cmd = "open"
default:
cmd = "xdg-open"
}
args = append(args, "localhost:"+port)
return exec.Command(cmd, args...).Start()
}

func Dashboard(config *cfg.ConfigValue) {
ex, _ := os.Executable()
statics := filepath.Join(filepath.Dir(ex), "static/")

// static files
http.Handle("/", http.FileServer(http.Dir(statics)))

// ng calls
http.HandleFunc("/api/get", getTasksHandler)
http.HandleFunc("/api/add", addTaskHandler)
http.HandleFunc("/api/remove", removeTaskHandler)
http.HandleFunc("/api/edit", editTaskHandler)
http.HandleFunc("/api/update", updateTaskHandler)

if config.OpenBrowser {
go openBrowser(config.DashboardPort)
}

log.Println("Serving dashboard on port " + config.DashboardPort)
http.ListenAndServe(":"+config.DashboardPort, nil)
}

func getTasksHandler(w http.ResponseWriter, req *http.Request) {
res, err := json.Marshal(map[string][]task.Task{"content": ng.TaskList.GetAllTasks()})

w.Header().Set("Content-Type", "application/json")

if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(`{"content": []}`))
} else {
w.WriteHeader(http.StatusOK)
w.Write(res)
}
}

func addTaskHandler(w http.ResponseWriter, req *http.Request) {

if req.Method != http.MethodPost {
w.WriteHeader(http.StatusNotImplemented)
return
}

defer req.Body.Close()

t := new(task.Task)

err := json.NewDecoder(req.Body).Decode(t)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"` + err.Error() + `"}`))
return
}

err = Add(*t)
if err != nil {
w.WriteHeader(http.StatusForbidden)
w.Write([]byte(`{"status":"Couldn't save changes because there's another task with this title. ` + err.Error() + `"}`))
return
}

killData()
w.WriteHeader(http.StatusCreated)
}

func removeTaskHandler(w http.ResponseWriter, req *http.Request) {

if req.Method != http.MethodDelete {
w.WriteHeader(http.StatusForbidden)
return
}

title := req.URL.Query().Get("title")

if title == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"Invalid title"}`))
return
}

err := Remove(title)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"` + err.Error() + `"}`))
return
}

killData()
w.WriteHeader(http.StatusOK)
}

func editTaskHandler(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPatch {
w.WriteHeader(http.StatusForbidden)
return
}

defer req.Body.Close()

t := new([]task.Task)

err := json.NewDecoder(req.Body).Decode(t)
if err != nil || len(*t) <= 0 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"` + err.Error() + `"}`))
return
}

err = Edit((*t)[1], (*t)[0])
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"` + err.Error() + `"}`))
return
}

killData()
w.WriteHeader(http.StatusOK)
}

func updateTaskHandler(w http.ResponseWriter, req *http.Request) {

if req.Method != http.MethodPatch {
w.WriteHeader(http.StatusForbidden)
return
}

defer req.Body.Close()

t := new(task.Task)

err := json.NewDecoder(req.Body).Decode(t)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"` + err.Error() + `"}`))
return
}

err = Update(*t)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"status":"` + err.Error() + `"}`))
return
}

killData()
w.WriteHeader(http.StatusOK)
}
7 changes: 7 additions & 0 deletions ng/ngops/kill.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ngops

import "github.com/leo-alvarenga/to-go/ng"

func killData() {
ng.Startup()
}
2 changes: 1 addition & 1 deletion ng/ngops/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
/*
Removes a task from the persistent volume chose by the user.
Returns an error if something in the remove proccess went badly or
Returns an error if something in the remove process went badly or
if the task does not exists.
*/
func Remove(title string) error {
Expand Down
2 changes: 2 additions & 0 deletions ng/ngops/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
func Update(t task.Task) error {
if t.Status == task.Statuses["done"] {
t.FinishedIn = getDateInToGosFmt(time.Now().Date())
} else {
t.FinishedIn = ""
}

ng.TaskList.Update(t)
Expand Down
Loading

0 comments on commit 9b87ce1

Please sign in to comment.