timet 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1bb43c1123df04f10728b72d13245307f1d67d8c1e3234c84ade0cc03836517
4
- data.tar.gz: b0f51950af5d3e6c0ac88ca8914194aa579b04cbc13fb3ae75e84d62bacd9cf2
3
+ metadata.gz: bec76070c29c2eab4a2a5792084a9980c1cd29c0ab3ac80dbae2c6310e74d78a
4
+ data.tar.gz: 551fe37b00ac0ca015e28fcdd37810216c0ff00ea4b800c97bd0fb539af1df7b
5
5
  SHA512:
6
- metadata.gz: e835f9f66149d036d3d7528a7563e91af26e0577f5e60e4984ca0471f2758e21e6ce4b5b45d4a150ac7f1eb496ecd339a9b8abad2c86814934c5c9f588e93699
7
- data.tar.gz: 9d0d081dd8190b5d3d30a13f5b1067f77e4ffb52a64ae4e1007ed80cedfd04ee26db0aeaef5b8cb4edbcc8e08f8e00686609953daeafdda335fa2ae7e595877c
6
+ metadata.gz: 290e56a65e8c9e163d1558efe87fb93c8d74522c9aa1410f77a21ea6fe81d4a8270ec03947deb959699940c1c40ff91b4749f9512f1de4e005ac822cb564934a
7
+ data.tar.gz: 0e27f41ad71bca972355c70c235d900ae0c4ec571c47f9fd7324b979b3036b02f4cd6dd5aaa0464d4dd5ac12f2989ae38aed5e15613c496eb182dacb92f3bf11
data/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.4.0] - 2024-10-29
4
+
5
+ **Improvements:**
6
+
7
+ - Introduced constants for fixed tag size and block character in the `TagDistribution` module.
8
+ - Refactored `process_and_print_tags` to use constants directly and ensure tags are truncated to fit within the defined size.
9
+ - Simplified `calculate_value_and_bar_length` method to directly calculate percentage value and bar length using `MAX_BAR_LENGTH`.
10
+ - Renamed `summary` to `report` in `application.rb` for clarity.
11
+ - Integrated `Formatter` functionality into `Table` and `TimeBlockChart` modules.
12
+ - Added new methods in `Table` for formatting specific parts of the table row.
13
+ - Enhanced `TimeBlockChart` with new methods for formatting and printing date information.
14
+ - Integrated `Table` and `TimeBlockChart` into `TimeReport` for a more modular structure.
15
+ - Removed redundant methods from `TimeReportHelper` and ensured all necessary methods are included in the appropriate modules.
16
+ - Added a `blue` method to the `String` class to apply blue color to text and applied it to the total time display in `TimeReport`.
17
+ - Refactored database initialization and column addition logic to improve reusability and maintainability.
18
+ - Refactored Pomodoro session handling and table formatting to improve readability and functionality.
19
+ - Refactored `summary` method to use `time_scope` instead of `filter` for clarity.
20
+ - Refactored insertion logic to improve clarity and prevent redundant checks.
21
+ - Refactored tag distribution formatting into a separate `TagDistribution` module for better code organization.
22
+
23
+ **Bug fixes:**
24
+
25
+ - Fixed a typo in the table header title.
26
+
27
+ ## [1.3.2] - 2024-10-25
28
+
29
+ **Improvements:**
30
+
31
+ - Refactor and enhance time tracking report formatting.
32
+ - Refactored the `format_table_header` method to improve readability and use the `blink` and `red` color methods.
33
+ - Updated the `format_tag_distribution` method to use the `color` method for horizontal bars.
34
+ - Refactored the `print_time_block_chart` method to use the `start_hour` variable consistently.
35
+ - Enhanced the `print_header` method to improve alignment and use the `gray` color method.
36
+ - Refactored the `print_blocks` method to use the `red` color method for weekends and the `underline` method for week numbers.
37
+ - Added a new `print_footer` method to print the footer of the report.
38
+ - Refactored the `print_colored_block` method to use the `color` method for colored blocks.
39
+ - Updated the `application.rb` file to improve the description of the `start` command.
40
+ - Refactor color codes and add new methods.
41
+ - Removed hardcoded color codes and replaced them with a dynamic color method.
42
+ - Added new methods for underline, blink, and green color.
43
+ - Updated the String class extension to use the new color methods.
44
+ - Added a new file 'color_codes.rb' to the 'lib/timet.rb' require list.
45
+ - Removed YARD documentation comments from 'lib/timet.rb' as they are no longer needed.
46
+ - Update JSON and SQLite3 dependencies.
47
+ - Add hours per day feature.
48
+
49
+ **Bug fixes:**
50
+
51
+ - Refactor error message printing to use color method.
52
+ - Updated the `print_error` method in `validation_edit_helper.rb` to use the `red` color method instead of hardcoded ANSI escape codes.
53
+ - This change improves readability and consistency with other color usage in the project.
54
+
55
+ **Additional Considerations:**
56
+
57
+ - The changes in this pull request improve the overall user experience by enhancing the visual presentation of the time tracking report and updating the documentation.
58
+ - The refactor of color codes and addition of new methods improve the flexibility and visual effects of terminal output.
59
+ - The update to JSON and SQLite3 dependencies ensures compatibility with the latest versions of these libraries.
60
+ - The addition of the hours per day feature provides more detailed information in the time tracking report.
61
+
3
62
  ## [1.3.1] - 2024-10-24
