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 listProjectsDetails() {
|
|
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("")
|
|
showHoursByDays(project.Name)
|
|
fmt.Println("")
|
|
}
|
|
if work.CurrentProjectName != "" {
|
|
fmt.Print("Current working project: ")
|
|
color.Blue(work.CurrentProjectName)
|
|
}
|
|
}
|
|
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)
|
|
showHoursByDays(project.Name)
|
|
fmt.Println("")
|
|
}
|
|
if work.CurrentProjectName != "" {
|
|
fmt.Print("Current working project: ")
|
|
color.Blue(work.CurrentProjectName)
|
|
}
|
|
}
|
|
func deleteProject(name string) {
|
|
i := getProjectIByName(name)
|
|
if i < 0 {
|
|
color.Red("Project name: " + name + ", no exists")
|
|
return
|
|
}
|
|
work.Projects = append(work.Projects[:i], work.Projects[i+1:]...)
|
|
}
|
|
func showHoursByDays(name string) {
|
|
timeFormat := "Mon, 01/02/06"
|
|
i := getProjectIByName(name)
|
|
if i < 0 {
|
|
color.Red("Project name: " + name + ", no exists")
|
|
return
|
|
}
|
|
p := work.Projects[i]
|
|
days := make(map[string]time.Duration)
|
|
for _, streak := range p.Streaks {
|
|
days[streak.Start.Format(timeFormat)] = addDurations(days[streak.Start.Format(timeFormat)], streak.Duration)
|
|
}
|
|
for day, hours := range days {
|
|
fmt.Print(" Day: " + day)
|
|
fmt.Print(", total time: ")
|
|
fmt.Println(hours)
|
|
}
|
|
}
|
|
func addDurations(d1 time.Duration, d2 time.Duration) time.Duration {
|
|
s := d1.Seconds() + d2.Seconds()
|
|
r := time.Duration(s) * time.Second
|
|
return r
|
|
}
|