dsu 0.1.0.alpha.5 → 1.1.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile.lock +6 -15
  5. data/README.md +33 -47
  6. data/lib/dsu/base_cli.rb +13 -6
  7. data/lib/dsu/cli.rb +46 -55
  8. data/lib/dsu/command_services/add_entry_service.rb +21 -21
  9. data/lib/dsu/core/ruby/not_today.rb +11 -0
  10. data/lib/dsu/models/entry.rb +32 -21
  11. data/lib/dsu/models/entry_group.rb +41 -105
  12. data/lib/dsu/services/configuration_loader_service.rb +19 -2
  13. data/lib/dsu/services/entry_group_editor_service.rb +37 -89
  14. data/lib/dsu/services/stdout_redirector_service.rb +27 -0
  15. data/lib/dsu/subcommands/list.rb +83 -15
  16. data/lib/dsu/support/colorable.rb +1 -0
  17. data/lib/dsu/support/command_options/dsu_times.rb +33 -0
  18. data/lib/dsu/support/command_options/time.rb +77 -0
  19. data/lib/dsu/support/command_options/time_mneumonic.rb +127 -0
  20. data/lib/dsu/support/command_options/time_mneumonics.rb +15 -0
  21. data/lib/dsu/support/configurable.rb +15 -0
  22. data/lib/dsu/support/configuration.rb +13 -1
  23. data/lib/dsu/support/entry_group_fileable.rb +31 -6
  24. data/lib/dsu/support/entry_group_loadable.rb +13 -16
  25. data/lib/dsu/support/entry_group_viewable.rb +26 -8
  26. data/lib/dsu/support/times_sortable.rb +1 -3
  27. data/lib/dsu/validators/description_validator.rb +38 -0
  28. data/lib/dsu/validators/entries_validator.rb +43 -32
  29. data/lib/dsu/validators/time_validator.rb +11 -20
  30. data/lib/dsu/version.rb +1 -1
  31. data/lib/dsu/views/edited_entries/shared/errors.rb +39 -0
  32. data/lib/dsu/views/entry_group/edit.rb +89 -39
  33. data/lib/dsu/views/entry_group/show.rb +10 -4
  34. data/lib/dsu/views/shared/messages.rb +56 -0
  35. data/lib/dsu.rb +8 -2
  36. metadata +24 -12
  37. data/lib/dsu/support/commander/command.rb +0 -130
  38. data/lib/dsu/support/commander/command_help.rb +0 -62
  39. data/lib/dsu/support/commander/subcommand.rb +0 -45
  40. data/lib/dsu/support/interactive/cli.rb +0 -161
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8563782a0b4d22e374313aa3373b38e62dec995a6f6d996eaa5fa9c58b0d1cb
4
- data.tar.gz: 65ebebe762dac44300a6d163c03275eaffd66018a83f9836b3f12cb6333569ad
3
+ metadata.gz: a0558e3688ef13d3969d4f42575742be25b847b18e822c7042ed2de38ff6450f
4
+ data.tar.gz: f72bd36cb559f2f99ba51687ffa2d13cb56e94dfe64a80f2634d8ad727fb3531
5
5
  SHA512:
6
- metadata.gz: a412bf735ce124b6df3bb419a1ed925b6b9aaf6cc7e8fdb13773fd883886119d92c03cb4bc68633d57bcfd293c274db16d5504200790f9be65d5d3d3f3e5e21e
7
- data.tar.gz: bf7ac4a28753385155d6e0cd7f1694723deaa3ad0d0e41205f63446c78a2a8b0b09d42f4e5557d3c3aef4befa8a6d46e568d308a1d9fb6c9a0f4110d301c025d
6
+ metadata.gz: bd93da3534ed0d6d11522a4a7e5b9adb9b4ec56eabc0633f5f314ccdaa900f98bb7f451bc86b083bd58b2aafe920ac214ce3b1bd4fee940713af39edcc09d9bd
7
+ data.tar.gz: fe1c030e83a19732cabe66389f9849125e5c72e4e5f23a30de2d2cda3b0a01ed26d9fc63077b67c7e10e7b3f54a9c9ce4d4bf893c7ed432c7b0e1b6f1d62e469
data/.rubocop.yml CHANGED
@@ -10,7 +10,7 @@ AllCops:
10
10
  - '.idea/**/*'
