dsu 2.0.8 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/dsu/cli.rb
CHANGED
@@ -4,6 +4,7 @@ require 'fileutils'
|
|
4
4
|
require 'time'
|
5
5
|
require_relative 'base_cli'
|
6
6
|
require_relative 'subcommands/config'
|
7
|
+
require_relative 'subcommands/delete'
|
7
8
|
require_relative 'subcommands/edit'
|
8
9
|
require_relative 'subcommands/list'
|
9
10
|
require_relative 'subcommands/theme'
|
@@ -11,53 +12,30 @@ require_relative 'subcommands/theme'
|
|
11
12
|
module Dsu
|
12
13
|
# The `dsu` command.
|
13
14
|
class CLI < BaseCLI
|
14
|
-
map
|
15
|
-
map
|
16
|
-
map
|
17
|
-
map
|
18
|
-
map
|
19
|
-
map
|
20
|
-
map
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
$ dsu add, -a [-d DATE|-n|-t|-y] DESCRIPTION
|
32
|
-
|
33
|
-
OPTIONS:
|
34
|
-
|
35
|
-
-d DATE: Adds a DSU entry having DESCRIPTION to the DATE.
|
36
|
-
|
37
|
-
#{date_option_description}
|
38
|
-
|
39
|
-
-n: Adds a DSU entry having DESCRIPTION to today's date (`Time.now`).
|
40
|
-
|
41
|
-
-t: Adds a DSU entry having DESCRIPTION to tomorrow's date (`Time.new.tomorrow`).
|
42
|
-
|
43
|
-
-y: Adds a DSU entry having DESCRIPTION to yesterday's date (`Time.new.yesterday`).
|
44
|
-
|
45
|
-
DESCRIPTION:
|
46
|
-
|
47
|
-
Must be be between 2 and 256 characters (inclusive) in length.
|
48
|
-
LONG_DESC
|
49
|
-
option :date, type: :string, aliases: '-d'
|
50
|
-
option :tomorrow, type: :boolean, aliases: '-t'
|
51
|
-
option :yesterday, type: :boolean, aliases: '-y'
|
52
|
-
option :today, type: :boolean, aliases: '-n', default: true
|
15
|
+
map I18n.t('commands.add.key_mappings') => :add
|
16
|
+
map I18n.t('commands.config.key_mappings') => :config
|
17
|
+
map I18n.t('commands.delete.key_mappings') => :delete
|
18
|
+
map I18n.t('commands.edit.key_mappings') => :edit
|
19
|
+
map I18n.t('commands.help.key_mappings') => :help
|
20
|
+
map I18n.t('commands.info.key_mappings') => :info
|
21
|
+
map I18n.t('commands.list.key_mappings') => :list
|
22
|
+
map I18n.t('commands.theme.key_mappings') => :theme
|
23
|
+
map I18n.t('commands.version.key_mappings') => :version
|
24
|
+
|
25
|
+
desc I18n.t('commands.add.desc'), I18n.t('commands.add.usage')
|
26
|
+
long_desc I18n.t('commands.add.long_desc', date_option_description: date_option_description)
|
27
|
+
option I18n.t('options.date.name'), aliases: I18n.t('options.date.aliases'), type: :string
|
28
|
+
option I18n.t('options.tomorrow.name'), aliases: I18n.t('options.tomorrow.aliases'), type: :boolean
|
29
|
+
option I18n.t('options.yesterday.name'), aliases: I18n.t('options.yesterday.aliases'), type: :boolean
|
30
|
+
option I18n.t('options.today.name'), aliases: I18n.t('options.today.aliases'), type: :boolean, default: true
|
53
31
|
def add(description)
|
54
|
-
time = if options[
|
55
|
-
Time.parse(options[
|
56
|
-
elsif options[
|
32
|
+
time = if options[I18n.t('options.date.name')].present?
|
33
|
+
Time.parse(options[I18n.t('options.date.name')])
|
34
|
+
elsif options[I18n.t('options.tomorrow.name')].present?
|
57
35
|
Time.now.tomorrow
|
58
|
-
elsif options[
|
36
|
+
elsif options[I18n.t('options.yesterday.name')].present?
|
59
37
|
Time.now.yesterday
|
60
|
-
elsif options[
|
38
|
+
elsif options[I18n.t('options.today.name')].present?
|
61
39
|
Time.now
|
62
40
|
end
|
63
41
|
entry = Models::Entry.new(description: description)
|
@@ -65,49 +43,43 @@ module Dsu
|
|
65
43
|
view_entry_group(time: time)
|
66
44
|
end
|
67
45
|
|
68
|
-
desc 'list,
|
69
|
-
'Displays DSU entries for the given SUBCOMMAND'
|
46
|
+
desc I18n.t('commands.list.desc'), I18n.t('commands.list.usage')
|
70
47
|
subcommand :list, Subcommands::List
|
71
48
|
|
72
|
-
desc 'config,
|
73
|
-
'Manage configuration file for this gem'
|
49
|
+
desc I18n.t('commands.config.desc'), I18n.t('commands.config.usage')
|
74
50
|
subcommand :config, Subcommands::Config
|
75
51
|
|
76
|
-
desc '
|
77
|
-
|
52
|
+
desc I18n.t('commands.delete.desc'), I18n.t('commands.delete.usage')
|
53
|
+
subcommand :delete, Subcommands::Delete
|
54
|
+
|
55
|
+
desc I18n.t('commands.edit.desc'), I18n.t('commands.edit.usage')
|
78
56
|
subcommand :edit, Subcommands::Edit
|
79
57
|
|
80
|
-
desc 'theme,
|
81
|
-
'Manage DSU themes'
|
58
|
+
desc I18n.t('commands.theme.desc'), I18n.t('commands.theme.usage')
|
82
59
|
subcommand :theme, Subcommands::Theme
|
83
60
|
|
84
|
-
desc 'info,
|
85
|
-
'Displays information about this dsu release'
|
61
|
+
desc I18n.t('commands.info.desc'), I18n.t('commands.info.usage')
|
86
62
|
def info
|
87
63
|
configuration_version = Models::Configuration::VERSION
|
88
64
|
entry_group_version = Models::EntryGroup::VERSION
|
89
65
|
color_theme_version = Models::ColorTheme::VERSION
|
90
|
-
info =
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
Migration version folder: #{Support::Fileable.migration_version_folder}
|
104
|
-
Migration file path: #{Support::Fileable.migration_version_path}
|
105
|
-
INFO
|
66
|
+
info = I18n.t('commands.info.info',
|
67
|
+
dsu_version: dsu_version,
|
68
|
+
configuration_version: configuration_version,
|
69
|
+
entry_group_version: entry_group_version,
|
70
|
+
color_theme_version: color_theme_version,
|
71
|
+
config_folder: Support::Fileable.config_path,
|
72
|
+
root_folder: Support::Fileable.root_folder,
|
73
|
+
entries_folder: Support::Fileable.entries_folder,
|
74
|
+
themes_folder: Support::Fileable.themes_folder,
|
75
|
+
gem_folder: Support::Fileable.gem_dir,
|
76
|
+
temp_folder: Support::Fileable.temp_folder,
|
77
|
+
migration_version_folder: Support::Fileable.migration_version_folder,
|
78
|
+
migration_file_folder: Support::Fileable.migration_version_path)
|
106
79
|
puts apply_theme(info, theme_color: color_theme.body)
|
107
80
|
end
|
108
81
|
|
109
|
-
desc 'version,
|
110
|
-
'Displays the version for this gem'
|
82
|
+
desc I18n.t('commands.version.desc'), I18n.t('commands.version.usage')
|
111
83
|
def version
|
112
84
|
puts apply_theme(dsu_version, theme_color: color_theme.body)
|
113
85
|
end
|
@@ -38,7 +38,7 @@ module Dsu
|
|
38
38
|
entry_group.save!
|
39
39
|
entry
|
40
40
|
rescue ActiveModel::ValidationError => e
|
41
|
-
header = '
|
41
|
+
header = I18n.t('headers.entry.could_not_be_added')
|
42
42
|
Views::Shared::Error.new(messages: e.message, header: header).render
|
43
43
|
end
|
44
44
|
|
data/lib/dsu/env.rb
CHANGED
@@ -88,11 +88,11 @@ module Dsu
|
|
88
88
|
self.class.class_eval do
|
89
89
|
attr_reader attr
|
90
90
|
attr_writer attr
|
91
|
-
private "#{attr}="
|
91
|
+
private :"#{attr}="
|
92
92
|
end
|
93
93
|
attr_value = theme_hash[attr]
|
94
94
|
attr_value = attr_value.merge_default_colors if default_theme_color_keys.include?(attr)
|
95
|
-
send("#{attr}=", attr_value)
|
95
|
+
send(:"#{attr}=", attr_value)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -133,6 +133,7 @@ module Dsu
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def merge(hash)
|
136
|
+
hash.transform_keys!(&:to_sym)
|
136
137
|
replace!(config_hash: to_h.merge(hash))
|
137
138
|
end
|
138
139
|
|
@@ -153,7 +154,8 @@ module Dsu
|
|
153
154
|
theme_path = themes_path(theme_name: theme_name)
|
154
155
|
return if File.exist?(theme_path)
|
155
156
|
|
156
|
-
errors.
|
157
|
+
i18n_key = 'configuration.errors.theme_file_missing'
|
158
|
+
errors.add(:base, I18n.t(i18n_key, theme_path: theme_path))
|
157
159
|
end
|
158
160
|
end
|
159
161
|
end
|
@@ -14,11 +14,13 @@ module Dsu
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def header
|
17
|
-
|
17
|
+
header = I18n.t('presenters.color_theme_presenter.headers.color_themes')
|
18
|
+
apply_theme(header, theme_color: color_theme.subheader)
|
18
19
|
end
|
19
20
|
|
20
21
|
def footer
|
21
|
-
|
22
|
+
header = I18n.t('presenters.color_theme_presenter.headers.current_theme')
|
23
|
+
apply_theme(header, theme_color: color_theme.footer)
|
22
24
|
end
|
23
25
|
|
24
26
|
def detail
|
@@ -10,7 +10,10 @@ module Dsu
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def detail
|
13
|
-
|
13
|
+
headers = [I18n.t('presenters.color_theme_show_presenter.headers.number'),
|
14
|
+
I18n.t('presenters.color_theme_show_presenter.headers.color'),
|
15
|
+
I18n.t('presenters.color_theme_show_presenter.headers.values')]
|
16
|
+
puts_detail(*headers, header: true)
|
14
17
|
|
15
18
|
Models::ColorTheme::DEFAULT_THEME_COLORS.keys.each_with_index do |color_key, index|
|
16
19
|
index = formatted_index(index: index)
|
@@ -24,11 +27,14 @@ module Dsu
|
|
24
27
|
end
|
25
28
|
|
26
29
|
def footer
|
27
|
-
|
30
|
+
header = I18n.t('presenters.color_theme_show_presenter.headers.footer_example')
|
31
|
+
apply_theme(header, theme_color: color_theme.footer)
|
28
32
|
end
|
29
33
|
|
30
34
|
def header
|
31
|
-
|
35
|
+
header = I18n.t('presenters.color_theme_show_presenter.headers.viewing_color_theme',
|
36
|
+
theme_name: color_theme.theme_name)
|
37
|
+
apply_theme(header, theme_color: color_theme.subheader)
|
32
38
|
end
|
33
39
|
|
34
40
|
private
|
@@ -15,8 +15,8 @@ module Dsu
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def configuration_header
|
18
|
-
|
19
|
-
|
18
|
+
header = I18n.t('presenters.configuration_presenter.headers.file_contents', config_path: config_path)
|
19
|
+
apply_theme(header, theme_color: color_theme.header)
|
20
20
|
end
|
21
21
|
|
22
22
|
def configuration_details
|
@@ -27,8 +27,8 @@ module Dsu
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def no_entries_available
|
30
|
-
|
31
|
-
apply_theme(
|
30
|
+
header = I18n.t('presenters.entry_group_presenter.headers.no_entries_available')
|
31
|
+
apply_theme(header, theme_color: color_theme.info)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../models/entry_group'
|
4
|
+
|
5
|
+
module Dsu
|
6
|
+
module Services
|
7
|
+
module EntryGroup
|
8
|
+
class CounterService
|
9
|
+
def initialize(times:, options: {})
|
10
|
+
raise ArgumentError, 'Argument times is nil' if times.nil?
|
11
|
+
|
12
|
+
@times = times
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
total_entry_groups = 0
|
18
|
+
|
19
|
+
times.each do |time|
|
20
|
+
total_entry_groups += 1 if Models::EntryGroup.exist?(time: time)
|
21
|
+
end
|
22
|
+
|
23
|
+
total_entry_groups
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :times, :options
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../models/entry_group'
|
4
|
+
|
5
|
+
module Dsu
|
6
|
+
module Services
|
7
|
+
module EntryGroup
|
8
|
+
class DeleterService
|
9
|
+
def initialize(times:, options: {})
|
10
|
+
raise ArgumentError, 'Argument times is nil' if times.nil?
|
11
|
+
|
12
|
+
@times = times
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
deleted_entry_groups = 0
|
18
|
+
|
19
|
+
times.each do |time|
|
20
|
+
next unless Models::EntryGroup.exist?(time: time)
|
21
|
+
|
22
|
+
Models::EntryGroup.delete(time: time)
|
23
|
+
deleted_entry_groups += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
deleted_entry_groups
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :times, :options
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -40,8 +40,9 @@ module Dsu
|
|
40
40
|
# Renders the edit view to a string so we can write it to a temporary file
|
41
41
|
# and edit it. The edits will be used to update the entry group.
|
42
42
|
def render_edit_view
|
43
|
-
|
44
|
-
|
43
|
+
message = I18n.t('services.editor_service.messages.editing',
|
44
|
+
formatted_time: formatted_time(time: entry_group.time))
|
45
|
+
puts apply_theme(message, theme_color: color_theme.header)
|
45
46
|
# TODO: Call #render_as_string directly below?
|
46
47
|
StdoutRedirectorService.call { Views::EntryGroup::Edit.new(entry_group: entry_group).render }
|
47
48
|
# Views::EntryGroup::Edit.new(entry_group: entry_group).render_as_string
|
@@ -63,15 +64,10 @@ module Dsu
|
|
63
64
|
|
64
65
|
process_entry_group!(entry_group_with_edits)
|
65
66
|
else
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
'Either set the EDITOR environment variable ' \
|
71
|
-
'or set the dsu editor configuration option (`$ dsu config info`).',
|
72
|
-
'Run `$ dsu help config` for more information.'
|
73
|
-
], theme_color: color_theme.error
|
74
|
-
)
|
67
|
+
message_array = I18n.t('services.editor_service.errors.temp_file_error',
|
68
|
+
editor: configuration.editor,
|
69
|
+
status: $CHILD_STATUS).split("\n")
|
70
|
+
puts apply_theme(message_array, theme_color: color_theme.error)
|
75
71
|
end
|
76
72
|
end
|
77
73
|
end
|
@@ -2,13 +2,11 @@
|
|
2
2
|
|
3
3
|
require_relative '../base_cli'
|
4
4
|
require_relative '../support/ask'
|
5
|
-
require_relative '../support/subcommand_help_colorizeable'
|
6
5
|
|
7
6
|
module Dsu
|
8
7
|
module Subcommands
|
9
8
|
class BaseSubcommand < Dsu::BaseCLI
|
10
9
|
include Support::Ask
|
11
|
-
include Support::SubcommandHelpColorizable
|
12
10
|
end
|
13
11
|
end
|
14
12
|
end
|
@@ -18,99 +18,40 @@ module Dsu
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
desc 'info', '
|
22
|
-
long_desc
|
23
|
-
NAME
|
24
|
-
|
25
|
-
`dsu config info` -- Displays information about this gem configuration.
|
26
|
-
|
27
|
-
SYNOPSIS
|
28
|
-
|
29
|
-
dsu config info
|
30
|
-
LONG_DESC
|
21
|
+
desc I18n.t('subcommands.config.info.desc'), I18n.t('subcommands.config.info.usage')
|
22
|
+
long_desc I18n.t('subcommands.config.info.long_desc')
|
31
23
|
def info
|
32
24
|
configuration = Models::Configuration.new
|
33
25
|
Views::Configuration::Show.new(config: configuration).call
|
34
26
|
end
|
35
27
|
|
36
|
-
if
|
37
|
-
desc 'init', '
|
38
|
-
long_desc
|
39
|
-
NAME
|
40
|
-
|
41
|
-
`dsu config init` -- will create and initialize a .dsu file ("#{Dsu::Support::Fileable.root_folder}/.dsu") that you may edit. Otherwise, the default configuration will be used.
|
42
|
-
|
43
|
-
SYNOPSIS
|
44
|
-
|
45
|
-
dsu config init
|
46
|
-
|
47
|
-
CONFIGURATION FILE OPTIONS
|
48
|
-
|
49
|
-
The following configuration file options are available:
|
50
|
-
|
51
|
-
version:
|
52
|
-
|
53
|
-
The configuration version - DO NOT ALTER THIS VALUE!
|
54
|
-
|
55
|
-
editor:
|
56
|
-
|
57
|
-
The default editor to use when editing entry groups if the EDITOR environment variable on your system is not set. The default is 'nano'. You'll need to change the default editor on Windows systems.
|
58
|
-
|
59
|
-
entries_display_order:
|
60
|
-
|
61
|
-
The order by which entries will be displayed, :asc or :desc (ascending or descending, respectively).
|
62
|
-
|
63
|
-
Default: :desc
|
64
|
-
|
65
|
-
entries_file_name:
|
66
|
-
|
67
|
-
The entries file name format. It is recommended that you do not change this. The file name must include `%Y`, `%m` and `%d` `Time` formatting specifiers to make sure the file name is unique and able to be located by `dsu` functions. For example, the default file name is `%Y-%m-%d.json`; however, something like `%m-%d-%Y.json` or `entry-group-%m-%d-%Y.json` would work as well.
|
68
|
-
|
69
|
-
ATTENTION: Please keep in mind that if you change this value `dsu` will not recognize entry files using a different format. You would (at this time), have to manually rename any existing entry file names to the new format.
|
70
|
-
|
71
|
-
Default: '%Y-%m-%d.json'
|
72
|
-
|
73
|
-
entries_folder:
|
74
|
-
|
75
|
-
This is the folder where `dsu` stores entry files. You may change this to anything you want. `dsu` will create this folder for you, as long as your system's write permissions allow this.
|
76
|
-
|
77
|
-
ATTENTION: Please keep in mind that if you change this value `dsu` will not be able to find entry files in any previous folder. You would (at this time), have to manually mode any existing entry files to this new folder.
|
78
|
-
|
79
|
-
Default: "'#{Dsu::Support::Fileable.root_folder}/dsu/entries'"
|
80
|
-
LONG_DESC
|
28
|
+
if Dsu.env.development?
|
29
|
+
desc I18n.t('subcommands.config.init.desc'), I18n.t('subcommands.config.init.usage')
|
30
|
+
long_desc I18n.t('subcommands.config.init.long_desc', home_folder: Dsu::Support::Fileable.root_folder)
|
81
31
|
def init
|
82
32
|
exit 1 if configuration_errors_or_wanings?
|
83
33
|
|
84
34
|
Models::Configuration.default.tap do |configuration|
|
85
35
|
configuration.save!
|
86
|
-
messages = [
|
36
|
+
messages = [I18n.t('messages.configuration_file.created',
|
37
|
+
configuration_file: Models::Configuration.config_file)]
|
87
38
|
Views::Shared::Success.new(messages: messages).render
|
88
39
|
Views::Configuration::Show.new(config: configuration).render
|
89
40
|
end
|
90
41
|
end
|
91
42
|
|
92
|
-
desc 'delete', '
|
93
|
-
long_desc
|
94
|
-
NAME
|
95
|
-
|
96
|
-
`dsu config delete` -- Deletes the configuration.
|
97
|
-
|
98
|
-
SYNOPSIS
|
99
|
-
|
100
|
-
dsu config delete
|
101
|
-
|
102
|
-
NOTES
|
103
|
-
|
104
|
-
Deleting the dsu configuration file will simply cause dsu to use the default configuration options (`Dsu::Models::Configuration::DEFAULT_CONFIGURATION`).
|
105
|
-
LONG_DESC
|
43
|
+
desc I18n.t('subcommands.config.delete.desc'), I18n.t('subcommands.config.delete.usage')
|
44
|
+
long_desc I18n.t('subcommands.config.delete.long_desc')
|
106
45
|
def delete
|
107
46
|
unless Models::Configuration.exist?
|
108
|
-
messages = [
|
47
|
+
messages = [I18n.t('messages.configuration_file.does_not_exist',
|
48
|
+
configuration_file: Models::Configuration.config_file)]
|
109
49
|
Views::Shared::Warning.new(messages: messages).render
|
110
50
|
exit 1
|
111
51
|
end
|
112
52
|
Models::Configuration.delete!
|
113
|
-
messages = [
|
53
|
+
messages = [I18n.t('messages.configuration_file.deleted',
|
54
|
+
configuration_file: Models::Configuration.config_file)]
|
114
55
|
Views::Shared::Success.new(messages: messages).render
|
115
56
|
end
|
116
57
|
end
|
@@ -119,10 +60,12 @@ module Dsu
|
|
119
60
|
|
120
61
|
def configuration_errors_or_wanings?
|
121
62
|
if Models::Configuration.exist?
|
122
|
-
messages = [
|
63
|
+
messages = [I18n.t('messages.configuration_file.already_exists',
|
64
|
+
configuration_file: Models::Configuration.config_file)]
|
123
65
|
Views::Shared::Warning.new(messages: messages).render
|
124
66
|
elsif !Dir.exist?(Models::Configuration.config_folder)
|
125
|
-
messages = [
|
67
|
+
messages = [I18n.t('messages.configuration_file.destination_folder_does_not_exist',
|
68
|
+
configuration_file: Models::Configuration.config_file)]
|
126
69
|
Views::Shared::Error.new(messages: messages).render
|
127
70
|
else
|
128
71
|
configuration = Models::Configuration.default
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../services/entry_group/counter_service'
|
4
|
+
require_relative '../services/entry_group/deleter_service'
|
5
|
+
require_relative '../support/command_options/dsu_times'
|
6
|
+
require_relative '../support/command_options/time_mnemonic'
|
7
|
+
require_relative '../support/time_formatable'
|
8
|
+
require_relative '../views/entry_group/shared/no_entries_to_display'
|
9
|
+
require_relative '../views/shared/error'
|
10
|
+
require_relative 'base_subcommand'
|
11
|
+
|
12
|
+
module Dsu
|
13
|
+
module Subcommands
|
14
|
+
class Delete < BaseSubcommand
|
15
|
+
include Support::CommandOptions::TimeMnemonic
|
16
|
+
include Support::TimeFormatable
|
17
|
+
|
18
|
+
map %w[d] => :date
|
19
|
+
map %w[dd] => :dates
|
20
|
+
map %w[n] => :today
|
21
|
+
map %w[t] => :tomorrow
|
22
|
+
map %w[y] => :yesterday
|
23
|
+
|
24
|
+
desc I18n.t('subcommands.delete.today.desc'), I18n.t('subcommands.delete.today.usage')
|
25
|
+
long_desc I18n.t('subcommands.delete.today.long_desc')
|
26
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
27
|
+
def today
|
28
|
+
delete_entry_groups_if times: [Time.now], options: options
|
29
|
+
end
|
30
|
+
|
31
|
+
desc I18n.t('subcommands.delete.tomorrow.desc'), I18n.t('subcommands.delete.tomorrow.usage')
|
32
|
+
long_desc I18n.t('subcommands.delete.tomorrow.long_desc')
|
33
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
34
|
+
def tomorrow
|
35
|
+
delete_entry_groups_if times: [Time.now.tomorrow], options: options
|
36
|
+
end
|
37
|
+
|
38
|
+
desc I18n.t('subcommands.delete.yesterday.desc'), I18n.t('subcommands.delete.yesterday.usage')
|
39
|
+
long_desc I18n.t('subcommands.delete.yesterday.long_desc')
|
40
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
41
|
+
def yesterday
|
42
|
+
delete_entry_groups_if times: [Time.now.yesterday], options: options
|
43
|
+
end
|
44
|
+
|
45
|
+
desc I18n.t('subcommands.delete.date.desc'), I18n.t('subcommands.delete.date.usage')
|
46
|
+
long_desc I18n.t('subcommands.delete.date.long_desc',
|
47
|
+
date_option_description: date_option_description,
|
48
|
+
mnemonic_option_description: mnemonic_option_description)
|
49
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
50
|
+
def date(date_or_mnemonic)
|
51
|
+
time = if time_mnemonic?(date_or_mnemonic)
|
52
|
+
time_from_mnemonic(command_option: date_or_mnemonic)
|
53
|
+
else
|
54
|
+
Time.parse(date_or_mnemonic)
|
55
|
+
end
|
56
|
+
delete_entry_groups_if times: [time], options: options
|
57
|
+
rescue ArgumentError => e
|
58
|
+
Views::Shared::Error.new(messages: e.message).render
|
59
|
+
end
|
60
|
+
|
61
|
+
desc I18n.t('subcommands.delete.dates.desc'), I18n.t('subcommands.delete.dates.usage')
|
62
|
+
long_desc I18n.t('subcommands.delete.dates.long_desc',
|
63
|
+
date_option_description: date_option_description,
|
64
|
+
mnemonic_option_description: mnemonic_option_description)
|
65
|
+
option :from, type: :string, required: true, aliases: '-f', banner: 'DATE|MNEMONIC'
|
66
|
+
option :to, type: :string, required: true, aliases: '-t', banner: 'DATE|MNEMONIC'
|
67
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
68
|
+
def dates
|
69
|
+
options = configuration.to_h.merge(self.options).with_indifferent_access
|
70
|
+
times, errors = Support::CommandOptions::DsuTimes.dsu_times_for(from_option: options[:from], to_option: options[:to]) # rubocop:disable Layout/LineLength
|
71
|
+
if errors.any?
|
72
|
+
Views::Shared::Error.new(messages: errors).render
|
73
|
+
return
|
74
|
+
end
|
75
|
+
|
76
|
+
times = times_sort(times: times, entries_display_order: options[:entries_display_order])
|
77
|
+
delete_entry_groups_if times: times, options: options
|
78
|
+
rescue ArgumentError => e
|
79
|
+
Views::Shared::Error.new(messages: e.message).render
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def delete_entry_groups_if(times:, options:)
|
85
|
+
prompt_string = I18n.t('subcommands.delete.prompts.are_you_sure',
|
86
|
+
dates: yyyy_mm_dd_or_through_for(times: times), count: total_entry_groups_for(times: times))
|
87
|
+
prompt = color_theme.prompt_with_options(prompt: prompt_string, options: %w[y N])
|
88
|
+
if yes?(prompt, options: options)
|
89
|
+
deleted_count = delete_entry_groups_for(times: times)
|
90
|
+
message = I18n.t('subcommands.delete.messages.deleted', count: deleted_count)
|
91
|
+
Views::Shared::Success.new(messages: message).render
|
92
|
+
else
|
93
|
+
message = I18n.t('subcommands.delete.messages.canceled')
|
94
|
+
Views::Shared::Info.new(messages: message).render
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def delete_entry_groups_for(times:)
|
99
|
+
Services::EntryGroup::DeleterService.new(times: times).call
|
100
|
+
end
|
101
|
+
|
102
|
+
def total_entry_groups_for(times:)
|
103
|
+
Services::EntryGroup::CounterService.new(times: times).call
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|