Skip to content

Commit 06a601b

Browse files
authored
Merge pull request #34 from cronofy/add-to-calendar-availability
Add to calendar availability
2 parents 448a976 + 19af2ba commit 06a601b

File tree

8 files changed

+246
-6
lines changed

8 files changed

+246
-6
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## [0.10.0]
2+
3+
* Support for add to calendar with availability [#34]
4+
15
## [0.9.0]
26

37
* Support for add to calendar [#31]
@@ -71,6 +75,7 @@
7175
[0.7.0]: https://github.com/cronofy/cronofy-csharp/releases/tag/rel-0.7.0
7276
[0.8.0]: https://github.com/cronofy/cronofy-csharp/releases/tag/rel-0.8.0
7377
[0.9.0]: https://github.com/cronofy/cronofy-csharp/releases/tag/rel-0.9.0
78+
[0.10.0]: https://github.com/cronofy/cronofy-csharp/releases/tag/rel-0.10.0
7479

7580
[#3]: https://github.com/cronofy/cronofy-csharp/pull/3
7681
[#10]: https://github.com/cronofy/cronofy-csharp/pull/10
@@ -88,3 +93,4 @@
8893
[#28]: https://github.com/cronofy/cronofy-csharp/pull/28
8994
[#29]: https://github.com/cronofy/cronofy-csharp/pull/29
9095
[#31]: https://github.com/cronofy/cronofy-csharp/pull/31
96+
[#34]: https://github.com/cronofy/cronofy-csharp/pull/34

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.9.0
1+
0.10.0

src/Cronofy/AddToCalendarRequestBuilder.cs

+105-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace Cronofy
22
{
33
using System;
4+
using System.Collections.Generic;
45
using Cronofy.Requests;
56

67
/// <summary>
@@ -18,6 +19,16 @@ public sealed class AddToCalendarRequestBuilder : IBuilder<AddToCalendarRequest>
1819
/// </summary>
1920
private IBuilder<UpsertEventRequest> upsertEventRequestBuilder;
2021

22+
/// <summary>
23+
/// The availability details builder for the request.
24+
/// </summary>
25+
private IBuilder<AvailabilityRequest> availabilityRequestBuilder;
26+
27+
/// <summary>
28+
/// The target calendars builder for the request.
29+
/// </summary>
30+
private IList<AddToCalendarRequest.TargetCalendar> targetCalendars;
31+
2132
/// <summary>
2233
/// Sets the OAuth details of the request.
2334
/// </summary>
@@ -31,7 +42,7 @@ public sealed class AddToCalendarRequestBuilder : IBuilder<AddToCalendarRequest>
3142
/// A reference to the <see cref="AddToCalendarRequestBuilder"/>.
3243
/// </returns>
3344
/// <exception cref="ArgumentException">
34-
/// Thrown if <paramref name="redirectUrl"/> or <paramref name="scope"/> are empty.
45+
/// Thrown if <paramref name="redirectUri"/> or <paramref name="scope"/> are empty.
3546
/// </exception>
3647
public AddToCalendarRequestBuilder OAuthDetails(string redirectUri, string scope)
3748
{
@@ -54,7 +65,7 @@ public AddToCalendarRequestBuilder OAuthDetails(string redirectUri, string scope
5465
/// A reference to the <see cref="AddToCalendarRequestBuilder"/>.
5566
/// </returns>
5667
/// <exception cref="ArgumentException">
57-
/// Thrown if <paramref name="redirectUrl"/> or <paramref name="scope"/> are empty.
68+
/// Thrown if <paramref name="redirectUri"/> or <paramref name="scope"/> are empty.
5869
/// </exception>
5970
public AddToCalendarRequestBuilder OAuthDetails(string redirectUri, string scope, string state)
6071
{
@@ -130,14 +141,105 @@ public AddToCalendarRequestBuilder UpsertEventRequest(UpsertEventRequest upsertE
130141
return this;
131142
}
132143

144+
/// <summary>
145+
/// Sets the availability details of the request.
146+
/// </summary>
147+
/// <param name="availabilityRequestBuilder">
148+
/// The availability details builder for the request, must not be null.
149+
/// </param>
150+
/// <returns>
151+
/// A reference to the <see cref="AddToCalendarRequestBuilder"/>
152+
/// </returns>
153+
public AddToCalendarRequestBuilder AvailabilityRequestBuilder(IBuilder<AvailabilityRequest> availabilityRequestBuilder)
154+
{
155+
Preconditions.NotNull("availabilityRequestBuilder", availabilityRequestBuilder);
156+
157+
this.availabilityRequestBuilder = availabilityRequestBuilder;
158+
159+
return this;
160+
}
161+
162+
/// <summary>
163+
/// Sets the availability details of the request.
164+
/// </summary>
165+
/// <param name="availabilityRequest">
166+
/// The event details for the request, must not be null.
167+
/// </param>
168+
/// <returns>
169+
/// A reference to the <see cref="AddToCalendarRequestBuilder"/>.
170+
/// </returns>
171+
public AddToCalendarRequestBuilder AvailabilityRequest(AvailabilityRequest availabilityRequest)
172+
{
173+
Preconditions.NotNull("availability", availabilityRequest);
174+
175+
this.availabilityRequestBuilder = Builder.Wrap(availabilityRequest);
176+
177+
return this;
178+
}
179+
180+
/// <summary>
181+
/// Adds a target calendar to the request.
182+
/// </summary>
183+
/// <param name="sub">
184+
/// The sub for the target calendar.
185+
/// </param>
186+
/// <param name="calendarId">
187+
/// The target calendar's id.
188+
/// </param>
189+
/// <returns>
190+
/// A reference to the <see cref="AddToCalendarRequestBuilder"/>.
191+
/// </returns>
192+
public AddToCalendarRequestBuilder AddTargetCalendar(string sub, string calendarId)
193+
{
194+
Preconditions.NotBlank("sub", sub);
195+
Preconditions.NotBlank("calendarId", calendarId);
196+
197+
if (this.targetCalendars == null)
198+
{
199+
this.targetCalendars = new List<AddToCalendarRequest.TargetCalendar>();
200+
}
201+
202+
this.targetCalendars.Add(new AddToCalendarRequest.TargetCalendar
203+
{
204+
Sub = sub,
205+
CalendarId = calendarId
206+
});
207+
208+
return this;
209+
}
210+
211+
/// <summary>
212+
/// Sets the target calendar details of the request.
213+
/// </summary>
214+
/// <param name="targetCalendars">
215+
/// The target calendars.
216+
/// </param>
217+
/// <returns>
218+
/// A reference to the <see cref="AddToCalendarRequestBuilder"/>.
219+
/// </returns>
220+
public AddToCalendarRequestBuilder TargetCalendars(IList<AddToCalendarRequest.TargetCalendar> targetCalendars)
221+
{
222+
this.targetCalendars = targetCalendars;
223+
224+
return this;
225+
}
226+
133227
/// <inheritdoc />
134228
public AddToCalendarRequest Build()
135229
{
136-
return new AddToCalendarRequest
230+
var request = new AddToCalendarRequest
137231
{
138232
OAuth = this.oauthBuilder.Build(),
139233
Event = this.upsertEventRequestBuilder.Build(),
234+
TargetCalendars = this.targetCalendars,
140235
};
236+
237+
if (this.availabilityRequestBuilder != null)
238+
{
239+
request.Availability = this.availabilityRequestBuilder.Build();
240+
}
241+
242+
return request;
141243
}
142244
}
143245
}

src/Cronofy/Requests/AddToCalendarRequest.cs

+43
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace Cronofy.Requests
22
{
33
using System;
4+
using System.Collections.Generic;
45
using Newtonsoft.Json;
56

67
/// <summary>
@@ -44,6 +45,24 @@ public sealed class AddToCalendarRequest
4445
[JsonProperty("event")]
4546
public UpsertEventRequest Event { get; set; }
4647

48+
/// <summary>
49+
/// Gets or sets the availability details for the request.
50+
/// </summary>
51+
/// <value>
52+
/// The availability details for the request.
53+
/// </value>
54+
[JsonProperty("availability")]
55+
public AvailabilityRequest Availability { get; set; }
56+
57+
/// <summary>
58+
/// Gets or sets the target calendars for the request.
59+
/// </summary>
60+
/// <value>
61+
/// The target calendars for the request.
62+
/// </value>
63+
[JsonProperty("target_calendars")]
64+
public IEnumerable<TargetCalendar> TargetCalendars { get; set; }
65+
4766
/// <summary>
4867
/// Class for the serialization of the oauth details.
4968
/// </summary>
@@ -76,5 +95,29 @@ public sealed class OAuthDetails
7695
[JsonProperty("state")]
7796
public string State { get; set; }
7897
}
98+
99+
/// <summary>
100+
/// Class for the serialization of the target calendars
101+
/// </summary>
102+
public sealed class TargetCalendar
103+
{
104+
/// <summary>
105+
/// Gets or sets the sub for the target calendar.
106+
/// </summary>
107+
/// <value>
108+
/// The sub for the target calendar.
109+
/// </value>
110+
[JsonProperty("sub")]
111+
public string Sub { get; set; }
112+
113+
/// <summary>
114+
/// Gets or sets the ID for the target calendar.
115+
/// </summary>
116+
/// <value>
117+
/// The ID for the target calendar.
118+
/// </value>
119+
[JsonProperty("calendar_id")]
120+
public string CalendarId { get; set; }
121+
}
79122
}
80123
}

src/Cronofy/Requests/UpsertEventRequest.cs

+7
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ public sealed class UpsertEventRequest
110110
[JsonProperty("transparency")]
111111
public string Transparency { get; set; }
112112

113+
/// <summary>
114+
/// Gets or sets the timezone ID of the event.
115+
/// </summary>
116+
/// <value>The time zone identifier.</value>
117+
[JsonProperty("tzid")]
118+
public string TimeZoneId { get; set; }
119+
113120
/// <summary>
114121
/// Class for the serialization of the location for an upsert event
115122
/// request.

src/Cronofy/UpsertEventRequestBuilder.cs

+8-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ public sealed class UpsertEventRequestBuilder : IBuilder<UpsertEventRequest>
7272
/// </summary>
7373
private string endTimeZoneId;
7474

75+
/// <summary>
76+
/// The time zone of the event.
77+
/// </summary>
78+
private string timeZoneId;
79+
7580
/// <summary>
7681
/// The reminders for the event.
7782
/// </summary>
@@ -418,6 +423,7 @@ public UpsertEventRequestBuilder TimeZoneId(string timeZoneId)
418423

419424
this.startTimeZoneId = timeZoneId;
420425
this.endTimeZoneId = timeZoneId;
426+
this.timeZoneId = timeZoneId;
421427

422428
return this;
423429
}
@@ -591,6 +597,7 @@ public UpsertEventRequest Build()
591597
End = GetEventTime("End", this.endTime, this.endDate, this.endTimeZoneId),
592598
Url = this.url,
593599
Transparency = this.transparency,
600+
TimeZoneId = this.timeZoneId,
594601
};
595602

596603
if (string.IsNullOrEmpty(this.locationDescription) == false
@@ -665,7 +672,7 @@ private static EventTime GetEventTime(string propertyName, DateTimeOffset? time,
665672
return new EventTime(date.Value, timeZoneId);
666673
}
667674

668-
throw new ArgumentException(string.Format("{0} is not specified", propertyName));
675+
return null;
669676
}
670677
}
671678
}

test/Cronofy.Test/CronofyAccountClientTests/UpsertEvent.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ public void CanUpsertEventWithTimeZoneId()
207207
"\"summary\":\"{1}\"," +
208208
"\"description\":\"{2}\"," +
209209
"\"start\":{{\"time\":\"{3}\",\"tzid\":\"{5}\"}}," +
210-
"\"end\":{{\"time\":\"{4}\",\"tzid\":\"{5}\"}}" +
210+
"\"end\":{{\"time\":\"{4}\",\"tzid\":\"{5}\"}}," +
211+
"\"tzid\":\"{5}\"" +
211212
"}}",
212213
eventId,
213214
summary,

test/Cronofy.Test/CronofyOAuthClientTests/AddToCalendar.cs

+74
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ public sealed class AddToCalendar
2121
private DateTimeOffset start = new DateTime(2014, 8, 5, 15, 30, 0, DateTimeKind.Utc);
2222
private DateTimeOffset end = new DateTime(2014, 8, 5, 16, 30, 0, DateTimeKind.Utc);
2323

24+
private string sub = "sub";
25+
private string calendarId = "calendarId";
26+
2427
private UpsertEventRequest upsertEventRequest;
28+
private UpsertEventRequest upsertEventRequestWithoutStartAndEnd;
29+
private AvailabilityRequest availabilityRequest;
2530

2631
private CronofyOAuthClient client;
2732
private StubHttpClient http;
@@ -40,6 +45,17 @@ public void SetUp()
4045
.Start(start)
4146
.End(end)
4247
.Build();
48+
49+
this.upsertEventRequestWithoutStartAndEnd = new UpsertEventRequestBuilder()
50+
.EventId(eventId)
51+
.Summary(summary)
52+
.Build();
53+
54+
this.availabilityRequest = new AvailabilityRequestBuilder()
55+
.AddParticipantGroup(new ParticipantGroupBuilder().AddMember(sub))
56+
.AddAvailablePeriod(start, end)
57+
.RequiredDuration(60)
58+
.Build();
4359
}
4460

4561
[Test]
@@ -95,5 +111,63 @@ public void CanGetOAuthUrlWithoutState()
95111

96112
Assert.AreEqual(expectedUrl, actualUrl);
97113
}
114+
115+
[Test]
116+
public void CanGetOAuthUrlWithAvailabilityAndTargetCalendars()
117+
{
118+
var expectedUrl = "http://test.com";
119+
120+
http.Stub(
121+
HttpPost
122+
.Url("https://api.cronofy.com/v1/add_to_calendar")
123+
.RequestHeader("Content-Type", "application/json; charset=utf-8")
124+
.RequestBodyFormat(
125+
"{{" +
126+
"\"client_id\":\"{0}\"," +
127+
"\"client_secret\":\"{1}\"," +
128+
"\"oauth\":{{" +
129+
"\"redirect_uri\":\"{2}\"," +
130+
"\"scope\":\"{3}\"" +
131+
"}}," +
132+
"\"event\":{{" +
133+
"\"event_id\":\"{4}\"," +
134+
"\"summary\":\"{5}\"" +
135+
"}}," +
136+
"\"availability\":{{" +
137+
"\"participants\":[{{" +
138+
"\"members\":[{{" +
139+
"\"sub\":\"{6}\"" +
140+
"}}]" +
141+
"}}]," +
142+
"\"required_duration\":{{" +
143+
"\"minutes\":60" +
144+
"}}," +
145+
"\"available_periods\":[{{" +
146+
"\"start\":\"{7}\"," +
147+
"\"end\":\"{8}\"" +
148+
"}}]" +
149+
"}}," +
150+
"\"target_calendars\":[{{" +
151+
"\"sub\":\"{9}\"," +
152+
"\"calendar_id\":\"{10}\"" +
153+
"}}]" +
154+
"}}",
155+
clientId, clientSecret, redirectUrl, scope, eventId, summary, sub, startString, endString, sub, calendarId)
156+
.ResponseCode(200)
157+
.ResponseBodyFormat(
158+
"{{\"url\":\"{0}\"}}", expectedUrl)
159+
);
160+
161+
var addToCalendarRequest = new AddToCalendarRequestBuilder()
162+
.OAuthDetails(redirectUrl, scope)
163+
.UpsertEventRequest(upsertEventRequestWithoutStartAndEnd)
164+
.AvailabilityRequest(availabilityRequest)
165+
.AddTargetCalendar(sub, calendarId)
166+
.Build();
167+
168+
var actualUrl = client.AddToCalendar(addToCalendarRequest);
169+
170+
Assert.AreEqual(expectedUrl, actualUrl);
171+
}
98172
}
99173
}

0 commit comments

Comments
 (0)