diff --git a/Hcs.WebApp/Components/Pages/Registry/Private.razor b/Hcs.WebApp/Components/Pages/Registry/Private.razor
new file mode 100644
index 0000000..d5d0164
--- /dev/null
+++ b/Hcs.WebApp/Components/Pages/Registry/Private.razor
@@ -0,0 +1,214 @@
+@page "/registry/private"
+
+@using System.IdentityModel.Claims
+@using Hcs.WebApp.BackgroundServices
+@using Hcs.WebApp.Components.Dialogs
+@using Hcs.WebApp.Services
+@using Microsoft.AspNetCore.Authorization
+@using Microsoft.AspNetCore.Identity
+@using Microsoft.EntityFrameworkCore
+
+@implements IDisposable
+
+@attribute [Authorize]
+
+@inject AuthenticationStateProvider AuthenticationStateProvider
+@inject HeadquartersService HeadquartersService
+@inject RegistryService RegistryService
+@inject DialogService DialogService
+@inject CampaignManagementState CampaignManagementState
+
+Частные справочники подсистемы НСИ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @errorMessage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@code {
+ enum PrivatePageState
+ {
+ Init,
+ Loading,
+ Idle,
+ OperationWaiting
+ }
+
+ IEnumerable registries;
+ PrivatePageState state;
+ string syncText = "...";
+ bool hasError;
+ string errorMessage;
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ await base.OnAfterRenderAsync(firstRender);
+
+ if (firstRender)
+ {
+ ChangeState(PrivatePageState.Init);
+
+ var finalState = PrivatePageState.Idle;
+ var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();
+ if (state.User.IsInRole(AppRole.ADMINISTRATOR_TYPE) || state.User.IsInRole(AppRole.OPERATOR_TYPE))
+ {
+ var operationInProgress = await HeadquartersService.HasActiveCampaignAsync(Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1);
+ if (operationInProgress)
+ {
+ finalState = PrivatePageState.OperationWaiting;
+ }
+
+ CampaignManagementState.OnCampaignCreated += OnCampaignCreated;
+ CampaignManagementState.OnCampaignEnded += OnCampaignEnded;
+
+ registries = await RegistryService.GetAllRegistriesAsync(false);
+ }
+
+ ChangeState(finalState);
+ }
+ }
+
+ async Task SyncRegistriesAsync()
+ {
+ if (state == PrivatePageState.OperationWaiting) return;
+
+ ChangeState(PrivatePageState.OperationWaiting);
+
+ if (await HeadquartersService.HasActiveCampaignAsync(Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1))
+ {
+ ChangeState(PrivatePageState.Idle);
+ }
+ else
+ {
+ // TODO: Use user id
+ var campaign = await HeadquartersService.InitiateCampaignAsync(Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1, "");
+ CampaignManagementState.EnqueueCampaign(campaign);
+ }
+ }
+
+ async Task RowExpandAsync(Registry registry)
+ {
+ if (registry.Elements == null)
+ {
+ registry.Elements = await RegistryService.GetRegistryElementsAsync(registry.Id);
+ }
+ }
+
+ async Task ShowElementAsync(RegistryElement registryElement)
+ {
+ await DialogService.OpenAsync(
+ "Просмотр записи",
+ new Dictionary()
+ {
+ { nameof(ViewRegistryElement.RegistryElement), registryElement }
+ },
+ new DialogOptions()
+ {
+ Width = "420px",
+ Height = "600px"
+ });
+ }
+
+ void ChangeState(PrivatePageState state)
+ {
+ if (this.state == state) return;
+
+ this.state = state;
+
+ SetSyncText();
+ StateHasChanged();
+ }
+
+ void SetSyncText()
+ {
+ switch (state)
+ {
+ case PrivatePageState.Init:
+ syncText = "...";
+ break;
+
+ case PrivatePageState.Loading:
+ case PrivatePageState.Idle:
+ syncText = "Синхронизировать";
+ break;
+
+ case PrivatePageState.OperationWaiting:
+ syncText = "Идет синхронизация...";
+ break;
+ }
+ }
+
+ void OnCampaignCreated(Campaign campaign)
+ {
+ if (campaign.Type == Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1)
+ {
+ InvokeAsync(() => ChangeState(PrivatePageState.OperationWaiting));
+ }
+ }
+
+ void OnCampaignEnded(Campaign campaign)
+ {
+ if (campaign.Type == Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1)
+ {
+ Task.Run(RefreshRegistries);
+ }
+ }
+
+ async Task RefreshRegistries()
+ {
+ await InvokeAsync(() => ChangeState(PrivatePageState.Loading));
+
+ var refreshedRegistries = await RegistryService.GetAllRegistriesAsync(false);
+
+ await InvokeAsync(() =>
+ {
+ registries = refreshedRegistries;
+
+ ChangeState(PrivatePageState.Idle);
+ });
+ }
+
+ public void Dispose()
+ {
+ CampaignManagementState.OnCampaignCreated -= OnCampaignCreated;
+ CampaignManagementState.OnCampaignEnded -= OnCampaignEnded;
+ }
+}