using System.ComponentModel; using System.Globalization; using SharepointToolbox.Core.Models; using SharepointToolbox.Services; using SharepointToolbox.Views.Dialogs; namespace SharepointToolbox.ViewModels.Dialogs; /// /// Headless logic for . Loads sites via /// and applies filter/sort in memory so the /// dialog's code-behind stays a thin shim and the logic is unit-testable /// without a WPF host. /// public class SitePickerDialogLogic { private readonly ISiteListService _siteListService; private readonly TenantProfile _profile; public SitePickerDialogLogic(ISiteListService siteListService, TenantProfile profile) { _siteListService = siteListService; _profile = profile; } /// /// Loads all accessible sites for the tenant profile and wraps them in /// so the dialog can bind checkboxes. /// public async Task> LoadAsync( IProgress progress, CancellationToken ct) { var sites = await _siteListService.GetSitesAsync(_profile, progress, ct); return sites .Select(s => new SitePickerItem(s.Url, s.Title, s.StorageUsedMb, s.StorageQuotaMb, s.Template)) .ToList(); } /// /// Filters items by free-text (title/url substring), storage-size range, /// and site kind. Empty or zero-range parameters become no-ops. /// public static IEnumerable ApplyFilter( IEnumerable items, string text, long minMb, long maxMb, string kindFilter) { var result = items; if (!string.IsNullOrEmpty(text)) { result = result.Where(i => i.Url.Contains(text, StringComparison.OrdinalIgnoreCase) || i.Title.Contains(text, StringComparison.OrdinalIgnoreCase)); } result = result.Where(i => i.StorageUsedMb >= minMb && i.StorageUsedMb <= maxMb); if (!string.IsNullOrEmpty(kindFilter) && kindFilter != "All") result = result.Where(i => i.Kind.ToString() == kindFilter); return result; } /// /// Stable sort by a named column and direction. Unknown column names /// return the input sequence unchanged. /// public static IEnumerable ApplySort( IEnumerable items, string column, ListSortDirection direction) { var asc = direction == ListSortDirection.Ascending; return column switch { "Title" => asc ? items.OrderBy(i => i.Title) : items.OrderByDescending(i => i.Title), "Url" => asc ? items.OrderBy(i => i.Url) : items.OrderByDescending(i => i.Url), "Kind" => asc ? items.OrderBy(i => i.KindDisplay) : items.OrderByDescending(i => i.KindDisplay), "StorageUsedMb" => asc ? items.OrderBy(i => i.StorageUsedMb) : items.OrderByDescending(i => i.StorageUsedMb), "IsSelected" => asc ? items.OrderBy(i => i.IsSelected) : items.OrderByDescending(i => i.IsSelected), _ => items }; } /// /// Lenient long parse: whitespace-only or unparseable input yields /// instead of throwing. /// public static long ParseLongOrDefault(string text, long fallback) { if (string.IsNullOrWhiteSpace(text)) return fallback; return long.TryParse(text.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var v) ? v : fallback; } }