280 lines
8.9 KiB
C#
280 lines
8.9 KiB
C#
namespace IronServices.Client;
|
|
|
|
/// <summary>
|
|
/// API client for IronNotify operations.
|
|
/// Access via IronServicesClient.Notify
|
|
/// </summary>
|
|
public class NotifyApi
|
|
{
|
|
private readonly IronServicesClient _client;
|
|
private readonly string _baseUrl;
|
|
|
|
internal NotifyApi(IronServicesClient client, string baseUrl)
|
|
{
|
|
_client = client;
|
|
_baseUrl = baseUrl;
|
|
}
|
|
|
|
private string Url(string endpoint) => IronServicesClient.BuildUrl(_baseUrl, endpoint);
|
|
|
|
#region Notifications
|
|
|
|
/// <summary>
|
|
/// Get notifications for the current user.
|
|
/// </summary>
|
|
public async Task<List<NotificationDto>> GetNotificationsAsync(string? appSlug = null, bool unreadOnly = false, int page = 1, int pageSize = 50, CancellationToken ct = default)
|
|
{
|
|
var query = new List<string> { $"page={page}", $"pageSize={pageSize}" };
|
|
if (unreadOnly) query.Add("isRead=false");
|
|
if (!string.IsNullOrEmpty(appSlug)) query.Add($"type={appSlug}");
|
|
var queryString = "?" + string.Join("&", query);
|
|
|
|
var result = await _client.GetAsync<NotificationsResponse>(Url($"api/v1/notifications{queryString}"), ct);
|
|
return result?.Notifications ?? [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get unread notification count.
|
|
/// </summary>
|
|
public async Task<int> GetUnreadCountAsync(CancellationToken ct = default)
|
|
{
|
|
var result = await _client.GetAsync<UnreadCountResponse>(Url("api/v1/notifications/unread-count"), ct);
|
|
return result?.Count ?? result?.UnreadCount ?? 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mark a notification as read.
|
|
/// </summary>
|
|
public async Task MarkAsReadAsync(Guid notificationId, CancellationToken ct = default)
|
|
{
|
|
await _client.PutAsync<object, object>(Url($"api/v1/notifications/{notificationId}/read"), new { }, ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mark all notifications as read.
|
|
/// </summary>
|
|
public async Task MarkAllAsReadAsync(CancellationToken ct = default)
|
|
{
|
|
await _client.PutAsync<object, object>(Url("api/v1/notifications/read-all"), new { }, ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acknowledge a notification (marks as read).
|
|
/// </summary>
|
|
public async Task AcknowledgeAsync(Guid notificationId, CancellationToken ct = default)
|
|
{
|
|
await MarkAsReadAsync(notificationId, ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a specific notification by ID.
|
|
/// </summary>
|
|
public async Task<NotificationDto?> GetNotificationAsync(Guid notificationId, CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<NotificationDto>(Url($"api/v1/notifications/{notificationId}"), ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolve a notification.
|
|
/// </summary>
|
|
public async Task ResolveAsync(Guid notificationId, string? resolution = null, CancellationToken ct = default)
|
|
{
|
|
await _client.PostAsync<object, object>(Url($"api/v1/notifications/{notificationId}/resolve"), new { resolution }, ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get notification preferences.
|
|
/// </summary>
|
|
public async Task<NotificationPreferences?> GetNotificationPreferencesAsync(CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<NotificationPreferences>(Url("api/v1/notifications/preferences"), ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update notification preferences.
|
|
/// </summary>
|
|
public async Task UpdateNotificationPreferencesAsync(NotificationPreferences prefs, CancellationToken ct = default)
|
|
{
|
|
await _client.PutAsync<NotificationPreferences, object>(Url("api/v1/notifications/preferences"), prefs, ct);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Apps
|
|
|
|
/// <summary>
|
|
/// Get all apps for the tenant.
|
|
/// </summary>
|
|
public async Task<List<AppSubscription>> GetMyAppsAsync(CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<List<AppSubscription>>(Url("api/v1/apps"), ct) ?? [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a specific app by ID.
|
|
/// </summary>
|
|
public async Task<AppSubscription?> GetAppAsync(Guid appId, CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<AppSubscription>(Url($"api/v1/apps/{appId}"), ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get an app by slug.
|
|
/// </summary>
|
|
public async Task<AppSubscription?> GetAppBySlugAsync(string slug, CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<AppSubscription>(Url($"api/v1/apps/by-slug/{slug}"), ct);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Members & On-Call
|
|
|
|
/// <summary>
|
|
/// Get all team members.
|
|
/// </summary>
|
|
public async Task<List<TeamMember>> GetTeamMembersAsync(CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<List<TeamMember>>(Url("api/v1/members"), ct) ?? [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get current on-call member.
|
|
/// </summary>
|
|
public async Task<TeamMember?> GetOnCallMemberAsync(Guid? teamId = null, CancellationToken ct = default)
|
|
{
|
|
var query = teamId.HasValue ? $"?teamId={teamId}" : "";
|
|
return await _client.GetAsync<TeamMember>(Url($"api/v1/members/on-call{query}"), ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get on-call status for the current user.
|
|
/// </summary>
|
|
public async Task<OnCallStatus?> GetOnCallStatusAsync(CancellationToken ct = default)
|
|
{
|
|
var member = await GetOnCallMemberAsync(ct: ct);
|
|
if (member == null) return new OnCallStatus { IsOnCall = false };
|
|
|
|
return new OnCallStatus
|
|
{
|
|
IsOnCall = true,
|
|
OnCallUserName = member.Name,
|
|
OnCallUserEmail = member.Email
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set on-call status for a member.
|
|
/// </summary>
|
|
public async Task<TeamMember?> SetOnCallAsync(Guid memberId, bool isOnCall, CancellationToken ct = default)
|
|
{
|
|
return await _client.PostAsync<object, TeamMember>(Url($"api/v1/members/{memberId}/on-call"), new { isOnCall }, ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Take on-call shift for current user.
|
|
/// </summary>
|
|
public async Task TakeOnCallAsync(CancellationToken ct = default)
|
|
{
|
|
// This would need the current user's member ID - placeholder for now
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// End on-call shift for current user.
|
|
/// </summary>
|
|
public async Task EndOnCallAsync(CancellationToken ct = default)
|
|
{
|
|
// This would need the current user's member ID - placeholder for now
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Request coverage from another team member.
|
|
/// </summary>
|
|
public async Task RequestCoverageAsync(Guid memberId, CancellationToken ct = default)
|
|
{
|
|
// Placeholder - would send notification to member
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get today's on-call schedule.
|
|
/// </summary>
|
|
public async Task<List<ScheduleSlot>> GetScheduleAsync(CancellationToken ct = default)
|
|
{
|
|
// Placeholder - schedule endpoint not implemented in backend
|
|
return await Task.FromResult(new List<ScheduleSlot>());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region App Muting
|
|
|
|
/// <summary>
|
|
/// Mute notifications from an app.
|
|
/// </summary>
|
|
public async Task MuteAppAsync(string appSlug, int? minutes = null, CancellationToken ct = default)
|
|
{
|
|
// Placeholder - mute endpoint not implemented in backend
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unmute notifications from an app.
|
|
/// </summary>
|
|
public async Task UnmuteAppAsync(string appSlug, CancellationToken ct = default)
|
|
{
|
|
// Placeholder - unmute endpoint not implemented in backend
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Teams
|
|
|
|
/// <summary>
|
|
/// Get all teams.
|
|
/// </summary>
|
|
public async Task<List<TeamInfo>> GetTeamsAsync(CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<List<TeamInfo>>(Url("api/v1/teams"), ct) ?? [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a specific team.
|
|
/// </summary>
|
|
public async Task<TeamInfo?> GetTeamAsync(Guid teamId, CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<TeamInfo>(Url($"api/v1/teams/{teamId}"), ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get members of a specific team.
|
|
/// </summary>
|
|
public async Task<List<TeamMember>> GetTeamMembersAsync(Guid teamId, CancellationToken ct = default)
|
|
{
|
|
return await _client.GetAsync<List<TeamMember>>(Url($"api/v1/teams/{teamId}/members"), ct) ?? [];
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class NotificationsResponse
|
|
{
|
|
public List<NotificationDto> Notifications { get; set; } = [];
|
|
public int TotalCount { get; set; }
|
|
public int UnreadCount { get; set; }
|
|
public int Page { get; set; }
|
|
public int PageSize { get; set; }
|
|
}
|
|
|
|
public class TeamInfo
|
|
{
|
|
public Guid Id { get; set; }
|
|
public string Name { get; set; } = string.Empty;
|
|
public string? Description { get; set; }
|
|
public int MemberCount { get; set; }
|
|
public DateTime CreatedAt { get; set; }
|
|
}
|