4
63
 
5
64
  **Improvements:**
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  Timet refers to a command-line tool designed to track your activities by recording the time spent on each task, allowing you to monitor your work hours and productivity directly from your terminal without needing a graphical interface; essentially, it's a way to log your time spent on different projects or tasks using simple text commands
11
11
 
12
- **Key Features:**
12
+ 🔑 **Key Features:**
13
13
 
14
14
  - **Local Data Storage:** Timet utilizes SQLite to store your time tracking data locally, ensuring privacy and security.
15
15
  - **Lightweight and Fast:** Its efficient design and local data storage make Timet a speedy and responsive tool.
@@ -22,29 +22,12 @@ Timet refers to a command-line tool designed to track your activities by recordi
22
22
  - **Block Time Plot:** Visualizes the distribution of tracked time across a specified range of dates, with bars in each column representing the amount of time tracked during that specific hour. The plot includes a header showing the hours and a row for each date, displaying the time blocks for each hour.
23
23
  - **Tag Distribution Plot:** Illustrates the proportion of total tracked time allocated to each tag, showing the relative contribution of each tag to the overall time tracked.
24
24
 
25
- Example:
26
25
 
27
- ```bash
28
- Tracked time report [today]:
29
- +-------+------------+--------+----------+----------+----------+--------------------------+
30
- | Id | Date | Tag | Start | End | Duration | Notes |
31
- +-------+------------+--------+----------+----------+----------+--------------------------+
32
- | 20 | 2024-10-10 | Tag8 | 19:26:58 | 20:26:58 | 01:00:00 | Notes 2 |
33
- | 19 | | Tag3 | 07:52:26 | 08:52:26 | 01:00:00 | Notes 7 |
34
- +-------+------------+--------+----------+----------+----------+--------------------------+
35
- | Total: | 02:00:00 | |
36
- +-------+------------+--------+----------+----------+----------+--------------------------+
37
-
38
- ⏳ ↦ [ 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ]
39
- [ ▂▂ ▇▇ ▅▅ ▄▄ ]
40
-
41
- Tag8: 50.0% ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅
42
- Tag3: 50.0% ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅
43
- ```
26
+ Examples:
44
27
 
45
- ![Timet monthly report](monthly_report.webp)
28
+ ![Timet1 demo](timet1.gif)
46
29
 
47
- ## Requirements
30
+ ## ✔️ Requirements
48
31
 
49
32
  - Ruby version: >= 3.0.0
50
33
  - sqlite3: > 1.7
@@ -55,7 +38,7 @@ Old versions of Ruby and Sqlite:
55
38
 
