fewald-worklog 0.2.15 → 0.2.18
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 +4 -4
- data/.version +1 -1
- data/lib/cli.rb +1 -0
- data/lib/printer.rb +11 -1
- data/lib/project.rb +17 -1
- data/lib/project_storage.rb +24 -7
- data/lib/storage.rb +4 -7
- data/lib/worklog.rb +49 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 226d608638c12cd6ed618d5669d1e675baf2826ec9f7092887cf08b2612bf845
|
4
|
+
data.tar.gz: 897ee2bbd7ee446a2397815632c0738115c7b2ce4e37251ef3197db7cbf1c7fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c313a4c546a9aa10ca55c718fda09a9ec3bedd3e16bea9beaea95cfb0153ac1b2ac3be1f8d06f5a5baa60e33d451bfbb270c2f6ddbc31a381462da6e549dd8db
|
7
|
+
data.tar.gz: bede43615c16b5c457e953c0f30a902cfaeaa4d55dc7ddcc9d00bdfe6f27e9b40676ee94a88d7c2d89d34b6321bd8e0284fd8233c4144c4ee1864a91505e7091
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.18
|
data/lib/cli.rb
CHANGED
@@ -92,6 +92,7 @@ class WorklogCLI < Thor
|
|
92
92
|
EOF
|
93
93
|
option :epics_only, type: :boolean, default: false, desc: 'Show only entries that are marked as epic'
|
94
94
|
option :tags, type: :array, default: [], desc: 'Filter entries by tags. Tags are treated as an OR condition.'
|
95
|
+
option :project, type: :string, desc: 'Filter entries by project key.'
|
95
96
|
def show
|
96
97
|
worklog = Worklog::Worklog.new
|
97
98
|
worklog.show(options)
|
data/lib/printer.rb
CHANGED
@@ -15,7 +15,15 @@ class Printer
|
|
15
15
|
# Prints a whole day of work log entries.
|
16
16
|
# If date_inline is true, the date is printed inline with the time.
|
17
17
|
# If epics_only is true, only epic entries are printed.
|
18
|
-
|
18
|
+
# @param daily_log [DailyLog] The daily log containing entries.
|
19
|
+
# @param date_inline [Boolean] If true, the date is printed inline with the time.
|
20
|
+
# @param epics_only [Boolean] If true, only epic entries are printed.
|
21
|
+
# @param filter [Hash] A hash of filters to apply to the entries.
|
22
|
+
# @return [void]
|
23
|
+
# @example
|
24
|
+
# printer.print_day(daily_log, date_inline: true, epics_only: false, project: 'xyz')
|
25
|
+
# printer.print_day(daily_log, date_inline: false, epics_only: true)
|
26
|
+
def print_day(daily_log, date_inline = false, epics_only = false, filter = {})
|
19
27
|
daily_log.date = Date.strptime(daily_log.date, '%Y-%m-%d') unless daily_log.date.respond_to?(:strftime)
|
20
28
|
|
21
29
|
date_string = daily_log.date.strftime('%a, %B %-d, %Y')
|
@@ -24,6 +32,8 @@ class Printer
|
|
24
32
|
daily_log.entries.each do |entry|
|
25
33
|
next if epics_only && !entry.epic?
|
26
34
|
|
35
|
+
next unless filter.compact.all? { |k, v| entry.send(k) == v }
|
36
|
+
|
27
37
|
print_entry(daily_log, entry, date_inline)
|
28
38
|
end
|
29
39
|
end
|
data/lib/project.rb
CHANGED
@@ -3,8 +3,24 @@
|
|
3
3
|
module Worklog
|
4
4
|
# Represents a project. A project is a longer running task or initiative.
|
5
5
|
# Single log entries can be associated with a project.
|
6
|
+
# @!attribute [rw] key
|
7
|
+
# @return [String] Unique identifier for the project, used in log entries.
|
8
|
+
# @!attribute [rw] name
|
9
|
+
# @return [String] The human-readable name of the project.
|
10
|
+
# @!attribute [rw] description
|
11
|
+
# @return [String, nil] A description of the project, can be nil
|
12
|
+
# @!attribute [rw] start_date
|
13
|
+
# @return [Date, nil] The start date of the project, can be nil
|
14
|
+
# @!attribute [rw] end_date
|
15
|
+
# @return [Date, nil] The end date of the project, can be nil
|
16
|
+
# @!attribute [rw] status
|
17
|
+
# @return [String, nil] The status of the project, can be nil
|
18
|
+
# Possible values: 'active', 'completed', 'archived', etc.
|
19
|
+
# Indicates the current state of the project.
|
20
|
+
# @!attribute [rw] last_activity
|
21
|
+
# @return [Date, nil] The last activity date or nil if not set.
|
6
22
|
class Project
|
7
|
-
attr_accessor :key, :name, :description, :start_date, :end_date, :status
|
23
|
+
attr_accessor :key, :name, :description, :start_date, :end_date, :status, :last_activity
|
8
24
|
|
9
25
|
# Creates a new Project instance from a hash of attributes.
|
10
26
|
# @param hash [Hash] A hash containing project attributes
|
data/lib/project_storage.rb
CHANGED
@@ -10,6 +10,8 @@ module Worklog
|
|
10
10
|
|
11
11
|
# ProjectStorage is responsible for loading and managing project data.
|
12
12
|
# It provides methods to load projects from a YAML file and check if a project exists.
|
13
|
+
# @!attribute [w] projects
|
14
|
+
# @return [Hash<String, Project>] A hash of projects keyed by their project keys.
|
13
15
|
#
|
14
16
|
# @see Project
|
15
17
|
# @see Configuration
|
@@ -17,6 +19,11 @@ module Worklog
|
|
17
19
|
class ProjectStorage
|
18
20
|
attr_writer :projects
|
19
21
|
|
22
|
+
# The name of the YAML file where projects are stored.
|
23
|
+
FILE_NAME = 'projects.yaml'
|
24
|
+
|
25
|
+
# The template for the projects YAML file.
|
26
|
+
# This template is used to create a new projects file if it does not exist.
|
20
27
|
PROJECT_TEMPLATE = <<~YAML
|
21
28
|
# Each project is defined by the following attributes:
|
22
29
|
# - key: <project_key>
|
@@ -44,7 +51,7 @@ module Worklog
|
|
44
51
|
def load_projects
|
45
52
|
create_template unless file_exist?
|
46
53
|
|
47
|
-
file_path = File.join(@configuration.storage_path,
|
54
|
+
file_path = File.join(@configuration.storage_path, FILE_NAME)
|
48
55
|
projects = {}
|
49
56
|
YAML.load_file(file_path, permitted_classes: [Date])&.each do |project_hash|
|
50
57
|
project = Project.from_hash(project_hash)
|
@@ -54,12 +61,14 @@ module Worklog
|
|
54
61
|
projects
|
55
62
|
end
|
56
63
|
|
57
|
-
# Check if a project with a given
|
58
|
-
# @param
|
64
|
+
# Check if a project with a given key exists.
|
65
|
+
# @param key [String] The key of the project to check.
|
59
66
|
# @return [Boolean] Returns true if the project exists, false otherwise.
|
60
|
-
|
67
|
+
# @note This method loads the projects from disk if they are not already loaded.
|
68
|
+
# @see load_projects
|
69
|
+
def exist?(key)
|
61
70
|
projects = load_projects
|
62
|
-
projects.key?(
|
71
|
+
projects.key?(key)
|
63
72
|
end
|
64
73
|
|
65
74
|
private
|
@@ -67,12 +76,20 @@ module Worklog
|
|
67
76
|
# Check whether projects.yaml exists in the project_dir
|
68
77
|
# @return [Boolean] Returns true if the project YAML file exists, false otherwise
|
69
78
|
def file_exist?
|
70
|
-
file_path = File.join(@configuration.storage_path,
|
79
|
+
file_path = File.join(@configuration.storage_path, FILE_NAME)
|
71
80
|
File.exist?(file_path)
|
72
81
|
end
|
73
82
|
|
83
|
+
# Creates a template for the projects YAML file if it does not exist.
|
84
|
+
# This method writes a predefined template to the projects.yml file.
|
85
|
+
# @return [void]
|
86
|
+
# @note This method will overwrite any existing projects.yml file.
|
87
|
+
# @see PROJECT_TEMPLATE for the structure of the template.
|
74
88
|
def create_template
|
75
|
-
|
89
|
+
return unless @configuration.storage_path_exist?
|
90
|
+
|
91
|
+
File.write(File.join(@configuration.storage_path, FILE_NAME), PROJECT_TEMPLATE)
|
92
|
+
nil
|
76
93
|
end
|
77
94
|
end
|
78
95
|
end
|
data/lib/storage.rb
CHANGED
@@ -93,8 +93,6 @@ class Storage
|
|
93
93
|
# Create file for a new day if it does not exist
|
94
94
|
# @param [Date] date The date, used as the file name.
|
95
95
|
def create_file_skeleton(date)
|
96
|
-
create_folder
|
97
|
-
|
98
96
|
File.write(filepath(date), YAML.dump(DailyLog.new(date:, entries: []))) unless File.exist?(filepath(date))
|
99
97
|
end
|
100
98
|
|
@@ -119,8 +117,6 @@ class Storage
|
|
119
117
|
end
|
120
118
|
|
121
119
|
def write_log(file, daily_log)
|
122
|
-
create_folder
|
123
|
-
|
124
120
|
WorkLogger.debug "Writing to file #{file}"
|
125
121
|
|
126
122
|
File.open(file, 'w') do |f|
|
@@ -162,8 +158,6 @@ class Storage
|
|
162
158
|
# Write people to the people file
|
163
159
|
# @param [Array<Person>] people List of people
|
164
160
|
def write_people!(people)
|
165
|
-
create_folder
|
166
|
-
|
167
161
|
people_file = File.join(@config.storage_path, 'people.yaml')
|
168
162
|
File.open(people_file, 'w') do |f|
|
169
163
|
f.puts people.to_yaml
|
@@ -171,7 +165,10 @@ class Storage
|
|
171
165
|
end
|
172
166
|
|
173
167
|
# Create folder if not exists already.
|
174
|
-
def
|
168
|
+
def create_default_folder
|
169
|
+
# Do nothing if the storage path is not the default path
|
170
|
+
return unless @config.default_storage_path?
|
171
|
+
|
175
172
|
Dir.mkdir(@config.storage_path) unless Dir.exist?(@config.storage_path)
|
176
173
|
end
|
177
174
|
|
data/lib/worklog.rb
CHANGED
@@ -22,6 +22,22 @@ module Worklog
|
|
22
22
|
# Main class providing all worklog functionality.
|
23
23
|
# This class is the main entry point for the application.
|
24
24
|
# It handles command line arguments, configuration, and logging.
|
25
|
+
# @!attribute [r] config
|
26
|
+
# @return [Configuration] The configuration object containing settings for the application.
|
27
|
+
# @!attribute [r] storage
|
28
|
+
# @return [Storage] The storage object for managing file operations.
|
29
|
+
#
|
30
|
+
# @see Configuration
|
31
|
+
# @see Storage
|
32
|
+
# @see ProjectStorage
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# worklog = Worklog.new
|
36
|
+
# worklog.add('Worked on feature X',
|
37
|
+
# date: '2023-10-01',
|
38
|
+
# time: '10:00:00',
|
39
|
+
# tags: ['feature', 'x'],
|
40
|
+
# ticket: 'TICKET-123')
|
25
41
|
class Worklog
|
26
42
|
include StringHelper
|
27
43
|
attr_reader :config, :storage
|
@@ -31,6 +47,13 @@ module Worklog
|
|
31
47
|
@storage = Storage.new(@config)
|
32
48
|
|
33
49
|
WorkLogger.level = @config.log_level == :debug ? Logger::Severity::DEBUG : Logger::Severity::INFO
|
50
|
+
|
51
|
+
bootstrap
|
52
|
+
end
|
53
|
+
|
54
|
+
# Bootstrap the worklog application.
|
55
|
+
def bootstrap
|
56
|
+
@storage.create_default_folder
|
34
57
|
end
|
35
58
|
|
36
59
|
# Add new entry to the work log.
|
@@ -92,6 +115,20 @@ module Worklog
|
|
92
115
|
WorkLogger.info Rainbow("Updated work log for #{options[:date]}").green
|
93
116
|
end
|
94
117
|
|
118
|
+
# Show the work log for a specific date range or a single date.
|
119
|
+
#
|
120
|
+
# @param options [Hash] the options hash containing date range or single date.
|
121
|
+
# @option options [Integer] :days the number of days to show from today (default: 1).
|
122
|
+
# @option options [String] :from the start date in 'YYYY-MM-DD' format.
|
123
|
+
# @option options [String] :to the end date in 'YYYY-MM-DD' format.
|
124
|
+
# @option options [String] :date a specific date in 'YYYY-MM-DD' format.
|
125
|
+
# @option options [Boolean] :epics_only whether to show only entries with epics (default: false).
|
126
|
+
# @option options [String] :project the project key to filter entries by project.
|
127
|
+
#
|
128
|
+
# @example
|
129
|
+
# worklog.show(days: 7)
|
130
|
+
# worklog.show(from: '2023-10-01', to: '2023-10-31')
|
131
|
+
# worklog.show(date: '2023-10-01')
|
95
132
|
def show(options = {})
|
96
133
|
people = @storage.load_people!
|
97
134
|
printer = Printer.new(people)
|
@@ -103,7 +140,7 @@ module Worklog
|
|
103
140
|
printer.no_entries(start_date, end_date)
|
104
141
|
else
|
105
142
|
entries.each do |entry|
|
106
|
-
printer.print_day(entry, entries.size > 1, options[:epics_only])
|
143
|
+
printer.print_day(entry, entries.size > 1, options[:epics_only], project: options[:project])
|
107
144
|
end
|
108
145
|
end
|
109
146
|
end
|
@@ -170,8 +207,8 @@ module Worklog
|
|
170
207
|
projects.each_value do |project|
|
171
208
|
puts "#{Rainbow(project.name).gold} (#{project.key})"
|
172
209
|
puts " Description: #{project.description}" if project.description
|
173
|
-
puts " Start date: #{project.start_date}" if project.start_date
|
174
|
-
puts " End date: #{project.end_date}" if project.end_date
|
210
|
+
puts " Start date: #{project.start_date.strftime('%b %d, %Y')}" if project.start_date
|
211
|
+
puts " End date: #{project.end_date.strftime('%b %d, %Y')}" if project.end_date
|
175
212
|
puts " Status: #{project.status}" if project.status
|
176
213
|
end
|
177
214
|
puts 'No projects found.' if projects.empty?
|
@@ -326,6 +363,15 @@ module Worklog
|
|
326
363
|
[start_date, end_date]
|
327
364
|
end
|
328
365
|
|
366
|
+
# Validate that the project exists in the project storage if a project key is provided.
|
367
|
+
#
|
368
|
+
# @param project_key [String] the project key to validate
|
369
|
+
# @raise [ProjectNotFoundError] if the project does not exist
|
370
|
+
#
|
371
|
+
# @return [void]
|
372
|
+
#
|
373
|
+
# @example
|
374
|
+
# validate_projects!('P001')
|
329
375
|
def validate_projects!(project_key)
|
330
376
|
project_storage = ProjectStorage.new(@config)
|
331
377
|
begin
|