@page "/templates" @attribute [Authorize] @inject IUserSessionService Session @inject IUserContextAccessor UserContext @inject ISessionManager SessionMgr @inject IElevationCoordinator Elevation @inject ITemplateService TemplateSvc @inject SharepointToolbox.Web.Infrastructure.Persistence.TemplateRepository TemplateRepo @rendermode InteractiveServer

Site Templates

Capture site structure and apply to new sites.

@if (!Session.HasProfile) { return; } @if (UserContext.Role < UserRole.TechN1) { return; }
Capture Template
Apply Template
@if (_selectedTemplate == null) {
Select a template from the list below.
} else {
Template: @_selectedTemplate.Name
}
@if (!string.IsNullOrEmpty(_error)) {
@_error
} @if (!string.IsNullOrEmpty(_successMsg)) {
@_successMsg
}
Saved Templates
@if (_templates.Count == 0) {
No templates saved.
} @foreach (var t in _templates) {
@t.Name
@t.SiteType · @t.CapturedAt.ToString("yyyy-MM-dd") · @t.Libraries.Count libraries
}
@code { private List _captureSites = new(); private string _captureName = string.Empty; private bool _capLibraries = true, _capFolders = true, _capGroups = true; private SiteTemplate? _selectedTemplate; private string _newTitle = string.Empty, _newAlias = string.Empty, _adminUrl = string.Empty; private bool _running; private string _status = string.Empty, _error = string.Empty, _successMsg = string.Empty; private List _templates = new(); private CancellationTokenSource? _cts; protected override async Task OnInitializedAsync() { _templates = (await TemplateRepo.GetAllAsync()).ToList(); } private async Task CaptureTemplate() { _error = string.Empty; _successMsg = string.Empty; _running = true; _cts = new CancellationTokenSource(); var siteUrl = _captureSites.FirstOrDefault()?.Url ?? Session.CurrentProfile!.TenantUrl; var progress = new Progress(p => { _status = p.Message; InvokeAsync(StateHasChanged); }); try { var opts = new SiteTemplateOptions { CaptureLibraries = _capLibraries, CaptureFolders = _capFolders, CapturePermissionGroups = _capGroups }; var template = await Elevation.RunAsync(async c => { var ctx = await SessionMgr.GetOrCreateContextAsync(siteUrl, Session.CurrentProfile!, c); return await TemplateSvc.CaptureTemplateAsync(ctx, opts, progress, c); }, _cts.Token); template.Name = string.IsNullOrWhiteSpace(_captureName) ? $"Template-{DateTime.Now:yyyyMMdd}" : _captureName; await TemplateRepo.SaveAsync(template); _templates = (await TemplateRepo.GetAllAsync()).ToList(); _successMsg = $"Template '{template.Name}' saved."; } catch (OperationCanceledException) { _status = "Cancelled."; } catch (Exception ex) { _error = ex.Message; } finally { _running = false; await InvokeAsync(StateHasChanged); } } private async Task ApplyTemplate() { if (_selectedTemplate == null) return; _error = string.Empty; _successMsg = string.Empty; _running = true; _cts = new CancellationTokenSource(); var adminUrl = string.IsNullOrWhiteSpace(_adminUrl) ? Session.CurrentProfile!.TenantUrl.Replace(".sharepoint.com", "-admin.sharepoint.com") : _adminUrl.Trim(); var progress = new Progress(p => { _status = p.Message; InvokeAsync(StateHasChanged); }); try { var ctx = await SessionMgr.GetOrCreateContextAsync(adminUrl, Session.CurrentProfile!, _cts.Token); var url = await TemplateSvc.ApplyTemplateAsync(ctx, _selectedTemplate, _newTitle, _newAlias, progress, _cts.Token); _successMsg = $"Site created: {url}"; } catch (OperationCanceledException) { _status = "Cancelled."; } catch (Exception ex) { _error = ex.Message; } finally { _running = false; await InvokeAsync(StateHasChanged); } } private async Task DeleteTemplate(SiteTemplate t) { await TemplateRepo.DeleteAsync(t.Id); _templates.RemoveAll(x => x.Id == t.Id); if (_selectedTemplate?.Id == t.Id) _selectedTemplate = null; } }