checkoff 0.45.1 → 0.46.1
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/Gemfile.lock +1 -1
- data/config/definitions.rb +2 -2
- data/lib/checkoff/internal/search_url/custom_field_param_converter.rb +25 -16
- data/lib/checkoff/internal/search_url/date_param_converter.rb +63 -0
- data/lib/checkoff/internal/search_url/parser.rb +41 -7
- data/lib/checkoff/internal/search_url/results_merger.rb +40 -0
- data/lib/checkoff/my_tasks.rb +21 -2
- data/lib/checkoff/projects.rb +4 -2
- data/lib/checkoff/sections.rb +15 -6
- data/lib/checkoff/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a4be48acbc5f3ab9954ca8f7ec3ef64f1c629bfbc0015f158cde7a87fcc4049
|
4
|
+
data.tar.gz: 1824e5607d750cc1d9b2161dc897cd4a08fd90c27fea1c4cc7a5f19ee4e2c497
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ef67e1152d4399b8b507a6b6b6555f300ac83ffda4b998a8ae031ada997deabdd60974228db9cb01101bf319a3092a36fa259391c4fbdc6940266e1d53f923d
|
7
|
+
data.tar.gz: e04b024a9f4def03f62fb7a8b1498e53ed2d08cc53cff3a5b76bc7f16b6a20402a450704a7f782372b5f3438a7ecad063f1e7047b552d50a360fa7c5d1d60dbc
|
data/Gemfile.lock
CHANGED
data/config/definitions.rb
CHANGED
@@ -83,7 +83,7 @@
|
|
83
83
|
# # just because another object it is associated with (e.g. a subtask)
|
84
84
|
# # is modified. Actions that count as modifying the task include
|
85
85
|
# # assigning, renaming, completing, and adding stories.
|
86
|
-
# # @return [
|
86
|
+
# # @return [Enumerable<Asana::Resources::Task>]
|
87
87
|
# def find_all(assignee: nil, workspace: nil, project: nil, section: nil,
|
88
88
|
# tag: nil, user_task_list: nil, completed_since: nil,
|
89
89
|
# modified_since: nil, per_page: 20, options: {}); end
|
@@ -106,7 +106,7 @@
|
|
106
106
|
# class Section
|
107
107
|
# # @param project_gid [String]
|
108
108
|
# # @return [Enumerable<Asana::Resources::Section>]
|
109
|
-
# def get_sections_for_project(
|
109
|
+
# def get_sections_for_project(project_gid:, options: {}); end
|
110
110
|
# end
|
111
111
|
# class Project
|
112
112
|
# # Returns the compact project records for all projects in the workspace.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'custom_field_variant'
|
4
|
+
require_relative 'results_merger'
|
4
5
|
|
5
6
|
module Checkoff
|
6
7
|
module Internal
|
@@ -8,44 +9,41 @@ module Checkoff
|
|
8
9
|
# Convert custom field parameters from an Asana search URL into
|
9
10
|
# API search arguments and Checkoff task selectors
|
10
11
|
class CustomFieldParamConverter
|
12
|
+
# @param custom_field_params [Hash<String, Array<String>>]
|
11
13
|
def initialize(custom_field_params:)
|
12
14
|
@custom_field_params = custom_field_params
|
13
15
|
end
|
14
16
|
|
17
|
+
# @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
|
15
18
|
def convert
|
19
|
+
# @type args [Hash<String, String>]
|
16
20
|
args = {}
|
21
|
+
# @type task_selector [Array<[Symbol, Array]>]
|
17
22
|
task_selector = []
|
18
23
|
by_custom_field.each do |gid, single_custom_field_params|
|
24
|
+
# @sg-ignore
|
19
25
|
new_args, new_task_selector = convert_single_custom_field_params(gid,
|
20
26
|
single_custom_field_params)
|
21
|
-
|
22
|
-
|
27
|
+
|
28
|
+
args = ResultsMerger.merge_args(args, new_args)
|
29
|
+
|
30
|
+
# @sg-ignore
|
31
|
+
task_selector = ResultsMerger.merge_task_selectors(task_selector, new_task_selector)
|
23
32
|
end
|
24
33
|
[args, task_selector]
|
25
34
|
end
|
26
35
|
|
27
36
|
private
|
28
37
|
|
38
|
+
# @sg-ignore
|
39
|
+
# @return [Hash<String, Hash>]
|
29
40
|
def by_custom_field
|
30
41
|
custom_field_params.group_by do |key, _value|
|
31
42
|
gid_from_custom_field_key(key)
|
32
43
|
end.transform_values(&:to_h)
|
33
44
|
end
|
34
45
|
|
35
|
-
|
36
|
-
final_args = args.merge(new_args)
|
37
|
-
|
38
|
-
final_task_selector = if new_task_selector == []
|
39
|
-
task_selector
|
40
|
-
elsif task_selector == []
|
41
|
-
new_task_selector
|
42
|
-
else
|
43
|
-
[:and, task_selector, new_task_selector]
|
44
|
-
end
|
45
|
-
|
46
|
-
[final_args, final_task_selector]
|
47
|
-
end
|
48
|
-
|
46
|
+
# @type [Hash<String, Class<CustomFieldVariant>]
|
49
47
|
VARIANTS = {
|
50
48
|
'is' => CustomFieldVariant::Is,
|
51
49
|
'no_value' => CustomFieldVariant::NoValue,
|
@@ -58,22 +56,33 @@ module Checkoff
|
|
58
56
|
'contains_all' => CustomFieldVariant::ContainsAll,
|
59
57
|
}.freeze
|
60
58
|
|
59
|
+
# @param gid [String]
|
60
|
+
# @param single_custom_field_params [Hash<String, Array<String>>]
|
61
|
+
# @sg-ignore
|
62
|
+
# @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
|
61
63
|
def convert_single_custom_field_params(gid, single_custom_field_params)
|
62
64
|
variant_key = "custom_field_#{gid}.variant"
|
63
65
|
variant = single_custom_field_params.fetch(variant_key)
|
64
66
|
remaining_params = single_custom_field_params.reject { |k, _v| k == variant_key }
|
65
67
|
raise "Teach me how to handle #{variant_key} = #{variant}" unless variant.length == 1
|
66
68
|
|
69
|
+
# @sg-ignore
|
70
|
+
# @type variant_class [Class<CustomFieldVariant>]
|
67
71
|
variant_class = VARIANTS[variant[0]]
|
72
|
+
# @type [Array(Hash<String, String>, Array<[Symbol, Array]>)]
|
73
|
+
# @sg-ignore
|
68
74
|
return variant_class.new(gid, remaining_params).convert unless variant_class.nil?
|
69
75
|
|
70
76
|
raise "Teach me how to handle #{variant_key} = #{variant}"
|
71
77
|
end
|
72
78
|
|
79
|
+
# @param key [String]
|
80
|
+
# @return [String]
|
73
81
|
def gid_from_custom_field_key(key)
|
74
82
|
key.split('_')[2].split('.')[0]
|
75
83
|
end
|
76
84
|
|
85
|
+
# @return [Hash<String, Array<String>>]
|
77
86
|
attr_reader :custom_field_params
|
78
87
|
end
|
79
88
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'custom_field_param_converter'
|
4
|
+
|
5
|
+
module Checkoff
|
6
|
+
module Internal
|
7
|
+
module SearchUrl
|
8
|
+
# Convert date parameters - ones where the param name itself
|
9
|
+
# doesn't encode any parameters'
|
10
|
+
class DateParamConverter
|
11
|
+
# @param date_url_params [Hash<String, Array<String>>] the simple params
|
12
|
+
def initialize(date_url_params:)
|
13
|
+
@date_url_params = date_url_params
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Array(Hash<String, String>, Array<[Symbol, Array]>)] See https://developers.asana.com/docs/search-tasks-in-a-workspace
|
17
|
+
def convert
|
18
|
+
return [{}, []] if date_url_params.empty?
|
19
|
+
|
20
|
+
# example params:
|
21
|
+
# due_date.operator=through_next
|
22
|
+
# due_date.value=0
|
23
|
+
# due_date.unit=day
|
24
|
+
validate_due_date_through_next!
|
25
|
+
|
26
|
+
value = date_url_params.fetch('due_date.value').fetch(0).to_i
|
27
|
+
|
28
|
+
# @sg-ignore
|
29
|
+
# @type [Date]
|
30
|
+
before = Date.today + value
|
31
|
+
|
32
|
+
validate_unit_is_day!
|
33
|
+
|
34
|
+
# 'due_on.before' => '2023-01-01',
|
35
|
+
# 'due_on.after' => '2023-01-01',
|
36
|
+
# [{ 'due_on.before' => '2023-09-01' }, []]
|
37
|
+
[{ 'due_on.before' => before.to_s }, []]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @return [void]
|
43
|
+
def validate_unit_is_day!
|
44
|
+
unit = date_url_params.fetch('due_date.unit').fetch(0)
|
45
|
+
|
46
|
+
raise 'Teach me how to handle other time units' unless unit == 'day'
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [void]
|
50
|
+
def validate_due_date_through_next!
|
51
|
+
due_date_operators = date_url_params.fetch('due_date.operator')
|
52
|
+
|
53
|
+
return if due_date_operators == ['through_next']
|
54
|
+
|
55
|
+
raise "Teach me how to handle date mode: #{due_date_operators}."
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Hash<String, Array<String>>]
|
59
|
+
attr_reader :date_url_params
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -6,6 +6,8 @@ require 'cgi'
|
|
6
6
|
require 'uri'
|
7
7
|
require_relative 'simple_param_converter'
|
8
8
|
require_relative 'custom_field_param_converter'
|
9
|
+
require_relative 'results_merger'
|
10
|
+
require_relative 'date_param_converter'
|
9
11
|
|
10
12
|
module Checkoff
|
11
13
|
module Internal
|
@@ -13,36 +15,68 @@ module Checkoff
|
|
13
15
|
# Parse Asana search URLs into parameters suitable to pass into
|
14
16
|
# the /workspaces/{workspace_gid}/tasks/search endpoint
|
15
17
|
class Parser
|
18
|
+
# @param _deps [Hash]
|
16
19
|
def initialize(_deps = {})
|
17
20
|
# allow dependencies to be passed in by tests
|
18
21
|
end
|
19
22
|
|
23
|
+
# @param url [String]
|
24
|
+
# @return [Array(Hash<String, String>, Hash<String, String>)]
|
20
25
|
def convert_params(url)
|
21
26
|
url_params = CGI.parse(URI.parse(url).query)
|
27
|
+
# @type custom_field_params [Hash<String, Array<String>>]
|
28
|
+
# @type date_url_params [Hash<String, Array<String>>]
|
29
|
+
# @type simple_url_params [Hash<String, Array<String>>]
|
30
|
+
# @sg-ignore
|
31
|
+
custom_field_params, date_url_params, simple_url_params = partition_url_params(url_params)
|
32
|
+
# @type custom_field_args [Hash<String, String>]
|
33
|
+
# @type custom_field_task_selector [Hash<String, String>]
|
22
34
|
# @sg-ignore
|
23
|
-
|
35
|
+
custom_field_args, custom_field_task_selector = convert_custom_field_params(custom_field_params)
|
36
|
+
# @type date_args [Hash<String, String>]
|
37
|
+
# @type date_task_selector [Hash<String, String>]
|
24
38
|
# @sg-ignore
|
25
|
-
|
39
|
+
date_url_args, date_task_selector = convert_date_params(date_url_params)
|
26
40
|
simple_url_args = convert_simple_params(simple_url_params)
|
27
|
-
|
41
|
+
# raise 'merge these things'
|
42
|
+
[ResultsMerger.merge_args(custom_field_args, date_url_args, simple_url_args),
|
43
|
+
ResultsMerger.merge_task_selectors(date_task_selector, custom_field_task_selector)]
|
28
44
|
end
|
29
45
|
|
30
46
|
private
|
31
47
|
|
48
|
+
# @param date_url_params [Hash<String, Array<String>>]
|
49
|
+
# @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
|
50
|
+
def convert_date_params(date_url_params)
|
51
|
+
DateParamConverter.new(date_url_params: date_url_params).convert
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param simple_url_params [Hash<String, Array<String>>]
|
55
|
+
# @return [Hash<String, String>]
|
32
56
|
def convert_simple_params(simple_url_params)
|
33
57
|
SimpleParamConverter.new(simple_url_params: simple_url_params).convert
|
34
58
|
end
|
35
59
|
|
60
|
+
# @param custom_field_params [Hash<String, Array<String>>]
|
61
|
+
# @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
|
36
62
|
def convert_custom_field_params(custom_field_params)
|
37
63
|
CustomFieldParamConverter.new(custom_field_params: custom_field_params).convert
|
38
64
|
end
|
39
65
|
|
40
66
|
# @param url_params [Hash<String, String>]
|
41
|
-
# @return [Array(Hash<String, String>, Hash<String, String>)]
|
67
|
+
# @return [Array(Hash<String, String>, Hash<String, String>, Hash<String, String>)]
|
42
68
|
def partition_url_params(url_params)
|
43
|
-
url_params.to_a.
|
44
|
-
key.start_with? 'custom_field_'
|
45
|
-
|
69
|
+
groups = url_params.to_a.group_by do |key, _values|
|
70
|
+
if key.start_with? 'custom_field_'
|
71
|
+
:custom_field
|
72
|
+
elsif key.include? '_date'
|
73
|
+
:date
|
74
|
+
else
|
75
|
+
:simple
|
76
|
+
end
|
77
|
+
end.transform_values(&:to_h)
|
78
|
+
# @sg-ignore
|
79
|
+
[groups.fetch(:custom_field, {}), groups.fetch(:date, {}), groups.fetch(:simple, {})]
|
46
80
|
end
|
47
81
|
end
|
48
82
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkoff
|
4
|
+
module Internal
|
5
|
+
module SearchUrl
|
6
|
+
# Merge task selectors and search API arguments
|
7
|
+
class ResultsMerger
|
8
|
+
# @param args [Array<[Hash<String, String>]>]
|
9
|
+
# @return [Hash<String, String>
|
10
|
+
def self.merge_args(*args)
|
11
|
+
# first element of args
|
12
|
+
# @sg-ignore
|
13
|
+
# @type [Hash<String, String>]
|
14
|
+
f = args.fetch(0)
|
15
|
+
# rest of args
|
16
|
+
r = args.drop(0)
|
17
|
+
f.merge(*r)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param task_selectors [Array<Array<[Symbol, Array]>>]
|
21
|
+
# @return [Array<[Symbol, Array]>]
|
22
|
+
def self.merge_task_selectors(*task_selectors)
|
23
|
+
return [] if task_selectors.empty?
|
24
|
+
|
25
|
+
first_task_selector = task_selectors.fetch(0)
|
26
|
+
|
27
|
+
return merge_task_selectors(*task_selectors.drop(1)) if first_task_selector.empty?
|
28
|
+
|
29
|
+
return first_task_selector if task_selectors.length == 1
|
30
|
+
|
31
|
+
rest_task_selectors = merge_task_selectors(*task_selectors.drop(1))
|
32
|
+
|
33
|
+
return first_task_selector if rest_task_selectors.empty?
|
34
|
+
|
35
|
+
[:and, first_task_selector, rest_task_selectors]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/checkoff/my_tasks.rb
CHANGED
@@ -12,8 +12,12 @@ module Checkoff
|
|
12
12
|
LONG_CACHE_TIME = MINUTE * 15
|
13
13
|
SHORT_CACHE_TIME = MINUTE * 5
|
14
14
|
|
15
|
+
# @return [Checkoff::Projects]
|
15
16
|
attr_reader :projects
|
16
17
|
|
18
|
+
# @param config [Hash<Symbol, Object>]
|
19
|
+
# @param client [Asana::Client]
|
20
|
+
# @param projects [Checkoff::Projects]
|
17
21
|
def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
|
18
22
|
client: Checkoff::Clients.new(config: config).client,
|
19
23
|
projects: Checkoff::Projects.new(config: config,
|
@@ -26,13 +30,23 @@ module Checkoff
|
|
26
30
|
# Given a 'My Tasks' project object, pull all tasks, then provide
|
27
31
|
# a Hash of tasks with section name -> task list of the
|
28
32
|
# uncompleted tasks.
|
29
|
-
|
33
|
+
#
|
34
|
+
# @param project [Asana::Resources::Project]
|
35
|
+
# @param only_uncompleted [Boolean]
|
36
|
+
# @param extra_fields [Array<String>]
|
37
|
+
# @return [Hash<String, Enumerable<Asana::Resources::Task>>]
|
38
|
+
def tasks_by_section_for_my_tasks(project,
|
39
|
+
only_uncompleted: true,
|
40
|
+
extra_fields: [])
|
30
41
|
raw_tasks = projects.tasks_from_project(project,
|
42
|
+
only_uncompleted: only_uncompleted,
|
31
43
|
extra_fields: extra_fields + ['assignee_section.name'])
|
32
44
|
active_tasks = projects.active_tasks(raw_tasks)
|
33
45
|
by_my_tasks_section(active_tasks, project.gid)
|
34
46
|
end
|
35
47
|
|
48
|
+
# @param name [String]
|
49
|
+
# @return [String, nil]
|
36
50
|
def section_key(name)
|
37
51
|
return nil if name == 'Recently assigned'
|
38
52
|
|
@@ -41,10 +55,14 @@ module Checkoff
|
|
41
55
|
|
42
56
|
# Given a list of tasks in 'My Tasks', pull a Hash of tasks with
|
43
57
|
# section name -> task list
|
58
|
+
#
|
59
|
+
# @param tasks [Enumerable<Asana::Resources::Task>]
|
60
|
+
# @param project_gid [String]
|
61
|
+
# @return [Hash<String, Enumerable<Asana::Resources::Task>>]
|
44
62
|
def by_my_tasks_section(tasks, project_gid)
|
45
63
|
by_section = {}
|
46
64
|
sections = client.sections.get_sections_for_project(project_gid: project_gid)
|
47
|
-
sections.
|
65
|
+
sections.each_entry { |section| by_section[section_key(section.name)] = [] }
|
48
66
|
tasks.each do |task|
|
49
67
|
assignee_section = task.assignee_section
|
50
68
|
current_section = section_key(assignee_section.name)
|
@@ -56,6 +74,7 @@ module Checkoff
|
|
56
74
|
|
57
75
|
private
|
58
76
|
|
77
|
+
# @return [Asana::Client]
|
59
78
|
attr_reader :client
|
60
79
|
end
|
61
80
|
end
|
data/lib/checkoff/projects.rb
CHANGED
@@ -91,12 +91,14 @@ module Checkoff
|
|
91
91
|
# @param [Boolean] only_uncompleted
|
92
92
|
# @param [Array<String>] extra_fields
|
93
93
|
# @return [Enumerable<Asana::Resources::Task>]
|
94
|
-
def tasks_from_project(project,
|
94
|
+
def tasks_from_project(project,
|
95
|
+
only_uncompleted: true,
|
96
|
+
extra_fields: [])
|
95
97
|
options = task_options
|
96
98
|
options[:completed_since] = '9999-12-01' if only_uncompleted
|
97
99
|
options[:project] = project.gid
|
98
100
|
options[:options][:fields] += extra_fields
|
99
|
-
client.tasks.find_all(**options)
|
101
|
+
client.tasks.find_all(**options)
|
100
102
|
end
|
101
103
|
cache_method :tasks_from_project, SHORT_CACHE_TIME
|
102
104
|
|
data/lib/checkoff/sections.rb
CHANGED
@@ -65,17 +65,21 @@ module Checkoff
|
|
65
65
|
# tasks with section name -> task list of the uncompleted tasks
|
66
66
|
# @param workspace_name [String]
|
67
67
|
# @param project_name [String, Symbol]
|
68
|
+
# @param only_uncompleted [Boolean]
|
68
69
|
# @param extra_fields [Array<String>]
|
69
70
|
# @return [Hash{[String, nil] => Enumerable<Asana::Resources::Task>}]
|
70
|
-
def tasks_by_section(workspace_name,
|
71
|
+
def tasks_by_section(workspace_name,
|
72
|
+
project_name,
|
73
|
+
only_uncompleted: true,
|
74
|
+
extra_fields: [])
|
71
75
|
raise ArgumentError, 'Provided nil workspace name' if workspace_name.nil?
|
72
76
|
raise ArgumentError, 'Provided nil project name' if project_name.nil?
|
73
77
|
|
74
78
|
project = project_or_raise(workspace_name, project_name)
|
75
79
|
if project_name == :my_tasks
|
76
|
-
my_tasks.tasks_by_section_for_my_tasks(project, extra_fields: extra_fields)
|
80
|
+
my_tasks.tasks_by_section_for_my_tasks(project, only_uncompleted: only_uncompleted, extra_fields: extra_fields)
|
77
81
|
else
|
78
|
-
tasks_by_section_for_project(project, extra_fields: extra_fields)
|
82
|
+
tasks_by_section_for_project(project, only_uncompleted: only_uncompleted, extra_fields: extra_fields)
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
@@ -140,10 +144,15 @@ module Checkoff
|
|
140
144
|
# Given a project object, pull all tasks, then provide a Hash of
|
141
145
|
# tasks with section name -> task list of the uncompleted tasks
|
142
146
|
# @param project [Asana::Resources::Project]
|
147
|
+
# @param only_uncompleted [Boolean]
|
143
148
|
# @param extra_fields [Array<String>]
|
144
149
|
# @return [Hash<[String,nil], Enumerable<Asana::Resources::Task>>]
|
145
|
-
def tasks_by_section_for_project(project,
|
146
|
-
|
150
|
+
def tasks_by_section_for_project(project,
|
151
|
+
only_uncompleted: true,
|
152
|
+
extra_fields: [])
|
153
|
+
raw_tasks = projects.tasks_from_project(project,
|
154
|
+
only_uncompleted: only_uncompleted,
|
155
|
+
extra_fields: extra_fields)
|
147
156
|
active_tasks = projects.active_tasks(raw_tasks)
|
148
157
|
by_section(active_tasks, project.gid)
|
149
158
|
end
|
@@ -165,7 +174,7 @@ module Checkoff
|
|
165
174
|
by_section = {}
|
166
175
|
# @sg-ignore
|
167
176
|
sections = client.sections.get_sections_for_project(project_gid: project_gid)
|
168
|
-
sections.
|
177
|
+
sections.each_entry { |section| by_section[section_key(section.name)] = [] }
|
169
178
|
tasks.each { |task| file_task_by_section(by_section, task, project_gid) }
|
170
179
|
by_section
|
171
180
|
end
|
data/lib/checkoff/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: checkoff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.46.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vince Broz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -135,7 +135,9 @@ files:
|
|
135
135
|
- lib/checkoff/internal/search_url.rb
|
136
136
|
- lib/checkoff/internal/search_url/custom_field_param_converter.rb
|
137
137
|
- lib/checkoff/internal/search_url/custom_field_variant.rb
|
138
|
+
- lib/checkoff/internal/search_url/date_param_converter.rb
|
138
139
|
- lib/checkoff/internal/search_url/parser.rb
|
140
|
+
- lib/checkoff/internal/search_url/results_merger.rb
|
139
141
|
- lib/checkoff/internal/search_url/simple_param_converter.rb
|
140
142
|
- lib/checkoff/internal/task_selector_evaluator.rb
|
141
143
|
- lib/checkoff/my_tasks.rb
|