asana 0.6.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/Gemfile.lock +1 -1
- data/lib/asana/errors.rb +2 -2
- data/lib/asana/http_client/error_handling.rb +9 -15
- data/lib/asana/resources/attachment.rb +1 -1
- data/lib/asana/resources/custom_field_settings.rb +5 -4
- data/lib/asana/resources/custom_fields.rb +99 -5
- data/lib/asana/resources/organization_export.rb +63 -0
- data/lib/asana/resources/project.rb +11 -15
- data/lib/asana/resources/project_membership.rb +51 -0
- data/lib/asana/resources/project_status.rb +79 -0
- data/lib/asana/resources/section.rb +110 -0
- data/lib/asana/resources/story.rb +35 -1
- data/lib/asana/resources/tag.rb +1 -3
- data/lib/asana/resources/task.rb +119 -9
- data/lib/asana/resources/team.rb +1 -1
- data/lib/asana/resources/user.rb +1 -1
- data/lib/asana/resources/webhook.rb +1 -1
- data/lib/asana/resources/workspace.rb +3 -2
- data/lib/asana/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d310a2dce08f1a0d3184d739bca9be4cd8ad88368337595f1ec7ac31330d745
|
4
|
+
data.tar.gz: eef90d3cc06cf5a93725f20ab4b67e6b369c97a20952c6d50ed249f1c08dc666
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44a15f43e827a51b5f215d892248d9304dd1fc5c584d8a0b6b15a197f550f5ce61b7f7a8c6181eb14581b2a2ff99d60403e7e71b82a342d111fe5e47bfae6f7e
|
7
|
+
data.tar.gz: 707eb76c9827419e3b89188680bf979cc6007b81eb090b56c319f9b2cf8b4b90712f68796459f95bcda296c6d6df2d6ac27b5b99fc14708a1820f0539085daef
|
data/examples/Gemfile.lock
CHANGED
data/lib/asana/errors.rb
CHANGED
@@ -19,7 +19,7 @@ module Asana
|
|
19
19
|
# user could not be authenticated.
|
20
20
|
NotAuthorized = Class.new(APIError) do
|
21
21
|
def to_s
|
22
|
-
'
|
22
|
+
'Valid credentials were not provided with the request, so the API could '\
|
23
23
|
'not associate a user with the request.'
|
24
24
|
end
|
25
25
|
end
|
@@ -37,7 +37,7 @@ module Asana
|
|
37
37
|
# access the requested resource or to perform the requested action on it.
|
38
38
|
Forbidden = Class.new(APIError) do
|
39
39
|
def to_s
|
40
|
-
'The
|
40
|
+
'The authorization and request syntax was valid but the server is refusing '\
|
41
41
|
'to complete the request. This can happen if you try to read or write '\
|
42
42
|
'to objects or properties that the user does not have access to.'
|
43
43
|
end
|
@@ -11,7 +11,7 @@ module Asana
|
|
11
11
|
|
12
12
|
module_function
|
13
13
|
|
14
|
-
|
14
|
+
MAX_TIMEOUTS = 5
|
15
15
|
|
16
16
|
# Public: Perform a request handling any API errors correspondingly.
|
17
17
|
#
|
@@ -28,7 +28,7 @@ module Asana
|
|
28
28
|
# Raises [Asana::Errors::APIError] when the API returns an unknown error.
|
29
29
|
#
|
30
30
|
# rubocop:disable all
|
31
|
-
def handle(&request)
|
31
|
+
def handle(num_timeouts=0, &request)
|
32
32
|
request.call
|
33
33
|
rescue Faraday::ClientError => e
|
34
34
|
raise e unless e.response
|
@@ -36,25 +36,19 @@ module Asana
|
|
36
36
|
when 400 then raise invalid_request(e.response)
|
37
37
|
when 401 then raise not_authorized(e.response)
|
38
38
|
when 402 then raise payment_required(e.response)
|
39
|
-
when 403
|
40
|
-
begin
|
41
|
-
body = body(e.response)
|
42
|
-
errors_str = body['errors'].collect {
|
43
|
-
|err| err['message']
|
44
|
-
}.join('; ')
|
45
|
-
if errors_str.include? PREMIUM_ONLY_STR
|
46
|
-
raise payment_required(e.response)
|
47
|
-
end
|
48
|
-
rescue
|
49
|
-
raise forbidden(e.response)
|
50
|
-
end
|
51
|
-
raise forbidden(e.response)
|
39
|
+
when 403 then raise forbidden(e.response)
|
52
40
|
when 404 then raise not_found(e.response)
|
53
41
|
when 412 then recover_response(e.response)
|
54
42
|
when 429 then raise rate_limit_enforced(e.response)
|
55
43
|
when 500 then raise server_error(e.response)
|
56
44
|
else raise api_error(e.response)
|
57
45
|
end
|
46
|
+
rescue Net::ReadTimeout => e
|
47
|
+
if num_timeouts < MAX_TIMEOUTS
|
48
|
+
handle(num_timeouts + 1, &request)
|
49
|
+
else
|
50
|
+
raise e
|
51
|
+
end
|
58
52
|
end
|
59
53
|
# rubocop:enable all
|
60
54
|
|
@@ -30,13 +30,14 @@ module Asana
|
|
30
30
|
# Returns a list of all of the custom fields settings on a project, in compact form. Note that, as in all queries to collections which return compact representation, `opt_fields` and `opt_expand` can be used to include more data than is returned in the compact representation. See the getting started guide on [input/output options](/developers/documentation/getting-started/input-output-options) for more information.
|
31
31
|
#
|
32
32
|
# project - [Id] The ID of the project for which to list custom field settings
|
33
|
+
# per_page - [Integer] the number of records to fetch per page.
|
33
34
|
# options - [Hash] the request I/O options.
|
34
|
-
def find_by_project(client, project: required("project"), options: {})
|
35
|
-
|
36
|
-
|
35
|
+
def find_by_project(client, project: required("project"), per_page: 20, options: {})
|
36
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
37
|
+
Collection.new(parse(client.get("/projects/#{project}/custom_field_settings", params: params, options: options)), type: Resource, client: client)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
41
|
end
|
41
42
|
end
|
42
|
-
end
|
43
|
+
end
|
@@ -13,10 +13,10 @@ module Asana
|
|
13
13
|
|
14
14
|
attr_reader :id
|
15
15
|
|
16
|
-
attr_reader :created_at
|
17
|
-
|
18
16
|
attr_reader :name
|
19
17
|
|
18
|
+
attr_reader :description
|
19
|
+
|
20
20
|
attr_reader :type
|
21
21
|
|
22
22
|
attr_reader :enum_options
|
@@ -29,6 +29,25 @@ module Asana
|
|
29
29
|
'custom_fields'
|
30
30
|
end
|
31
31
|
|
32
|
+
# Creates a new custom field in a workspace. Every custom field is required to be created in a specific workspace, and this workspace cannot be changed once set.
|
33
|
+
#
|
34
|
+
# A custom field's `name` must be unique within a workspace and not conflict with names of existing task properties such as 'Due Date' or 'Assignee'. A custom field's `type` must be one of 'text', 'enum', or 'number'.
|
35
|
+
#
|
36
|
+
# Returns the full record of the newly created custom field.
|
37
|
+
#
|
38
|
+
# workspace - [Id] The workspace to create a custom field in.
|
39
|
+
# type - [String] The type of the custom field.
|
40
|
+
# name - [String] The name of the custom field.
|
41
|
+
# description - [String] The description of the custom field.
|
42
|
+
# precision - [Integer] The number of decimal places for the numerical values. Required if the custom field is of type 'number'.
|
43
|
+
# enum_options - [String] The discrete values the custom field can assume. Required if the custom field is of type 'enum'.
|
44
|
+
# options - [Hash] the request I/O options.
|
45
|
+
# data - [Hash] the attributes to post.
|
46
|
+
def create(client, workspace: required("workspace"), type: required("type"), name: required("name"), description: nil, precision: nil, enum_options: nil, options: {}, **data)
|
47
|
+
with_params = data.merge(workspace: workspace, type: type, name: name, description: description, precision: precision, enum_options: enum_options).reject { |_,v| v.nil? || Array(v).empty? }
|
48
|
+
Resource.new(parse(client.post("/custom_fields", body: with_params, options: options)).first, client: client)
|
49
|
+
end
|
50
|
+
|
32
51
|
# Returns the complete definition of a custom field's metadata.
|
33
52
|
#
|
34
53
|
# id - [Id] Globally unique identifier for the custom field.
|
@@ -42,13 +61,88 @@ module Asana
|
|
42
61
|
# Returns a list of the compact representation of all of the custom fields in a workspace.
|
43
62
|
#
|
44
63
|
# workspace - [Id] The workspace or organization to find custom field definitions in.
|
64
|
+
# per_page - [Integer] the number of records to fetch per page.
|
65
|
+
# options - [Hash] the request I/O options.
|
66
|
+
def find_by_workspace(client, workspace: required("workspace"), per_page: 20, options: {})
|
67
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
68
|
+
Collection.new(parse(client.get("/workspaces/#{workspace}/custom_fields", params: params, options: options)), type: Resource, client: client)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Creates an enum option and adds it to this custom field's list of enum options. A custom field can have at most 50 enum options (including disabled options). By default new enum options are inserted at the end of a custom field's list.
|
72
|
+
#
|
73
|
+
# Returns the full record of the newly created enum option.
|
74
|
+
#
|
75
|
+
# custom_field - [Id] Globally unique identifier for the custom field.
|
76
|
+
#
|
77
|
+
# name - [String] The name of the enum option.
|
78
|
+
# color - [String] The color of the enum option. Defaults to 'none'.
|
79
|
+
# insert_before - [Id] An existing enum option within this custom field before which the new enum option should be inserted. Cannot be provided together with after_enum_option.
|
80
|
+
# insert_after - [Id] An existing enum option within this custom field after which the new enum option should be inserted. Cannot be provided together with before_enum_option.
|
45
81
|
# options - [Hash] the request I/O options.
|
46
|
-
|
82
|
+
# data - [Hash] the attributes to post.
|
83
|
+
def add_enum_option(client, custom_field: required("custom_field"), name: required("name"), color: nil, insert_before: nil, insert_after: nil, options: {}, **data)
|
84
|
+
with_params = data.merge(name: name, color: color, insert_before: insert_before, insert_after: insert_after).reject { |_,v| v.nil? || Array(v).empty? }
|
85
|
+
Resource.new(parse(client.post("/custom_fields/#{custom_field}/enum_options", body: with_params, options: options)).first, client: client)
|
86
|
+
end
|
47
87
|
|
48
|
-
|
88
|
+
# Moves a particular enum option to be either before or after another specified enum option in the custom field.
|
89
|
+
#
|
90
|
+
# custom_field - [Id] Globally unique identifier for the custom field.
|
91
|
+
#
|
92
|
+
# enum_option - [Id] The ID of the enum option to relocate.
|
93
|
+
# name - [String] The name of the enum option.
|
94
|
+
# color - [String] The color of the enum option. Defaults to 'none'.
|
95
|
+
# before_enum_option - [Id] An existing enum option within this custom field before which the new enum option should be inserted. Cannot be provided together with after_enum_option.
|
96
|
+
# after_enum_option - [Id] An existing enum option within this custom field after which the new enum option should be inserted. Cannot be provided together with before_enum_option.
|
97
|
+
# options - [Hash] the request I/O options.
|
98
|
+
# data - [Hash] the attributes to post.
|
99
|
+
def reorder_enum_option(client, custom_field: required("custom_field"), enum_option: required("enum_option"), name: required("name"), color: nil, before_enum_option: nil, after_enum_option: nil, options: {}, **data)
|
100
|
+
with_params = data.merge(enum_option: enum_option, name: name, color: color, before_enum_option: before_enum_option, after_enum_option: after_enum_option).reject { |_,v| v.nil? || Array(v).empty? }
|
101
|
+
Resource.new(parse(client.post("/custom_fields/#{custom_field}/enum_options/insert", body: with_params, options: options)).first, client: client)
|
49
102
|
end
|
50
103
|
end
|
51
104
|
|
105
|
+
# A specific, existing custom field can be updated by making a PUT request on the URL for that custom field. Only the fields provided in the `data` block will be updated; any unspecified fields will remain unchanged
|
106
|
+
#
|
107
|
+
# When using this method, it is best to specify only those fields you wish to change, or else you may overwrite changes made by another user since you last retrieved the custom field.
|
108
|
+
#
|
109
|
+
# A custom field's `type` cannot be updated.
|
110
|
+
#
|
111
|
+
# An enum custom field's `enum_options` cannot be updated with this endpoint. Instead see "Work With Enum Options" for information on how to update `enum_options`.
|
112
|
+
#
|
113
|
+
# Returns the complete updated custom field record.
|
114
|
+
#
|
115
|
+
# options - [Hash] the request I/O options.
|
116
|
+
# data - [Hash] the attributes to post.
|
117
|
+
def update(options: {}, **data)
|
118
|
+
|
119
|
+
refresh_with(parse(client.put("/custom_fields/#{id}", body: data, options: options)).first)
|
120
|
+
end
|
121
|
+
|
122
|
+
# A specific, existing custom field can be deleted by making a DELETE request on the URL for that custom field.
|
123
|
+
#
|
124
|
+
# Returns an empty data record.
|
125
|
+
def delete()
|
126
|
+
|
127
|
+
client.delete("/custom_fields/#{id}") && true
|
128
|
+
end
|
129
|
+
|
130
|
+
# Updates an existing enum option. Enum custom fields require at least one enabled enum option.
|
131
|
+
#
|
132
|
+
# Returns the full record of the updated enum option.
|
133
|
+
#
|
134
|
+
# enum_option - [Id] Globally unique identifier for the enum option.
|
135
|
+
#
|
136
|
+
# name - [String] The name of the enum option.
|
137
|
+
# color - [String] The color of the enum option. Defaults to 'none'.
|
138
|
+
# enabled - [Boolean] Whether or not the enum option is a selectable value for the custom field.
|
139
|
+
# options - [Hash] the request I/O options.
|
140
|
+
# data - [Hash] the attributes to post.
|
141
|
+
def update_enum_option(enum_option: required("enum_option"), name: required("name"), color: nil, enabled: nil, options: {}, **data)
|
142
|
+
with_params = data.merge(name: name, color: color, enabled: enabled).reject { |_,v| v.nil? || Array(v).empty? }
|
143
|
+
refresh_with(parse(client.put("/enum_options/#{enum_option}", body: with_params, options: options)).first)
|
144
|
+
end
|
145
|
+
|
52
146
|
end
|
53
147
|
end
|
54
|
-
end
|
148
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
2
|
+
### edit it manually.
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Resources
|
6
|
+
# An _organization_export_ object represents a request to export the complete data of an Organization
|
7
|
+
# in JSON format.
|
8
|
+
#
|
9
|
+
# To export an Organization using this API:
|
10
|
+
#
|
11
|
+
# * Create an `organization_export` [request](#create) and store the id that is returned.\
|
12
|
+
# * Request the `organization_export` every few minutes, until the `state` field contains 'finished'.\
|
13
|
+
# * Download the file located at the URL in the `download_url` field.
|
14
|
+
#
|
15
|
+
# Exports can take a long time, from several minutes to a few hours for large Organizations.
|
16
|
+
#
|
17
|
+
# **Note:** These endpoints are only available to [Service Accounts](/guide/help/premium/service-accounts)
|
18
|
+
# of an [Enterprise](/enterprise) Organization.
|
19
|
+
class OrganizationExport < Resource
|
20
|
+
|
21
|
+
|
22
|
+
attr_reader :id
|
23
|
+
|
24
|
+
attr_reader :created_at
|
25
|
+
|
26
|
+
attr_reader :download_url
|
27
|
+
|
28
|
+
attr_reader :state
|
29
|
+
|
30
|
+
attr_reader :organization
|
31
|
+
|
32
|
+
class << self
|
33
|
+
# Returns the plural name of the resource.
|
34
|
+
def plural_name
|
35
|
+
'organization_exports'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns details of a previously-requested Organization export.
|
39
|
+
#
|
40
|
+
# id - [Id] Globally unique identifier for the Organization export.
|
41
|
+
#
|
42
|
+
# options - [Hash] the request I/O options.
|
43
|
+
def find_by_id(client, id, options: {})
|
44
|
+
|
45
|
+
self.new(parse(client.get("/organization_exports/#{id}", options: options)).first, client: client)
|
46
|
+
end
|
47
|
+
|
48
|
+
# This method creates a request to export an Organization. Asana will complete the export at some
|
49
|
+
# point after you create the request.
|
50
|
+
#
|
51
|
+
# organization - [Id] Globally unique identifier for the workspace or organization.
|
52
|
+
#
|
53
|
+
# options - [Hash] the request I/O options.
|
54
|
+
# data - [Hash] the attributes to post.
|
55
|
+
def create(client, organization: required("organization"), options: {}, **data)
|
56
|
+
with_params = data.merge(organization: organization).reject { |_,v| v.nil? || Array(v).empty? }
|
57
|
+
Resource.new(parse(client.post("/organization_exports", body: with_params, options: options)).first, client: client)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -3,14 +3,15 @@
|
|
3
3
|
|
4
4
|
module Asana
|
5
5
|
module Resources
|
6
|
-
# A _project_ represents a prioritized list of tasks in Asana
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# A _project_ represents a prioritized list of tasks in Asana or a board with
|
7
|
+
# columns of tasks represented as cards. It exists in a single workspace or
|
8
|
+
# organization and is accessible to a subset of users in that workspace or
|
9
|
+
# organization, depending on its permissions.
|
9
10
|
#
|
10
11
|
# Projects in organizations are shared with a single team. You cannot currently
|
11
12
|
# change the team of a project via the API. Non-organization workspaces do not
|
12
|
-
# have teams and so you should not specify the team of project in a
|
13
|
-
#
|
13
|
+
# have teams and so you should not specify the team of project in a regular
|
14
|
+
# workspace.
|
14
15
|
class Project < Resource
|
15
16
|
|
16
17
|
include EventSubscription
|
@@ -26,6 +27,8 @@ module Asana
|
|
26
27
|
|
27
28
|
attr_reader :due_date
|
28
29
|
|
30
|
+
attr_reader :start_on
|
31
|
+
|
29
32
|
attr_reader :created_at
|
30
33
|
|
31
34
|
attr_reader :modified_at
|
@@ -48,6 +51,8 @@ module Asana
|
|
48
51
|
|
49
52
|
attr_reader :team
|
50
53
|
|
54
|
+
attr_reader :layout
|
55
|
+
|
51
56
|
class << self
|
52
57
|
# Returns the plural name of the resource.
|
53
58
|
def plural_name
|
@@ -179,15 +184,6 @@ module Asana
|
|
179
184
|
client.delete("/projects/#{id}") && true
|
180
185
|
end
|
181
186
|
|
182
|
-
# Returns compact records for all sections in the specified project.
|
183
|
-
#
|
184
|
-
# per_page - [Integer] the number of records to fetch per page.
|
185
|
-
# options - [Hash] the request I/O options.
|
186
|
-
def sections(per_page: 20, options: {})
|
187
|
-
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
188
|
-
Collection.new(parse(client.get("/projects/#{id}/sections", params: params, options: options)), type: Resource, client: client)
|
189
|
-
end
|
190
|
-
|
191
187
|
# Returns the compact task records for all tasks within the given project,
|
192
188
|
# ordered by their priority within the project. Tasks can exist in more than one project at a time.
|
193
189
|
#
|
@@ -271,4 +267,4 @@ module Asana
|
|
271
267
|
|
272
268
|
end
|
273
269
|
end
|
274
|
-
end
|
270
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
2
|
+
### edit it manually.
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Resources
|
6
|
+
# With the introduction of "comment-only" projects in Asana, a user's membership
|
7
|
+
# in a project comes with associated permissions. These permissions (whether a
|
8
|
+
# user has full access to the project or comment-only access) are accessible
|
9
|
+
# through the project memberships endpoints described here.
|
10
|
+
class ProjectMembership < Resource
|
11
|
+
|
12
|
+
|
13
|
+
attr_reader :id
|
14
|
+
|
15
|
+
attr_reader :user
|
16
|
+
|
17
|
+
attr_reader :project
|
18
|
+
|
19
|
+
attr_reader :write_access
|
20
|
+
|
21
|
+
class << self
|
22
|
+
# Returns the plural name of the resource.
|
23
|
+
def plural_name
|
24
|
+
'project_memberships'
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the compact project membership records for the project.
|
28
|
+
#
|
29
|
+
# project - [Id] The project for which to fetch memberships.
|
30
|
+
# user - [String] If present, the user to filter the memberships to.
|
31
|
+
# per_page - [Integer] the number of records to fetch per page.
|
32
|
+
# options - [Hash] the request I/O options.
|
33
|
+
def get_many(client, project: required("project"), user: nil, per_page: 20, options: {})
|
34
|
+
params = { user: user, limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
35
|
+
Collection.new(parse(client.get("/projects/#{project}/project_memberships", params: params, options: options)), type: Resource, client: client)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the project membership record.
|
39
|
+
#
|
40
|
+
# project - [Id] Globally unique identifier for the project membership.
|
41
|
+
#
|
42
|
+
# options - [Hash] the request I/O options.
|
43
|
+
def get_single(client, project: required("project"), options: {})
|
44
|
+
|
45
|
+
Resource.new(parse(client.get("/project_memberships/#{project}", options: options)).first, client: client)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
2
|
+
### edit it manually.
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Resources
|
6
|
+
# A _project status_ is an update on the progress of a particular project, and is sent out to all project
|
7
|
+
# followers when created. These updates include both text describing the update and a color code intended to
|
8
|
+
# represent the overall state of the project: "green" for projects that are on track, "yellow" for projects
|
9
|
+
# at risk, and "red" for projects that are behind.
|
10
|
+
#
|
11
|
+
# Project statuses can be created and deleted, but not modified.
|
12
|
+
class ProjectStatus < Resource
|
13
|
+
|
14
|
+
|
15
|
+
attr_reader :id
|
16
|
+
|
17
|
+
attr_reader :title
|
18
|
+
|
19
|
+
attr_reader :text
|
20
|
+
|
21
|
+
attr_reader :color
|
22
|
+
|
23
|
+
attr_reader :created_by
|
24
|
+
|
25
|
+
attr_reader :created_at
|
26
|
+
|
27
|
+
class << self
|
28
|
+
# Returns the plural name of the resource.
|
29
|
+
def plural_name
|
30
|
+
'project_statuses'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Creates a new status update on the project.
|
34
|
+
#
|
35
|
+
# Returns the full record of the newly created project status update.
|
36
|
+
#
|
37
|
+
# project - [Id] The project on which to create a status update.
|
38
|
+
# text - [String] The text of the project status update.
|
39
|
+
#
|
40
|
+
# color - [String] The color to associate with the status update. Must be one of `"red"`, `"yellow"`, or `"green"`.
|
41
|
+
#
|
42
|
+
# options - [Hash] the request I/O options.
|
43
|
+
# data - [Hash] the attributes to post.
|
44
|
+
def create(client, project: required("project"), text: required("text"), color: required("color"), options: {}, **data)
|
45
|
+
with_params = data.merge(text: text, color: color).reject { |_,v| v.nil? || Array(v).empty? }
|
46
|
+
Resource.new(parse(client.post("/projects/#{project}/project_statuses", body: with_params, options: options)).first, client: client)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the compact project status update records for all updates on the project.
|
50
|
+
#
|
51
|
+
# project - [Id] The project to find status updates for.
|
52
|
+
# per_page - [Integer] the number of records to fetch per page.
|
53
|
+
# options - [Hash] the request I/O options.
|
54
|
+
def find_by_project(client, project: required("project"), per_page: 20, options: {})
|
55
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
56
|
+
Collection.new(parse(client.get("/projects/#{project}/project_statuses", params: params, options: options)), type: Resource, client: client)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the complete record for a single status update.
|
60
|
+
#
|
61
|
+
# id - [Id] The project status update to get.
|
62
|
+
# options - [Hash] the request I/O options.
|
63
|
+
def find_by_id(client, id, options: {})
|
64
|
+
|
65
|
+
self.new(parse(client.get("/project_statuses/#{id}", options: options)).first, client: client)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Deletes a specific, existing project status update.
|
70
|
+
#
|
71
|
+
# Returns an empty data record.
|
72
|
+
def delete()
|
73
|
+
|
74
|
+
client.delete("/project_statuses/#{id}") && true
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
2
|
+
### edit it manually.
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Resources
|
6
|
+
# A _section_ is a subdivision of a project that groups tasks together. It can
|
7
|
+
# either be a header above a list of tasks in a list view or a column in a
|
8
|
+
# board view of a project.
|
9
|
+
class Section < Resource
|
10
|
+
|
11
|
+
|
12
|
+
attr_reader :id
|
13
|
+
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
attr_reader :project
|
17
|
+
|
18
|
+
attr_reader :created_at
|
19
|
+
|
20
|
+
class << self
|
21
|
+
# Returns the plural name of the resource.
|
22
|
+
def plural_name
|
23
|
+
'sections'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a new section in a project.
|
27
|
+
#
|
28
|
+
# Returns the full record of the newly created section.
|
29
|
+
#
|
30
|
+
# project - [Id] The project to create the section in
|
31
|
+
# name - [String] The text to be displayed as the section name. This cannot be an empty string.
|
32
|
+
# options - [Hash] the request I/O options.
|
33
|
+
# data - [Hash] the attributes to post.
|
34
|
+
def create_in_project(client, project: required("project"), name: required("name"), options: {}, **data)
|
35
|
+
with_params = data.merge(name: name).reject { |_,v| v.nil? || Array(v).empty? }
|
36
|
+
self.new(parse(client.post("/projects/#{project}/sections", body: with_params, options: options)).first, client: client)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the compact records for all sections in the specified project.
|
40
|
+
#
|
41
|
+
# project - [Id] The project to get sections from.
|
42
|
+
# options - [Hash] the request I/O options.
|
43
|
+
def find_by_project(client, project: required("project"), options: {})
|
44
|
+
|
45
|
+
self.new(parse(client.get("/projects/#{project}/sections", options: options)).first, client: client)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the complete record for a single section.
|
49
|
+
#
|
50
|
+
# id - [Id] The section to get.
|
51
|
+
# options - [Hash] the request I/O options.
|
52
|
+
def find_by_id(client, id, options: {})
|
53
|
+
|
54
|
+
self.new(parse(client.get("/sections/#{id}", options: options)).first, client: client)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# A specific, existing section can be updated by making a PUT request on
|
59
|
+
# the URL for that project. Only the fields provided in the `data` block
|
60
|
+
# will be updated; any unspecified fields will remain unchanged. (note that
|
61
|
+
# at this time, the only field that can be updated is the `name` field.)
|
62
|
+
#
|
63
|
+
# When using this method, it is best to specify only those fields you wish
|
64
|
+
# to change, or else you may overwrite changes made by another user since
|
65
|
+
# you last retrieved the task.
|
66
|
+
#
|
67
|
+
# Returns the complete updated section record.
|
68
|
+
#
|
69
|
+
# options - [Hash] the request I/O options.
|
70
|
+
# data - [Hash] the attributes to post.
|
71
|
+
def update(options: {}, **data)
|
72
|
+
|
73
|
+
refresh_with(parse(client.put("/sections/#{id}", body: data, options: options)).first)
|
74
|
+
end
|
75
|
+
|
76
|
+
# A specific, existing section can be deleted by making a DELETE request
|
77
|
+
# on the URL for that section.
|
78
|
+
#
|
79
|
+
# Note that sections must be empty to be deleted.
|
80
|
+
#
|
81
|
+
# The last remaining section in a board view cannot be deleted.
|
82
|
+
#
|
83
|
+
# Returns an empty data block.
|
84
|
+
def delete()
|
85
|
+
|
86
|
+
client.delete("/sections/#{id}") && true
|
87
|
+
end
|
88
|
+
|
89
|
+
# Move sections relative to each other in a board view. One of
|
90
|
+
# `before_section` or `after_section` is required.
|
91
|
+
#
|
92
|
+
# Sections cannot be moved between projects.
|
93
|
+
#
|
94
|
+
# At this point in time, moving sections is not supported in list views, only board views.
|
95
|
+
#
|
96
|
+
# Returns an empty data block.
|
97
|
+
#
|
98
|
+
# project - [Id] The project in which to reorder the given section
|
99
|
+
# before_section - [Id] Insert the given section immediately before the section specified by this parameter.
|
100
|
+
# after_section - [Id] Insert the given section immediately after the section specified by this parameter.
|
101
|
+
# options - [Hash] the request I/O options.
|
102
|
+
# data - [Hash] the attributes to post.
|
103
|
+
def insert_in_project(project: required("project"), before_section: nil, after_section: nil, options: {}, **data)
|
104
|
+
with_params = data.merge(before_section: before_section, after_section: after_section).reject { |_,v| v.nil? || Array(v).empty? }
|
105
|
+
client.post("/projects/#{project}/sections/insert", body: with_params, options: options) && true
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -19,18 +19,31 @@ module Asana
|
|
19
19
|
|
20
20
|
attr_reader :created_by
|
21
21
|
|
22
|
+
# DEPRECATED: prefer "liked"
|
22
23
|
attr_reader :hearted
|
23
24
|
|
25
|
+
# DEPRECATED: prefer "likes"
|
24
26
|
attr_reader :hearts
|
25
27
|
|
28
|
+
# DEPRECATED: prefer "num_likes"
|
26
29
|
attr_reader :num_hearts
|
27
30
|
|
31
|
+
attr_reader :liked
|
32
|
+
|
33
|
+
attr_reader :likes
|
34
|
+
|
35
|
+
attr_reader :num_likes
|
36
|
+
|
28
37
|
attr_reader :text
|
29
38
|
|
30
39
|
attr_reader :html_text
|
31
40
|
|
32
41
|
attr_reader :target
|
33
42
|
|
43
|
+
attr_reader :is_pinned
|
44
|
+
|
45
|
+
attr_reader :is_edited
|
46
|
+
|
34
47
|
attr_reader :source
|
35
48
|
|
36
49
|
attr_reader :type
|
@@ -79,6 +92,27 @@ module Asana
|
|
79
92
|
end
|
80
93
|
end
|
81
94
|
|
95
|
+
# Updates the story and returns the full record for the updated story.
|
96
|
+
# Only comment stories can have their text updated, and only comment stories and
|
97
|
+
# attachment stories can be pinned. Only one of `text` and `html_text` can be specified.
|
98
|
+
#
|
99
|
+
# text - [String] The plain text with which to update the comment.
|
100
|
+
#
|
101
|
+
# html_text - [String] The rich text with which to update the comment.
|
102
|
+
# is_pinned - [Boolean] Whether the story should be pinned on the resource.
|
103
|
+
# options - [Hash] the request I/O options.
|
104
|
+
# data - [Hash] the attributes to post.
|
105
|
+
def update(text: nil, html_text: nil, is_pinned: nil, options: {}, **data)
|
106
|
+
with_params = data.merge(text: text, html_text: html_text, is_pinned: is_pinned).reject { |_,v| v.nil? || Array(v).empty? }
|
107
|
+
refresh_with(parse(client.put("/stories/#{id}", body: with_params, options: options)).first)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Deletes a story. A user can only delete stories they have created. Returns an empty data record.
|
111
|
+
def delete()
|
112
|
+
|
113
|
+
client.delete("/stories/#{id}") && true
|
114
|
+
end
|
115
|
+
|
82
116
|
end
|
83
117
|
end
|
84
|
-
end
|
118
|
+
end
|
data/lib/asana/resources/tag.rb
CHANGED
data/lib/asana/resources/task.rb
CHANGED
@@ -28,6 +28,10 @@ module Asana
|
|
28
28
|
|
29
29
|
attr_reader :custom_fields
|
30
30
|
|
31
|
+
attr_reader :dependencies
|
32
|
+
|
33
|
+
attr_reader :dependents
|
34
|
+
|
31
35
|
attr_reader :due_on
|
32
36
|
|
33
37
|
attr_reader :due_at
|
@@ -36,22 +40,33 @@ module Asana
|
|
36
40
|
|
37
41
|
attr_reader :followers
|
38
42
|
|
43
|
+
# DEPRECATED: prefer "liked"
|
39
44
|
attr_reader :hearted
|
40
45
|
|
46
|
+
# DEPRECATED: prefer "likes"
|
41
47
|
attr_reader :hearts
|
42
48
|
|
49
|
+
attr_reader :liked
|
50
|
+
|
51
|
+
attr_reader :likes
|
52
|
+
|
43
53
|
attr_reader :modified_at
|
44
54
|
|
45
55
|
attr_reader :name
|
46
56
|
|
47
57
|
attr_reader :notes
|
48
58
|
|
59
|
+
# DEPRECATED: prefer "num_likes"
|
49
60
|
attr_reader :num_hearts
|
50
61
|
|
62
|
+
attr_reader :num_likes
|
63
|
+
|
51
64
|
attr_reader :projects
|
52
65
|
|
53
66
|
attr_reader :parent
|
54
67
|
|
68
|
+
attr_reader :start_on
|
69
|
+
|
55
70
|
attr_reader :workspace
|
56
71
|
|
57
72
|
attr_reader :memberships
|
@@ -129,12 +144,23 @@ module Asana
|
|
129
144
|
Collection.new(parse(client.get("/tags/#{tag}/tasks", params: params, options: options)), type: self, client: client)
|
130
145
|
end
|
131
146
|
|
147
|
+
# <b>Board view only:</b> Returns the compact section records for all tasks within the given section.
|
148
|
+
#
|
149
|
+
# section - [Id] The section in which to search for tasks.
|
150
|
+
# per_page - [Integer] the number of records to fetch per page.
|
151
|
+
# options - [Hash] the request I/O options.
|
152
|
+
def find_by_section(client, section: required("section"), per_page: 20, options: {})
|
153
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
154
|
+
Collection.new(parse(client.get("/sections/#{section}/tasks", params: params, options: options)), type: self, client: client)
|
155
|
+
end
|
156
|
+
|
132
157
|
# Returns the compact task records for some filtered set of tasks. Use one
|
133
158
|
# or more of the parameters provided to filter the tasks returned. You must
|
134
159
|
# specify a `project` or `tag` if you do not specify `assignee` and `workspace`.
|
135
160
|
#
|
136
161
|
# assignee - [String] The assignee to filter tasks on.
|
137
162
|
# project - [Id] The project to filter tasks on.
|
163
|
+
# section - [Id] The section to filter tasks on.
|
138
164
|
# workspace - [Id] The workspace or organization to filter tasks on.
|
139
165
|
# completed_since - [String] Only return tasks that are either incomplete or that have been
|
140
166
|
# completed since this time.
|
@@ -147,6 +173,8 @@ module Asana
|
|
147
173
|
#
|
148
174
|
# If you specify `assignee`, you must also specify the `workspace` to filter on.
|
149
175
|
#
|
176
|
+
# Currently, this is only supported in board views.
|
177
|
+
#
|
150
178
|
# If you specify `workspace`, you must also specify the `assignee` to filter on.
|
151
179
|
#
|
152
180
|
# A task is considered "modified" if any of its properties change,
|
@@ -155,10 +183,20 @@ module Asana
|
|
155
183
|
# just because another object it is associated with (e.g. a subtask)
|
156
184
|
# is modified. Actions that count as modifying the task include
|
157
185
|
# assigning, renaming, completing, and adding stories.
|
158
|
-
def find_all(client, assignee: nil, project: nil, workspace: nil, completed_since: nil, modified_since: nil, per_page: 20, options: {})
|
159
|
-
params = { assignee: assignee, project: project, workspace: workspace, completed_since: completed_since, modified_since: modified_since, limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
186
|
+
def find_all(client, assignee: nil, project: nil, section: nil, workspace: nil, completed_since: nil, modified_since: nil, per_page: 20, options: {})
|
187
|
+
params = { assignee: assignee, project: project, section: section, workspace: workspace, completed_since: completed_since, modified_since: modified_since, limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
160
188
|
Collection.new(parse(client.get("/tasks", params: params, options: options)), type: self, client: client)
|
161
189
|
end
|
190
|
+
|
191
|
+
# The search endpoint allows you to build complex queries to find and fetch exactly the data you need from Asana. For a more comprehensive description of all the query parameters and limitations of this endpoint, see our [long-form documentation](/developers/documentation/getting-started/search-api) for this feature.
|
192
|
+
#
|
193
|
+
# workspace - [Id] The workspace or organization in which to search for tasks.
|
194
|
+
# per_page - [Integer] the number of records to fetch per page.
|
195
|
+
# options - [Hash] the request I/O options.
|
196
|
+
def search(client, workspace: required("workspace"), per_page: 20, options: {})
|
197
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
198
|
+
Collection.new(parse(client.get("/workspaces/#{workspace}/tasks/search", params: params, options: options)), type: Resource, client: client)
|
199
|
+
end
|
162
200
|
end
|
163
201
|
|
164
202
|
# A specific, existing task can be updated by making a PUT request on the
|
@@ -189,6 +227,64 @@ module Asana
|
|
189
227
|
client.delete("/tasks/#{id}") && true
|
190
228
|
end
|
191
229
|
|
230
|
+
# Returns the compact representations of all of the dependencies of a task.
|
231
|
+
#
|
232
|
+
# options - [Hash] the request I/O options.
|
233
|
+
def dependencies(options: {})
|
234
|
+
|
235
|
+
Resource.new(parse(client.get("/tasks/#{id}/dependencies", options: options)).first, client: client)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Returns the compact representations of all of the dependents of a task.
|
239
|
+
#
|
240
|
+
# options - [Hash] the request I/O options.
|
241
|
+
def dependents(options: {})
|
242
|
+
|
243
|
+
Resource.new(parse(client.get("/tasks/#{id}/dependents", options: options)).first, client: client)
|
244
|
+
end
|
245
|
+
|
246
|
+
# Marks a set of tasks as dependencies of this task, if they are not
|
247
|
+
# already dependencies. *A task can have at most 15 dependencies.*
|
248
|
+
#
|
249
|
+
# dependencies - [Array] An array of task IDs that this task should depend on.
|
250
|
+
# options - [Hash] the request I/O options.
|
251
|
+
# data - [Hash] the attributes to post.
|
252
|
+
def add_dependencies(dependencies: required("dependencies"), options: {}, **data)
|
253
|
+
with_params = data.merge(dependencies: dependencies).reject { |_,v| v.nil? || Array(v).empty? }
|
254
|
+
Resource.new(parse(client.post("/tasks/#{id}/addDependencies", body: with_params, options: options)).first, client: client)
|
255
|
+
end
|
256
|
+
|
257
|
+
# Marks a set of tasks as dependents of this task, if they are not already
|
258
|
+
# dependents. *A task can have at most 30 dependents.*
|
259
|
+
#
|
260
|
+
# dependents - [Array] An array of task IDs that should depend on this task.
|
261
|
+
# options - [Hash] the request I/O options.
|
262
|
+
# data - [Hash] the attributes to post.
|
263
|
+
def add_dependents(dependents: required("dependents"), options: {}, **data)
|
264
|
+
with_params = data.merge(dependents: dependents).reject { |_,v| v.nil? || Array(v).empty? }
|
265
|
+
Resource.new(parse(client.post("/tasks/#{id}/addDependents", body: with_params, options: options)).first, client: client)
|
266
|
+
end
|
267
|
+
|
268
|
+
# Unlinks a set of dependencies from this task.
|
269
|
+
#
|
270
|
+
# dependencies - [Array] An array of task IDs to remove as dependencies.
|
271
|
+
# options - [Hash] the request I/O options.
|
272
|
+
# data - [Hash] the attributes to post.
|
273
|
+
def remove_dependencies(dependencies: required("dependencies"), options: {}, **data)
|
274
|
+
with_params = data.merge(dependencies: dependencies).reject { |_,v| v.nil? || Array(v).empty? }
|
275
|
+
Resource.new(parse(client.post("/tasks/#{id}/removeDependencies", body: with_params, options: options)).first, client: client)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Unlinks a set of dependents from this task.
|
279
|
+
#
|
280
|
+
# dependents - [Array] An array of task IDs to remove as dependents.
|
281
|
+
# options - [Hash] the request I/O options.
|
282
|
+
# data - [Hash] the attributes to post.
|
283
|
+
def remove_dependents(dependents: required("dependents"), options: {}, **data)
|
284
|
+
with_params = data.merge(dependents: dependents).reject { |_,v| v.nil? || Array(v).empty? }
|
285
|
+
Resource.new(parse(client.post("/tasks/#{id}/removeDependents", body: with_params, options: options)).first, client: client)
|
286
|
+
end
|
287
|
+
|
192
288
|
# Adds each of the specified followers to the task, if they are not already
|
193
289
|
# following. Returns the complete, updated record for the affected task.
|
194
290
|
#
|
@@ -222,11 +318,17 @@ module Asana
|
|
222
318
|
|
223
319
|
# Adds the task to the specified project, in the optional location
|
224
320
|
# specified. If no location arguments are given, the task will be added to
|
225
|
-
# the
|
321
|
+
# the end of the project.
|
226
322
|
#
|
227
|
-
# `addProject` can also be used to reorder a task within a project that
|
323
|
+
# `addProject` can also be used to reorder a task within a project or section that
|
228
324
|
# already contains it.
|
229
325
|
#
|
326
|
+
# At most one of `insert_before`, `insert_after`, or `section` should be
|
327
|
+
# specified. Inserting into a section in an non-order-dependent way can be
|
328
|
+
# done by specifying `section`, otherwise, to insert within a section in a
|
329
|
+
# particular place, specify `insert_before` or `insert_after` and a task
|
330
|
+
# within the section to anchor the position of this task.
|
331
|
+
#
|
230
332
|
# Returns an empty data block.
|
231
333
|
#
|
232
334
|
# project - [Id] The project to add the task to.
|
@@ -237,7 +339,7 @@ module Asana
|
|
237
339
|
# insert at the end of the list.
|
238
340
|
#
|
239
341
|
# section - [Id] A section in the project to insert the task into. The task will be
|
240
|
-
# inserted at the
|
342
|
+
# inserted at the bottom of the section.
|
241
343
|
#
|
242
344
|
# options - [Hash] the request I/O options.
|
243
345
|
# data - [Hash] the attributes to post.
|
@@ -308,13 +410,21 @@ module Asana
|
|
308
410
|
end
|
309
411
|
|
310
412
|
# Changes the parent of a task. Each task may only be a subtask of a single
|
311
|
-
# parent, or no parent task at all. Returns an empty data block.
|
413
|
+
# parent, or no parent task at all. Returns an empty data block. When using `insert_before` and `insert_after`,
|
414
|
+
# at most one of those two options can be specified, and they must already be subtasks
|
415
|
+
# of the parent.
|
312
416
|
#
|
313
417
|
# parent - [Id] The new parent of the task, or `null` for no parent.
|
418
|
+
# insert_after - [Id] A subtask of the parent to insert the task after, or `null` to
|
419
|
+
# insert at the beginning of the list.
|
420
|
+
#
|
421
|
+
# insert_before - [Id] A subtask of the parent to insert the task before, or `null` to
|
422
|
+
# insert at the end of the list.
|
423
|
+
#
|
314
424
|
# options - [Hash] the request I/O options.
|
315
425
|
# data - [Hash] the attributes to post.
|
316
|
-
def set_parent(parent: required("parent"), options: {}, **data)
|
317
|
-
with_params = data.merge(parent: parent).reject { |_,v| v.nil? || Array(v).empty? }
|
426
|
+
def set_parent(parent: required("parent"), insert_after: nil, insert_before: nil, options: {}, **data)
|
427
|
+
with_params = data.merge(parent: parent, insert_after: insert_after, insert_before: insert_before).reject { |_,v| v.nil? || Array(v).empty? }
|
318
428
|
client.post("/tasks/#{id}/setParent", body: with_params, options: options) && true
|
319
429
|
end
|
320
430
|
|
@@ -343,4 +453,4 @@ module Asana
|
|
343
453
|
|
344
454
|
end
|
345
455
|
end
|
346
|
-
end
|
456
|
+
end
|
data/lib/asana/resources/team.rb
CHANGED
data/lib/asana/resources/user.rb
CHANGED
@@ -73,7 +73,8 @@ module Asana
|
|
73
73
|
# result set is limited to a single page of results with a maximum size,
|
74
74
|
# so you won't be able to fetch large numbers of results.
|
75
75
|
#
|
76
|
-
# type - [Enum] The type of values the typeahead should return.
|
76
|
+
# type - [Enum] The type of values the typeahead should return. You can choose from
|
77
|
+
# one of the following: custom_field, project, tag, task, and user.
|
77
78
|
# Note that unlike in the names of endpoints, the types listed here are
|
78
79
|
# in singular form (e.g. `task`). Using multiple types is not yet supported.
|
79
80
|
#
|
@@ -122,4 +123,4 @@ module Asana
|
|
122
123
|
|
123
124
|
end
|
124
125
|
end
|
125
|
-
end
|
126
|
+
end
|
data/lib/asana/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Txus
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oauth2
|
@@ -183,7 +183,11 @@ files:
|
|
183
183
|
- lib/asana/resources/attachment.rb
|
184
184
|
- lib/asana/resources/custom_field_settings.rb
|
185
185
|
- lib/asana/resources/custom_fields.rb
|
186
|
+
- lib/asana/resources/organization_export.rb
|
186
187
|
- lib/asana/resources/project.rb
|
188
|
+
- lib/asana/resources/project_membership.rb
|
189
|
+
- lib/asana/resources/project_status.rb
|
190
|
+
- lib/asana/resources/section.rb
|
187
191
|
- lib/asana/resources/story.rb
|
188
192
|
- lib/asana/resources/tag.rb
|
189
193
|
- lib/asana/resources/task.rb
|
@@ -216,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
220
|
version: '0'
|
217
221
|
requirements: []
|
218
222
|
rubyforge_project:
|
219
|
-
rubygems_version: 2.7.
|
223
|
+
rubygems_version: 2.7.7
|
220
224
|
signing_key:
|
221
225
|
specification_version: 4
|
222
226
|
summary: Official Ruby client for the Asana API
|