11
11
  - 'init/*'
12
12
  - 'Rakefile'
13
- # - '*.gemspec'
13
+ - '*.gemspec'
14
14
  # - 'spec/**/*'
15
15
  - 'vendor/**/*'
16
16
  - 'scratch*.rb'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [1.1.0.alpha.1] - 2023-05-23
2
+ * Changes
3
+ - Added new configuration option `carry_over_entries_to_today` (`true|false`, default: `false`); if true, when editing DSU entries **for the first time** on any given day (e.g. `dsu edit today`), DSU entries from the previous day will be copied to the editing session. If there are no DSU entries from the previous day, `dsu` will search backwards up to 7 days to find a DSU date that has entries to copy. If after searching back 7 days, no DSU entries are found, the editor session will simply start with no previous DSU entries.
4
+ - Added new configuration option `include_all` (`true|false`, default: `false`); if true, when using dsu commands that list date ranges (e.g. `dsu list dates`), the displayed list will include dates that have no dsu entries. If false, the displayed list will only include dates that have dsu entries. For all other `dsu list` commands, if true, this option will behave in the aforementioned manner. If false, the displayed list will unconditionally display the first and last dates regardless of whether or not the DSU date has entries or not; all other dates will not be displayed if the DSU date has no entries.
5
+ - Changed the look of the editor template when editing entry group entries.
6
+ ## [1.0.0] - 2023-05-18
7
+ * First official release.
8
+ * NOTE: If you have been using the alpha version of `dsu`, you will need to delete the `entries` folder (e.g. `/Users/<whoami>/dsu/entries` on a nix os) as the old entries .json files are incompatible with this official release.
9
+ * Changes from the alpha version
10
+ - When editing an entry group, editor commands are no longer necessary. Simply add, remove or change entries as needed. See the README.md for more information.
11
+ - When editing an entry group and saving the results, take note of the folowing behavior:
12
+ - Entering duplicate entries are not allowed, only one entry with a given description is allowed per entry group.
13
+ - Entering entries whose descriptions are < 2 or > 256 characters will fail validation and will not be saved.
14
+ - When editing and encountering any of the aforementioned, the errors will be displayed to the console after the editor file is saved.
15
+ - Sha's are no longer being used, as I've not found a good use (currently) to use them. I may add them back in the future if I find a good use for them (tracking entries across entry groups, etc.).
16
+ - When adding an entry (`dsu add OPTION`), it used to be that after the entry was added, the entry group for the date being edited would be displayed, as well as "yesterday's" date. This is no longer the case; now, only the entry group for the date being edited is displayed.
1
17
  ## [0.1.0.alpha.5] - 2023-05-12
2
18
  * Changes
3
19
  - `dsu edit SUBCOMMAND` will now allow editing of an entry group for a date that does not yet exist. This will allow you to add entries in the editor using `+|a|add DESCRIPTION`. Be sure to follow the instructions in the editor when editing entry group entries.
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dsu (0.1.0.alpha.5)
4
+ dsu (1.1.0.alpha.1)
5
+ activemodel (~> 7.0, >= 7.0.4.3)
5
6
  activesupport (~> 7.0, >= 7.0.4)
6
7
  colorize (~> 0.8.1)
7
- deco_lite (~> 1.3)
8
8
  os (~> 1.1, >= 1.1.4)
9
9
  thor (~> 1.2, >= 1.2.1)
10
10
  thor_nested_subcommand (~> 1.0)
@@ -24,11 +24,6 @@ GEM
24
24
  coderay (1.1.3)
25
25
  colorize (0.8.1)
26
26
  concurrent-ruby (1.2.2)
27
- deco_lite (1.5.3)
28
- activemodel (~> 7.0, >= 7.0.3.1)
29
- activesupport (~> 7.0, >= 7.0.3.1)
30
- immutable_struct_ex (~> 0.2.0)
31
- mad_flatter (~> 2.0)
32
27
  diff-lcs (1.5.0)
33
28
  docile (1.4.0)
34
29
  dotenv (2.8.1)
@@ -37,12 +32,8 @@ GEM
37
32
  ffaker (2.21.0)
