fewald-worklog 0.3.7 → 0.3.9
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/github/client.rb +0 -1
- data/lib/people_storage.rb +111 -0
- data/lib/storage.rb +6 -69
- data/lib/worklog.rb +41 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a5a920425a1afeebc25dfcc71d12b6df1019cee84acb600121371d42e041004f
|
|
4
|
+
data.tar.gz: 1f2de59cecee3fd2ed0d553488738bb908aefa1f907c2125aa8c28b3c0a4a641
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1c4d4203b735ebe240623eddfed044793bc6a1a9dc45ade6e28c171f8f9b458a0624228d864b743ffe7396eb1cf432563331027ed68e521e74445ccb27af5107
|
|
7
|
+
data.tar.gz: 648c610f794c778610de43a4698cbb6cbf04cfd8ac3abf09c3d219d3bb9552e0502bf7cb4b823036b1b95c1526114c7ae7b774f6acacd3f208b8683129d214d0
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.3.
|
|
1
|
+
0.3.9
|
data/lib/github/client.rb
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require_relative 'worklogger'
|
|
5
|
+
require_relative 'person'
|
|
6
|
+
module Worklog
|
|
7
|
+
# Handles storage of people
|
|
8
|
+
class PeopleStorage
|
|
9
|
+
PEOPLE_FILE = 'people.yaml'
|
|
10
|
+
|
|
11
|
+
# The template for the people YAML file.
|
|
12
|
+
# This template is used to create a new people file if it does not exist.
|
|
13
|
+
PERSON_TEMPLATE = <<~YAML
|
|
14
|
+
---
|
|
15
|
+
# Each person is defined by the following attributes:
|
|
16
|
+
# - handle: <unique_handle>
|
|
17
|
+
# github_username: <github_username>
|
|
18
|
+
# name: <full_name>
|
|
19
|
+
# team: <team_name>
|
|
20
|
+
# email: <email_address>
|
|
21
|
+
# title: <title_or_role>
|
|
22
|
+
# inactive: <true_or_false>
|
|
23
|
+
# --- Define your people below this line ---
|
|
24
|
+
YAML
|
|
25
|
+
|
|
26
|
+
def initialize(config)
|
|
27
|
+
@config = config
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Return the full absolute filepath for the people.yaml file
|
|
31
|
+
# @return [String] The filepath
|
|
32
|
+
def people_filepath
|
|
33
|
+
File.join(@config.storage_path, PEOPLE_FILE)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Load all people from the people file and return them as a hash with handle as key
|
|
37
|
+
# @return [Hash<String, Person>] Hash of people with handle as key
|
|
38
|
+
def load_people_hash
|
|
39
|
+
load_people.to_h { |person| [person.handle, person] }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Load all people from the people YAML file
|
|
43
|
+
# Return empty array if file does not exist
|
|
44
|
+
# @return [Array<Person>] List of all people
|
|
45
|
+
def load_people
|
|
46
|
+
load_people!
|
|
47
|
+
rescue Errno::ENOENT
|
|
48
|
+
# If the file does not exist, create it with the template
|
|
49
|
+
File.write(people_filepath, PERSON_TEMPLATE)
|
|
50
|
+
[]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Load all people from the people YAML file
|
|
54
|
+
# @return [Array<Person>] List of all people
|
|
55
|
+
# @raise [Errno::ENOENT] if the people file does not exist
|
|
56
|
+
def load_people!
|
|
57
|
+
# TODO: Remove this migration code in future versions
|
|
58
|
+
# This was introduced in v0.2.26 (Oct 2 2025) to fix deprecated YAML syntax
|
|
59
|
+
yamltext = File.read(people_filepath)
|
|
60
|
+
if yamltext != yamltext.gsub(/^- !.*$/, '-')
|
|
61
|
+
WorkLogger.debug 'The people.yaml file contains deprecated syntax. Migrating now.'
|
|
62
|
+
yamltext.gsub!(/^- !.*$/, '-')
|
|
63
|
+
File.write(people_filepath, yamltext)
|
|
64
|
+
end
|
|
65
|
+
# End TODO
|
|
66
|
+
|
|
67
|
+
data = YAML.load(yamltext, permitted_classes: [])
|
|
68
|
+
return [] unless data.is_a?(Array)
|
|
69
|
+
|
|
70
|
+
data.map { |person_hash| Person.from_hash(person_hash) }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Write people to the people file
|
|
74
|
+
# @param [Array<Person>] people List of people
|
|
75
|
+
def write_people!(people)
|
|
76
|
+
raise ArgumentError, 'people must be an array of Person objects' if people.nil? || !people.is_a?(Array)
|
|
77
|
+
|
|
78
|
+
File.open(people_filepath, 'w') do |f|
|
|
79
|
+
f.puts people.to_yaml
|
|
80
|
+
end
|
|
81
|
+
@people = people
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Create the default people file if it does not exist
|
|
85
|
+
# @return [void]
|
|
86
|
+
def create_default_file
|
|
87
|
+
if File.exist?(people_filepath)
|
|
88
|
+
WorkLogger.info 'people.yaml already exists, skipping creation.'
|
|
89
|
+
else
|
|
90
|
+
WorkLogger.info 'Creating default people.yaml file.'
|
|
91
|
+
File.write(people_filepath, PERSON_TEMPLATE)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Find a person by their handle
|
|
96
|
+
# @param [String] handle The handle of the person
|
|
97
|
+
# @return [Person, nil] The person if found, nil otherwise
|
|
98
|
+
def find_by_handle(handle)
|
|
99
|
+
@people ||= load_people
|
|
100
|
+
@people.find { |person| person.handle == handle }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Find a person by their GitHub username
|
|
104
|
+
# @param [String] github_username The GitHub username of the person
|
|
105
|
+
# @return [Person, nil] The person if found, nil otherwise
|
|
106
|
+
def find_by_github_username(github_username)
|
|
107
|
+
@people ||= load_people
|
|
108
|
+
@people.find { |person| person.github_username == github_username }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
data/lib/storage.rb
CHANGED
|
@@ -17,21 +17,6 @@ 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
|
-
|
|
35
20
|
def initialize(config)
|
|
36
21
|
@config = config
|
|
37
22
|
end
|
|
@@ -153,44 +138,6 @@ module Worklog
|
|
|
153
138
|
daily_log.entries
|
|
154
139
|
end
|
|
155
140
|
|
|
156
|
-
# Load all people from the people file, or return an empty array if the file does not exist
|
|
157
|
-
#
|
|
158
|
-
# @return [Array<Person>] List of people
|
|
159
|
-
def load_people
|
|
160
|
-
load_people!
|
|
161
|
-
rescue Errno::ENOENT
|
|
162
|
-
WorkLogger.info 'Unable to load people.'
|
|
163
|
-
[]
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Load all people from the people file and return them as a hash with handle as key
|
|
167
|
-
# @return [Hash<String, Person>] Hash of people with handle as key
|
|
168
|
-
def load_people_hash
|
|
169
|
-
load_people.to_h { |person| [person.handle, person] }
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
# Load all people from the people file
|
|
173
|
-
# @return [Array<Person>] List of people
|
|
174
|
-
def load_people!
|
|
175
|
-
return [] unless File.exist?(people_filepath)
|
|
176
|
-
|
|
177
|
-
yamltext = File.read(people_filepath)
|
|
178
|
-
if yamltext != yamltext.gsub(/^- !.*$/, '-')
|
|
179
|
-
WorkLogger.debug 'The people.yaml file contains deprecated syntax. Migrating now.'
|
|
180
|
-
yamltext.gsub!(/^- !.*$/, '-')
|
|
181
|
-
File.write(people_filepath, yamltext)
|
|
182
|
-
end
|
|
183
|
-
YAML.load(yamltext, permitted_classes: []).map { |person_hash| Person.from_hash(person_hash) }
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
# Write people to the people file
|
|
187
|
-
# @param [Array<Person>] people List of people
|
|
188
|
-
def write_people!(people)
|
|
189
|
-
File.open(people_filepath, 'w') do |f|
|
|
190
|
-
f.puts people.to_yaml
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
141
|
# Create folder if not exists already.
|
|
195
142
|
# @return [void]
|
|
196
143
|
def create_default_folder
|
|
@@ -214,18 +161,14 @@ module Worklog
|
|
|
214
161
|
# File.write(projects_file, [].to_yaml)
|
|
215
162
|
# end
|
|
216
163
|
|
|
217
|
-
if
|
|
218
|
-
|
|
164
|
+
# Write the default config file if it does not exist
|
|
165
|
+
if File.exist?(Configuration.config_file_path)
|
|
166
|
+
WorkLogger.info "Configuration file (#{Configuration.config_file_path}) already exists, skipping creation."
|
|
219
167
|
else
|
|
220
|
-
WorkLogger.info
|
|
221
|
-
File.write(
|
|
168
|
+
WorkLogger.info "Creating default configuration file at #{Configuration.config_file_path}."
|
|
169
|
+
File.write(Configuration.config_file_path,
|
|
170
|
+
Configuration::CONFIGURATION_TEMPLATE.result)
|
|
222
171
|
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
172
|
end
|
|
230
173
|
|
|
231
174
|
# Construct filepath for a given date.
|
|
@@ -234,11 +177,5 @@ module Worklog
|
|
|
234
177
|
def filepath(date)
|
|
235
178
|
File.join(@config.storage_path, "#{date}#{FILE_SUFFIX}")
|
|
236
179
|
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
|
|
243
180
|
end
|
|
244
181
|
end
|
data/lib/worklog.rb
CHANGED
|
@@ -14,6 +14,7 @@ require 'hasher'
|
|
|
14
14
|
require 'log_entry'
|
|
15
15
|
require 'worklogger'
|
|
16
16
|
require 'string_helper'
|
|
17
|
+
require 'people_storage'
|
|
17
18
|
require 'printer'
|
|
18
19
|
require 'project_storage'
|
|
19
20
|
require 'statistics'
|
|
@@ -57,6 +58,7 @@ module Worklog
|
|
|
57
58
|
|
|
58
59
|
# Initialize (project) storage
|
|
59
60
|
@storage = Storage.new(@config)
|
|
61
|
+
@people_storage = PeopleStorage.new(@config)
|
|
60
62
|
@project_storage = ProjectStorage.new(@config)
|
|
61
63
|
|
|
62
64
|
bootstrap
|
|
@@ -67,7 +69,7 @@ module Worklog
|
|
|
67
69
|
@storage.create_default_folder
|
|
68
70
|
|
|
69
71
|
# Load all people as they're used in multiple/most of the methods.
|
|
70
|
-
@people = @
|
|
72
|
+
@people = @people_storage.load_people_hash
|
|
71
73
|
|
|
72
74
|
# Load all projects from disk
|
|
73
75
|
@projects = @project_storage.load_projects
|
|
@@ -134,6 +136,44 @@ module Worklog
|
|
|
134
136
|
WorkLogger.info Rainbow("Updated work log for #{options[:date]}").green
|
|
135
137
|
end
|
|
136
138
|
|
|
139
|
+
# Fetch latest events from GitHub for a specified user and add them to the work log.
|
|
140
|
+
#
|
|
141
|
+
# @param options [Hash] the options hash containing GitHub username and other parameters.
|
|
142
|
+
def github(_options = {})
|
|
143
|
+
github = Github::Client.new(@config)
|
|
144
|
+
github_events = github.fetch_events
|
|
145
|
+
|
|
146
|
+
WorkLogger.info Rainbow("Fetched #{github_events.size} events from GitHub.").green
|
|
147
|
+
|
|
148
|
+
events_by_date = github_events.group_by { |event| event.to_log_entry.time.to_date }
|
|
149
|
+
|
|
150
|
+
events_by_date.each do |date, events|
|
|
151
|
+
WorkLogger.info Rainbow("Found #{events.size} events for #{date}").green
|
|
152
|
+
puts "Processing #{events.size} events for '#{date}'"
|
|
153
|
+
@storage.create_file_skeleton(date)
|
|
154
|
+
daily_log = @storage.load_log!(@storage.filepath(date))
|
|
155
|
+
entries_before = daily_log.entries.size
|
|
156
|
+
events.each do |event|
|
|
157
|
+
log_entry = event.to_log_entry
|
|
158
|
+
WorkLogger.debug('Entry already exists, skipping') if daily_log.key?(log_entry.key)
|
|
159
|
+
daily_log << log_entry unless daily_log.key?(log_entry.key)
|
|
160
|
+
WorkLogger.debug "Added entry: #{log_entry.message_string}"
|
|
161
|
+
end
|
|
162
|
+
entries_after = daily_log.entries.size
|
|
163
|
+
WorkLogger.info Rainbow("Added #{entries_after - entries_before} new entries for #{date}").green
|
|
164
|
+
|
|
165
|
+
# Write log back to storage
|
|
166
|
+
@storage.write_log(@storage.filepath(date), daily_log)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Initialize the work log storage with default files and folders.
|
|
171
|
+
# This method will not overwrite existing files and is thus safe to run multiple times.
|
|
172
|
+
def init(_options = {})
|
|
173
|
+
@storage.create_default_files
|
|
174
|
+
@people_storage.create_default_file
|
|
175
|
+
end
|
|
176
|
+
|
|
137
177
|
# Show the work log for a specific date range or a single date.
|
|
138
178
|
#
|
|
139
179
|
# @param options [Hash] the options hash containing date range or single date.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fewald-worklog
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Friedrich Ewald
|
|
@@ -149,6 +149,7 @@ files:
|
|
|
149
149
|
- lib/hash.rb
|
|
150
150
|
- lib/hasher.rb
|
|
151
151
|
- lib/log_entry.rb
|
|
152
|
+
- lib/people_storage.rb
|
|
152
153
|
- lib/person.rb
|
|
153
154
|
- lib/printer.rb
|
|
154
155
|
- lib/project.rb
|