Skip to content

Commit

Permalink
[69653] Support Calendar availability (#329)
Browse files Browse the repository at this point in the history
This PR enables support for the /calendars/availability and /calendars/availability/consecutive endpoints.
  • Loading branch information
mrashed-dev authored Oct 28, 2021
1 parent 4ca4475 commit b029210
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Metrics/BlockLength:

Metrics/ParameterLists:
Max: 8
Exclude:
- "lib/nylas/calendar_collection.rb"

Metrics/ClassLength:
Exclude:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Unreleased
* Add Component CRUD Support
* Add Scheduler support
* Add support for calendar availability
* Add support for `File` delete operation
* Fix issue where `file_ids` get reset to empty

Expand Down
2 changes: 2 additions & 0 deletions lib/nylas.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
require_relative "nylas/when"
require_relative "nylas/free_busy"
require_relative "nylas/time_slot"
require_relative "nylas/open_hours"
require_relative "nylas/event_conferencing"
require_relative "nylas/event_conferencing_details"
require_relative "nylas/event_conferencing_autocreate"
Expand All @@ -62,6 +63,7 @@
require_relative "nylas/search_collection"
require_relative "nylas/deltas_collection"
require_relative "nylas/free_busy_collection"
require_relative "nylas/calendar_collection"
require_relative "nylas/component_collection"

# Models supported by the API
Expand Down
3 changes: 2 additions & 1 deletion lib/nylas/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def accounts

# @return [Collection<Calendar>] A queryable collection of {Calendar}s
def calendars
@calendars ||= Collection.new(model: Calendar, api: self)
@calendars ||= CalendarCollection.new(model: Calendar, api: self)
end

# @return [DeltasCollection<Delta>] A queryable collection of Deltas, which are themselves a collection.
Expand Down Expand Up @@ -184,6 +184,7 @@ def webhooks
@webhooks ||= Collection.new(model: Webhook, api: as(client.app_secret))
end

# TODO: Move this into calendar collection
def free_busy(emails:, start_time:, end_time:)
FreeBusyCollection.new(
api: self,
Expand Down
100 changes: 100 additions & 0 deletions lib/nylas/calendar_collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# frozen_string_literal: true

module Nylas
# Additional methods for some of Calendar's other functionality
# @see https://developer.nylas.com/docs/connectivity/calendar
class CalendarCollection < Collection
def availability(duration_minutes:,
interval:,
start_time:,
end_time:,
emails:,
buffer: nil,
round_robin: nil,
free_busy: [],
open_hours: [])
validate_open_hours(emails, free_busy, open_hours) unless open_hours.empty?

execute_availability("/calendars/availability",
duration_minutes: duration_minutes,
interval: interval,
start_time: start_time,
end_time: end_time,
emails: emails,
buffer: buffer,
round_robin: round_robin,
free_busy: free_busy,
open_hours: open_hours)
end

def consecutive_availability(duration_minutes:,
interval:,
start_time:,
end_time:,
emails:,
buffer: nil,
free_busy: [],
open_hours: [])
validate_open_hours(emails, free_busy, open_hours) unless open_hours.empty?

execute_availability("/calendars/availability/consecutive",
duration_minutes: duration_minutes,
interval: interval,
start_time: start_time,
end_time: end_time,
emails: emails,
buffer: buffer,
free_busy: free_busy,
open_hours: open_hours)
end

private

def execute_availability(path, **payload)
api.execute(
method: :post,
path: path,
payload: JSON.dump(payload)
)
end

def validate_open_hours(emails, free_busy, open_hours)
raise TypeError, "open_hours' must be an array." unless open_hours.is_a?(Array)

open_hours_emails = map_open_hours_emails(open_hours)
free_busy_emails = map_free_busy_emails(free_busy)
emails = merge_arrays(emails) if emails[0].is_a?(Array)

open_hours_emails.each do |email|
next if emails.include?(email) || free_busy_emails.include?(email)

raise ArgumentError, "Open Hours cannot contain an email not present in the main email list or
the free busy email list."
end
end

def map_open_hours_emails(open_hours)
open_hours_emails = []
open_hours.map do |oh|
open_hours_emails += oh.emails
end
open_hours_emails
end

def map_free_busy_emails(free_busy)
free_busy_emails = []
free_busy.map do |fb|
free_busy_emails.append(fb.email)
end
free_busy_emails
end

def merge_arrays(array)
list = []
array.each do |x|
list += x
end
list
end
end
end
15 changes: 15 additions & 0 deletions lib/nylas/open_hours.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Nylas
# Additional times email accounts are available
# @see https://developer.nylas.com/docs/api/#post/calendars/availability
class OpenHours
include Model::Attributable

attribute :timezone, :string
attribute :start, :string
attribute :end, :string
has_n_of_attribute :emails, :string
has_n_of_attribute :days, :integer
end
end
148 changes: 148 additions & 0 deletions spec/nylas/calendar_collection_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# frozen_string_literal: true

require "spec_helper"

describe Nylas::CalendarCollection do
describe "availability" do
it "makes a request to get single availability" do
api = instance_double(Nylas::API, execute: JSON.parse("{}"))

calendar_collection = described_class.new(model: Nylas::Calendar, api: api)
free_busy = Nylas::FreeBusy.new(
email: "[email protected]",
time_slots: [
{
object: "time_slot",
status: "busy",
start_time: 1_609_439_400,
end_time: 1_640_975_400
}
]
)
open_hours = Nylas::OpenHours.new(
emails: ["[email protected]"],
days: [0],
timezone: "America/Chicago",
start: "10:00",
end: "14:00"
)

calendar_collection.availability(
duration_minutes: 30,
interval: 5,
start_time: 1590454800,
end_time: 1590780800,
emails: ["[email protected]"],
buffer: 5,
round_robin: "max-fairness",
free_busy: [free_busy],
open_hours: [open_hours]
)

expect(api).to have_received(:execute).with(
method: :post,
path: "/calendars/availability",
payload: JSON.dump(
duration_minutes: 30,
interval: 5,
start_time: 1590454800,
end_time: 1590780800,
emails: ["[email protected]"],
buffer: 5,
round_robin: "max-fairness",
free_busy: [free_busy],
open_hours: [open_hours]
)
)
end

it "makes a request to get multiple availability" do
api = instance_double(Nylas::API, execute: JSON.parse("{}"))

calendar_collection = described_class.new(model: Nylas::Calendar, api: api)
free_busy = Nylas::FreeBusy.new(
email: "[email protected]",
time_slots: [
{
object: "time_slot",
status: "busy",
start_time: 1_609_439_400,
end_time: 1_640_975_400
}
]
)
open_hours = Nylas::OpenHours.new(
emails: %w[[email protected] [email protected] [email protected] [email protected]],
days: [0],
timezone: "America/Chicago",
start: "10:00",
end: "14:00"
)

calendar_collection.consecutive_availability(
duration_minutes: 30,
interval: 5,
start_time: 1590454800,
end_time: 1590780800,
emails: [["[email protected]"], %w[[email protected] [email protected]]],
buffer: 5,
free_busy: [free_busy],
open_hours: [open_hours]
)

expect(api).to have_received(:execute).with(
method: :post,
path: "/calendars/availability/consecutive",
payload: JSON.dump(
duration_minutes: 30,
interval: 5,
start_time: 1590454800,
end_time: 1590780800,
emails: [["[email protected]"], %w[[email protected] [email protected]]],
buffer: 5,
free_busy: [free_busy],
open_hours: [open_hours]
)
)
end
end

describe "verification" do
it "throws an error if an email does not exist in open hours" do
api = instance_double(Nylas::API, execute: JSON.parse("{}"))

calendar_collection = described_class.new(model: Nylas::Calendar, api: api)
free_busy = Nylas::FreeBusy.new(
email: "[email protected]",
time_slots: [
{
object: "time_slot",
status: "busy",
start_time: 1_609_439_400,
end_time: 1_640_975_400
}
]
)
open_hours = Nylas::OpenHours.new(
emails: %w[[email protected] [email protected] [email protected] [email protected]],
days: [0],
timezone: "America/Chicago",
start: "10:00",
end: "14:00"
)

expect do
calendar_collection.consecutive_availability(
duration_minutes: 30,
interval: 5,
start_time: 1590454800,
end_time: 1590780800,
emails: [["[email protected]"], %w[[email protected] [email protected]]],
buffer: 5,
free_busy: [free_busy],
open_hours: [open_hours]
)
end.to raise_error(ArgumentError)
end
end
end

0 comments on commit b029210

Please sign in to comment.