38
33
  i18n (1.13.0)
39
34
  concurrent-ruby (~> 1.0)
40
- immutable_struct_ex (0.2.3)
41
35
  json (2.6.3)
42
36
  kwalify (0.7.2)
43
- mad_flatter (2.0.0)
44
- activesupport (~> 7.0, >= 7.0.3.1)
45
- immutable_struct_ex (~> 0.2.0)
46
37
  method_source (1.0.0)
47
38
  minitest (5.18.0)
48
39
  os (1.1.4)
@@ -76,7 +67,7 @@ GEM
76
67
  diff-lcs (>= 1.2.0, < 2.0)
77
68
  rspec-support (~> 3.12.0)
78
69
  rspec-support (3.12.0)
79
- rubocop (1.50.2)
70
+ rubocop (1.51.0)
80
71
  json (~> 2.3)
81
72
  parallel (~> 1.10)
82
73
  parser (>= 3.2.0.0)
@@ -90,9 +81,9 @@ GEM
90
81
  parser (>= 3.2.1.0)
91
82
  rubocop-capybara (2.18.0)
92
83
  rubocop (~> 1.41)
93
- rubocop-factory_bot (2.22.0)
84
+ rubocop-factory_bot (2.23.1)
94
85
  rubocop (~> 1.33)
95
- rubocop-performance (1.17.1)
86
+ rubocop-performance (1.18.0)
96
87
  rubocop (>= 1.7.0, < 2.0)
97
88
  rubocop-ast (>= 0.4.0)
98
89
  rubocop-rspec (2.22.0)
@@ -106,7 +97,7 @@ GEM
106
97
  simplecov_json_formatter (~> 0.1)
107
98
  simplecov-html (0.12.3)
108
99
  simplecov_json_formatter (0.1.4)
109
- thor (1.2.1)
100
+ thor (1.2.2)
110
101
  thor_nested_subcommand (1.0.0)
111
102
  tzinfo (2.0.6)
112
103
  concurrent-ruby (~> 1.0)
data/README.md CHANGED
@@ -9,8 +9,6 @@
9
9
  ## About
10
10
  `dsu` is little gem that helps manage your Agile DSU (Daily Stand Up) participation. How? by providing a simple command line interface (CLI) which allows you to create, read, update, and delete (CRUD) noteworthy activities that you performed during your day. During your DSU, you can then easily recall and share these these activities with your team. Activities are grouped by day and can be viewed in simple text format from the command line. When viewing a particular day, `dsu` will automatically display the previous day's activities as well. This is useful for remembering what you did yesterday, so you can share your "Today" and "Yesterday" activities with your team during your DSU. If the day you are trying to view falls on a weekend or Monday, `dsu` will display back to, and including the weekend and previous Friday inclusive, so that you can share what you did over the weekend (if anything) and the previous Friday.
11
11
 
