fewald-worklog 0.3.4 → 0.3.6
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 +7 -0
- data/lib/configuration.rb +28 -1
- data/lib/person.rb +17 -1
- data/lib/project_storage.rb +3 -0
- data/lib/storage.rb +55 -7
- data/lib/worklog.rb +17 -6
- 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: e2554331b36043db6a3386effbe1c243c99c97bbceae33b4faa4fcbdf8242101
|
|
4
|
+
data.tar.gz: 8497987c745fad61def23bb27eb02a2c1785cd988bdcc21598cf13d8a0fa01b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d40bccfd27b7da9e638259a5eec07d3cb5f7c898fc9692eee088dfe93a5abeb39023a617434f784ff9a4a6047ba4a9acd2c5db672c82d4006180c4b1663636cc
|
|
7
|
+
data.tar.gz: 8cb2393190a637bdff6cb4147d8296f71fae468103dee080778c17035d1438c23db5b3e8cee8a79533029f8acb784690da1deb5f24a6d548406457ab6f2b9f6e
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.3.
|
|
1
|
+
0.3.6
|
data/lib/cli.rb
CHANGED
|
@@ -77,6 +77,12 @@ class WorklogCLI < Thor
|
|
|
77
77
|
worklog.github(options)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
desc 'init', 'Initialize the work log storage and configuration in the home directory'
|
|
81
|
+
def init
|
|
82
|
+
worklog = Worklog::Worklog.new
|
|
83
|
+
worklog.init(options)
|
|
84
|
+
end
|
|
85
|
+
|
|
80
86
|
desc 'remove', 'Remove last entry from the log'
|
|
81
87
|
option :date, type: :string, default: Time.now.strftime('%Y-%m-%d')
|
|
82
88
|
def remove
|
|
@@ -110,6 +116,7 @@ class WorklogCLI < Thor
|
|
|
110
116
|
end
|
|
111
117
|
|
|
112
118
|
desc 'people', 'Show all people mentioned in the work log'
|
|
119
|
+
option :inactive, type: :boolean, default: false, desc: 'Include inactive people in the list'
|
|
113
120
|
def people(person = nil)
|
|
114
121
|
worklog = Worklog::Worklog.new
|
|
115
122
|
worklog.people(person, options)
|
data/lib/configuration.rb
CHANGED
|
@@ -72,6 +72,27 @@ module Worklog
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
CONFIGURATION_TEMPLATE = ERB.new <<~YAML
|
|
76
|
+
# Worklog Configuration File
|
|
77
|
+
# This file contains configuration settings for Worklog.
|
|
78
|
+
# You can modify the values below to customize your setup.
|
|
79
|
+
# For more information, refer to the documentation.
|
|
80
|
+
storage_path: <%= Dir.home %>/.worklog
|
|
81
|
+
log_level: info
|
|
82
|
+
timezone: 'America/Los_Angeles'
|
|
83
|
+
webserver_port: 3000
|
|
84
|
+
|
|
85
|
+
project:
|
|
86
|
+
# Number of last projects to show in the project list
|
|
87
|
+
show_last: 3
|
|
88
|
+
|
|
89
|
+
github:
|
|
90
|
+
# Your GitHub API key for accessing the GitHub API
|
|
91
|
+
api_key: ""
|
|
92
|
+
# Your GitHub username for finding assigned issues and PRs
|
|
93
|
+
username: ""
|
|
94
|
+
YAML
|
|
95
|
+
|
|
75
96
|
# Initialize configuration with optional block for setting attributes.
|
|
76
97
|
# If no block is given, default values are used.
|
|
77
98
|
# @example
|
|
@@ -98,7 +119,7 @@ module Worklog
|
|
|
98
119
|
# If the file does not exist, it will use default values.
|
|
99
120
|
# @return [Configuration] the loaded configuration
|
|
100
121
|
def self.load
|
|
101
|
-
file_path =
|
|
122
|
+
file_path = config_file_path
|
|
102
123
|
config = Configuration.new
|
|
103
124
|
if File.exist?(file_path)
|
|
104
125
|
file_cfg = YAML.load_file(file_path)
|
|
@@ -126,5 +147,11 @@ module Worklog
|
|
|
126
147
|
def default_storage_path?
|
|
127
148
|
@storage_path == File.join(Dir.home, '.worklog')
|
|
128
149
|
end
|
|
150
|
+
|
|
151
|
+
# Get the default configuration file path.
|
|
152
|
+
# @return [String] the default configuration file path
|
|
153
|
+
def self.config_file_path
|
|
154
|
+
File.join(Dir.home, '.worklog.yaml')
|
|
155
|
+
end
|
|
129
156
|
end
|
|
130
157
|
end
|
data/lib/person.rb
CHANGED
|
@@ -13,8 +13,10 @@ module Worklog
|
|
|
13
13
|
# @return [String, nil] The team the person belongs to, can be nil
|
|
14
14
|
# !attribute [r] notes
|
|
15
15
|
# @return [Array<String>] An array of notes about the person
|
|
16
|
+
# !attribute [r] inactive
|
|
17
|
+
# @return [Boolean] Whether the person is inactive (for example left the company)
|
|
16
18
|
class Person
|
|
17
|
-
attr_reader :handle, :github_username, :name, :email, :team, :notes
|
|
19
|
+
attr_reader :handle, :github_username, :name, :email, :team, :notes, :inactive
|
|
18
20
|
|
|
19
21
|
def initialize(handle:, name:, **params)
|
|
20
22
|
# params to symbol keys
|
|
@@ -26,6 +28,20 @@ module Worklog
|
|
|
26
28
|
@email = params[:email]
|
|
27
29
|
@team = params[:team]
|
|
28
30
|
@notes = params[:notes] || []
|
|
31
|
+
@inactive = params[:inactive] || false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns true if the person is active (not inactive).
|
|
35
|
+
# If not specified, persons are active by default.
|
|
36
|
+
# @return [Boolean] true if active, false otherwise
|
|
37
|
+
def active?
|
|
38
|
+
!@inactive
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns true if the person is marked as inactive.
|
|
42
|
+
# @return [Boolean] true if inactive, false otherwise
|
|
43
|
+
def inactive?
|
|
44
|
+
@inactive
|
|
29
45
|
end
|
|
30
46
|
|
|
31
47
|
# Creates a new Person instance from a hash of attributes.
|
data/lib/project_storage.rb
CHANGED
|
@@ -41,6 +41,9 @@ module Worklog
|
|
|
41
41
|
@configuration = configuration
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
# Returns all loaded projects.
|
|
45
|
+
# If the projects are not already loaded, it loads them from disk.
|
|
46
|
+
# @return [Hash<String, Project>] A hash of project objects keyed by their unique project keys.
|
|
44
47
|
def projects
|
|
45
48
|
@projects ||= load_projects
|
|
46
49
|
end
|
data/lib/storage.rb
CHANGED
|
@@ -17,6 +17,21 @@ module Worklog
|
|
|
17
17
|
# Regular expression to match daily log file names
|
|
18
18
|
LOG_PATTERN = /\d{4}-\d{2}-\d{2}#{FILE_SUFFIX}\z/
|
|
19
19
|
|
|
20
|
+
# The template for the people YAML file.
|
|
21
|
+
# This template is used to create a new people file if it does not exist.
|
|
22
|
+
PERSON_TEMPLATE = <<~YAML
|
|
23
|
+
---
|
|
24
|
+
# Each person is defined by the following attributes:
|
|
25
|
+
# - handle: <unique_handle>
|
|
26
|
+
# github_username: <github_username>
|
|
27
|
+
# name: <full_name>
|
|
28
|
+
# team: <team_name>
|
|
29
|
+
# email: <email_address>
|
|
30
|
+
# role: <role_in_team>
|
|
31
|
+
# inactive: <true_or_false>
|
|
32
|
+
# --- Define your people below this line ---
|
|
33
|
+
YAML
|
|
34
|
+
|
|
20
35
|
def initialize(config)
|
|
21
36
|
@config = config
|
|
22
37
|
end
|
|
@@ -157,14 +172,13 @@ module Worklog
|
|
|
157
172
|
# Load all people from the people file
|
|
158
173
|
# @return [Array<Person>] List of people
|
|
159
174
|
def load_people!
|
|
160
|
-
|
|
161
|
-
return [] unless File.exist?(people_file)
|
|
175
|
+
return [] unless File.exist?(people_filepath)
|
|
162
176
|
|
|
163
|
-
yamltext = File.read(
|
|
177
|
+
yamltext = File.read(people_filepath)
|
|
164
178
|
if yamltext != yamltext.gsub(/^- !.*$/, '-')
|
|
165
179
|
WorkLogger.debug 'The people.yaml file contains deprecated syntax. Migrating now.'
|
|
166
180
|
yamltext.gsub!(/^- !.*$/, '-')
|
|
167
|
-
File.write(
|
|
181
|
+
File.write(people_filepath, yamltext)
|
|
168
182
|
end
|
|
169
183
|
YAML.load(yamltext, permitted_classes: []).map { |person_hash| Person.from_hash(person_hash) }
|
|
170
184
|
end
|
|
@@ -172,25 +186,59 @@ module Worklog
|
|
|
172
186
|
# Write people to the people file
|
|
173
187
|
# @param [Array<Person>] people List of people
|
|
174
188
|
def write_people!(people)
|
|
175
|
-
|
|
176
|
-
File.open(people_file, 'w') do |f|
|
|
189
|
+
File.open(people_filepath, 'w') do |f|
|
|
177
190
|
f.puts people.to_yaml
|
|
178
191
|
end
|
|
179
192
|
end
|
|
180
193
|
|
|
181
194
|
# Create folder if not exists already.
|
|
195
|
+
# @return [void]
|
|
182
196
|
def create_default_folder
|
|
197
|
+
WorkLogger.debug 'Creating storage folder if it does not exist.'
|
|
198
|
+
|
|
183
199
|
# Do nothing if the storage path is not the default path
|
|
184
|
-
|
|
200
|
+
unless @config.default_storage_path?
|
|
201
|
+
WorkLogger.debug 'Custom storage path detected, skipping creation of default storage folder.'
|
|
202
|
+
return
|
|
203
|
+
end
|
|
185
204
|
|
|
186
205
|
Dir.mkdir(@config.storage_path) unless Dir.exist?(@config.storage_path)
|
|
187
206
|
end
|
|
188
207
|
|
|
208
|
+
# This method assumes that the storage folder already exists.
|
|
209
|
+
# It creates default files like people.yaml if they do not exist.
|
|
210
|
+
def create_default_files
|
|
211
|
+
WorkLogger.info 'Creating default files in storage folder if they do not exist.'
|
|
212
|
+
# projects_file = File.join(@config.storage_path, 'projects.yaml')
|
|
213
|
+
# unless File.exist?(projects_file)
|
|
214
|
+
# File.write(projects_file, [].to_yaml)
|
|
215
|
+
# end
|
|
216
|
+
|
|
217
|
+
if File.exist?(people_filepath)
|
|
218
|
+
WorkLogger.info 'people.yaml already exists, skipping creation.'
|
|
219
|
+
else
|
|
220
|
+
WorkLogger.info 'Creating default people.yaml file.'
|
|
221
|
+
File.write(people_filepath, PERSON_TEMPLATE)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Write the default config file if it does not exist
|
|
225
|
+
return if File.exist?(Configuration.config_file_path)
|
|
226
|
+
|
|
227
|
+
File.write(Configuration.config_file_path,
|
|
228
|
+
Configuration::CONFIGURATION_TEMPLATE.result)
|
|
229
|
+
end
|
|
230
|
+
|
|
189
231
|
# Construct filepath for a given date.
|
|
190
232
|
# @param [Date] date The date
|
|
191
233
|
# @return [String] The filepath
|
|
192
234
|
def filepath(date)
|
|
193
235
|
File.join(@config.storage_path, "#{date}#{FILE_SUFFIX}")
|
|
194
236
|
end
|
|
237
|
+
|
|
238
|
+
# Return the full absolute filepath for the people.yaml file
|
|
239
|
+
# @return [String] The filepath
|
|
240
|
+
def people_filepath
|
|
241
|
+
File.join(@config.storage_path, 'people.yaml')
|
|
242
|
+
end
|
|
195
243
|
end
|
|
196
244
|
end
|
data/lib/worklog.rb
CHANGED
|
@@ -24,7 +24,7 @@ require 'takeout'
|
|
|
24
24
|
module Worklog
|
|
25
25
|
# Main class providing all worklog functionality.
|
|
26
26
|
# This class is the main entry point for the application.
|
|
27
|
-
# It handles
|
|
27
|
+
# It handles configuration, data storage, and logging.
|
|
28
28
|
# @!attribute [r] config
|
|
29
29
|
# @return [Configuration] The configuration object containing settings for the application.
|
|
30
30
|
# @!attribute [r] storage
|
|
@@ -40,7 +40,9 @@ module Worklog
|
|
|
40
40
|
# date: '2023-10-01',
|
|
41
41
|
# time: '10:00:00',
|
|
42
42
|
# tags: ['feature', 'x'],
|
|
43
|
-
# ticket: 'TICKET-123'
|
|
43
|
+
# ticket: 'TICKET-123',
|
|
44
|
+
# epic: true,
|
|
45
|
+
# project: 'my_project')
|
|
44
46
|
class Worklog
|
|
45
47
|
include StringHelper
|
|
46
48
|
|
|
@@ -50,11 +52,13 @@ module Worklog
|
|
|
50
52
|
# Load or use provided configuration
|
|
51
53
|
@config = config || Configuration.load
|
|
52
54
|
|
|
53
|
-
#
|
|
54
|
-
@storage = Storage.new(@config)
|
|
55
|
-
|
|
55
|
+
# Set log level based on configuration
|
|
56
56
|
WorkLogger.level = @config.log_level == :debug ? Logger::Severity::DEBUG : Logger::Severity::INFO
|
|
57
57
|
|
|
58
|
+
# Initialize (project) storage
|
|
59
|
+
@storage = Storage.new(@config)
|
|
60
|
+
@project_storage = ProjectStorage.new(@config)
|
|
61
|
+
|
|
58
62
|
bootstrap
|
|
59
63
|
end
|
|
60
64
|
|
|
@@ -64,6 +68,9 @@ module Worklog
|
|
|
64
68
|
|
|
65
69
|
# Load all people as they're used in multiple/most of the methods.
|
|
66
70
|
@people = @storage.load_people_hash
|
|
71
|
+
|
|
72
|
+
# Load all projects from disk
|
|
73
|
+
@projects = @project_storage.load_projects
|
|
67
74
|
end
|
|
68
75
|
|
|
69
76
|
# Add new entry to the work log.
|
|
@@ -157,7 +164,7 @@ module Worklog
|
|
|
157
164
|
end
|
|
158
165
|
|
|
159
166
|
# Show all known people and details about a specific person.
|
|
160
|
-
def people(person = nil,
|
|
167
|
+
def people(person = nil, options = {})
|
|
161
168
|
all_logs = @storage.all_days
|
|
162
169
|
|
|
163
170
|
if person
|
|
@@ -180,6 +187,8 @@ module Worklog
|
|
|
180
187
|
|
|
181
188
|
mentions.each do |handle, v|
|
|
182
189
|
if @people.key?(handle)
|
|
190
|
+
next unless @people[handle].active? || options[:inactive]
|
|
191
|
+
|
|
183
192
|
person = @people[handle]
|
|
184
193
|
print "#{Rainbow(person.name).gold} (#{handle})"
|
|
185
194
|
print " (#{person.team})" if person.team
|
|
@@ -195,6 +204,8 @@ module Worklog
|
|
|
195
204
|
printer = Printer.new(@config, all_people)
|
|
196
205
|
puts "All interactions with #{Rainbow(person.name).gold}"
|
|
197
206
|
|
|
207
|
+
puts "GitHub: #{Rainbow(person.github_username).blue}" if person.github_username
|
|
208
|
+
|
|
198
209
|
if person.notes
|
|
199
210
|
puts 'Notes:'
|
|
200
211
|
person.notes.each do |note|
|