lib/wlog/ui/issue_ui.rb

Summary

Maintainability
A
55 mins
Test Coverage
require 'date'
require 'readline'
require 'base64'

require 'wlog/commands/replace_pattern'
require 'wlog/commands/new_entry'
require 'wlog/commands/make_csv'
require 'wlog/commands/innit_db'
require 'wlog/commands/concat_description'
require 'wlog/domain/sys_config'
require 'wlog/domain/timelog_helper'
require 'wlog/domain/attachment'
require 'wlog/ui/edit_handler'

module Wlog
# The interface when focusing on an issue
# @author Simon
class IssueUi
  def initialize(issue)
    @issue = issue
    @strmaker = SysConfig.string_decorator
  end

  # Start up the interface
  def run
    cmd = "default"
    until cmd == "end" do
      cmd = Readline.readline("[issue ##{@issue.id}] ") || ""
      cmd.chomp!

      case cmd
      when /^new/       then new_entry
      when /^(ls|show)/ then show_entries
      when /^desc/      then describe_issue
      when /^delete/    then delete_entry(cmd.split.drop 1)
      when /^edit/      then EditHandler.new(@issue).edit_what(cmd.split.drop 1)
      when /^concat/    then concat_description
      when /^replace/   then replace_pattern
      when /^search/    then search_term((cmd.split.drop 1).join ' ')
      when /^lt/        then time(cmd.split.drop 1) # lt for log time
      when /^forget/    then cmd = "end"
      when /^finish/    then finish ? cmd = "end" : nil
      when /^attachout/  then output_attach
      when /^attachls/ then show_attach
      when /^attach/ then attach
      when /^help/      then print_help
      when /^end/       then next
      else puts "Type 'help' for help"
      end
    end
  end

  # Focusing on the current issue
  attr_accessor :issue

private
  # This needs updating
  def print_help
    ["new",   "Create a new log entry",
    'ls',     "list issues",
    'desc',   "describe an issue",
    'edit',   "edit fields of an issue",
    'concat', "append information to an issue",
    'replace', 'replace text within an issue',
    'lt',     'log time on an issue',
    "outcsv", "Export everything to CSV",
    'attach', 'Attach a file to the current issue',
    'attachls', 'Show what files have been attached to an issue',
    'attachout', 'Extract a file from the database',
    "help",   "print this dialog",
    "end",    "Exit the progam (alias: forget, finish)",
    "search", "Search for a string in the log description text",
    "delete", "Remove the task with a given id"].each_with_index do |el,ix|
      print "  " if 1 == ix % 2
      puts el
    end
  end
  # Wriet out the data contained in the database of the attachment
  def output_attach
    att_id = Readline.readline('Which attachment to output? : ').to_i
    loc = Readline.readline('Output where (abs dir) ? : ')
    loc.chomp!
    att = Attachment.find(att_id)

    fh = File.open("#{loc}/#{att.filename}", 'w')
    fh.write(Base64.decode64(att.data))
    fh.close
  end

  def show_attach
    atts = @issue.attachments
    atts.each do |att|
      printf "[%d] - %s (alias: %s)\n", att.id, att.filename, att.given_name
    end
  end

  def attach
    loc = Readline.readline('Absolute file location: ')
    loc.strip!
    name_alias = Readline.readline('Alias name for file (optional): ')
    name_alias.strip!

    fh = File.open(loc, "rb")
    data = Base64.strict_encode64(fh.read)
    fh.close

    att = Attachment.new
    att.filename = File.basename(loc)
    att.data = data
    att.given_name = name_alias

    @issue.attachments << att

    puts 'Attached file.'
  rescue Zlib::DataError
    puts 'Problem attaching file due to wrong data'
  rescue => e
    puts 'Problem performing attachment'
    puts e.backtrace
  end

  # Time logging command
  def time(rest)
    time = TimelogHelper.parse(rest.join)
    @issue.log_time(time)
    puts @strmaker.green('logged time!')
  end

  # Print the description of the issue
  def describe_issue;
    puts @issue
  end

  # Exit the issue, mark as finished
  def finish
    question = 'Are you done with this task? [yes/no] :'
    if ret = !! Readline.readline(question).match(/^yes/i)
      @issue.mark_finished!
      @issue.save
    end
  ret end

  # new entry command
  def new_entry
    description = Readline.readline("Enter new issue:#{$/}  ")
    description.chomp!
    @issue.mark_working!
    @issue.save
    NewEntry.new(description, @issue).execute
  end

  def delete_entry(cmd_a)
    case cmd_a[0]
    when /t/, /task/       then LogEntry.delete(cmd_a[1])
    when /a/, /attachment/ then Attachment.delete(cmd_a[1])
    else puts "Usage:\n  delete <(t|task)|(a|attachment)> <id>"
    end
    # If something gets deleted, we need to reload the issue so that the
    # relations are ok.
    @issue.reload
  end

  # Concatenate an aggregate description to a previous item
  def concat_description
    id = Readline.readline("ID of task to concatenate to: ").to_i
    str = Readline.readline("Information to concatenate: ").chomp
    ok = ConcatDescription.new(id, str).execute
    puts "No such issue" if !ok
  end

  # Replace a pattern from a description of a log entry
  def replace_pattern
    id = Readline.readline("ID of task to perform replace: ").to_i
    old_pattern = Readline.readline('replace : ').chomp
    new_pattern = Readline.readline('with    : ').chomp
    ok = ReplacePattern.new(id, old_pattern, new_pattern).execute
    puts "No such task" if !ok
  end

  def search_term(term)
    term ||= ''
    term.chomp!
    print_entries(LogEntry.where(["description LIKE ?", "%#{term}%"]))
  end

  # TODO might need refactoring
  def show_entries
    @issue.reload
    print_entries(@issue.log_entries)
  end

  def print_entries(entries_a)
    date_collections = entries_a.group_by{|le| le.created_at.strftime("%Y-%m-%d")}
    date_collections.each_key do |date_c|
    print @strmaker.green("#{date_c} - ")
    print @strmaker.yellow(date_collections[date_c].first.created_at.strftime("%A"))
    puts " [#{@strmaker.magenta(date_collections[date_c].count.to_s)}]"
      date_collections[date_c].each do |le|
        puts "  #{le}"
      end
    end
  end
end
end # end module