diff --git a/README.md b/README.md index 736c59a..07bd957 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ # wtt Work Time Tracker - console time tracking app + + +### Use +Create new project +``` +./wtt new ProjectName +``` + + +Start working on a project +``` +./wtt start ProjectName +``` + +Stop working on the current project +``` +./wtt stop +``` + +List projects +``` +./wtt list +``` diff --git a/errors.go b/errors.go new file mode 100755 index 0000000..e997ec1 --- /dev/null +++ b/errors.go @@ -0,0 +1,9 @@ +package main + +import "log" + +func check(err error) { + if err != nil { + log.Println(err) + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..8e43d9f --- /dev/null +++ b/main.go @@ -0,0 +1,97 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/user" + "time" + + "github.com/fatih/color" +) + +var directoryPath string +var filePath string + +func main() { + usr, err := user.Current() + if err != nil { + log.Fatal(err) + } + directoryPath = usr.HomeDir + "/.wtt" + filePath = directoryPath + "/work.json" + readProjects() + + //get the command line parameters + if len(os.Args) > 1 { + switch os.Args[1] { + case "new": + //create project os.Args[2] + if len(os.Args) > 2 { + projectName := os.Args[2] + color.Green("creating new project: " + projectName) + err := newProject(projectName) + if err != nil { + break + } + saveWork() + } else { + color.Red("No project name specified") + } + break + case "list": + //list projects + listProjects() + break + case "start": + //check if already there is any project started + if work.CurrentProjectName != "" { + color.Red("Can not start project, already project " + work.CurrentProjectName + " running") + break + } + //start project os.Args[2] + if len(os.Args) > 2 { + projectName := os.Args[2] + i := getProjectIByName(projectName) + if i < 0 { + color.Red("Project name: " + projectName + ", no exists") + break + } + var newStreak Streak + newStreak.Start = time.Now() + work.Projects[i].Streaks = append(work.Projects[i].Streaks, newStreak) + work.CurrentProjectName = projectName + saveWork() + fmt.Println("starting to work in project " + work.Projects[i].Name) + } + break + case "stop": + if work.CurrentProjectName == "" { + color.Red("no project started to stop") + break + } + i := getProjectIByName(work.CurrentProjectName) + if i < 0 { + color.Red("Project name: " + work.CurrentProjectName + ", no exists") + break + } + j := len(work.Projects[i].Streaks) - 1 + work.Projects[i].Streaks[j].End = time.Now() + work.Projects[i].Streaks[j].Duration = time.Now().Sub(work.Projects[i].Streaks[j].Start) + work.CurrentProjectName = "" + saveWork() + fmt.Print("Worked ") + fmt.Print(work.Projects[i].Streaks[j].Duration) + fmt.Println(" in the project " + work.Projects[i].Name) + + //stop project os.Args[2] + break + default: + color.Red("no option selected") + os.Exit(1) + } + } else { + color.Red("no option selected") + os.Exit(1) + } +} diff --git a/work.go b/work.go new file mode 100644 index 0000000..da3a7f0 --- /dev/null +++ b/work.go @@ -0,0 +1,98 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "strconv" + "time" + + "github.com/fatih/color" +) + +type Project struct { + Name string `json:"name"` + Streaks []Streak `json:"streaks"` +} +type Streak struct { + Start time.Time `json:"start"` + End time.Time `json:"end"` + Duration time.Duration `json:"duration"` + Description string `json:"description"` +} +type Work struct { + Projects []Project `json:"projects"` + CurrentProjectName string `json:"currentProjectName"` +} + +var work Work + +func readProjects() { + file, err := ioutil.ReadFile(filePath) + if err != nil { + //file not exists, create directory and file + color.Yellow(directoryPath + " not exists, creating directory") + _ = os.Mkdir(directoryPath, os.ModePerm) + saveWork() + } + content := string(file) + json.Unmarshal([]byte(content), &work) +} + +func saveWork() { + + jsonProjects, err := json.Marshal(work) + check(err) + err = ioutil.WriteFile(filePath, jsonProjects, 0644) + check(err) +} +func getProjectIByName(name string) int { + for i, project := range work.Projects { + if project.Name == name { + return i + } + } + return -1 +} +func projectExist(name string) bool { + for _, project := range work.Projects { + if project.Name == name { + return true + } + } + return false +} +func newProject(name string) error { + //first, check if the project name is not taken yet + if projectExist(name) { + color.Red("Project name: " + name + ", already exists") + return errors.New("project name already exist") + } + var newProject Project + newProject.Name = name + work.Projects = append(work.Projects, newProject) + return nil +} +func listProjects() { + fmt.Println("") + fmt.Println("") + fmt.Println("Listing projects") + fmt.Println("") + for k, project := range work.Projects { + fmt.Println("project " + strconv.Itoa(k)) + fmt.Print("name: ") + color.Blue(project.Name) + for k2, streak := range project.Streaks { + fmt.Println(" streak: " + strconv.Itoa(k2)) + fmt.Print(" Start:") + fmt.Println(streak.Start) + fmt.Print(" End:") + fmt.Println(streak.End) + fmt.Print(" Duration:") + fmt.Println(streak.Duration) + } + fmt.Println("") + } +} diff --git a/wtt b/wtt new file mode 100755 index 0000000..dcc10ad Binary files /dev/null and b/wtt differ