Merge pull request 'Add report logos and configurable folder scan depth' (#2) from feat/report-logos-and-scan-depth into main
Reviewed-on: #2
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
@inject ISiteDiscoveryService SiteDiscovery
|
||||
|
||||
<div class="site-picker">
|
||||
<div class="flex-row" style="gap:8px;align-items:flex-end">
|
||||
<div class="form-group" style="flex:1">
|
||||
<label class="form-label">Sites</label>
|
||||
<input class="form-input" @bind="_filter" @bind:event="oninput" placeholder="Filter loaded sites by name or URL…" />
|
||||
</div>
|
||||
<button class="btn btn-secondary" @onclick="LoadSites" disabled="@_loading">
|
||||
@(_loading ? "Loading…" : (_all.Count > 0 ? "Reload sites" : "Load sites"))
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if (!string.IsNullOrEmpty(_error))
|
||||
{
|
||||
<div class="alert alert-error mt-8">@_error</div>
|
||||
}
|
||||
|
||||
@if (_all.Count > 0)
|
||||
{
|
||||
<div class="flex-row mt-8" style="gap:12px;align-items:center">
|
||||
<button class="btn btn-link btn-sm" @onclick="SelectAllFiltered">Select all (@Filtered.Count())</button>
|
||||
<button class="btn btn-link btn-sm" @onclick="ClearSelection">Clear</button>
|
||||
<span class="spacer"></span>
|
||||
<span class="count-badge">@SelectedSites.Count selected</span>
|
||||
</div>
|
||||
<div class="site-picker-list" style="max-height:240px;overflow:auto;border:1px solid var(--border);border-radius:4px;padding:4px;margin-top:6px">
|
||||
@foreach (var s in Filtered)
|
||||
{
|
||||
<label style="display:flex;align-items:center;gap:8px;padding:3px 6px;cursor:pointer">
|
||||
<input type="checkbox" checked="@IsSelected(s)" @onchange="e => Toggle(s, (bool)(e.Value ?? false))" />
|
||||
<span>@s.Title</span>
|
||||
<span class="text-muted" style="font-size:11px">@s.Url</span>
|
||||
</label>
|
||||
}
|
||||
@if (!Filtered.Any())
|
||||
{
|
||||
<div class="text-muted" style="padding:6px">No sites match the filter.</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else if (!_loading)
|
||||
{
|
||||
<div class="text-muted mt-8" style="font-size:12px">Click “Load sites” to list the tenant’s SharePoint sites, then tick the ones to scan.</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public TenantProfile Profile { get; set; } = default!;
|
||||
[Parameter] public List<SiteInfo> SelectedSites { get; set; } = new();
|
||||
[Parameter] public EventCallback<List<SiteInfo>> SelectedSitesChanged { get; set; }
|
||||
[Parameter] public bool Disabled { get; set; }
|
||||
|
||||
private List<SiteInfo> _all = new();
|
||||
private string _filter = string.Empty;
|
||||
private bool _loading;
|
||||
private string _error = string.Empty;
|
||||
|
||||
private IEnumerable<SiteInfo> Filtered =>
|
||||
string.IsNullOrWhiteSpace(_filter)
|
||||
? _all
|
||||
: _all.Where(s =>
|
||||
s.Title.Contains(_filter, StringComparison.OrdinalIgnoreCase) ||
|
||||
s.Url.Contains(_filter, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
private bool IsSelected(SiteInfo s) =>
|
||||
SelectedSites.Any(x => string.Equals(x.Url, s.Url, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
private async Task LoadSites()
|
||||
{
|
||||
_loading = true; _error = string.Empty;
|
||||
try
|
||||
{
|
||||
_all = (await SiteDiscovery.SearchSitesAsync(Profile)).ToList();
|
||||
if (_all.Count == 0) _error = "No sites returned. The account may lack Sites.Read.All.";
|
||||
}
|
||||
catch (Exception ex) { _error = ex.Message; }
|
||||
finally { _loading = false; }
|
||||
}
|
||||
|
||||
private async Task Toggle(SiteInfo s, bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
if (!IsSelected(s)) SelectedSites.Add(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedSites.RemoveAll(x => string.Equals(x.Url, s.Url, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
await SelectedSitesChanged.InvokeAsync(SelectedSites);
|
||||
}
|
||||
|
||||
private async Task SelectAllFiltered()
|
||||
{
|
||||
foreach (var s in Filtered)
|
||||
if (!IsSelected(s)) SelectedSites.Add(s);
|
||||
await SelectedSitesChanged.InvokeAsync(SelectedSites);
|
||||
}
|
||||
|
||||
private async Task ClearSelection()
|
||||
{
|
||||
SelectedSites.Clear();
|
||||
await SelectedSitesChanged.InvokeAsync(SelectedSites);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user