12
- **NOTE:** This gem is in development (alpha version). Please see the [WIP Notes](#wip-notes) section for current `dsu` features.
13
-
14
12
  ## Help
15
13
 
16
14
  After installation (`gem install dsu`), the first thing you may want to do is run the `dsu` help:
@@ -73,12 +71,11 @@ The following displays the entries for "Today", where `Time.now == '2023-05-06 0
73
71
  ```shell
74
72
  #=>
75
73
  Saturday, (Today) 2023-05-06
76
- 1. 587a2f29 Blocked for locally failing test IN-12345
77
- Hope to pair with John on it
74
+ 1. Blocked for locally failing test IN-12345
78
75
 
79
76
  Friday, (Yesterday) 2023-05-05
80
- 1. edc25a9a Pick up ticket IN-12345
81
- 2. f7d3018c Attend new hire meet & greet
77
+ 1. Pick up ticket IN-12345
78
+ 2. Attend new hire meet & greet
82
79
  ```
83
80
 
84
81
  `$ dsu list date "2023-05-06"`
@@ -88,16 +85,15 @@ See the [Dates](#dates) section for more information on acceptable DATE formats
88
85
  ```shell
89
86
  #=>
90
87
  Saturday, (Today) 2023-05-06
91
- 1. 587a2f29 Blocked for locally failing test IN-12345
92
- Hope to pair with John on it
88
+ 1. Blocked for locally failing test IN-12345
93
89
 
94
90
  Friday, (Yesterday) 2023-05-05
95
- 1. edc25a9a Pick up ticket IN-12345
96
- 2. f7d3018c Attend new hire meet & greet
91
+ 1. Pick up ticket IN-12345
92
+ 2. Attend new hire meet & greet
97
93
  ```
98
94
  ## Editing DSU Entries
99
95
 
100
- You can edit DSU entry groups by date. `dsu` will allow you to edit a DSU entry group using the `dsu edit SUBCOMMAND` date (today|tomorrow|yesterday|date DATE) you specify. `dsu edit` will open your DSU entry group entries in your editor, where you'll be able to perform editing functions against one or all of the entries. If no entries exist in the entry group, you can add entries using any of the the *add* (`+|a|add`) editor commands, followed by the entry description. *NOTE: you cannot add duplicate entries; that is, the entry SHA and DESCRIPTION need to be unique within an entry group. Non-unique entries will not be added to the entry group.*
96
+ You can edit DSU entry groups by date. `dsu` will allow you to edit a DSU entry group using the `dsu edit SUBCOMMAND` date (today|tomorrow|yesterday|date DATE) you specify. `dsu edit` will open your DSU entry group entries in your editor, where you'll be able to perform editing functions against one or all of the entries. If no entries exist in the entry group the the date, the editor will allow you to add entries for that date. *NOTE: duplicate entries are not allowed; that is, the entry DESCRIPTION need to be unique within an entry group. Non-unique entries will not be added to the entry group. The same holds true for entries whose DESCRIPTION that do not pass validation (between 2 and 256 characters (inclusive) in length).*
101
97
 
102
98
  Note: See the "[Customizing the `dsu` Configuration File](#customizing-the-dsu-configuration-file)"" section to configure `dsu` to use the editor of your choice.
103
99
 
@@ -116,20 +112,20 @@ The following will edit your DSU entry group entries for "Today", where `Time.no
116
112
  ```shell
117
113
  #=> In your editor, you will see...
118
114
  # Editing DSU Entries for Tuesday, (Today) 2023-05-09 EDT
115
+ # [ENTRY DESCRIPTION]
119
116
 
120
- # [SHA/COMMAND] [DESCRIPTION]
121
- 3849f0c0 Interative planning meeting 11:00AM.
122
- 586478f5 Pair with Chad on ticket 31211.
123
- 9e5f82c8 Investigate spike ticket 31255.
124
- 59b25ca7 Review Kelsey's PR ticket 30721.
117
+ Interative planning meeting 11:00AM.
118
+ Pair with Chad on ticket 31211.
119
+ Investigate spike ticket 31255.
120
+ Review Kelsey's PR ticket 30721.
125
121
 
126
122
  # INSTRUCTIONS:
127
- # ADD a DSU entry: use one of the following commands: [+|a|add] followed by the description.
128
- # EDIT a DSU entry: change the description.
129
- # DELETE a DSU entry: delete the entry or replace the sha with one of the following commands: [-|d|delete].
130
- # NOTE: deleting all the entries will delete the entry group file;
131
- # this is preferable if this is what you want to do :)
132
- # REORDER a DSU entry: reorder the DSU entries in order preference.
123
+ # ADD a DSU entry: type an ENTRY DESCRIPTION on a new line.
124
+ # EDIT a DSU entry: change the existing ENTRY DESCRIPTION.
125
+ # DELETE a DSU entry: delete the ENTRY DESCRIPTION.
126
+ # NOTE: deleting all of the ENTRY DESCRIPTIONs will delete the entry group file;
127
+ # this is preferable if this is what you want to do :)
128
+ # REORDER a DSU entry: reorder the ENTRY DESCRIPTIONs in order preference.
133
129
  #
134
130
  # *** When you are done, save and close your editor ***
135
131
  ```
@@ -140,32 +136,28 @@ Simply change the entry descripton text.
140
136
 
141
137
  For example...
142
138
  ```
143
- from: 3849f0c0 Interative planning meeting 11:00AM.
144
- to: 3849f0c0 Interative planning meeting 12:00AM.
139
+ from: Interative planning meeting 11:00AM.
140
+ to: Interative planning meeting 12:00AM.
145
141
  ```
146
142
 
147
143
  #### Add an Entry
148
144
 
149
- Replace the entry `sha` one of the add commands: `[+|a|add]`.
145
+ Simply type a new entry on a separate line. *Note: any entry that starts with a `#` in the first character position will be ignored.*
150
146
 
151
147
  For example...
152
148
  ```
153
- + Add me to this entry group.
149
+ Add me to this entry group.
154
150
  ```
155
151
 
156
152
  #### Delete an Entry
157
153
 
158
- Simply delete the entry or replace the entry `sha` one of the delete commands: `[-|d|delete]`.
154
+ Simply delete the entry.
159
155
 
160
156
  For example...
161
157
  ```
162
158
  # Delete this this entry from the editor file
163
- 3849f0c0 Interative planning meeting 11:00AM.
164
- ```
165
- or
166
- ```
167
- from: 3849f0c0 Interative planning meeting 11:00AM.
168
- to: - Interative planning meeting 11:00AM.
159
+ from: Interative planning meeting 11:00AM.
160
+ to: <deleted>
169
161
  ```
170
162
 
171
163
  #### Reorder Entries
@@ -174,14 +166,14 @@ Simply reorder the entries in the editor.
174
166
 
175
167
  For example...
176
168
  ```
177
- from: 3849f0c0 Interative planning meeting 11:00AM.
178
- 586478f5 Pair with Chad on ticket 31211.
179
- 9e5f82c8 Investigate spike ticket 31255.
180
- 59b25ca7 Review Kelsey's PR ticket 30721.
181
- to: 59b25ca7 Review Kelsey's PR ticket 30721.
182
- 9e5f82c8 Investigate spike ticket 31255.
183
- 586478f5 Pair with Chad on ticket 31211.
184
- 3849f0c0 Interative planning meeting 11:00AM.
169
+ from: Interative planning meeting 11:00AM.
170
+ Pair with Chad on ticket 31211.
171
+ Investigate spike ticket 31255.
172
+ Review Kelsey's PR ticket 30721.
173
+ to: Review Kelsey's PR ticket 30721.
174
+ Investigate spike ticket 31255.
175
+ Pair with Chad on ticket 31211.
176
+ Interative planning meeting 11:00AM.
185
177
  ```
186
178
 
187
179
  ## Customizing the `dsu` Configuration File
@@ -242,12 +234,6 @@ These notes apply to anywhere DATE is used...
242
234
 
243
235
  DATE may be any date string that can be parsed using `Time.parse`. Consequently, you may use also use '/' as date separators, as well as omit the year if the date you want to display is the current year (e.g. <month>/<day>, or 1/31). For example: `require 'time'; Time.parse('2023-01-02'); Time.parse('1/2') # etc.`
244
236
 
245
- ## WIP Notes
246
- This gem is in development (alpha release).
247
-
248
- - Not all edge cases are being handled currently by `dsu edit SUBCOMMAND`.
249
- - `dsu add OPTION` will raise an error if the entry discription (Entry#description) are not unique. This will be handled gracefully in a future release.
250
-
251
237
  ## Installation
252
238
 
253
239
  $ gem install dsu
data/lib/dsu/base_cli.rb CHANGED
@@ -15,9 +15,6 @@ require_relative 'version'
15
15
  require_relative 'views/entry_group/show'
16
16
 
17
17
  module Dsu
18
- #
19
- # The `dsu` command.
20
- #
21
18
  class BaseCLI < ::Thor
22
19
  include Support::Colorable
23
20
  include Support::EntryGroupViewable
@@ -33,9 +30,19 @@ module Dsu
33
30
  end
34
31
 
35
32
  def date_option_description
36
- <<-DATE_OPTION_DESC
37
- Where DATE may be any date string that can be parsed using `Time.parse`. Consequently, you may use also use '/' as date separators, as well as omit thee year if the date you want to display is the current year (e.g. <month>/<day>, or 1/31). For example: `require 'time'; Time.parse('2023-01-02'); Time.parse('1/2') # etc.`
38
- DATE_OPTION_DESC
33
+ <<-OPTION_DESC
34
+ DATE:
35
+ \x5
36
+ This may be any date string that can be parsed using `Time.parse`. Consequently, you may use also use '/' as date separators, as well as omit thee year if the date you want to display is the current year (e.g. <month>/<day>, or 1/31). For example: `require 'time'; Time.parse('01/02/2023'); Time.parse('1/2') # etc.`
37
+ OPTION_DESC
38
+ end
39
+
40
+ def mneumonic_option_description
41
+ <<-OPTION_DESC
42
+ MNEUMONIC:
43
+ \x5
44
+ This may be any of the following: DATE (see DATE)|n|today|t|tomorrow|y|yesterday.
45
+ OPTION_DESC
39
46
  end
40
47
  end
41
48
 
data/lib/dsu/cli.rb CHANGED
@@ -20,7 +20,7 @@ module Dsu
20
20
  long_desc <<-LONG_DESC
21
21
  NAME
22
22
  \x5
23
- `DSU add, -a [OPTIONS] DESCRIPTION` -- will add a DSU entry having DESCRIPTION to the date associated with the given OPTION.
23
+ `dsu add, -a [OPTIONS] DESCRIPTION` -- will add a DSU entry having DESCRIPTION to the date associated with the given OPTION.
24
24
 
25
25
  SYNOPSIS
26
26
  \x5
@@ -30,14 +30,21 @@ module Dsu
30
30
  \x5
31
31
  -d DATE: Adds a DSU entry having DESCRIPTION to the DATE.
32
32
 
33
- \x5 #{date_option_description}
33
+ \x5
34
+ #{date_option_description}
34
35
 
35
- \x5 -n: Adds a DSU entry having DESCRIPTION to today's date (`Time.now`).
36
+ \x5
37
+ -n: Adds a DSU entry having DESCRIPTION to today's date (`Time.now`).
36
38
 
37
- \x5 -t: Adds a DSU entry having DESCRIPTION to tomorrow's date (`Time.new.tomorrow`).
39
+ \x5
40
+ -t: Adds a DSU entry having DESCRIPTION to tomorrow's date (`Time.new.tomorrow`).
38
41
 
39
- \x5 -y: Adds a DSU entry having DESCRIPTION to yesterday's date (`Time.new.yesterday`).
42
+ \x5
43
+ -y: Adds a DSU entry having DESCRIPTION to yesterday's date (`Time.new.yesterday`).
40
44
 
45
+ DESCRIPTION:
46
+ \x5
47
+ Must be be between 2 and 256 characters (inclusive) in length.
41
48
  LONG_DESC
42
49
  option :date, type: :string, aliases: '-d'
43
50
  option :tomorrow, type: :boolean, aliases: '-t'
@@ -45,52 +52,48 @@ module Dsu
45
52
  option :today, type: :boolean, aliases: '-n', default: true
46
53
 
47
54
  def add(description)
48
- times = if options[:date].present?
49
- time = Time.parse(options[:date])
50
- [time, time.yesterday]
51
- else
52
- time = Time.now
53
- if options[:tomorrow].present?
54
- [time.tomorrow, time.tomorrow.yesterday]
55
- elsif options[:yesterday].present?
56
- [time.yesterday, time.yesterday.yesterday]
57
- elsif options[:today].present?
58
- [time, time.yesterday]
59
- end
55
+ time = if options[:date].present?
56
+ Time.parse(options[:date])
57
+ elsif options[:tomorrow].present?
58
+ Time.now.tomorrow
59
+ elsif options[:yesterday].present?
60
+ Time.now.yesterday
61
+ elsif options[:today].present?
62
+ Time.now
60
63
  end
61
64
  entry = Models::Entry.new(description: description)
62
- # NOTE: We need to add the Entry to the date that is the furthest in the future
63
- # (time.max) because this is the DSU entry that the user specified.
64
- CommandServices::AddEntryService.new(entry: entry, time: times.max).call
65
- sorted_dsu_times_for(times: times).each do |t|
66
- view_entry_group(time: t)
67
- puts
68
- end
65
+ CommandServices::AddEntryService.new(entry: entry, time: time).call
66
+ view_entry_group(time: time)
69
67
  end
70
68
 
69
+ # def add(description)
70
+ # times = if options[:date].present?
71
+ # time = Time.parse(options[:date])
72
+ # [time, time.yesterday]
73
+ # else
74
+ # time = Time.now
75
+ # if options[:tomorrow].present?
76
+ # [time.tomorrow, time.tomorrow.yesterday]
77
+ # elsif options[:yesterday].present?
78
+ # [time.yesterday, time.yesterday.yesterday]
79
+ # elsif options[:today].present?
80
+ # [time, time.yesterday]
81
+ # end
82
+ # end
83
+ # entry = Models::Entry.new(description: description)
84
+ # # NOTE: We need to add the Entry to the date that is the furthest in the future
85
+ # # (time.max) because this is the DSU entry that the user specified.
86
+ # CommandServices::AddEntryService.new(entry: entry, time: times.max).call
87
+ # sorted_dsu_times_for(times: times).each do |t|
88
+ # view_entry_group(time: t)
89
+ # puts
90
+ # end
91
+ # end
92
+
71
93
  desc 'list, -l SUBCOMMAND',
72
94
  'Displays DSU entries for the given SUBCOMMAND'
73
95
  subcommand :list, Subcommands::List
74
96
 
75
- # TODO: Implement this.
76
- # desc 'interactive', 'Opens a DSU interactive session'
77
- # long_desc ''
78
- # option :next_day, type: :boolean, aliases: '-n'
79
- # option :previous_day, type: :boolean, aliases: '-p'
80
- # option :today, type: :boolean, aliases: '-t'
81
-
82
- # # https://stackoverflow.com/questions/4604905/interactive-prompt-with-thor
83
- # def interactive
84
- # exit_commands = %w[x q exit quit]
85
- # display_interactive_help
86
- # loop do
87
- # command = ask('dsu > ')
88
- # display_interactive_help if command == 'h'
89
- # break if exit_commands.include? command
90
- # end
91
- # say 'Done.'
92
- # end
93
-
94
97
  desc 'config, -c SUBCOMMAND',
95
98
  'Manage configuration file for this gem'
96
99
  subcommand :config, Subcommands::Config
@@ -104,17 +107,5 @@ module Dsu
104
107
  def version
105
108
  say VERSION
106
109
  end
107
-
108
- private
109
-
110
- def display_interactive_help
111
- say 'Interactive Mode Commands:'
112
- say '---'
113
- say '[h]: show this help screen'
114
- say '[t]: next day'
115
- say '[y]: previous day'
116
- say '[n]: today'
117
- say '[x|q|exit|quit]: Exit interactive mode'
118
- end
119
110
  end
120
111
  end
@@ -1,60 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../services/entry_group_writer_service'
4
3
  require_relative '../models/entry'
4
+ require_relative '../services/entry_group_writer_service'
5
+ require_relative '../support/colorable'
6
+ require_relative '../support/descriptable'
5
7
  require_relative '../support/entry_group_loadable'
6
8
  require_relative '../support/folder_locations'
9
+ require_relative '../support/say'
10
+ require_relative '../views/shared/messages'
7
11
 
8
12
  module Dsu
9
13
  module CommandServices
10
- # This class adds (does NOT update) an entry to an entry group.
14
+ # This class adds (does NOT update) an entry to an entry group by
15
+ # writing it to the appropriate entry group json file.
11
16
  class AddEntryService
12
- include Dsu::Support::EntryGroupLoadable
13
- include Dsu::Support::FolderLocations
17
+ include Support::Colorable
18
+ include Support::Descriptable
19
+ include Support::EntryGroupLoadable
20
+ include Support::FolderLocations
21
+ include Support::Say
14
22
 
15
23
  attr_reader :entry, :entry_group, :time
16
24
 
25
+ delegate :description, to: :entry
26
+
17
27
  # :entry is an Entry object
18
28
  # :time is a Time object; the time of the entry group.
19
29
  def initialize(entry:, time:)
20
30
  raise ArgumentError, 'entry is nil' if entry.nil?
21
- raise ArgumentError, 'entry is the wrong object type' unless entry.is_a?(Dsu::Models::Entry)
31
+ raise ArgumentError, 'entry is the wrong object type' unless entry.is_a?(Models::Entry)
22
32
  raise ArgumentError, 'time is nil' if time.nil?
23
33
  raise ArgumentError, 'time is the wrong object type' unless time.is_a?(Time)
24
34
 
25
35
  @entry = entry
26
36
  @time = time
27
- @entry_group = Dsu::Models::EntryGroup.load(time: time)
37
+ @entry_group = Models::EntryGroup.load(time: time)
28
38
  end
29
39
 
30
40
  def call
31
41
  entry.validate!
32
42
  save_entry_group!
33
- entry.uuid
34
- rescue ActiveModel::ValidationError
35
- puts "Error(s) encountered: #{entry.errors.full_messages}"
36
- raise
43
+ entry
44
+ rescue ActiveModel::ValidationError => e
45
+ header = 'An error was encountered; the entry could not be added added:'
46
+ Views::Shared::Messages.new(messages: e.message, message_type: :error, options: { header: header }).render
37
47
  end
38
48
 
39
49
  private
40
50
 
41
51
  attr_writer :entry, :entry_group, :time
42
52
 
43
- def entry_exists?
44
- @entry_exists ||= entry_group.entries.include? entry.uuid
45
- end
46
-
47
- def entry_group_hash
48
- @entry_group_hash ||= entry_group_hash_for time: time
49
- end
50
-
51
53
  def save_entry_group!
52
- raise "Entry #{entry.uuid} already exists in entry group #{time}" if entry_exists?
53
-
54
54
  entry_group.entries << entry
55
55
  entry_group.validate!
56
56
 
57
- Dsu::Services::EntryGroupWriterService.new(entry_group: entry_group).call
57
+ Services::EntryGroupWriterService.new(entry_group: entry_group).call
58
58
  end
59
59
  end
60
60
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/date/calculations'
4
+
5
+ module DateAndTime
6
+ module Calculations
7
+ def not_today?
8
+ !today?
9
+ end
10
+ end
11
+ end
@@ -1,44 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'deco_lite'
4
- require 'securerandom'
3
+ require 'active_model'
5
4
  require_relative '../support/descriptable'
5
+ require_relative '../validators/description_validator'
6
6
 
7
7
  module Dsu
8
8
  module Models
9
- class Entry < DecoLite::Model
9
+ # This class represents something someone might want to share at their
10
+ # daily standup (DSU).
11
+ class Entry
12
+ include ActiveModel::Model
10
13
  include Support::Descriptable
11
14
 
12
- ENTRY_UUID_REGEX = /\A[0-9a-f]{8}\z/i
15
+ validates_with Validators::DescriptionValidator
13
16
 
14
- validates :uuid, presence: true, format: {
15
- with: ENTRY_UUID_REGEX,
16
- message: 'is the wrong format. ' \
17
- '0-9, a-f, and 8 characters were expected.' \
18
- }
19
- validates :description, presence: true, length: { minimum: 2, maximum: 256 }
17
+ attr_reader :description
20
18
 
21
- def initialize(description:, uuid: nil)
22
- raise ArgumentError, 'description is nil' if description.nil?
19
+ def initialize(description:)
23
20
  raise ArgumentError, 'description is the wrong object type' unless description.is_a?(String)
24
- raise ArgumentError, 'uuid is the wrong object type' unless uuid.is_a?(String) || uuid.nil?
25
21
 
26
- uuid ||= SecureRandom.uuid[0..7]
22
+ self.description = description
23
+ end
24
+
25
+ class << self
26
+ def clean_description(description)
27
+ return if description.nil?
28
+
29
+ description.strip.gsub(/\s+/, ' ')
30
+ end
31
+ end
27
32
 
28
- super(hash: {
29
- uuid: uuid,
30
- description: description
31
- })
33
+ def description=(description)
34
+ @description = self.class.clean_description description
32
35
  end
33
36
 
34
- def required_fields
35
- %i[uuid description]
37
+ def to_h
38
+ { description: description }
36
39
  end
37
40
 
41
+ # Override == and hash so that we can compare Entry objects based
42
+ # on description alone. This is useful for comparing entries in
43
+ # an array, for example.
38
44
  def ==(other)
39
45
  return false unless other.is_a?(Entry)
40
46
 
41
- uuid == other.uuid && description == other.description
47
+ description == other.description
48
+ end
49
+ alias eql? ==
50
+
51
+ def hash
52
+ description.hash
42
53
  end
43
54
  end
44
55
  end