Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a dsu export command #54

Merged
merged 3 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## [2.3.0] 2023-12-25

Enhancements

- Added `dsu export` command to export all DSU entries or DSU entries between two given dates. Entries are written to a comma-delimited csv file located in your OS temp folder. For more information see `dsu help export` or the README.md file.

Changes

- Updated README.md to reflect new `dsu export` command.
- Fix misspelling of "cancelable" to "cancellable" in the codebase.
- Update ruby gems.

## [2.2.2] 2023-12-23

Changes
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
dsu (2.2.2)
dsu (2.3.0)
activemodel (>= 7.0.8, < 8.0)
activesupport (>= 7.0.8, < 8.0)
colorize (>= 0.8.1, < 1.0)
Expand Down Expand Up @@ -98,7 +98,7 @@ GEM
rubocop (~> 1.41)
rubocop-factory_bot (2.24.0)
rubocop (~> 1.33)
rubocop-performance (1.20.0)
rubocop-performance (1.20.1)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.25.0)
Expand Down
50 changes: 42 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# `dsu`- Streamline Your Daily Stand-Up Meeting Participation!

[![Ruby](https://github.com/gangelo/dsu/actions/workflows/ruby.yml/badge.svg)](https://github.com/gangelo/dsu/actions/workflows/ruby.yml)
[![GitHub version](http://badge.fury.io/gh/gangelo%2Fdsu.svg?refresh=1)](https://badge.fury.io/gh/gangelo%2Fdsu)
[![Gem Version](https://badge.fury.io/rb/dsu.svg?refresh=1)](https://badge.fury.io/rb/dsu)
[![GitHub version](http://badge.fury.io/gh/gangelo%2Fdsu.svg?refresh=2)](https://badge.fury.io/gh/gangelo%2Fdsu)
[![Gem Version](https://badge.fury.io/rb/dsu.svg?refresh=2)](https://badge.fury.io/rb/dsu)
[![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/dsu/)
[![Report Issues](https://img.shields.io/badge/report-issues-red.svg)](https://github.com/gangelo/dsu/issues)
[![License](http://img.shields.io/badge/license-MIT-yellowgreen.svg)](#license)
Expand Down Expand Up @@ -42,6 +42,7 @@ Commands:
dsu config|c SUBCOMMAND # Manage configuration...
dsu delete|d SUBCOMMAND # Delete DSU entries...
dsu edit|e SUBCOMMAND # Edit DSU entries...
dsu export|x SUBCOMMAND # Export DSU entries...
dsu help [COMMAND] # Describe available...
dsu info|i # Displays information...
dsu list|l SUBCOMMAND # Displays DSU entries...
Expand Down Expand Up @@ -105,13 +106,13 @@ You can display DSU entries for a particular day or date using any of the follow

- `$ dsu list today`
- `$ dsu l n` # Equivalent to the above, only using shortcuts
- `$ dsu list tomorrow|t`
- `$ dsu list tomorrow`
- `$ dsu l t` # Equivalent to the above, only using shortcuts
- `$ dsu list yesterday|y`
- `$ dsu list yesterday`
- `$ dsu l y` # Equivalent to the above, only using shortcuts
- `$ dsu list date|d DATE|MNEMONIC`
- `$ dsu list date DATE|MNEMONIC`
- `$ dsu l d DATE|MNEMONIC` # Equivalent to the above, only using shortcuts
- `$ dsu list dates|dd OPTIONS`
- `$ dsu list dates OPTIONS`
- `$ dsu l dd OPTIONS` # Equivalent to the above, only using shortcuts

See the [Dates](#dates) section for more information on acceptable DATE formats used by `dsu`.
Expand Down Expand Up @@ -272,20 +273,22 @@ from: Interative planning meeting 11:00AM.

#### Add an Entry

Simply type a new entry on a separate line. *Note: any entry that starts with a `#` in the first character position will be ignored.*
Simply type a new entry on a separate line.

For example...
```
Add me to this entry group.
```

**NOTE:** Any entry that starts with a `#` in the first character position will be ignored.*

#### Delete an Entry

Simply delete the entry.

For example...
```
# Delete this this entry from the editor file
# Delete this entry from the editor file
from: Interative planning meeting 11:00AM.
to: <deleted>
```
Expand Down Expand Up @@ -379,6 +382,37 @@ The following deletes the entry group and all entries for the past week, startin
Are you sure you want to delete all the entries for 2023-12-11 thru 2023-12-17 (7 entry groups)? [y/N]> y
Deleted 7 entry group(s).
```

## Exporting DSU Entries

Some ingenious soul may want to write a utility at some point, so `dsu` provides the means to export its data into a `csv` file for convenience. Of course, if you feel so inclined, you may also use the `dsu` entry group `json` files directly. The `dsu` entry group `json` files can be located by running the `dsu info` command, and locating the "Entries folder" value.

If you want to use a `csv` file, you can export `dsu` entries to a `csv` file by using any of the following commands:

- `$ dsu export all`
- `$ dsu x a` # Equivalent to the above, only using shortcuts
- `$ dsu export dates OPTIONS`
- `$ dsu x dd OPTIONS` # Equivalent to the above, only using shortcuts

**NOTE:** Each `export` command will prompt you to confirm the export. If confirmed, `dsu` will write a `csv` file to your operating systems temp folder, in the following format: `"dsu-<timestamp>-<from date>-thru-<to date>.csv"`:

Where:
- <timestamp> = '%Y%m%d%H%M%S'
- <from date> = the date of the earliest entry group exported (if `export all`) or the earliest date of the entry group dates to be exported (if `export dates`).
- <to date> = the date of the most resent entry group exported (if `export all`) or the most recent date of the entry group dates to be exported (if `export dates`).
-
### For example

The following command, when run on December 25, 2023, at 20:15:46...

`$ dsu export dates -f 1/1/1999 -t 12/23/2023`

...will export `dsu` entries for all Entry Groups that fall between the dates of January 1st, 1999 through December 23rd 2023 in the time zone it was executed, and write them to the following file:

`/var/folders/yv/5n77gtzn7z33ytwgr9mlbbrhf5rws6/T/dsu-20231225201546-1999-01-01-thru-2023-12-23.csv`

For more information, see `dsu` help (`$ dsu export` or `dsu help export`) for more information.

## Customizing the `dsu` Configuration File
To customize the `dsu` configuration file, you may follow the instructions outlined here. It is only recommended that you customize the `dsu` configuration file *only* if you are working with an official release (`n.n.n.n`).

Expand Down
5 changes: 5 additions & 0 deletions lib/dsu/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require_relative 'subcommands/config'
require_relative 'subcommands/delete'
require_relative 'subcommands/edit'
require_relative 'subcommands/export'
require_relative 'subcommands/list'
require_relative 'subcommands/theme'

Expand All @@ -18,6 +19,7 @@ class CLI < BaseCLI
map I18n.t('commands.config.key_mappings') => :config
map I18n.t('commands.delete.key_mappings') => :delete
map I18n.t('commands.edit.key_mappings') => :edit
map I18n.t('commands.export.key_mappings') => :export
map I18n.t('commands.help.key_mappings') => :help
map I18n.t('commands.info.key_mappings') => :info
map I18n.t('commands.list.key_mappings') => :list
Expand Down Expand Up @@ -60,6 +62,9 @@ def add(description)
desc I18n.t('commands.edit.desc'), I18n.t('commands.edit.usage')
subcommand :edit, Subcommands::Edit

desc I18n.t('commands.export.desc'), I18n.t('commands.export.usage')
subcommand :export, Subcommands::Export

desc I18n.t('commands.theme.desc'), I18n.t('commands.theme.usage')
subcommand :theme, Subcommands::Theme

Expand Down
10 changes: 7 additions & 3 deletions lib/dsu/models/entry_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ def all
next unless entry_file_name.match?(ENTRIES_FILE_NAME_REGEX)

entry_date = File.basename(entry_file_name, '.*')
file_path = entries_path_for(time: Time.parse(entry_date))
entry_group_hash = read!(file_path: file_path)
Services::EntryGroup::HydratorService.new(entry_group_hash: entry_group_hash).call
find time: Time.parse(entry_date)
end
end

Expand Down Expand Up @@ -167,6 +165,12 @@ def entry_group_times(between: nil)
end
end

def entry_groups(between:)
entry_group_times(between: between).filter_map do |time|
Models::EntryGroup.find(time: Time.parse(time))
end
end

def find(time:)
file_path = entries_path_for(time: time)
entry_group_hash = read!(file_path: file_path)
Expand Down
26 changes: 26 additions & 0 deletions lib/dsu/presenters/base_presenter_ex.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'delegate'
require_relative '../models/color_theme'
require_relative '../support/color_themable'

module Dsu
module Presenters
class BasePresenterEx
include Support::ColorThemable

def initialize(options: {})
@options = options || {}
@color_theme = Models::ColorTheme.find(theme_name: theme_name)
end

private

attr_reader :color_theme, :options

def theme_name
@theme_name ||= options.fetch(:theme_name, Models::Configuration.new.theme_name)
end
end
end
end
47 changes: 47 additions & 0 deletions lib/dsu/presenters/export/all_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require_relative '../../models/entry_group'
require_relative '../../services/entry_group/exporter_service'
require_relative '../../support/ask'
require_relative '../base_presenter_ex'
require_relative 'messages'
require_relative 'service_callable'

module Dsu
module Presenters
module Export
class AllPresenter < BasePresenterEx
include Messages
include ServiceCallable
include Support::Ask

def render(response:)
return display_cancelled_message unless response

export_file_path = exporter_service_call

display_exported_message
display_exported_to_message(file_path: export_file_path)
end

def display_export_prompt
yes?(prompt_with_options(prompt: export_prompt, options: export_prompt_options))
end

private

def entry_groups
@entry_groups ||= Models::EntryGroup.all
end

def export_prompt
I18n.t('subcommands.export.prompts.export_all_confirm', count: entry_groups.count)
end

def export_prompt_options
I18n.t('subcommands.export.prompts.options')
end
end
end
end
end
56 changes: 56 additions & 0 deletions lib/dsu/presenters/export/dates_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require_relative '../../models/entry_group'
require_relative '../../support/ask'
require_relative '../base_presenter_ex'
require_relative 'messages'
require_relative 'service_callable'

module Dsu
module Presenters
module Export
class DatesPresenter < BasePresenterEx
include Messages
include ServiceCallable
include Support::Ask

def initialize(from:, to:, options: {})
super(options: options)

@from = from
@to = to
end

def render(response:)
return display_cancelled_message unless response

export_file_path = exporter_service_call

display_exported_message
display_exported_to_message(file_path: export_file_path)
end

def display_export_prompt
yes?(prompt_with_options(prompt: export_prompt, options: export_prompt_options))
end

private

attr_reader :from, :to, :options

def entry_groups
Models::EntryGroup.entry_groups(between: [from, to])
end

def export_prompt
I18n.t('subcommands.export.prompts.export_dates_confirm',
from: from.to_date, to: to.to_date, count: entry_groups.count)
end

def export_prompt_options
I18n.t('subcommands.export.prompts.options')
end
end
end
end
end
31 changes: 31 additions & 0 deletions lib/dsu/presenters/export/messages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require_relative '../../models/entry_group'
require_relative '../base_presenter_ex'

module Dsu
module Presenters
module Export
module Messages
def display_export_prompt
raise NotImplementedError
end

private

def display_cancelled_message
puts apply_theme(I18n.t('subcommands.export.messages.cancelled'), theme_color: color_theme.info)
end

def display_exported_message
puts apply_theme(I18n.t('subcommands.export.messages.exported'), theme_color: color_theme.success)
end

def display_exported_to_message(file_path:)
puts apply_theme(I18n.t('subcommands.export.messages.exported_to', file_path: file_path),
theme_color: color_theme.success)
end
end
end
end
end
20 changes: 20 additions & 0 deletions lib/dsu/presenters/export/service_callable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require_relative '../../services/entry_group/exporter_service'

module Dsu
module Presenters
module Export
module ServiceCallable
private

def exporter_service_call
@exporter_service_call ||= begin
exporter_service = Services::EntryGroup::ExporterService.new(entry_groups: entry_groups, options: options)
exporter_service.call
end
end
end
end
end
end
Loading