UI Enhancements in IT Service Request, Announcements, Workforce and notification fixes
This commit is contained in:
@@ -80,6 +80,14 @@ final announcementCommentsProvider =
|
||||
return wrapper.stream.map((result) => result.data);
|
||||
});
|
||||
|
||||
/// Active banner announcements for the current user.
|
||||
/// Returns only non-template announcements whose banner is currently in its
|
||||
/// active time window ([Announcement.isBannerActive]).
|
||||
final activeBannerAnnouncementsProvider = Provider<List<Announcement>>((ref) {
|
||||
final all = ref.watch(announcementsProvider).valueOrNull ?? [];
|
||||
return all.where((a) => !a.isTemplate && a.isBannerActive).toList();
|
||||
});
|
||||
|
||||
final announcementsControllerProvider =
|
||||
Provider<AnnouncementsController>((ref) {
|
||||
final client = ref.watch(supabaseClientProvider);
|
||||
@@ -100,6 +108,10 @@ class AnnouncementsController {
|
||||
required List<String> visibleRoles,
|
||||
bool isTemplate = false,
|
||||
String? templateId,
|
||||
bool bannerEnabled = false,
|
||||
DateTime? bannerShowAt,
|
||||
DateTime? bannerHideAt,
|
||||
int? pushIntervalMinutes,
|
||||
}) async {
|
||||
final authorId = _client.auth.currentUser?.id;
|
||||
if (authorId == null) return;
|
||||
@@ -111,6 +123,10 @@ class AnnouncementsController {
|
||||
'visible_roles': visibleRoles,
|
||||
'is_template': isTemplate,
|
||||
'template_id': templateId,
|
||||
'banner_enabled': bannerEnabled,
|
||||
'banner_show_at': bannerShowAt?.toUtc().toIso8601String(),
|
||||
'banner_hide_at': bannerHideAt?.toUtc().toIso8601String(),
|
||||
'push_interval_minutes': pushIntervalMinutes,
|
||||
};
|
||||
|
||||
final result = await _client
|
||||
@@ -123,6 +139,12 @@ class AnnouncementsController {
|
||||
// Don't send notifications for templates (they are drafts for reuse)
|
||||
if (isTemplate) return;
|
||||
|
||||
// Skip the one-time creation push when a scheduled banner push is
|
||||
// configured. The banner scheduler will send the first push on its own
|
||||
// interval, so firing an extra push here would result in two back-to-back
|
||||
// notifications for the same announcement.
|
||||
if (bannerEnabled && pushIntervalMinutes != null) return;
|
||||
|
||||
// Query users whose role matches visible_roles, excluding the author
|
||||
try {
|
||||
final profiles = await _client
|
||||
@@ -161,6 +183,13 @@ class AnnouncementsController {
|
||||
required String body,
|
||||
required List<String> visibleRoles,
|
||||
bool? isTemplate,
|
||||
bool? bannerEnabled,
|
||||
DateTime? bannerShowAt,
|
||||
DateTime? bannerHideAt,
|
||||
int? pushIntervalMinutes,
|
||||
bool clearBannerShowAt = false,
|
||||
bool clearBannerHideAt = false,
|
||||
bool clearPushInterval = false,
|
||||
}) async {
|
||||
final payload = <String, dynamic>{
|
||||
'title': title,
|
||||
@@ -168,12 +197,53 @@ class AnnouncementsController {
|
||||
'visible_roles': visibleRoles,
|
||||
'updated_at': AppTime.nowUtc().toIso8601String(),
|
||||
};
|
||||
if (isTemplate != null) {
|
||||
payload['is_template'] = isTemplate;
|
||||
if (isTemplate != null) payload['is_template'] = isTemplate;
|
||||
if (bannerEnabled != null) payload['banner_enabled'] = bannerEnabled;
|
||||
if (bannerShowAt != null) {
|
||||
payload['banner_show_at'] = bannerShowAt.toUtc().toIso8601String();
|
||||
} else if (clearBannerShowAt) {
|
||||
payload['banner_show_at'] = null;
|
||||
}
|
||||
if (bannerHideAt != null) {
|
||||
payload['banner_hide_at'] = bannerHideAt.toUtc().toIso8601String();
|
||||
} else if (clearBannerHideAt) {
|
||||
payload['banner_hide_at'] = null;
|
||||
}
|
||||
if (pushIntervalMinutes != null) {
|
||||
payload['push_interval_minutes'] = pushIntervalMinutes;
|
||||
} else if (clearPushInterval) {
|
||||
payload['push_interval_minutes'] = null;
|
||||
}
|
||||
await _client.from('announcements').update(payload).eq('id', id);
|
||||
}
|
||||
|
||||
/// Update only the banner settings on an existing announcement.
|
||||
/// Intended for the "Manage Banner" popup available to the poster and admins.
|
||||
Future<void> updateBannerSettings({
|
||||
required String id,
|
||||
required bool bannerEnabled,
|
||||
DateTime? bannerShowAt,
|
||||
DateTime? bannerHideAt,
|
||||
int? pushIntervalMinutes,
|
||||
}) async {
|
||||
await _client.from('announcements').update({
|
||||
'banner_enabled': bannerEnabled,
|
||||
'banner_show_at': bannerShowAt?.toUtc().toIso8601String(),
|
||||
'banner_hide_at': bannerHideAt?.toUtc().toIso8601String(),
|
||||
'push_interval_minutes': pushIntervalMinutes,
|
||||
'updated_at': AppTime.nowUtc().toIso8601String(),
|
||||
}).eq('id', id);
|
||||
}
|
||||
|
||||
/// Immediately stops a banner by setting [banner_hide_at] to now.
|
||||
/// Usable by the poster or an admin.
|
||||
Future<void> dismissBanner(String id) async {
|
||||
await _client.from('announcements').update({
|
||||
'banner_hide_at': AppTime.nowUtc().toIso8601String(),
|
||||
'updated_at': AppTime.nowUtc().toIso8601String(),
|
||||
}).eq('id', id);
|
||||
}
|
||||
|
||||
/// Delete an announcement.
|
||||
Future<void> deleteAnnouncement(String id) async {
|
||||
await _client.from('announcements').delete().eq('id', id);
|
||||
|
||||
Reference in New Issue
Block a user