myhours

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2025 License: MIT Imports: 11 Imported by: 0

README

My Hours

go build and test golangci-lint

This is a simple leisure project to build a small CLI for tracking daily hours at work.

Key requirements:

  • must be able to start and stop tracking freely
  • able to get a summary of time spent per day, week, and month
  • data must persist and can be transferred between computers if needed.

Current state

  • Ability to track time is there
  • Supports three categories of time (uncategorized, personal, and work)
  • Timer is preserved if program is closed (restored on startup)
  • Supports weekly, monthly and yearly reports
    • reports can be fetched independently per category.
  • Support importing data from a text file.

Install

No pre-built binaries right now. Easiest install is with go install:

$> go install github.com/msepp/myhours/cmd/myhours@v0.1.0
$> $GOPATH/bin/myhours -h

Roadmap

Everything is done on best effort, when-I-feel-like-it basis. With that said, some things that could be taken care of in the near future:

  • Support adding custom categories
    • Category selecting needs to be better if we there's more than 3, or custom amount.
  • Notes are missing. Would be nice to be able to record for example issue ids per record.
  • No way to amend records currently, except going into the database directly.

Documentation

Overview

Package myhours contains implementation for a bubbletea application for tracking time spent at work (or for personal projects).

New returns the application model that is ready to be passed into a new bubbletea program.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Category

type Category struct {
	// ID of the category, identifies a single category.
	ID int64
	// Name of the category.
	Name string
	// BackgroundDark is the background color when rendering on a dark terminal.
	BackgroundDark string
	// BackgroundLight is the background color when rendering on a light terminal.
	BackgroundLight string
	// ForegroundDark is the foreground color when rendering on a dark terminal.
	ForegroundDark string
	// ForegroundLight is the foreground color when rendering on a light terminal.
	ForegroundLight string
}

Category of a record. Used to define what the time was spent on.

func (Category) BackgroundColor

func (c Category) BackgroundColor() lipgloss.AdaptiveColor

BackgroundColor returns adaptive color for rendering the category name for example.

func (Category) ForegroundColor

func (c Category) ForegroundColor() lipgloss.AdaptiveColor

ForegroundColor returns adaptive color for rendering the category name for example.

type Database

type Database interface {
	// ActiveRecord returns currently active record.
	//
	// If none is active, both return values are nil.
	ActiveRecord() (*Record, error)
	// Record returns a single Record matching given ID.
	Record(recordID int64) (*Record, error)
	// Records returns all records that fit into the given timespan.
	// Records where starting time is equal or greater to from, and less than before,
	// are returned.
	Records(from, before time.Time) ([]Record, error)
	// RecordsInCategory behaves exactly like Records, but filters also by given
	// categoryID.
	RecordsInCategory(from, before time.Time, categoryID int64) ([]Record, error)
	// ImportRecords with given details. Expects that all records are finished.
	//
	// On success returns the imported record ID.
	ImportRecords(records []Record) ([]int64, error)
	// StartRecord inserts a new active record into the database. If an already active
	// record exist, error is returned instead.
	//
	// On success returns the new record IDs
	StartRecord(start time.Time, categoryID int64, notes string) (int64, error)
	// UpdateRecord details for record identified by record ID.
	UpdateRecord(recordID int64, categoryID int64, from, end time.Time, notes string) error
	// Categories returns all available categories.
	Categories() ([]Category, error)
	// UpdateSetting updates a configuration setting value identified by key.
	UpdateSetting(key Setting, value string) error
	// Settings returns application settings
	Settings() (*Settings, error)
}

Database defines the database access requirements for stopwatch.

type MyHours

type MyHours struct {
	// contains filtered or unexported fields
}

MyHours is the my-hours application model. Keep track of the whole application state and implements tea.Model.

func New

func New(db Database, options ...Option) MyHours

New returns an initialized MyHours model that can be passed into a bubbletea program for running the time tracking application.

db must be some working implementation of Database. Reference implementations can be found under database sub-package.

To use the returned model, call for example tea.NewProgram(model).Run()

func (MyHours) Init

func (m MyHours) Init() tea.Cmd

Init performs application initialization.

Returns a set of commands that to update the application to a state where it is ready to function. Posts tea.Quit command if initiation fails at any point.

Provides compatibility with tea.Model.

func (MyHours) Update

func (m MyHours) Update(message tea.Msg) (tea.Model, tea.Cmd)

Update model state based on the incoming message.

Returns the updated model (MyHours) and command that needs to be executed next. Note that the returned command is always the result of tea.Batch, meaning multiple commands may be executed as result.

Provides compatibility with tea.Model.

func (MyHours) View

func (m MyHours) View() string

View renders the current model state.

Provides compatibility with tea.Model.

type Option

type Option func(app *MyHours)

Option defines a function that configures the application. Use with NewApplication or directly on MyHours.

func UseLogger

func UseLogger(l *slog.Logger) Option

UseLogger sets the logger for application. If nil, a logger based on slog.DiscardHandler is used as default.

type Record

type Record struct {
	// ID of this particular record
	ID int64
	// Start datetime, when recording started.
	Start time.Time
	// End datetime, when recording finished. If zero, record is considered to be
	// active still, but prefer Finished method.
	End time.Time
	// CategoryID defines the category for the recorded time.
	CategoryID int64
	// Notes for this particular record.
	Notes string
}

Record of time spent. A span of time spent on something.

func (Record) Active added in v0.1.0

func (r Record) Active() bool

Active returns if the record has been started and isn't yet finished.

func (Record) Duration

func (r Record) Duration() time.Duration

Duration of the record. If Start or End is zero, return value is zero.

func (Record) Finished

func (r Record) Finished() bool

Finished returns if the record has been finished.

func (Record) Validate

func (r Record) Validate() error

Validate Record for any inconsistencies. Returns error with validation failure reason if Record is somehow broken.

type Setting

type Setting string

Setting identifies a value in application configuration settings.

const (
	// SettingDefaultCategory is the setting key for default category.
	SettingDefaultCategory Setting = "default_category"
)

func (Setting) String

func (s Setting) String() string

type Settings

type Settings struct {
	// DefaultCategoryID is the category that is set by default work any recorded
	// time.
	DefaultCategoryID int64
}

Settings contains the global configuration values for the application.

Directories

Path Synopsis
cmd
myhours command
database
sqlite
Package sqlite implements myhours.Database on top of SQLite.
Package sqlite implements myhours.Database on top of SQLite.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL