abt-cli 0.0.19 → 0.0.24
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/bin/abt +3 -3
- data/lib/abt.rb +6 -6
- data/lib/abt/ari.rb +2 -2
- data/lib/abt/ari_list.rb +1 -1
- data/lib/abt/base_command.rb +7 -7
- data/lib/abt/cli.rb +49 -47
- data/lib/abt/cli/arguments_parser.rb +6 -3
- data/lib/abt/cli/global_commands.rb +23 -0
- data/lib/abt/cli/global_commands/commands.rb +23 -0
- data/lib/abt/cli/global_commands/examples.rb +23 -0
- data/lib/abt/cli/global_commands/help.rb +23 -0
- data/lib/abt/cli/global_commands/readme.rb +23 -0
- data/lib/abt/cli/global_commands/share.rb +36 -0
- data/lib/abt/cli/global_commands/version.rb +23 -0
- data/lib/abt/cli/prompt.rb +64 -52
- data/lib/abt/docs.rb +48 -26
- data/lib/abt/docs/cli.rb +3 -3
- data/lib/abt/docs/markdown.rb +10 -7
- data/lib/abt/git_config.rb +4 -6
- data/lib/abt/helpers.rb +26 -8
- data/lib/abt/providers/asana/api.rb +9 -9
- data/lib/abt/providers/asana/base_command.rb +12 -10
- data/lib/abt/providers/asana/commands/add.rb +13 -12
- data/lib/abt/providers/asana/commands/branch_name.rb +8 -8
- data/lib/abt/providers/asana/commands/clear.rb +7 -8
- data/lib/abt/providers/asana/commands/current.rb +14 -15
- data/lib/abt/providers/asana/commands/finalize.rb +17 -18
- data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +18 -16
- data/lib/abt/providers/asana/commands/init.rb +8 -41
- data/lib/abt/providers/asana/commands/pick.rb +22 -26
- data/lib/abt/providers/asana/commands/projects.rb +5 -5
- data/lib/abt/providers/asana/commands/share.rb +7 -5
- data/lib/abt/providers/asana/commands/start.rb +28 -21
- data/lib/abt/providers/asana/commands/tasks.rb +6 -6
- data/lib/abt/providers/asana/configuration.rb +37 -29
- data/lib/abt/providers/asana/path.rb +6 -6
- data/lib/abt/providers/devops/api.rb +12 -12
- data/lib/abt/providers/devops/base_command.rb +14 -10
- data/lib/abt/providers/devops/commands/boards.rb +5 -7
- data/lib/abt/providers/devops/commands/branch_name.rb +9 -9
- data/lib/abt/providers/devops/commands/clear.rb +7 -8
- data/lib/abt/providers/devops/commands/current.rb +17 -18
- data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +21 -19
- data/lib/abt/providers/devops/commands/init.rb +21 -14
- data/lib/abt/providers/devops/commands/pick.rb +25 -19
- data/lib/abt/providers/devops/commands/share.rb +7 -5
- data/lib/abt/providers/devops/commands/{work-items.rb → work_items.rb} +3 -3
- data/lib/abt/providers/devops/configuration.rb +15 -15
- data/lib/abt/providers/devops/path.rb +7 -6
- data/lib/abt/providers/git/commands/branch.rb +23 -21
- data/lib/abt/providers/harvest/api.rb +8 -8
- data/lib/abt/providers/harvest/base_command.rb +10 -8
- data/lib/abt/providers/harvest/commands/clear.rb +7 -8
- data/lib/abt/providers/harvest/commands/current.rb +13 -14
- data/lib/abt/providers/harvest/commands/init.rb +10 -39
- data/lib/abt/providers/harvest/commands/pick.rb +15 -11
- data/lib/abt/providers/harvest/commands/projects.rb +5 -5
- data/lib/abt/providers/harvest/commands/share.rb +7 -5
- data/lib/abt/providers/harvest/commands/start.rb +5 -3
- data/lib/abt/providers/harvest/commands/stop.rb +12 -12
- data/lib/abt/providers/harvest/commands/tasks.rb +7 -7
- data/lib/abt/providers/harvest/commands/track.rb +52 -37
- data/lib/abt/providers/harvest/configuration.rb +18 -18
- data/lib/abt/providers/harvest/path.rb +6 -6
- data/lib/abt/version.rb +1 -1
- metadata +12 -5
| @@ -6,74 +6,45 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Init < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt init harvest"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        "Pick Harvest project for current git repository"
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 |  | 
| 16 16 | 
             
                      def perform
         | 
| 17 | 
            -
                         | 
| 18 | 
            -
             | 
| 17 | 
            +
                        require_local_config!
         | 
| 19 18 | 
             
                        projects # Load projects up front to make it obvious that searches are instant
         | 
| 20 | 
            -
                        project =  | 
| 19 | 
            +
                        project = cli.prompt.search("Select a project", searchable_projects)["project"]
         | 
| 21 20 |  | 
| 22 | 
            -
                        config.path = Path.from_ids(project[ | 
| 21 | 
            +
                        config.path = Path.from_ids(project_id: project["id"])
         | 
| 23 22 |  | 
| 24 23 | 
             
                        print_project(project)
         | 
| 25 24 | 
             
                      end
         | 
| 26 25 |  | 
| 27 26 | 
             
                      private
         | 
| 28 27 |  | 
| 29 | 
            -
                      def find_search_result
         | 
| 30 | 
            -
                        warn 'Select a project'
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                        loop do
         | 
| 33 | 
            -
                          matches = matches_for_string cli.prompt.text('Enter search')
         | 
| 34 | 
            -
                          if matches.empty?
         | 
| 35 | 
            -
                            warn 'No matches'
         | 
| 36 | 
            -
                            next
         | 
| 37 | 
            -
                          end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                          warn 'Showing the 10 first matches' if matches.size > 10
         | 
| 40 | 
            -
                          choice = cli.prompt.choice 'Select a project', matches[0...10], true
         | 
| 41 | 
            -
                          break choice['project'] unless choice.nil?
         | 
| 42 | 
            -
                        end
         | 
| 43 | 
            -
                      end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                      def matches_for_string(string)
         | 
| 46 | 
            -
                        search_string = sanitize_string(string)
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                        searchable_projects.select do |project|
         | 
| 49 | 
            -
                          sanitize_string(project['name']).include?(search_string)
         | 
| 50 | 
            -
                        end
         | 
| 51 | 
            -
                      end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                      def sanitize_string(string)
         | 
| 54 | 
            -
                        string.downcase.gsub(/[^\w]/, '')
         | 
| 55 | 
            -
                      end
         | 
| 56 | 
            -
             | 
| 57 28 | 
             
                      def searchable_projects
         | 
| 58 29 | 
             
                        @searchable_projects ||= projects.map do |project|
         | 
| 59 30 | 
             
                          {
         | 
| 60 | 
            -
                             | 
| 61 | 
            -
                             | 
| 31 | 
            +
                            "name" => "#{project['client']['name']} > #{project['name']}",
         | 
| 32 | 
            +
                            "project" => project
         | 
| 62 33 | 
             
                          }
         | 
| 63 34 | 
             
                        end
         | 
| 64 35 | 
             
                      end
         | 
| 65 36 |  | 
| 66 37 | 
             
                      def projects
         | 
| 67 38 | 
             
                        @projects ||= begin
         | 
| 68 | 
            -
                          warn | 
| 39 | 
            +
                          warn("Fetching projects...")
         | 
| 69 40 | 
             
                          project_assignments.map do |project_assignment|
         | 
| 70 | 
            -
                            project_assignment[ | 
| 41 | 
            +
                            project_assignment["project"].merge("client" => project_assignment["client"])
         | 
| 71 42 | 
             
                          end
         | 
| 72 43 | 
             
                        end
         | 
| 73 44 | 
             
                      end
         | 
| 74 45 |  | 
| 75 46 | 
             
                      def project_assignments
         | 
| 76 | 
            -
                        @project_assignments ||= api.get_paged( | 
| 47 | 
            +
                        @project_assignments ||= api.get_paged("users/me/project_assignments")
         | 
| 77 48 | 
             
                      end
         | 
| 78 49 | 
             
                    end
         | 
| 79 50 | 
             
                  end
         | 
| @@ -6,51 +6,55 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Pick < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt pick harvest[:<project-id>]"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        "Pick task for current git repository"
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 |  | 
| 16 16 | 
             
                      def self.flags
         | 
| 17 17 | 
             
                        [
         | 
| 18 | 
            -
                          [ | 
| 18 | 
            +
                          ["-d", "--dry-run", "Keep existing configuration"]
         | 
| 19 19 | 
             
                        ]
         | 
| 20 20 | 
             
                      end
         | 
| 21 21 |  | 
| 22 22 | 
             
                      def perform
         | 
| 23 | 
            -
                         | 
| 23 | 
            +
                        require_local_config!
         | 
| 24 24 | 
             
                        require_project!
         | 
| 25 25 |  | 
| 26 | 
            -
                        warn | 
| 27 | 
            -
                        task =  | 
| 26 | 
            +
                        warn(project["name"])
         | 
| 27 | 
            +
                        task = pick_task
         | 
| 28 28 |  | 
| 29 29 | 
             
                        print_task(project, task)
         | 
| 30 30 |  | 
| 31 31 | 
             
                        return if flags[:"dry-run"]
         | 
| 32 32 |  | 
| 33 | 
            -
                        config.path = Path.from_ids(project_id, task[ | 
| 33 | 
            +
                        config.path = Path.from_ids(project_id: project_id, task_id: task["id"])
         | 
| 34 34 | 
             
                      end
         | 
| 35 35 |  | 
| 36 36 | 
             
                      private
         | 
| 37 37 |  | 
| 38 38 | 
             
                      def project
         | 
| 39 | 
            -
                        project_assignment[ | 
| 39 | 
            +
                        project_assignment["project"]
         | 
| 40 | 
            +
                      end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      def pick_task
         | 
| 43 | 
            +
                        cli.prompt.choice("Select a task", tasks)
         | 
| 40 44 | 
             
                      end
         | 
| 41 45 |  | 
| 42 46 | 
             
                      def tasks
         | 
| 43 | 
            -
                        @tasks ||= project_assignment[ | 
| 47 | 
            +
                        @tasks ||= project_assignment["task_assignments"].map { |ta| ta["task"] }
         | 
| 44 48 | 
             
                      end
         | 
| 45 49 |  | 
| 46 50 | 
             
                      def project_assignment
         | 
| 47 51 | 
             
                        @project_assignment ||= begin
         | 
| 48 | 
            -
                          project_assignments.find { |pa| pa[ | 
| 52 | 
            +
                          project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
         | 
| 49 53 | 
             
                        end
         | 
| 50 54 | 
             
                      end
         | 
| 51 55 |  | 
| 52 56 | 
             
                      def project_assignments
         | 
| 53 | 
            -
                        @project_assignments ||= api.get_paged( | 
| 57 | 
            +
                        @project_assignments ||= api.get_paged("users/me/project_assignments")
         | 
| 54 58 | 
             
                      end
         | 
| 55 59 | 
             
                    end
         | 
| 56 60 | 
             
                  end
         | 
| @@ -6,11 +6,11 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Projects < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt projects harvest"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        "List all available projects - useful for piping into grep etc."
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 |  | 
| 16 16 | 
             
                      def perform
         | 
| @@ -23,15 +23,15 @@ module Abt | |
| 23 23 |  | 
| 24 24 | 
             
                      def projects
         | 
| 25 25 | 
             
                        @projects ||= begin
         | 
| 26 | 
            -
                          warn | 
| 26 | 
            +
                          warn("Fetching projects...")
         | 
| 27 27 | 
             
                          project_assignments.map do |project_assignment|
         | 
| 28 | 
            -
                            project_assignment[ | 
| 28 | 
            +
                            project_assignment["project"].merge("client" => project_assignment["client"])
         | 
| 29 29 | 
             
                          end
         | 
| 30 30 | 
             
                        end
         | 
| 31 31 | 
             
                      end
         | 
| 32 32 |  | 
| 33 33 | 
             
                      def project_assignments
         | 
| 34 | 
            -
                        @project_assignments ||= api.get_paged( | 
| 34 | 
            +
                        @project_assignments ||= api.get_paged("users/me/project_assignments")
         | 
| 35 35 | 
             
                      end
         | 
| 36 36 | 
             
                    end
         | 
| 37 37 | 
             
                  end
         | 
| @@ -6,17 +6,19 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Share < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt share harvest[:<project-id>[/<task-id>]]"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        "Print project/task ARI"
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 |  | 
| 16 16 | 
             
                      def perform
         | 
| 17 | 
            -
                         | 
| 18 | 
            -
             | 
| 19 | 
            -
                        cli. | 
| 17 | 
            +
                        if path != ""
         | 
| 18 | 
            +
                          cli.print_ari("harvest", path)
         | 
| 19 | 
            +
                        elsif cli.output.isatty
         | 
| 20 | 
            +
                          warn("No configuration for project. Did you initialize Harvest?")
         | 
| 21 | 
            +
                        end
         | 
| 20 22 | 
             
                      end
         | 
| 21 23 | 
             
                    end
         | 
| 22 24 | 
             
                  end
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require_relative  | 
| 3 | 
            +
            require_relative "track"
         | 
| 4 4 |  | 
| 5 5 | 
             
            module Abt
         | 
| 6 6 | 
             
              module Providers
         | 
| @@ -8,11 +8,13 @@ module Abt | |
| 8 8 | 
             
                  module Commands
         | 
| 9 9 | 
             
                    class Start < Track
         | 
| 10 10 | 
             
                      def self.usage
         | 
| 11 | 
            -
                         | 
| 11 | 
            +
                        "abt start harvest[:<project-id>/<task-id>] [options]"
         | 
| 12 12 | 
             
                      end
         | 
| 13 13 |  | 
| 14 14 | 
             
                      def self.description
         | 
| 15 | 
            -
                         | 
| 15 | 
            +
                        <<~TXT
         | 
| 16 | 
            +
                          Alias for: `abt track harvest`. Meant to used in combination with other ARIs, e.g. `abt start harvest asana`
         | 
| 17 | 
            +
                        TXT
         | 
| 16 18 | 
             
                      end
         | 
| 17 19 | 
             
                    end
         | 
| 18 20 | 
             
                  end
         | 
| @@ -6,19 +6,19 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Stop < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt stop harvest"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        "Stop running harvest tracker"
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 |  | 
| 16 16 | 
             
                      def perform
         | 
| 17 | 
            -
                        abort | 
| 17 | 
            +
                        abort("No running time entry") if time_entry.nil?
         | 
| 18 18 |  | 
| 19 19 | 
             
                        stop_time_entry
         | 
| 20 20 |  | 
| 21 | 
            -
                        warn | 
| 21 | 
            +
                        warn("Harvest time entry stopped")
         | 
| 22 22 | 
             
                        print_task(project, task)
         | 
| 23 23 | 
             
                      end
         | 
| 24 24 |  | 
| @@ -27,28 +27,28 @@ module Abt | |
| 27 27 | 
             
                      def stop_time_entry
         | 
| 28 28 | 
             
                        api.patch("time_entries/#{time_entry['id']}/stop")
         | 
| 29 29 | 
             
                      rescue Abt::HttpError::HttpError => e
         | 
| 30 | 
            -
                        warn | 
| 31 | 
            -
                        abort | 
| 30 | 
            +
                        warn(e)
         | 
| 31 | 
            +
                        abort("Unable to stop time entry")
         | 
| 32 32 | 
             
                      end
         | 
| 33 33 |  | 
| 34 34 | 
             
                      def project
         | 
| 35 | 
            -
                        time_entry[ | 
| 35 | 
            +
                        time_entry["project"]
         | 
| 36 36 | 
             
                      end
         | 
| 37 37 |  | 
| 38 38 | 
             
                      def task
         | 
| 39 | 
            -
                        time_entry[ | 
| 39 | 
            +
                        time_entry["task"]
         | 
| 40 40 | 
             
                      end
         | 
| 41 41 |  | 
| 42 42 | 
             
                      def time_entry
         | 
| 43 43 | 
             
                        @time_entry ||= begin
         | 
| 44 44 | 
             
                          api.get_paged(
         | 
| 45 | 
            -
                             | 
| 45 | 
            +
                            "time_entries",
         | 
| 46 46 | 
             
                            is_running: true,
         | 
| 47 47 | 
             
                            user_id: config.user_id
         | 
| 48 48 | 
             
                          ).first
         | 
| 49 | 
            -
                        rescue Abt::HttpError::HttpError => e | 
| 50 | 
            -
                          warn | 
| 51 | 
            -
                          abort | 
| 49 | 
            +
                        rescue Abt::HttpError::HttpError => e
         | 
| 50 | 
            +
                          warn(e)
         | 
| 51 | 
            +
                          abort("Unable to fetch running time entry")
         | 
| 52 52 | 
             
                        end
         | 
| 53 53 | 
             
                      end
         | 
| 54 54 | 
             
                    end
         | 
| @@ -6,11 +6,11 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Tasks < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt tasks harvest"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        "List available tasks on project - useful for piping into grep etc."
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 |  | 
| 16 16 | 
             
                      def perform
         | 
| @@ -24,24 +24,24 @@ module Abt | |
| 24 24 | 
             
                      private
         | 
| 25 25 |  | 
| 26 26 | 
             
                      def project
         | 
| 27 | 
            -
                        project_assignment[ | 
| 27 | 
            +
                        project_assignment["project"]
         | 
| 28 28 | 
             
                      end
         | 
| 29 29 |  | 
| 30 30 | 
             
                      def tasks
         | 
| 31 31 | 
             
                        @tasks ||= begin
         | 
| 32 | 
            -
                          warn | 
| 33 | 
            -
                          project_assignment[ | 
| 32 | 
            +
                          warn("Fetching tasks...")
         | 
| 33 | 
            +
                          project_assignment["task_assignments"].map { |ta| ta["task"] }
         | 
| 34 34 | 
             
                        end
         | 
| 35 35 | 
             
                      end
         | 
| 36 36 |  | 
| 37 37 | 
             
                      def project_assignment
         | 
| 38 38 | 
             
                        @project_assignment ||= begin
         | 
| 39 | 
            -
                          project_assignments.find { |pa| pa[ | 
| 39 | 
            +
                          project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
         | 
| 40 40 | 
             
                        end
         | 
| 41 41 | 
             
                      end
         | 
| 42 42 |  | 
| 43 43 | 
             
                      def project_assignments
         | 
| 44 | 
            -
                        @project_assignments ||= api.get_paged( | 
| 44 | 
            +
                        @project_assignments ||= api.get_paged("users/me/project_assignments")
         | 
| 45 45 | 
             
                      end
         | 
| 46 46 | 
             
                    end
         | 
| 47 47 | 
             
                  end
         | 
| @@ -6,30 +6,33 @@ module Abt | |
| 6 6 | 
             
                  module Commands
         | 
| 7 7 | 
             
                    class Track < BaseCommand
         | 
| 8 8 | 
             
                      def self.usage
         | 
| 9 | 
            -
                         | 
| 9 | 
            +
                        "abt track harvest[:<project-id>/<task-id>] [options]"
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 |  | 
| 12 12 | 
             
                      def self.description
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        <<~TXT
         | 
| 14 | 
            +
                          Start tracker for current or specified task. Add a relevant ARI to link the time entry, e.g. `abt track harvest asana`
         | 
| 15 | 
            +
                        TXT
         | 
| 14 16 | 
             
                      end
         | 
| 15 17 |  | 
| 16 18 | 
             
                      def self.flags
         | 
| 17 19 | 
             
                        [
         | 
| 18 | 
            -
                          [ | 
| 19 | 
            -
                          [ | 
| 20 | 
            -
                          [ | 
| 21 | 
            -
             | 
| 20 | 
            +
                          ["-s", "--set", "Set specified task as current"],
         | 
| 21 | 
            +
                          ["-c", "--comment COMMENT", "Override comment"],
         | 
| 22 | 
            +
                          ["-t", "--time HOURS",
         | 
| 23 | 
            +
                           "Set hours. Creates a stopped entry unless used with --running"],
         | 
| 24 | 
            +
                          ["-r", "--running", "Used with --time, starts the created time entry"]
         | 
| 22 25 | 
             
                        ]
         | 
| 23 26 | 
             
                      end
         | 
| 24 27 |  | 
| 25 28 | 
             
                      def perform
         | 
| 26 29 | 
             
                        require_task!
         | 
| 27 30 |  | 
| 28 | 
            -
                        print_task(created_time_entry[ | 
| 31 | 
            +
                        print_task(created_time_entry["project"], created_time_entry["task"])
         | 
| 29 32 |  | 
| 30 33 | 
             
                        maybe_override_current_task
         | 
| 31 34 | 
             
                      rescue Abt::HttpError::HttpError => _e
         | 
| 32 | 
            -
                        abort | 
| 35 | 
            +
                        abort("Invalid task")
         | 
| 33 36 | 
             
                      end
         | 
| 34 37 |  | 
| 35 38 | 
             
                      private
         | 
| @@ -39,65 +42,77 @@ module Abt | |
| 39 42 | 
             
                      end
         | 
| 40 43 |  | 
| 41 44 | 
             
                      def create_time_entry
         | 
| 42 | 
            -
                        body =  | 
| 43 | 
            -
                        body.merge!(hours: flags[:time]) if flags.key? :time
         | 
| 45 | 
            +
                        body = time_entry_data
         | 
| 44 46 |  | 
| 45 | 
            -
                        result = api.post( | 
| 47 | 
            +
                        result = api.post("time_entries", Oj.dump(body, mode: :json))
         | 
| 46 48 |  | 
| 47 | 
            -
                        if flags.key?(:time) && flags[:running]
         | 
| 48 | 
            -
                          api.patch("time_entries/#{result['id']}/restart")
         | 
| 49 | 
            -
                        end
         | 
| 49 | 
            +
                        api.patch("time_entries/#{result['id']}/restart") if flags.key?(:time) && flags[:running]
         | 
| 50 50 |  | 
| 51 51 | 
             
                        result
         | 
| 52 52 | 
             
                      end
         | 
| 53 53 |  | 
| 54 | 
            +
                      def time_entry_data
         | 
| 55 | 
            +
                        body = time_entry_base_data
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                        maybe_add_external_link(body)
         | 
| 58 | 
            +
                        maybe_add_comment(body)
         | 
| 59 | 
            +
                        maybe_add_time(body)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                        body
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
             | 
| 54 64 | 
             
                      def time_entry_base_data
         | 
| 55 | 
            -
                         | 
| 65 | 
            +
                        {
         | 
| 56 66 | 
             
                          project_id: project_id,
         | 
| 57 67 | 
             
                          task_id: task_id,
         | 
| 58 68 | 
             
                          user_id: config.user_id,
         | 
| 59 69 | 
             
                          spent_date: Date.today.iso8601
         | 
| 60 70 | 
             
                        }
         | 
| 71 | 
            +
                      end
         | 
| 61 72 |  | 
| 73 | 
            +
                      def maybe_add_external_link(body)
         | 
| 62 74 | 
             
                        if external_link_data
         | 
| 63 | 
            -
                          warn | 
| 75 | 
            +
                          warn(<<~TXT)
         | 
| 64 76 | 
             
                            Linking to:
         | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 77 | 
            +
                            #{external_link_data[:notes]}
         | 
| 78 | 
            +
                            #{external_link_data[:external_reference][:permalink]}
         | 
| 67 79 | 
             
                          TXT
         | 
| 68 | 
            -
                          body.merge! | 
| 80 | 
            +
                          body.merge!(external_link_data)
         | 
| 69 81 | 
             
                        else
         | 
| 70 | 
            -
                          warn | 
| 82 | 
            +
                          warn("No external link provided")
         | 
| 71 83 | 
             
                        end
         | 
| 84 | 
            +
                      end
         | 
| 72 85 |  | 
| 86 | 
            +
                      def maybe_add_comment(body)
         | 
| 73 87 | 
             
                        body[:notes] = flags[:comment] if flags.key?(:comment)
         | 
| 74 | 
            -
                        body[:notes] ||= cli.prompt.text( | 
| 75 | 
            -
             | 
| 88 | 
            +
                        body[:notes] ||= cli.prompt.text("Fill in comment (optional)")
         | 
| 89 | 
            +
                      end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                      def maybe_add_time(body)
         | 
| 92 | 
            +
                        body[:hours] = flags[:time] if flags.key?(:time)
         | 
| 76 93 | 
             
                      end
         | 
| 77 94 |  | 
| 78 95 | 
             
                      def external_link_data
         | 
| 79 | 
            -
                        @external_link_data  | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
                            end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                            Oj.load(lines.first, symbol_keys: true)
         | 
| 90 | 
            -
                          end
         | 
| 96 | 
            +
                        return @external_link_data if instance_variable_defined?(:@external_link_data)
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                        lines = fetch_link_data_lines
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                        return @external_link_data = nil if lines.empty?
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                        if lines.length > 1
         | 
| 103 | 
            +
                          abort("Got reference data from multiple scheme providers, only one is supported at a time")
         | 
| 91 104 | 
             
                        end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                        @external_link_data = Oj.load(lines.first, symbol_keys: true)
         | 
| 92 107 | 
             
                      end
         | 
| 93 108 |  | 
| 94 | 
            -
                      def  | 
| 109 | 
            +
                      def fetch_link_data_lines
         | 
| 95 110 | 
             
                        other_aris = cli.aris - [ari]
         | 
| 96 111 | 
             
                        return [] if other_aris.empty?
         | 
| 97 112 |  | 
| 98 113 | 
             
                        input = StringIO.new(other_aris.to_s)
         | 
| 99 114 | 
             
                        output = StringIO.new
         | 
| 100 | 
            -
                        Abt::Cli.new(argv: [ | 
| 115 | 
            +
                        Abt::Cli.new(argv: ["harvest-time-entry-data"], output: output, input: input).perform
         | 
| 101 116 |  | 
| 102 117 | 
             
                        output.string.strip.lines
         | 
| 103 118 | 
             
                      end
         | 
| @@ -108,7 +123,7 @@ module Abt | |
| 108 123 | 
             
                        return unless config.local_available?
         | 
| 109 124 |  | 
| 110 125 | 
             
                        config.path = path
         | 
| 111 | 
            -
                        warn | 
| 126 | 
            +
                        warn("Current task updated")
         | 
| 112 127 | 
             
                      end
         | 
| 113 128 | 
             
                    end
         | 
| 114 129 | 
             
                  end
         |