This commit is contained in:
2026-06-03 09:50:35 +02:00
16 changed files with 183 additions and 29 deletions
+1 -1
View File
@@ -31,7 +31,7 @@
</div>
<div class="data-table-wrap" style="max-height:200px;overflow-y:auto">
<table class="data-table">
<thead><tr><th>@T["report.col.group"]</th><th>@T["bulkmembers.email"]</th><th>@T["bulkmembers.role"]</th><th>@T["bulkmembers.status"]</th></tr></thead>
<thead><tr><th>@T["report.col.group"]<HelpTip Text="@T["help.spGroup"]" Wide="true" /></th><th>@T["bulkmembers.email"]</th><th>@T["bulkmembers.role"]<HelpTip Text="@T["help.spRole"]" Wide="true" /></th><th>@T["bulkmembers.status"]</th></tr></thead>
<tbody>
@foreach (var row in _rows.Take(50))
{
+2 -2
View File
@@ -18,7 +18,7 @@
<div class="card">
<div class="form-group">
<label class="form-label">@T["bulksites.adminurl"]</label>
<label class="form-label">@T["bulksites.adminurl"]<HelpTip Text="@T["help.adminUrl"]" Wide="true" /></label>
<input class="form-input" @bind="_adminUrl" placeholder="https://contoso-admin.sharepoint.com" />
</div>
<div class="form-group">
@@ -31,7 +31,7 @@
<div class="alert alert-info mt-8">@string.Format(T["bulksites.validcount"], _rows.Count(r => r.IsValid), _rows.Count(r => !r.IsValid))</div>
<div class="data-table-wrap" style="max-height:200px;overflow-y:auto">
<table class="data-table">
<thead><tr><th>@T["bulksites.name"]</th><th>@T["bulksites.type"]</th><th>@T["bulksites.alias"]</th><th>@T["bulksites.col.status"]</th></tr></thead>
<thead><tr><th>@T["bulksites.name"]</th><th>@T["bulksites.type"]<HelpTip Text="@T["help.siteType"]" Wide="true" /></th><th>@T["bulksites.alias"]<HelpTip Text="@T["help.siteAlias"]" Wide="true" /></th><th>@T["bulksites.col.status"]</th></tr></thead>
<tbody>
@foreach (var row in _rows.Take(50))
{
+1 -1
View File
@@ -52,7 +52,7 @@
</select>
</div>
<div class="form-group" style="display:flex;align-items:center;padding-top:20px">
<label><input type="checkbox" @bind="_includeSourceFolder" /> @T["transfer.chk.include_source_short"]</label>
<label><input type="checkbox" @bind="_includeSourceFolder" /> @T["transfer.chk.include_source_short"]<HelpTip Text="@T["transfer.chk.include_source.tooltip"]" Wide="true" /></label>
</div>
</div>
<div class="flex-row mt-8">
+4 -4
View File
@@ -24,9 +24,9 @@
<input class="form-input" type="number" @bind="_folderDepth" min="0" max="999" style="width:80px" />
</div>
<div class="form-group" style="display:flex;align-items:center;gap:16px;padding-top:20px">
<label><input type="checkbox" @bind="_includeInherited" /> @T["chk.inherited.perms"]</label>
<label><input type="checkbox" @bind="_includeInherited" /> @T["chk.inherited.perms"]<HelpTip Text="@T["help.inheritedPerms"]" /></label>
<label><input type="checkbox" @bind="_scanFolders" /> @T["chk.scan.folders"]</label>
<label><input type="checkbox" @bind="_includeSubsites" /> @T["chk.include.subsites"]</label>
<label><input type="checkbox" @bind="_includeSubsites" /> @T["chk.include.subsites"]<HelpTip Text="@T["help.subsites"]" /></label>
</div>
</div>
<div class="flex-row mt-8">
@@ -63,8 +63,8 @@
<th>@T["directory.col.type"]</th>
<th>@T["report.col.title"]</th>
<th>@T["perm.col.users"]</th>
<th>@T["perm.col.permission"]</th>
<th>@T["report.col.granted_through"]</th>
<th>@T["perm.col.permission"]<HelpTip Text="@T["help.permissionLevel"]" /></th>
<th>@T["report.col.granted_through"]<HelpTip Text="@T["help.grantedThrough"]" /></th>
</tr>
</thead>
<tbody>
+1 -1
View File
@@ -26,7 +26,7 @@
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">@T["lbl.regex"]</label>
<label class="form-label">@T["lbl.regex"]<HelpTip Text="@T["help.regex"]" Wide="true" /></label>
<input class="form-input" @bind="_regex" placeholder="@T["ph.regex"]" />
</div>
<div class="form-group">
+4 -4
View File
@@ -27,9 +27,9 @@
</div>
<div class="form-row">
<div class="form-group" style="display:flex;align-items:center;gap:16px;padding-top:20px">
<label><input type="checkbox" @bind="_includeSubsites" /> @T["chk.include.subsites"]</label>
<label><input type="checkbox" @bind="_includeHidden" /> @T["stor.chk.include_hidden_libs"]</label>
<label><input type="checkbox" @bind="_includeRecycleBin" /> @T["stor.chk.include_recycle_bin"]</label>
<label><input type="checkbox" @bind="_includeSubsites" /> @T["chk.include.subsites"]<HelpTip Text="@T["help.subsites"]" /></label>
<label><input type="checkbox" @bind="_includeHidden" /> @T["stor.chk.include_hidden_libs"]<HelpTip Text="@T["help.hiddenLibs"]" /></label>
<label><input type="checkbox" @bind="_includeRecycleBin" /> @T["stor.chk.include_recycle_bin"]<HelpTip Text="@T["help.recycleBin"]" /></label>
</div>
</div>
<div class="flex-row mt-8">
@@ -62,7 +62,7 @@
<th>@T["stor.col.site"]</th>
<th class="num">@T["stor.col.files"]</th>
<th class="num">@T["stor.col.total_mb"]</th>
<th class="num">@T["stor.col.versions_mb"]</th>
<th class="num">@T["stor.col.versions_mb"]<HelpTip Text="@T["help.versionStorage"]" /></th>
<th>@T["stor.col.lastmod"]</th>
</tr>
</thead>
+5 -5
View File
@@ -17,16 +17,16 @@
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
<div class="card">
<div class="card-title">@T["templates.capture"]</div>
<div class="card-title">@T["templates.capture"]<HelpTip Text="@T["help.templateCapture"]" Wide="true" /></div>
<SitePicker Profile="Session.CurrentProfile!" @bind-SelectedSites="_captureSites" Single="true" />
<div class="form-group mt-8">
<label class="form-label">@T["templates.name"]</label>
<input class="form-input" @bind="_captureName" placeholder="@T["templates.name.placeholder"]" />
</div>
<div class="flex-row" style="flex-wrap:wrap">
<label><input type="checkbox" @bind="_capLibraries" /> @T["templates.opt.libraries"]</label>
<label><input type="checkbox" @bind="_capLibraries" /> @T["templates.opt.libraries"]<HelpTip Text="@T["help.library"]" /></label>
<label><input type="checkbox" @bind="_capFolders" /> @T["templates.opt.folders"]</label>
<label><input type="checkbox" @bind="_capGroups" /> @T["templates.opt.permissions"]</label>
<label><input type="checkbox" @bind="_capGroups" /> @T["templates.opt.permissions"]<HelpTip Text="@T["help.permissionGroups"]" Wide="true" /></label>
</div>
<button class="btn btn-primary mt-8" @onclick="CaptureTemplate" disabled="@_running">
@(_running ? T["templates.btn.capturing"] : T["templates.btn.capture"])
@@ -48,11 +48,11 @@
<input class="form-input" @bind="_newTitle" />
</div>
<div class="form-group">
<label class="form-label">@T["templates.newalias"]</label>
<label class="form-label">@T["templates.newalias"]<HelpTip Text="@T["help.siteAlias"]" Wide="true" /></label>
<input class="form-input" @bind="_newAlias" />
</div>
<div class="form-group">
<label class="form-label">@T["templates.adminurl"]</label>
<label class="form-label">@T["templates.adminurl"]<HelpTip Text="@T["help.adminUrl"]" Wide="true" /></label>
<input class="form-input" @bind="_adminUrl" placeholder="https://contoso-admin.sharepoint.com" />
</div>
<button class="btn btn-primary" @onclick="ApplyTemplate" disabled="@_running">
+4 -4
View File
@@ -21,7 +21,7 @@
<div class="flex-row">
<label class="form-label" style="margin:0">@T["audit.lbl.users"]</label>
<div class="spacer"></div>
<label style="font-weight:normal"><input type="checkbox" @bind="_includeGuests" /> @T["directory.chk.guests"]</label>
<label style="font-weight:normal"><input type="checkbox" @bind="_includeGuests" /> @T["directory.chk.guests"]<HelpTip Text="@T["help.guests"]" Wide="true" /></label>
<button class="btn btn-secondary btn-sm" @onclick="LoadUsers" disabled="@_loadingUsers">
@(_loadingUsers ? string.Format(T["audit.btn.loading"], _loadCount) : T["audit.btn.loadUsers"])
</button>
@@ -58,9 +58,9 @@
<SitePicker Profile="Session.CurrentProfile!" @bind-SelectedSites="_sites" />
<div class="form-row">
<div class="form-group" style="display:flex;align-items:center;gap:16px;padding-top:20px">
<label><input type="checkbox" @bind="_includeInherited" /> @T["audit.chk.includeInherited"]</label>
<label><input type="checkbox" @bind="_includeInherited" /> @T["audit.chk.includeInherited"]<HelpTip Text="@T["help.inheritedPerms"]" /></label>
<label><input type="checkbox" @bind="_scanFolders" /> @T["chk.scan.folders"]</label>
<label><input type="checkbox" @bind="_includeSubsites" /> @T["chk.include.subsites"]</label>
<label><input type="checkbox" @bind="_includeSubsites" /> @T["chk.include.subsites"]<HelpTip Text="@T["help.subsites"]" /></label>
</div>
</div>
<div class="flex-row mt-8">
@@ -85,7 +85,7 @@
</div>
<div class="data-table-wrap">
<table class="data-table">
<thead><tr><th>@T["report.col.user"]</th><th>@T["report.col.site"]</th><th>@T["report.col.object"]</th><th>@T["audit.col.permission"]</th><th>@T["report.col.access_type"]</th><th>@T["report.col.granted_through"]</th></tr></thead>
<thead><tr><th>@T["report.col.user"]</th><th>@T["report.col.site"]</th><th>@T["report.col.object"]</th><th>@T["audit.col.permission"]<HelpTip Text="@T["help.permissionLevel"]" /></th><th>@T["report.col.access_type"]<HelpTip Text="@T["help.accessType"]" Wide="true" /></th><th>@T["report.col.granted_through"]<HelpTip Text="@T["help.grantedThrough"]" /></th></tr></thead>
<tbody>
@foreach (var r in _results.Take(500))
{
+2 -2
View File
@@ -13,7 +13,7 @@
<div class="card">
<div class="flex-row">
<label><input type="checkbox" @bind="_includeGuests" /> @T["directory.chk.guests"]</label>
<label><input type="checkbox" @bind="_includeGuests" /> @T["directory.chk.guests"]<HelpTip Text="@T["help.guests"]" Wide="true" /></label>
<button class="btn btn-primary" @onclick="LoadUsers" disabled="@_running">
@(_running ? string.Format(T["directory.btn.loading"], _loadCount) : T["directory.btn.loadUsers"])
</button>
@@ -32,7 +32,7 @@
</div>
<div class="data-table-wrap">
<table class="data-table">
<thead><tr><th>@T["directory.col.name"]</th><th>@T["directory.col.upn"]</th><th>@T["directory.col.department"]</th><th>@T["directory.col.jobtitle"]</th><th>@T["directory.col.type"]</th></tr></thead>
<thead><tr><th>@T["directory.col.name"]</th><th>@T["directory.col.upn"]<HelpTip Text="@T["help.upn"]" Wide="true" /></th><th>@T["directory.col.department"]</th><th>@T["directory.col.jobtitle"]</th><th>@T["directory.col.type"]<HelpTip Text="@T["help.userType"]" Wide="true" /></th></tr></thead>
<tbody>
@foreach (var u in FilteredUsers.Take(500))
{
+3 -3
View File
@@ -25,7 +25,7 @@
@if (_libraries.Count > 0)
{
<div class="form-group mt-8">
<label class="form-label">@T["versions.lbl.libsNoneAll"]</label>
<label class="form-label">@T["versions.lbl.libsNoneAll"]<HelpTip Text="@T["help.library"]" /></label>
<div style="max-height:200px;overflow-y:auto;border:1px solid var(--border);border-radius:4px;padding:4px">
@foreach (var lib in _libraries)
{
@@ -39,11 +39,11 @@
}
<div class="form-row mt-8">
<div class="form-group" style="flex:0 0 auto">
<label class="form-label">@T["versions.lbl.keepLastN"]</label>
<label class="form-label">@T["versions.lbl.keepLastN"]<HelpTip Text="@T["help.keepVersions"]" Wide="true" /></label>
<input class="form-input" type="number" @bind="_keepLast" min="0" max="999" style="width:80px" />
</div>
<div class="form-group" style="display:flex;align-items:center;padding-top:20px">
<label><input type="checkbox" @bind="_keepFirst" /> @T["versions.chk.keepFirstShort"]</label>
<label><input type="checkbox" @bind="_keepFirst" /> @T["versions.chk.keepFirstShort"]<HelpTip Text="@T["help.keepFirst"]" /></label>
</div>
</div>
<div class="flex-row mt-8">
+35
View File
@@ -0,0 +1,35 @@
@* Clickable "?" button that reveals an explanatory tooltip. Use to demystify SharePoint
jargon for users with limited SharePoint knowledge. Pass the explanation via Text
(typically a localized string: <HelpTip Text="@T["some.help"]" />). Click toggles the
bubble; it closes on a second click or when focus leaves the button. *@
@if (!string.IsNullOrWhiteSpace(Text))
{
<span class="help-tip @(Wide ? "help-tip-wide" : "") @(_open ? "open" : "")">
<button type="button" class="help-tip-mark" @onclick="Toggle" @onclick:stopPropagation="true"
@onclick:preventDefault="true" @onfocusout="Close"
aria-label="@Text" aria-expanded="@_open" title="@Text">?</button>
<span class="help-tip-bubble" role="tooltip">@Text</span>
</span>
}
@code {
/// <summary>The explanation shown inside the tooltip bubble.</summary>
[Parameter] public string? Text { get; set; }
/// <summary>Use a wider bubble for longer explanations.</summary>
[Parameter] public bool Wide { get; set; }
private bool _open;
private void Toggle() => _open = !_open;
// Delay the close so a click that moves focus off the button still toggles cleanly,
// and so the bubble doesn't vanish before a click on it registers.
private async Task Close()
{
await Task.Delay(150);
_open = false;
StateHasChanged();
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
@* Library name field with a picker: type a title, or click Browse to load and
choose from the libraries on the selected site. *@
<div class="form-group library-picker">
<label class="form-label">@Label</label>
<label class="form-label">@Label<HelpTip Text="@T["help.library"]" /></label>
<div class="flex-row" style="gap:8px;align-items:stretch">
<input class="form-input" style="flex:1"
placeholder="@Placeholder"
+1 -1
View File
@@ -4,7 +4,7 @@
<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">@(Single ? T["sitepicker.label.site"] : T["sitepicker.label.sites"])</label>
<label class="form-label">@(Single ? T["sitepicker.label.site"] : T["sitepicker.label.sites"])<HelpTip Text="@T["sitepicker.help.site"]" /></label>
<input class="form-input" @bind="_filter" @bind:event="oninput" placeholder="@T["sitepicker.ph.filter"]" />
</div>
<button class="btn btn-secondary" @onclick="LoadSites" disabled="@_loading">