dsu 2.0.8 → 2.1.2
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/CHANGELOG.md +39 -2
- data/Gemfile.lock +9 -9
- data/README.md +178 -69
- data/lib/core/ruby/color_theme_mode.rb +1 -1
- data/lib/dsu/base_cli.rb +3 -17
- data/lib/dsu/cli.rb +44 -72
- data/lib/dsu/command_services/add_entry_service.rb +1 -1
- data/lib/dsu/env.rb +4 -0
- data/lib/dsu/models/color_theme.rb +2 -2
- data/lib/dsu/models/configuration.rb +3 -1
- data/lib/dsu/models/entry_group.rb +1 -1
- data/lib/dsu/presenters/color_theme_presenter.rb +4 -2
- data/lib/dsu/presenters/color_theme_show_presenter.rb +9 -3
- data/lib/dsu/presenters/configuration_presenter.rb +2 -2
- data/lib/dsu/presenters/entry_group_presenter.rb +2 -2
- data/lib/dsu/services/entry_group/counter_service.rb +32 -0
- data/lib/dsu/services/entry_group/deleter_service.rb +35 -0
- data/lib/dsu/services/entry_group/editor_service.rb +7 -11
- data/lib/dsu/subcommands/base_subcommand.rb +0 -2
- data/lib/dsu/subcommands/config.rb +17 -74
- data/lib/dsu/subcommands/delete.rb +107 -0
- data/lib/dsu/subcommands/edit.rb +16 -30
- data/lib/dsu/subcommands/list.rb +26 -96
- data/lib/dsu/subcommands/theme.rb +50 -79
- data/lib/dsu/support/ask.rb +1 -1
- data/lib/dsu/support/command_help_colorizeable.rb +7 -0
- data/lib/dsu/support/command_hookable.rb +2 -0
- data/lib/dsu/support/command_options/dsu_times.rb +10 -10
- data/lib/dsu/support/command_options/time.rb +1 -0
- data/lib/dsu/support/command_options/time_mnemonic.rb +108 -0
- data/lib/dsu/support/command_options/{time_mneumonics.rb → time_mnemonics.rb} +2 -1
- data/lib/dsu/support/time_formatable.rb +13 -0
- data/lib/dsu/validators/description_validator.rb +2 -0
- data/lib/dsu/validators/entries_validator.rb +1 -0
- data/lib/dsu/version.rb +1 -1
- data/lib/dsu/views/color_theme/show.rb +1 -0
- data/lib/dsu/views/entry_group/edit.rb +2 -1
- data/lib/dsu/views/entry_group/shared/no_entries_to_display.rb +4 -1
- data/lib/dsu/views/shared/model_errors.rb +1 -0
- data/lib/dsu.rb +5 -1
- data/lib/locales/en/active_record.yml +8 -0
- data/lib/locales/en/commands.yml +136 -0
- data/lib/locales/en/miscellaneous.yml +23 -0
- data/lib/locales/en/presenters.yml +19 -0
- data/lib/locales/en/services.yml +10 -0
- data/lib/locales/en/subcommands.yml +348 -0
- metadata +26 -27
- data/exe/dsu_migrate.rb +0 -43
- data/lib/dsu/support/command_options/time_mneumonic.rb +0 -108
- data/lib/dsu/support/subcommand_help_colorizeable.rb +0 -27
@@ -10,6 +10,7 @@ module Dsu
|
|
10
10
|
module TimeFormatable
|
11
11
|
module_function
|
12
12
|
|
13
|
+
# TODO: I18n.
|
13
14
|
def formatted_time(time:)
|
14
15
|
time = time.localtime if time.utc?
|
15
16
|
|
@@ -28,10 +29,12 @@ module Dsu
|
|
28
29
|
time.strftime("%A, (#{today_yesterday_or_tomorrow}) %Y-%m-%d #{time_zone}")
|
29
30
|
end
|
30
31
|
|
32
|
+
# TODO: I18n.
|
31
33
|
def mm_dd(time:, separator: '/')
|
32
34
|
time.strftime("%m#{separator}%d")
|
33
35
|
end
|
34
36
|
|
37
|
+
# TODO: I18n.
|
35
38
|
def mm_dd_yyyy(time:, separator: '/')
|
36
39
|
time.strftime("%m#{separator}%d#{separator}%Y")
|
37
40
|
end
|
@@ -40,6 +43,16 @@ module Dsu
|
|
40
43
|
time.zone
|
41
44
|
end
|
42
45
|
|
46
|
+
# TODO: I18n.
|
47
|
+
def yyyy_mm_dd_or_through_for(times:)
|
48
|
+
return yyyy_mm_dd(time: times[0]) if times.one?
|
49
|
+
|
50
|
+
times = [yyyy_mm_dd(time: times.min), yyyy_mm_dd(time: times.max)]
|
51
|
+
|
52
|
+
I18n.t('information.dates.through', from: times[0], to: times[1])
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO: I18n.
|
43
56
|
def yyyy_mm_dd(time:, separator: '-')
|
44
57
|
time.strftime("%Y#{separator}%m#{separator}%d")
|
45
58
|
end
|
@@ -28,8 +28,10 @@ module Dsu
|
|
28
28
|
return if description.length.between?(2, 256)
|
29
29
|
|
30
30
|
if description.length < 2
|
31
|
+
# TODO: I18n.
|
31
32
|
record.errors.add(:description, "is too short: \"#{record.short_description}\" (minimum is 2 characters).")
|
32
33
|
elsif description.length > 256
|
34
|
+
# TODO: I18n.
|
33
35
|
record.errors.add(:description, "is too long: \"#{record.short_description}\" (maximum is 256 characters).")
|
34
36
|
end
|
35
37
|
end
|
@@ -46,6 +46,7 @@ module Dsu
|
|
46
46
|
|
47
47
|
non_unique_descriptions = descriptions.select { |description| descriptions.count(description) > 1 }.uniq
|
48
48
|
non_unique_descriptions.each do |non_unique_description|
|
49
|
+
# TODO: I18n.
|
49
50
|
record.errors.add(:entries,
|
50
51
|
"array contains duplicate entry: \"#{short_description(non_unique_description)}\".",
|
51
52
|
type: Support::FieldErrors::FIELD_DUPLICATE_ERROR)
|
data/lib/dsu/version.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative '../../models/entry_group'
|
|
6
6
|
module Dsu
|
7
7
|
module Views
|
8
8
|
module EntryGroup
|
9
|
+
# TODO: I18n this class.
|
9
10
|
class Edit
|
10
11
|
def initialize(entry_group:, options: {})
|
11
12
|
raise ArgumentError, 'entry_group is nil' if entry_group.nil?
|
@@ -98,7 +99,7 @@ module Dsu
|
|
98
99
|
end
|
99
100
|
|
100
101
|
def previous_entry_group?
|
101
|
-
previous_entry_group
|
102
|
+
previous_entry_group&.entries&.present?
|
102
103
|
end
|
103
104
|
|
104
105
|
def previous_entry_group
|
@@ -21,8 +21,9 @@ module Dsu
|
|
21
21
|
@options = options || {}
|
22
22
|
end
|
23
23
|
|
24
|
+
# TODO: I18n.
|
24
25
|
def render
|
25
|
-
|
26
|
+
times.sort!
|
26
27
|
time_range = "#{formatted_time(time: times.first)} " \
|
27
28
|
"through #{formatted_time(time: times.last)}"
|
28
29
|
message = "(nothing to display for #{time_range})"
|
@@ -31,6 +32,8 @@ module Dsu
|
|
31
32
|
|
32
33
|
private
|
33
34
|
|
35
|
+
attr_reader :times, :options
|
36
|
+
|
34
37
|
def color_theme
|
35
38
|
@color_theme ||= Models::ColorTheme.current_or_default
|
36
39
|
end
|
@@ -10,6 +10,7 @@ module Dsu
|
|
10
10
|
raise ArgumentError, 'model is nil' if model.nil?
|
11
11
|
raise ArgumentError, "model is the wrong object type: \"#{model}\"" unless model.is_a?(ActiveModel::Model)
|
12
12
|
|
13
|
+
# TODO: I18n.
|
13
14
|
header = options[:header] || 'The following ERRORS were encountered; changes could not be saved:'
|
14
15
|
super(messages: model.errors.full_messages, header: header, options: options)
|
15
16
|
|
data/lib/dsu.rb
CHANGED
@@ -2,9 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'active_support/core_ext/hash/indifferent_access'
|
4
4
|
require 'active_support/core_ext/object/blank'
|
5
|
+
require 'i18n'
|
5
6
|
require 'thor'
|
6
7
|
require 'time'
|
7
8
|
|
9
|
+
I18n.load_path += Dir[File.join(__dir__, 'locales/**/*', '*.yml')]
|
10
|
+
# I18n.default_locale = :en # (note that `en` is already the default!)
|
11
|
+
|
8
12
|
Dir.glob("#{__dir__}/core/**/*.rb").each do |file|
|
9
13
|
require file
|
10
14
|
end
|
@@ -24,7 +28,7 @@ if !(Dsu.env.test? || Dsu.env.development?) && Dsu::Migration::Service.run_migra
|
|
24
28
|
begin
|
25
29
|
Dsu::Migration::Service.new.call
|
26
30
|
rescue StandardError => e
|
27
|
-
puts
|
31
|
+
puts I18n.t('errors.migration.error', message: e.message)
|
28
32
|
exit 1
|
29
33
|
end
|
30
34
|
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# lib/dsu/cli.rb
|
2
|
+
#
|
3
|
+
# NOTE:
|
4
|
+
#
|
5
|
+
# Commands should have the following layout:
|
6
|
+
#
|
7
|
+
# en:
|
8
|
+
# commands:
|
9
|
+
# my_command:
|
10
|
+
# key_mappings: thor key mappings
|
11
|
+
# desc: thor command description
|
12
|
+
# usage: thor command usage
|
13
|
+
# long_desc: thor long description
|
14
|
+
#
|
15
|
+
# Place key_mappings: at the top of the command entries:
|
16
|
+
#
|
17
|
+
# en:
|
18
|
+
# commands:
|
19
|
+
# my_command:
|
20
|
+
# key_mappings: m # Single mapping
|
21
|
+
# key_mappings: # Array of mappings
|
22
|
+
# - 'm'
|
23
|
+
# - '-m'
|
24
|
+
en:
|
25
|
+
commands:
|
26
|
+
add:
|
27
|
+
key_mappings: a
|
28
|
+
desc: add|a [OPTIONS] DESCRIPTION
|
29
|
+
usage: Adds a DSU entry having DESCRIPTION to the date associated with the given OPTION
|
30
|
+
long_desc: |
|
31
|
+
Will add a DSU entry having DESCRIPTION to the date associated with the given OPTION.
|
32
|
+
|
33
|
+
$ dsu add [-d DATE|-n|-t|-y] DESCRIPTION
|
34
|
+
|
35
|
+
$ dsu a [-d DATE|-n|-t|-y] DESCRIPTION
|
36
|
+
|
37
|
+
OPTIONS:
|
38
|
+
|
39
|
+
-d DATE: Adds a DSU entry having DESCRIPTION to the DATE.
|
40
|
+
|
41
|
+
%{date_option_description}
|
42
|
+
|
43
|
+
-n: Adds a DSU entry having DESCRIPTION to today's date (`Time.now`).
|
44
|
+
|
45
|
+
-t: Adds a DSU entry having DESCRIPTION to tomorrow's date (`Time.new.tomorrow`).
|
46
|
+
|
47
|
+
-y: Adds a DSU entry having DESCRIPTION to yesterday's date (`Time.new.yesterday`).
|
48
|
+
|
49
|
+
DESCRIPTION
|
50
|
+
|
51
|
+
Must be be between 2 and 256 characters (inclusive) in length.
|
52
|
+
config:
|
53
|
+
key_mappings: c
|
54
|
+
desc: config|c SUBCOMMAND
|
55
|
+
usage: Manage configuration file for this gem
|
56
|
+
delete:
|
57
|
+
key_mappings: c
|
58
|
+
desc: delete|d SUBCOMMAND
|
59
|
+
usage: Delete DSU entries for the given SUBCOMMAND
|
60
|
+
edit:
|
61
|
+
desc: edit|e SUBCOMMAND
|
62
|
+
usage: Edit DSU entries for the given SUBCOMMAND
|
63
|
+
key_mappings: e
|
64
|
+
info:
|
65
|
+
key_mappings: i
|
66
|
+
desc: info|i
|
67
|
+
usage: Displays information about this DSU release
|
68
|
+
info: |
|
69
|
+
Dsu Info
|
70
|
+
--------------------------------------------------
|
71
|
+
Dsu version: %{dsu_version}
|
72
|
+
Configuration version: %{configuration_version}
|
73
|
+
Entry group version: %{entry_group_version}
|
74
|
+
Color theme version: %{color_theme_version}
|
75
|
+
|
76
|
+
Config folder: %{config_folder}
|
77
|
+
Root folder: %{root_folder}
|
78
|
+
Entries folder: %{entries_folder}
|
79
|
+
Themes folder: %{themes_folder}
|
80
|
+
Gem folder: %{gem_folder}
|
81
|
+
Temp folder: %{temp_folder}
|
82
|
+
|
83
|
+
Migration version folder: %{migration_version_folder}
|
84
|
+
Migration file folder: %{migration_file_folder}
|
85
|
+
list:
|
86
|
+
key_mappings: l
|
87
|
+
desc: list|l SUBCOMMAND
|
88
|
+
usage: Displays DSU entries for the given SUBCOMMAND
|
89
|
+
theme:
|
90
|
+
key_mappings: t
|
91
|
+
desc: theme|t SUBCOMMAND
|
92
|
+
usage: Manage DSU themes
|
93
|
+
version:
|
94
|
+
key_mappings:
|
95
|
+
- v
|
96
|
+
- '-v'
|
97
|
+
desc: version|v|-v
|
98
|
+
usage: Displays the DSU version for this gem
|
99
|
+
# Should these options go under their respective commands
|
100
|
+
# (e.g. commands.options.date.name, commands.options.today.aliases, etc.)?
|
101
|
+
options:
|
102
|
+
date:
|
103
|
+
aliases: -d
|
104
|
+
name: 'date'
|
105
|
+
today:
|
106
|
+
aliases: -n
|
107
|
+
name: 'today'
|
108
|
+
tomorrow:
|
109
|
+
aliases: -t
|
110
|
+
name: 'tomorrow'
|
111
|
+
yesterday:
|
112
|
+
aliases: -y
|
113
|
+
name: 'yesterday'
|
114
|
+
include_all: Include dates that have no DSU entries
|
115
|
+
date_option_description: |
|
116
|
+
DATE
|
117
|
+
|
118
|
+
This may be any date string that can be parsed using `Time.parse`.
|
119
|
+
Consequently, you may use also use '/' as date separators,
|
120
|
+
as well as omit the year if the date you want to display is the
|
121
|
+
current year (e.g. <month>/<day>, or 1/31). For example: `require 'time';
|
122
|
+
Time.parse('01/02/2023'); Time.parse('1/2') # etc.`
|
123
|
+
mnemonic_option_description: |
|
124
|
+
MNEMONIC
|
125
|
+
|
126
|
+
This may be any of the following: n|today|t|tomorrow|y|yesterday|+n|-n.
|
127
|
+
|
128
|
+
Where n, t, y are aliases for today, tomorrow, and yesterday, respectively.
|
129
|
+
|
130
|
+
Where +n, -n are relative date mnemonics (RDMs). Generally speaking,
|
131
|
+
RDMs are relative to the current date. For example, a RDM of +1 would be
|
132
|
+
equal to `Time.now + 1.day` (tomorrow), and a RDM of -1 would be equal to
|
133
|
+
`Time.now - 1.day` (yesterday).
|
134
|
+
|
135
|
+
In some cases the behavior RDMs have on some commands are context dependent;
|
136
|
+
in such cases the behavior will be noted.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
en:
|
2
|
+
configuration:
|
3
|
+
errors:
|
4
|
+
theme_file_missing: Theme file "%{theme_path}" does not exist.
|
5
|
+
errors:
|
6
|
+
error: "Error: %{message}"
|
7
|
+
from_option_invalid: Option -f, [--from=DATE|MNEMONIC] value is invalid ["%{from_option}"]
|
8
|
+
to_option_invalid: Option -t, [--to=DATE|MNEMONIC] value is invalid ["%{to_option}"]
|
9
|
+
migration:
|
10
|
+
error: "Error running migrations: %{message}"
|
11
|
+
headers:
|
12
|
+
entry:
|
13
|
+
could_not_be_added: "An error was encountered; the entry could not be added:"
|
14
|
+
messages:
|
15
|
+
configuration_file:
|
16
|
+
already_exists: Configuration file (%{configuration_file}) already exists.
|
17
|
+
created: Configuration file (%{configuration_file}) created.
|
18
|
+
deleted: Configuration file (%{configuration_file}) deleted.
|
19
|
+
destination_folder_does_not_exist: "Destination folder for configuration file (%{configuration_folder}) does not exist."
|
20
|
+
does_not_exist: "Configuration file (%{configuration_file}) does not exist."
|
21
|
+
information:
|
22
|
+
dates:
|
23
|
+
through: "%{from} thru %{to}"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
en:
|
2
|
+
presenters:
|
3
|
+
color_theme_presenter:
|
4
|
+
headers:
|
5
|
+
color_themes: Color Themes
|
6
|
+
current_theme: "* current theme"
|
7
|
+
color_theme_show_presenter:
|
8
|
+
headers:
|
9
|
+
number: No.
|
10
|
+
color: Color
|
11
|
+
values: Values
|
12
|
+
viewing_color_theme: "Viewing color theme: %{theme_name}"
|
13
|
+
footer_example: Footer example
|
14
|
+
configuration_presenter:
|
15
|
+
headers:
|
16
|
+
file_contents: "Configuration file contents (%{config_path})"
|
17
|
+
entry_group_presenter:
|
18
|
+
headers:
|
19
|
+
no_entries_available: (no entries available for this day)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
en:
|
2
|
+
services:
|
3
|
+
editor_service:
|
4
|
+
errors:
|
5
|
+
temp_file_error: |
|
6
|
+
Failed to open temporary file in editor '%{editor}'; the system error returned was: '%{status}'.
|
7
|
+
Either set the EDITOR environment variable or set the dsu editor configuration option (`$ dsu config info`).
|
8
|
+
Run `$ dsu help config` for more information.
|
9
|
+
messages:
|
10
|
+
editing: "Editing entry group %{formatted_time}..."
|