56
39
  - [Ruby >= 2.4](https://github.com/frankvielma/timet/tree/ruby-2.4.0)
57
40
 
58
- ## Installation
41
+ ## 💾 Installation
59
42
 
60
43
  Install the gem by executing:
61
44
 
@@ -63,7 +46,7 @@ Install the gem by executing:
63
46
  gem install timet
64
47
  ```
65
48
 
66
- ## Usage
49
+ ## Usage
67
50
 
68
51
  ### Command Aliases
69
52
 
@@ -180,7 +163,7 @@ gem install timet
180
163
  +-------+------------+--------+----------+----------+----------+--------------------------+
181
164
  ```
182
165
 
183
- ## Command Reference
166
+ ## 📋 Command Reference
184
167
 
185
168
  | Command | Description | Example Usage |
186
169
  | ----------------------------------- | --------------------------------------------------------------------------- | --------------------------------- |
@@ -36,7 +36,8 @@ module Timet
36
36
  VALID_STATUSES_FOR_INSERTION = %i[no_items complete].freeze
37
37
 
38
38
  desc "start [tag] --notes='' --pomodoro=[min]",
39
- 'Starts tracking time for a task labeled with the provided [tag], notes and "pomodoro time" in minutes (optional).'
39
+ 'Starts tracking time for a task labeled with the provided [tag], notes and "pomodoro time" in minutes
40
+ (optional).'
40
41
  option :notes, type: :string, desc: 'Add a note'
41
42
  option :pomodoro, type: :numeric, desc: 'Pomodoro time in minutes'
42
43
  # Starts a new tracking session with the given tag and optional notes.
@@ -68,10 +69,12 @@ module Timet
68
69
  notes = options[:notes] || notes
69
70
  pomodoro = (options[:pomodoro] || pomodoro).to_i
70
71
 
71
- if VALID_STATUSES_FOR_INSERTION.include?(@db.last_item_status)
72
- @db.insert_item(start_time, tag, notes)
73
- play_sound_and_notify(pomodoro * 60, tag) if pomodoro.positive?
72
+ unless VALID_STATUSES_FOR_INSERTION.include?(@db.last_item_status)
73
+ return puts 'A task is currently being tracked.'
74
74
  end
75
+
76
+ @db.insert_item(start_time, tag, notes, pomodoro)
77
+ play_sound_and_notify(pomodoro * 60, tag) if pomodoro.positive?
75
78
  summary
76
79
  end
77
80
 
@@ -127,15 +130,15 @@ module Timet
127
130
  end
128
131
  end
129
132
 
130
- desc 'summary (su) [filter] [tag] --csv=csv_filename',
131
- '[filter] => [today (t), yesterday (y), week (w), month (m), [start_date]..[end_date]] [tag]'
133
+ desc 'summary (su) [time_scope] [tag] --csv=csv_filename',
134
+ '[time_scope] => [today (t), yesterday (y), week (w), month (m), [start_date]..[end_date]] [tag]'
132
135
  option :csv, type: :string, desc: 'Export to CSV file'
133
- # Generates a summary of tracking items based on the provided filter and tag, and optionally exports the summary
136
+ # Generates a summary of tracking items based on the provided time_scope and tag, and optionally exports the summary
134
137
  # to a CSV file.
135
138
  #
136
- # @param filter [String, nil] The filter to apply when generating the summary. Possible values include 'today',
137
- # 'yesterday', 'week', 'month', or a date range in the format '[start_date]..[end_date]'.
138
- # @param tag [String, nil] The tag to filter the tracking items by.
139
+ # @param time_scope [String, nil] The time_scope to apply when generating the summary. Possible values include
140
+ # 'today', 'yesterday', 'week', 'month', or a date range in the format '[start_date]..[end_date]'.
141
+ # @param tag [String, nil] The tag to time_scope the tracking items by.
139
142
  #
140
143
  # @return [void] This method does not return a value; it performs side effects such as displaying the summary and
141
144
  # exporting to CSV if specified.
@@ -149,19 +152,19 @@ module Timet
149
152
  # @example Generate a summary for a date range and export to CSV
150
153
  # summary('2023-01-01..2023-01-31', nil, csv: 'summary.csv')
151
154
  #
152
- # @note The method initializes a `TimeReport` object with the database, filter, tag, and optional CSV filename.
155
+ # @note The method initializes a `TimeReport` object with the database, time_scope, tag, and optional CSV filename.
153
156
  # @note The method calls `display` on the `TimeReport` object to show the summary.
154
157
  # @note If a CSV filename is provided and there are items to export, the method calls `export_sheet` to export the
155
158
  # summary to a CSV file.
156
159
  # @note If no items are found to export, it prints a message indicating that no items were found.
157
- def summary(filter = nil, tag = nil)
160
+ def summary(time_scope = nil, tag = nil)
158
161
  csv_filename = options[:csv]&.split('.')&.first
159
- summary = TimeReport.new(@db, filter, tag, csv_filename)
162
+ report = TimeReport.new(@db, time_scope, tag, csv_filename)
160
163
 
161
- summary.display
162
- items = summary.items
164
+ report.display
165
+ items = report.items
163
166
  if csv_filename && items.any?
164
- summary.export_sheet
167
+ report.export_sheet
165
168
  elsif items.empty?
166
169
  puts 'No items found to export'
167
170
  end
@@ -280,25 +283,5 @@ module Timet
280
283
  def version
281
284
  puts Timet::VERSION
282
285
  end
283
-
284
- private
285
-
286
- # Deletes a tracking item from the database by its ID and prints a confirmation message.
287
- #
288
- # @param id [Integer] The ID of the tracking item to be deleted.
289
- # @param message [String] The message to be printed after the item is deleted.
290
- #
291
- # @return [void] This method does not return a value; it performs side effects such as deleting the tracking item
292
- # and printing a message.
293
- #
294
- # @example Delete a tracking item with ID 1 and print a confirmation message
295
- # delete_item_and_print_message(1, 'Deleted item 1')
296
- #
297
- # @note The method deletes the tracking item from the database using `@db.delete_item(id)`.
298
- # @note After deleting the item, the method prints the provided message using `puts message`.
299
- def delete_item_and_print_message(id, message)
300
- @db.delete_item(id)
301
- puts message
302
- end
303
286
  end
304
287
  end
@@ -109,10 +109,10 @@ module Timet
109
109
  # @param tag [String] A tag or label for the session, used in the notification message.
110
110
  # @return [void]
111
111
  def run_linux_session(time, tag)
112
- notification_command = "notify-send --icon=clock 'Pomodoro session complete! (tag: #{tag}) Time for a break.'"
112
+ notification_command = "notify-send --icon=clock '#{show_message(tag)}'"
113
113
  command = "sleep #{time} && tput bel && tt stop 0 && #{notification_command} &"
114
114
  pid = spawn(command)
115
- Process.wait(pid)
115
+ Process.detach(pid)
116
116
  end
117
117
 
118
118
  # Runs a Pomodoro session on a macOS system.
@@ -120,11 +120,42 @@ module Timet
120
120
  # @param time [Integer] The duration of the Pomodoro session in seconds.
121
121
  # @param _tag [String] A tag or label for the session, not used in the notification message on macOS.
122
122
  # @return [void]
123
- def run_mac_session(time, _tag)
124
- notification_command = "osascript -e 'display notification \"Pomodoro session complete! Time for a break.\"'"
123
+ def run_mac_session(time, tag)
124
+ notification_command = "osascript -e 'display notification \"#{show_message(tag)}\"'"
125
125
  command = "sleep #{time} && afplay /System/Library/Sounds/Basso.aiff && tt stop 0 && #{notification_command} &"
126
126
  pid = spawn(command)
127
- Process.wait(pid)
127
+ Process.detach(pid)
128
+ end
129
+
130
+ # Generates a message indicating that a Pomodoro session is complete and it's time for a break.
131
+ #
132
+ # @param tag [String] The tag associated with the completed Pomodoro session.
133
+ # @return [String] A message indicating the completion of the Pomodoro session and suggesting a break.
134
+ #
135
+ # @example
136
+ # show_message("work")
137
+ # # => "Pomodoro session complete (work). Time for a break."
138
+ #
139
+ def show_message(tag)
140
+ "Pomodoro session complete (#{tag}). Time for a break."
141
+ end
142
+
143
+ # Deletes a tracking item from the database by its ID and prints a confirmation message.
144
+ #
145
+ # @param id [Integer] The ID of the tracking item to be deleted.
146
+ # @param message [String] The message to be printed after the item is deleted.
147
+ #
148
+ # @return [void] This method does not return a value; it performs side effects such as deleting the tracking item
149
+ # and printing a message.
150
+ #
151
+ # @example Delete a tracking item with ID 1 and print a confirmation message
152
+ # delete_item_and_print_message(1, 'Deleted item 1')
153
+ #
154
+ # @note The method deletes the tracking item from the database using `@db.delete_item(id)`.
155
+ # @note After deleting the item, the method prints the provided message using `puts message`.
156
+ def delete_item_and_print_message(id, message)
157
+ @db.delete_item(id)
158
+ puts message
128
159
  end
129
160
  end
130
161
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Timet
4
+ # ColorCodes class
5
+ class ColorCodes
6
+ RESET = "\u001b[0m"
7
+ UNDERLINE = "\e[4m"
8
+ BLINK = "\e[5m"
9
+
10
+ def self.reset
11
+ RESET
12
+ end
13
+
14
+ def self.underline
15
+ UNDERLINE
16
+ end
17
+
18
+ def self.blink
19
+ BLINK
20
+ end
21
+
22
+ def self.color(num)
23
+ "\u001b[38;5;#{num}m"
24
+ end
25
+ end
26
+ end
27
+
28
+ # Extend String class globally
29
+ class String
30
+ def white
31
+ "#{Timet::ColorCodes.color(246)}#{self}#{Timet::ColorCodes.reset}"
32
+ end
33
+
34
+ def gray
35
+ "#{Timet::ColorCodes.color(242)}#{self}#{Timet::ColorCodes.reset}"
36
+ end
37
+
38
+ def red
39
+ "#{Timet::ColorCodes.color(1)}#{self}#{Timet::ColorCodes.reset}"
40
+ end
41
+
42
+ def blue
43
+ "#{Timet::ColorCodes.color(12)}#{self}#{Timet::ColorCodes.reset}"
44
+ end
45
+
46
+ def underline
47
+ "#{Timet::ColorCodes.underline}#{self}#{Timet::ColorCodes.reset}"
48
+ end
49
+
50
+ def blink
51
+ "#{Timet::ColorCodes.blink}#{self}#{Timet::ColorCodes.reset}"
52
+ end
53
+
54
+ def green
55
+ "#{Timet::ColorCodes.color(10)}#{self}#{Timet::ColorCodes.reset}"
56
+ end
57
+
58
+ def color(num)
59
+ "#{Timet::ColorCodes.color(num)}#{self}#{Timet::ColorCodes.reset}"
60
+ end
61
+ end
@@ -28,7 +28,9 @@ module Timet
28
28
  def initialize(database_path = DEFAULT_DATABASE_PATH)
29
29
  @db = SQLite3::Database.new(database_path)
30
30
  create_table
31
- add_notes
31
+
32
+ add_column('items', 'notes', 'TEXT')
33
+ add_column('items', 'pomodoro', 'INTEGER')
32
34
  end
33
35
 
34
36
  # Creates the items table if it doesn't already exist.
@@ -51,23 +53,27 @@ module Timet
51
53
  SQL
52
54
  end
53
55
 
54
- # Adds a new column named "notes" to the "items" table if it doesn't exist.
56
+ # Adds a new column to the specified table if it does not already exist.
55
57
  #
56
- # @return [void] This method does not return a value; it performs side effects such as executing SQL to add
57
- # the column.
58
+ # @param table_name [String] The name of the table to which the column will be added.
59
+ # @param new_column_name [String] The name of the new column to be added.
60
+ # @param date_type [String] The data type of the new column (e.g., 'INTEGER', 'TEXT', 'BOOLEAN').
61
+ # @return [void] This method does not return a value; it performs side effects such as adding the column and
62
+ # printing a message.
58
63
  #
59
- # @example Add the notes column to the items table
60
- # add_notes
64
+ # @example Add a new 'completed' column to the 'tasks' table
65
+ # add_column('tasks', 'completed', 'INTEGER')
61
66
  #
62
- # @note The method checks if the 'notes' column already exists and adds it if it does not.
63
- def add_notes
64
- table_name = 'items'
65
- new_column_name = 'notes'
67
+ # @note The method first checks if the column already exists in the table using `pragma_table_info`.
68
+ # @note If the column exists, the method returns without making any changes.
69
+ # @note If the column does not exist, the method executes an SQL `ALTER TABLE` statement to add the column.
70
+ # @note The method prints a message indicating that the column has been added.
71
+ def add_column(table_name, new_column_name, date_type)
66
72
  result = execute_sql("SELECT count(*) FROM pragma_table_info('items') where name='#{new_column_name}'")
67
73
  column_exists = result[0][0].positive?
68
74
  return if column_exists
69
75
 
70
- execute_sql("ALTER TABLE #{table_name} ADD COLUMN #{new_column_name} TEXT")
76
+ execute_sql("ALTER TABLE #{table_name} ADD COLUMN #{new_column_name} #{date_type}")
71
77
  puts "Column '#{new_column_name}' added to table '#{table_name}'."
72
78
  end
73
79
 
@@ -84,8 +90,8 @@ module Timet
84
90
  # insert_item(1633072800, 'work', 'Completed task X')
85
91
  #
86
92
  # @note The method executes SQL to insert a new row into the 'items' table.
87
- def insert_item(start, tag, notes)
88
- execute_sql('INSERT INTO items (start, tag, notes) VALUES (?, ?, ?)', [start, tag, notes])
93
+ def insert_item(start, tag, notes, pomodoro = nil)
94
+ execute_sql('INSERT INTO items (start, tag, notes, pomodoro) VALUES (?, ?, ?, ?)', [start, tag, notes, pomodoro])
89
95
  end
90
96
 
91
97
  # Updates an existing item in the items table.
@@ -171,7 +177,7 @@ module Timet
171
177
  #
172
178
  # @note The method executes SQL to find the item with the given ID in the 'items' table.
173
179
  def find_item(id)
174
- execute_sql("select * from items where id=#{id}").first
180
+ execute_sql("SELECT * from items where id=#{id}").first
175
181
  end
176
182
 
177
183
  # Fetches all items from the items table that have a start time greater than or equal to today.