moduleDefintions - profiles validation changes
This commit is contained in:
		| @ -10,67 +10,71 @@ | ||||
|  | ||||
| @if (_templates != null) | ||||
| { | ||||
|     <div class="container"> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="owner" class="form-control" @bind="@_owner" /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="module" class="form-control" @bind="@_module" /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <textarea id="description" class="form-control" @bind="@_description" rows="3"></textarea> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="template" HelpText="Select a module template. Templates are located in the wwwroot/Modules/Templates folder on the server." ResourceKey="Template">Template: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <select id="template" class="form-select" @onchange="(e => TemplateChanged(e))"> | ||||
|                     <option value="-"><@Localizer["Template.Select"]></option> | ||||
|                     @foreach (Template template in _templates) | ||||
|                     { | ||||
|                         <option value="@template.Name">@template.Title</option> | ||||
|                     } | ||||
|                 </select> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <select id="reference" class="form-select" @bind="@_reference"> | ||||
|                     @foreach (string version in _versions) | ||||
|                     { | ||||
|                         if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0) | ||||
|                         { | ||||
|                             <option value="@(version)">@(version)</option> | ||||
|                         } | ||||
|                     } | ||||
|                     <option value="local">@SharedLocalizer["LocalVersion"]</option> | ||||
|                 </select> | ||||
|             </div> | ||||
|         </div> | ||||
|         @if (!string.IsNullOrEmpty(_location)) | ||||
|         { | ||||
|     <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|         <div class="container"> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label> | ||||
|                 <Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="module" class="form-control" @bind="@_location" readonly /> | ||||
|                     <input id="owner" class="form-control" @bind="@_owner" maxlength="256" required /> | ||||
|                 </div> | ||||
|             </div> | ||||
|         } | ||||
|     </div> | ||||
|     <button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["CreateModule"]</button> | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="module" class="form-control" @bind="@_module" maxlength="256" required /> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <textarea id="description" class="form-control" @bind="@_description" rows="3" required></textarea> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="template" HelpText="Select a module template. Templates are located in the wwwroot/Modules/Templates folder on the server." ResourceKey="Template">Template: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <select id="template" class="form-select" @onchange="(e => TemplateChanged(e))" required> | ||||
|                         <option value="-"><@Localizer["Template.Select"]></option> | ||||
|                         @foreach (Template template in _templates) | ||||
|                         { | ||||
|                             <option value="@template.Name">@template.Title</option> | ||||
|                         } | ||||
|                     </select> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <select id="reference" class="form-select" @bind="@_reference" required> | ||||
|                         @foreach (string version in _versions) | ||||
|                         { | ||||
|                             if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0) | ||||
|                             { | ||||
|                                 <option value="@(version)">@(version)</option> | ||||
|                             } | ||||
|                         } | ||||
|                         <option value="local">@SharedLocalizer["LocalVersion"]</option> | ||||
|                     </select> | ||||
|                 </div> | ||||
|             </div> | ||||
|             @if (!string.IsNullOrEmpty(_location)) | ||||
|             { | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="module" class="form-control" @bind="@_location" readonly /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             } | ||||
|         </div> | ||||
|         <button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["CreateModule"]</button> | ||||
|         <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
|     </form> | ||||
| } | ||||
|  | ||||
| @code { | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|     private string _owner = string.Empty; | ||||
|     private string _module = string.Empty; | ||||
|     private string _description = string.Empty; | ||||
| @ -99,23 +103,32 @@ | ||||
|  | ||||
|     private async Task CreateModule() | ||||
|     { | ||||
|         try | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-") | ||||
|             try | ||||
|             { | ||||
|                 var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference }; | ||||
|                 moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition); | ||||
|                 GetLocation(); | ||||
|                 AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success); | ||||
|                 if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-") | ||||
|                 { | ||||
|                     var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference }; | ||||
|                     moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition); | ||||
|                     GetLocation(); | ||||
|                     AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     AddModuleMessage(Localizer["Message.Require.ValidName"], MessageType.Warning); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 AddModuleMessage(Localizer["Message.Require.ValidName"], MessageType.Warning); | ||||
|                 await logger.LogError(ex, "Error Creating Module"); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         else | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Creating Module"); | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -5,90 +5,94 @@ | ||||
| @inject IStringLocalizer<Edit> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <TabStrip> | ||||
|     <TabPanel Name="Definition" ResourceKey="Definition"> | ||||
|         <div class="container"> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="name" class="form-control" @bind="@_name" /> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="description" HelpText="The description of the module" ResourceKey="Description">Description: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <textarea id="description" class="form-control" @bind="@_description" rows="2"></textarea> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="categories" HelpText="Comma delimited list of module categories" ResourceKey="Categories">Categories: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="categories" class="form-control" @bind="@_categories" /> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <Section Name="Information" ResourceKey="Information"> | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <TabStrip> | ||||
|         <TabPanel Name="Definition" ResourceKey="Definition"> | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="moduledefinitionname" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label> | ||||
|                     <Label Class="col-sm-3" For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="moduledefinitionname" class="form-control" @bind="@_moduledefinitionname" disabled /> | ||||
|                         <input id="name" class="form-control" @bind="@_name" maxlength="256" required /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="version" HelpText="The version of the module" ResourceKey="Version">Version: </Label> | ||||
|                     <Label Class="col-sm-3" For="description" HelpText="The description of the module" ResourceKey="Description">Description: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="version" class="form-control" @bind="@_version" disabled /> | ||||
|                         <textarea id="description" class="form-control" @bind="@_description" rows="2" required></textarea> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label> | ||||
|                     <Label Class="col-sm-3" For="categories" HelpText="Comma delimited list of module categories" ResourceKey="Categories">Categories: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="owner" class="form-control" @bind="@_owner" disabled /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="url" HelpText="The reference url of the module" ResourceKey="ReferenceUrl">Reference Url: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="url" class="form-control" @bind="@_url" disabled /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="contact" HelpText="The contact for the module" ResourceKey="Contact">Contact: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="contact" class="form-control" @bind="@_contact" disabled /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="license" HelpText="The module license terms" ResourceKey="License">License: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="runtimes" HelpText="The Blazor runtimes which this module supports" ResourceKey="Runtimes">Runtimes: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="runtimes" class="form-control" @bind="@_runtimes" disabled /> | ||||
|                         <input id="categories" class="form-control" @bind="@_categories" required /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </Section> | ||||
|     </TabPanel> | ||||
|     <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|         <div class="container"> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|             <Section Name="Information" ResourceKey="Information"> | ||||
|                 <div class="container"> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="moduledefinitionname" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="moduledefinitionname" class="form-control" @bind="@_moduledefinitionname" disabled /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="version" HelpText="The version of the module" ResourceKey="Version">Version: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="version" class="form-control" @bind="@_version" disabled /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="owner" class="form-control" @bind="@_owner" disabled /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="url" HelpText="The reference url of the module" ResourceKey="ReferenceUrl">Reference Url: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="url" class="form-control" @bind="@_url" disabled /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="contact" HelpText="The contact for the module" ResourceKey="Contact">Contact: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="contact" class="form-control" @bind="@_contact" disabled /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="license" HelpText="The module license terms" ResourceKey="License">License: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="runtimes" HelpText="The Blazor runtimes which this module supports" ResourceKey="Runtimes">Runtimes: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="runtimes" class="form-control" @bind="@_runtimes" disabled /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </Section> | ||||
|         </TabPanel> | ||||
|         <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </TabPanel> | ||||
| </TabStrip> | ||||
| <button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button> | ||||
| <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| <br /> | ||||
| <br /> | ||||
| <AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo> | ||||
|         </TabPanel> | ||||
|     </TabStrip> | ||||
|     <button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button> | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
|     <br /> | ||||
|     <br /> | ||||
|     <AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo> | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|     private int _moduleDefinitionId; | ||||
|     private string _name; | ||||
|     private string _version; | ||||
| @ -146,30 +150,39 @@ | ||||
|  | ||||
|     private async Task SaveModuleDefinition() | ||||
|     { | ||||
|         try | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId); | ||||
|             if (moduledefinition.Name != _name) | ||||
|             try | ||||
|             { | ||||
|                 moduledefinition.Name = _name; | ||||
|                 var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId); | ||||
|                 if (moduledefinition.Name != _name) | ||||
|                 { | ||||
|                     moduledefinition.Name = _name; | ||||
|                 } | ||||
|                 if (moduledefinition.Description != _description) | ||||
|                 { | ||||
|                     moduledefinition.Description = _description; | ||||
|                 } | ||||
|                 if (moduledefinition.Categories != _categories) | ||||
|                 { | ||||
|                     moduledefinition.Categories = _categories; | ||||
|                 } | ||||
|                 moduledefinition.Permissions = _permissionGrid.GetPermissions(); | ||||
|                 await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition); | ||||
|                 await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition); | ||||
|                 NavigationManager.NavigateTo(NavigateUrl()); | ||||
|             } | ||||
|             if (moduledefinition.Description != _description) | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 moduledefinition.Description = _description; | ||||
|                 await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message); | ||||
|                 AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error); | ||||
|             } | ||||
|             if (moduledefinition.Categories != _categories) | ||||
|             { | ||||
|                 moduledefinition.Categories = _categories; | ||||
|             } | ||||
|             moduledefinition.Permissions = _permissionGrid.GetPermissions(); | ||||
|             await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition); | ||||
|             await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition); | ||||
|             NavigationManager.NavigateTo(NavigateUrl()); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         else | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error); | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -5,28 +5,39 @@ | ||||
| @inject IStringLocalizer<Export> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <div class="container"> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="content" HelpText="Enter the module content" ResourceKey="Content">Content: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <textarea id="content" class="form-control" @bind="@_content" rows="5"></textarea> | ||||
|                 <textarea id="content" class="form-control" @bind="@_content" rows="5" required></textarea> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <button type="button" class="btn btn-success" @onclick="ExportModule">@Localizer["Export"]</button> | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|     private string _content = string.Empty; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|     public override string Title => "Export Content"; | ||||
|  | ||||
|  | ||||
|     @code { | ||||
|         private string _content = string.Empty; | ||||
|  | ||||
|         public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|         public override string Title => "Export Content"; | ||||
|  | ||||
|  | ||||
|         private async Task ExportModule() | ||||
|     private async Task ExportModule() | ||||
|     { | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             _content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| @inject IStringLocalizer<Import> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <div class="container"> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="content" HelpText="Enter the module content" ResourceKey="Content">Content: </Label> | ||||
| @ -17,15 +18,21 @@ | ||||
|  | ||||
|     <button type="button" class="btn btn-success" @onclick="ImportModule">@Localizer["Import"]</button> | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     private string _content = string.Empty; | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|  | ||||
|     @code { | ||||
|         private string _content = string.Empty; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|     public override string Title => "Import Content"; | ||||
|  | ||||
|         public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|         public override string Title => "Import Content"; | ||||
|  | ||||
|         private async Task ImportModule() | ||||
|     private async Task ImportModule() | ||||
|     { | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             if (_content != string.Empty) | ||||
|             { | ||||
| @ -52,4 +59,9 @@ | ||||
|                 AddModuleMessage(Localizer["Message.Required.ImportContent"], MessageType.Warning); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -8,88 +8,92 @@ | ||||
| @inject IStringLocalizer<Settings> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <TabStrip> | ||||
|     <TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings"> | ||||
|         @if (_containers != null) | ||||
|         { | ||||
|         <div class="container"> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="title" type="text" name="Title" class="form-control" @bind="@_title" /> | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <TabStrip> | ||||
|         <TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings"> | ||||
|             @if (_containers != null) | ||||
|             { | ||||
|                 <div class="container"> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="title" type="text" name="Title" class="form-control" @bind="@_title" required /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="container" class="form-select" @bind="@_containerType" required> | ||||
|                                 @foreach (var container in _containers) | ||||
|                                 { | ||||
|                                     <option value="@container.TypeName">@container.Name</option> | ||||
|                                 } | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="allpages" class="form-select" @bind="@_allPages" required> | ||||
|                                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="page" class="form-select" @bind="@_pageId" required> | ||||
|                                 @foreach (Page p in PageState.Pages) | ||||
|                                 { | ||||
|                                     if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions)) | ||||
|                                     { | ||||
|                                         <option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option> | ||||
|                                     } | ||||
|                                 } | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <select id="container" class="form-select" @bind="@_containerType"> | ||||
|                         @foreach (var container in _containers) | ||||
|                         { | ||||
|                             <option value="@container.TypeName">@container.Name</option> | ||||
|                         } | ||||
|                     </select> | ||||
|             } | ||||
|         </TabPanel> | ||||
|         <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|             @if (_permissions != null) | ||||
|             { | ||||
|                 <div class="container"> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <select id="allpages" class="form-select" @bind="@_allPages"> | ||||
|                         <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                         <option value="False">@SharedLocalizer["No"]</option> | ||||
|                     </select> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <select id="page" class="form-select" @bind="@_pageId"> | ||||
|                         @foreach (Page p in PageState.Pages) | ||||
|                         { | ||||
|                             if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions)) | ||||
|                             { | ||||
|                                 <option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option> | ||||
|                             } | ||||
|                         } | ||||
|                     </select> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         } | ||||
|     </TabPanel> | ||||
|     <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|         @if (_permissions != null) | ||||
|         { | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             } | ||||
|         </TabPanel> | ||||
|         @if (_moduleSettingsType != null) | ||||
|         { | ||||
|             <TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings"> | ||||
|                 @ModuleSettingsComponent | ||||
|             </TabPanel> | ||||
|         } | ||||
|     </TabPanel> | ||||
|     @if (_moduleSettingsType != null) | ||||
|     { | ||||
|         <TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings"> | ||||
|             @ModuleSettingsComponent | ||||
|         </TabPanel> | ||||
|     } | ||||
|     @if (_containerSettingsType != null) | ||||
|     { | ||||
|         <TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings"> | ||||
|             @ContainerSettingsComponent | ||||
|         </TabPanel> | ||||
|     } | ||||
| </TabStrip> | ||||
| <button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button> | ||||
| <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| <br /> | ||||
| <br /> | ||||
| <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo> | ||||
|         @if (_containerSettingsType != null) | ||||
|         { | ||||
|             <TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings"> | ||||
|                 @ContainerSettingsComponent | ||||
|             </TabPanel> | ||||
|         } | ||||
|     </TabStrip> | ||||
|     <button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button> | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
|     <br /> | ||||
|     <br /> | ||||
|     <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo> | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; | ||||
|     public override string Title => "Module Settings"; | ||||
|  | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|     private List<Theme> _themes; | ||||
|     private List<ThemeControl> _containers = new List<ThemeControl>(); | ||||
|     private string _title; | ||||
| @ -170,52 +174,61 @@ | ||||
|  | ||||
|     private async Task SaveModule() | ||||
|     { | ||||
|         if (!string.IsNullOrEmpty(_title)) | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); | ||||
|             pagemodule.PageId = int.Parse(_pageId); | ||||
|             pagemodule.Title = _title; | ||||
|             pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty; | ||||
|             if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType) | ||||
|             if (!string.IsNullOrEmpty(_title)) | ||||
|             { | ||||
|                 pagemodule.ContainerType = string.Empty; | ||||
|             } | ||||
|             if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType) | ||||
|             { | ||||
|                 pagemodule.ContainerType = string.Empty; | ||||
|             } | ||||
|             await PageModuleService.UpdatePageModuleAsync(pagemodule); | ||||
|             await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane); | ||||
|  | ||||
|             var module = ModuleState; | ||||
|             module.AllPages = bool.Parse(_allPages); | ||||
|             module.Permissions = _permissionGrid.GetPermissions(); | ||||
|             await ModuleService.UpdateModuleAsync(module); | ||||
|  | ||||
|             if (_moduleSettingsType != null) | ||||
|             { | ||||
|                 if (_moduleSettings is ISettingsControl moduleSettingsControl) | ||||
|                 var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); | ||||
|                 pagemodule.PageId = int.Parse(_pageId); | ||||
|                 pagemodule.Title = _title; | ||||
|                 pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty; | ||||
|                 if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType) | ||||
|                 { | ||||
|                     // module settings updated using explicit interface | ||||
|                     await moduleSettingsControl.UpdateSettings(); | ||||
|                     pagemodule.ContainerType = string.Empty; | ||||
|                 } | ||||
|                 else | ||||
|                 if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType) | ||||
|                 { | ||||
|                     // legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component ) | ||||
|                     _moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null); | ||||
|                     pagemodule.ContainerType = string.Empty; | ||||
|                 } | ||||
|             } | ||||
|                 await PageModuleService.UpdatePageModuleAsync(pagemodule); | ||||
|                 await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane); | ||||
|  | ||||
|             if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl) | ||||
|                 var module = ModuleState; | ||||
|                 module.AllPages = bool.Parse(_allPages); | ||||
|                 module.Permissions = _permissionGrid.GetPermissions(); | ||||
|                 await ModuleService.UpdateModuleAsync(module); | ||||
|  | ||||
|                 if (_moduleSettingsType != null) | ||||
|                 { | ||||
|                     if (_moduleSettings is ISettingsControl moduleSettingsControl) | ||||
|                     { | ||||
|                         // module settings updated using explicit interface | ||||
|                         await moduleSettingsControl.UpdateSettings(); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component ) | ||||
|                         _moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl) | ||||
|                 { | ||||
|                     await containerSettingsControl.UpdateSettings(); | ||||
|                 } | ||||
|  | ||||
|                 NavigationManager.NavigateTo(NavigateUrl()); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 await containerSettingsControl.UpdateSettings(); | ||||
|                 AddModuleMessage(Localizer["Message.Required.Title"], MessageType.Warning); | ||||
|             } | ||||
|  | ||||
|             NavigationManager.NavigateTo(NavigateUrl()); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AddModuleMessage(Localizer["Message.Required.Title"], MessageType.Warning); | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -6,151 +6,154 @@ | ||||
| @inject IStringLocalizer<Add> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <TabStrip Refresh="@_refresh"> | ||||
|     <TabPanel Name="Settings" ResourceKey="Settings"> | ||||
|         @if (_themeList != null) | ||||
|         { | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="Name" class="form-control" @bind="@_name" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="Parent" class="form-select" @onchange="(e => ParentChanged(e))"> | ||||
|                             <option value="-1"><@Localizer["SiteRoot"]></option> | ||||
|                             @foreach (Page page in _pageList) | ||||
|                             { | ||||
|                                 <option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option> | ||||
|                             } | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="Insert" class="form-select" @bind="@_insert"> | ||||
|                             <option value="<<">@Localizer["AtBeginning"]</option> | ||||
|                             @if (_children != null && _children.Count > 0) | ||||
|                             { | ||||
|                                 <option value="<">@Localizer["Before"]</option> | ||||
|                                 <option value=">">@Localizer["After"]</option> | ||||
|                             } | ||||
|                             <option value=">>">@Localizer["AtEnd"]</option> | ||||
|                         </select> | ||||
|                         @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) | ||||
|                         { | ||||
|                             <select class="form-select" @bind="@_childid"> | ||||
|                                 <option value="-1"><@Localizer["Page.Select"]></option> | ||||
|                                 @foreach (Page page in _children) | ||||
|                                 { | ||||
|                                     <option value="@(page.PageId)">@(page.Name)</option> | ||||
|                                 } | ||||
|                             </select> | ||||
|                         } | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="navigation" class="form-select" @bind="@_isnavigation"> | ||||
|                             <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                             <option value="False">@SharedLocalizer["No"]</option> | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="clickable" class="form-select" @bind="@_isclickable"> | ||||
|                             <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                             <option value="False">@SharedLocalizer["No"]</option> | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="Path" class="form-control" @bind="@_path" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="Url" class="form-control" @bind="@_url" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <Section Name="Appearance" ResourceKey="Appearance"> | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <TabStrip Refresh="@_refresh"> | ||||
|         <TabPanel Name="Settings" ResourceKey="Settings"> | ||||
|             @if (_themeList != null) | ||||
|             { | ||||
|                 <div class="container"> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label> | ||||
|                         <Label Class="col-sm-3" For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Title" class="form-control" @bind="@_title" /> | ||||
|                             <input id="Name" class="form-control" @bind="@_name" required /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label> | ||||
|                         <Label Class="col-sm-3" For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="Theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))"> | ||||
|                                 @foreach (var theme in _themes) | ||||
|                             <select id="Parent" class="form-select" @onchange="(e => ParentChanged(e))" required> | ||||
|                                 <option value="-1"><@Localizer["SiteRoot"]></option> | ||||
|                                 @foreach (Page page in _pageList) | ||||
|                                 { | ||||
|                                     <option value="@theme.TypeName">@theme.Name</option> | ||||
|                                     <option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option> | ||||
|                                 } | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label> | ||||
|                         <Label Class="col-sm-3" For="Insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="defaultContainer" class="form-select" @bind="@_containertype"> | ||||
|                                 <option value="-"><@Localizer["Container.Select"]></option> | ||||
|                                 @foreach (var container in _containers) | ||||
|                             <select id="Insert" class="form-select" @bind="@_insert" required> | ||||
|                                 <option value="<<">@Localizer["AtBeginning"]</option> | ||||
|                                 @if (_children != null && _children.Count > 0) | ||||
|                                 { | ||||
|                                     <option value="@container.TypeName">@container.Name</option> | ||||
|                                     <option value="<">@Localizer["Before"]</option> | ||||
|                                     <option value=">">@Localizer["After"]</option> | ||||
|                                 } | ||||
|                                 <option value=">>">@Localizer["AtEnd"]</option> | ||||
|                             </select> | ||||
|                             @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) | ||||
|                             { | ||||
|                                 <select class="form-select" @bind="@_childid"> | ||||
|                                     <option value="-1"><@Localizer["Page.Select"]></option> | ||||
|                                     @foreach (Page page in _children) | ||||
|                                     { | ||||
|                                         <option value="@(page.PageId)">@(page.Name)</option> | ||||
|                                     } | ||||
|                                 </select> | ||||
|                             } | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label> | ||||
|                         <Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Icon" class="form-control" @bind="@_icon" /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="Personalizable" class="form-select" @bind="@_ispersonalizable"> | ||||
|                             <select id="navigation" class="form-select" @bind="@_isnavigation" required> | ||||
|                                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="clickable" class="form-select" @bind="@_isclickable" required> | ||||
|                                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Path" class="form-control" @bind="@_path" /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Url" class="form-control" @bind="@_url" /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </Section> | ||||
|         } | ||||
|     </TabPanel> | ||||
|     <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|         <div class="container"> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|             </div> | ||||
|         </div> | ||||
|     </TabPanel> | ||||
|     @if (_themeSettingsType != null) | ||||
|     { | ||||
|         <TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings"> | ||||
|             @ThemeSettingsComponent | ||||
|  | ||||
|                 <Section Name="Appearance" ResourceKey="Appearance"> | ||||
|                     <div class="container"> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <input id="Title" class="form-control" @bind="@_title" /> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <select id="Theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required> | ||||
|                                     @foreach (var theme in _themes) | ||||
|                                     { | ||||
|                                         <option value="@theme.TypeName">@theme.Name</option> | ||||
|                                     } | ||||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <select id="defaultContainer" class="form-select" @bind="@_containertype" required> | ||||
|                                     <option value="-"><@Localizer["Container.Select"]></option> | ||||
|                                     @foreach (var container in _containers) | ||||
|                                     { | ||||
|                                         <option value="@container.TypeName">@container.Name</option> | ||||
|                                     } | ||||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <input id="Icon" class="form-control" @bind="@_icon" /> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <select id="Personalizable" class="form-select" @bind="@_ispersonalizable" required> | ||||
|                                     <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                     <option value="False">@SharedLocalizer["No"]</option> | ||||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </Section> | ||||
|             } | ||||
|         </TabPanel> | ||||
|     } | ||||
| </TabStrip> | ||||
| <button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button> | ||||
| <button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button> | ||||
|         <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </TabPanel> | ||||
|         @if (_themeSettingsType != null) | ||||
|         { | ||||
|             <TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings"> | ||||
|                 @ThemeSettingsComponent | ||||
|             </TabPanel> | ||||
|         } | ||||
|     </TabStrip> | ||||
|     <button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button> | ||||
|     <button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button> | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
| @ -179,6 +182,8 @@ | ||||
|     private object _themeSettings; | ||||
|     private RenderFragment ThemeSettingsComponent { get; set; } | ||||
|     private bool _refresh = false; | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
| @ -275,110 +280,119 @@ | ||||
|  | ||||
|     private async Task SavePage() | ||||
|     { | ||||
|         Page page = null; | ||||
|         try | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             if (!string.IsNullOrEmpty(_name) && !string.IsNullOrEmpty(_themetype) && _containertype != "-") | ||||
|             Page page = null; | ||||
|             try | ||||
|             { | ||||
|                 page = new Page(); | ||||
|                 page.SiteId = PageState.Page.SiteId; | ||||
|                 page.Name = _name; | ||||
|                 page.Title = _title; | ||||
|                 if (_path == "") | ||||
|                 if (!string.IsNullOrEmpty(_name) && !string.IsNullOrEmpty(_themetype) && _containertype != "-") | ||||
|                 { | ||||
|                     _path = _name; | ||||
|                 } | ||||
|  | ||||
|                 if (_path.Contains("/")) | ||||
|                 { | ||||
|                     _path = _path.Substring(_path.LastIndexOf("/") + 1); | ||||
|                 } | ||||
|  | ||||
|                 if (string.IsNullOrEmpty(_parentid)) | ||||
|                 { | ||||
|                     page.ParentId = null; | ||||
|                     page.Path = Utilities.GetFriendlyUrl(_path); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     page.ParentId = Int32.Parse(_parentid); | ||||
|                     var parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault(); | ||||
|                     if (parent.Path == string.Empty) | ||||
|                     page = new Page(); | ||||
|                     page.SiteId = PageState.Page.SiteId; | ||||
|                     page.Name = _name; | ||||
|                     page.Title = _title; | ||||
|                     if (_path == "") | ||||
|                     { | ||||
|                         page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         _path = _name; | ||||
|                     } | ||||
|  | ||||
|                     if (_path.Contains("/")) | ||||
|                     { | ||||
|                         _path = _path.Substring(_path.LastIndexOf("/") + 1); | ||||
|                     } | ||||
|  | ||||
|                     if (string.IsNullOrEmpty(_parentid)) | ||||
|                     { | ||||
|                         page.ParentId = null; | ||||
|                         page.Path = Utilities.GetFriendlyUrl(_path); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         page.ParentId = Int32.Parse(_parentid); | ||||
|                         var parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault(); | ||||
|                         if (parent.Path == string.Empty) | ||||
|                         { | ||||
|                             page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (!PagePathIsUnique(page.Path, page.SiteId, _pageList)) | ||||
|                 { | ||||
|                     AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning); | ||||
|                     return; | ||||
|                 } | ||||
|                     if (!PagePathIsUnique(page.Path, page.SiteId, _pageList)) | ||||
|                     { | ||||
|                         AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning); | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                 Page child; | ||||
|                 switch (_insert) | ||||
|                 { | ||||
|                     case "<<": | ||||
|                         page.Order = 0; | ||||
|                         break; | ||||
|                     case "<": | ||||
|                         child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault(); | ||||
|                         page.Order = child.Order - 1; | ||||
|                         break; | ||||
|                     case ">": | ||||
|                         child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault(); | ||||
|                         page.Order = child.Order + 1; | ||||
|                         break; | ||||
|                     case ">>": | ||||
|                         page.Order = int.MaxValue; | ||||
|                         break; | ||||
|                 } | ||||
|                     Page child; | ||||
|                     switch (_insert) | ||||
|                     { | ||||
|                         case "<<": | ||||
|                             page.Order = 0; | ||||
|                             break; | ||||
|                         case "<": | ||||
|                             child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault(); | ||||
|                             page.Order = child.Order - 1; | ||||
|                             break; | ||||
|                         case ">": | ||||
|                             child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault(); | ||||
|                             page.Order = child.Order + 1; | ||||
|                             break; | ||||
|                         case ">>": | ||||
|                             page.Order = int.MaxValue; | ||||
|                             break; | ||||
|                     } | ||||
|  | ||||
|                 page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation)); | ||||
|                 page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); | ||||
|                 page.Url = _url; | ||||
|                 page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; | ||||
|                 if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) | ||||
|                 { | ||||
|                     page.ThemeType = string.Empty; | ||||
|                 } | ||||
|                 page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty; | ||||
|                 if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType) | ||||
|                 { | ||||
|                     page.DefaultContainerType = string.Empty; | ||||
|                 } | ||||
|                 page.Icon = (_icon == null ? string.Empty : _icon); | ||||
|                 page.Permissions = _permissionGrid.GetPermissions(); | ||||
|                 page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable)); | ||||
|                 page.UserId = null; | ||||
|                     page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation)); | ||||
|                     page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); | ||||
|                     page.Url = _url; | ||||
|                     page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; | ||||
|                     if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) | ||||
|                     { | ||||
|                         page.ThemeType = string.Empty; | ||||
|                     } | ||||
|                     page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty; | ||||
|                     if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType) | ||||
|                     { | ||||
|                         page.DefaultContainerType = string.Empty; | ||||
|                     } | ||||
|                     page.Icon = (_icon == null ? string.Empty : _icon); | ||||
|                     page.Permissions = _permissionGrid.GetPermissions(); | ||||
|                     page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable)); | ||||
|                     page.UserId = null; | ||||
|  | ||||
|                 page = await PageService.AddPageAsync(page); | ||||
|                 await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId); | ||||
|                     page = await PageService.AddPageAsync(page); | ||||
|                     await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId); | ||||
|  | ||||
|                 await logger.LogInformation("Page Added {Page}", page); | ||||
|                 if (PageState.QueryString.ContainsKey("cp")) | ||||
|                 { | ||||
|                     NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path)); | ||||
|                     await logger.LogInformation("Page Added {Page}", page); | ||||
|                     if (PageState.QueryString.ContainsKey("cp")) | ||||
|                     { | ||||
|                         NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path)); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         NavigationManager.NavigateTo(NavigateUrl(page.Path)); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     NavigationManager.NavigateTo(NavigateUrl(page.Path)); | ||||
|                     AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning); | ||||
|             } | ||||
|  | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message); | ||||
|                 AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         else | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error); | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -7,168 +7,172 @@ | ||||
| @inject IStringLocalizer<Edit> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <TabStrip Refresh="@_refresh"> | ||||
|     <TabPanel Name="Settings" ResourceKey="Settings"> | ||||
|         @if (_themeList != null) | ||||
|         { | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="Name" class="form-control" @bind="@_name" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="Parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))"> | ||||
|                             <option value="-1"><@Localizer["SiteRoot"]></option> | ||||
|                             @foreach (Page page in _pageList) | ||||
|                             { | ||||
|                                 if (page.PageId != _pageId) | ||||
|                                 { | ||||
|                                     <option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option> | ||||
|                                 } | ||||
|                             } | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="Move" class="form-select" @bind="@_insert"> | ||||
|                             @if (_parentid == _currentparentid) | ||||
|                             { | ||||
|                                 <option value="="><@Localizer["ThisLocation.Keep"]></option> | ||||
|                             } | ||||
|                             <option value="<<">@Localizer["ToBeginning"]</option> | ||||
|                             @if (_children != null && _children.Count > 0) | ||||
|                             { | ||||
|                                 <option value="<">@Localizer["Before"]</option> | ||||
|                                 <option value=">">@Localizer["After"]</option> | ||||
|                             } | ||||
|                             <option value=">>">@Localizer["ToEnd"]</option> | ||||
|                         </select> | ||||
|                         @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) | ||||
|                         { | ||||
|                             <select class="form-select" @bind="@_childid"> | ||||
|                                 <option value="-1"><@Localizer["Page.Select"]></option> | ||||
|                                 @foreach (Page page in _children) | ||||
|                                 { | ||||
|                                     <option value="@(page.PageId)">@(page.Name)</option> | ||||
|                                 } | ||||
|                             </select> | ||||
|                         } | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="Navigation" class="form-select" @bind="@_isnavigation"> | ||||
|                             <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                             <option value="False">@SharedLocalizer["No"]</option> | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Clickablen" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="Navigation" class="form-select" @bind="@_isclickable"> | ||||
|                             <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                             <option value="False">@SharedLocalizer["No"]</option> | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="Path" class="form-control" @bind="@_path" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <input id="Url" class="form-control" @bind="@_url" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <Section Name="Appearance" ResourceKey="Appearance"> | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <TabStrip Refresh="@_refresh"> | ||||
|         <TabPanel Name="Settings" ResourceKey="Settings"> | ||||
|             @if (_themeList != null) | ||||
|             { | ||||
|                 <div class="container"> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label> | ||||
|                         <Label Class="col-sm-3" For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Title" class="form-control" @bind="@_title" /> | ||||
|                             <input id="Name" class="form-control" @bind="@_name" required /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label> | ||||
|                         <Label Class="col-sm-3" For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="Theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))"> | ||||
|                                 @foreach (var theme in _themes) | ||||
|                             <select id="Parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required> | ||||
|                                 <option value="-1"><@Localizer["SiteRoot"]></option> | ||||
|                                 @foreach (Page page in _pageList) | ||||
|                                 { | ||||
|                                     <option value="@theme.TypeName">@theme.Name</option> | ||||
|                                     if (page.PageId != _pageId) | ||||
|                                     { | ||||
|                                         <option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option> | ||||
|                                     } | ||||
|                                 } | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label> | ||||
|                         <Label Class="col-sm-3" For="Move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="defaultContainer" class="form-select" @bind="@_containertype"> | ||||
|                                 <option value="-"><@Localizer["Container.Select"]></option> | ||||
|                                 @foreach (var container in _containers) | ||||
|                             <select id="Move" class="form-select" @bind="@_insert" required> | ||||
|                                 @if (_parentid == _currentparentid) | ||||
|                                 { | ||||
|                                     <option value="@container.TypeName">@container.Name</option> | ||||
|                                     <option value="="><@Localizer["ThisLocation.Keep"]></option> | ||||
|                                 } | ||||
|                                 <option value="<<">@Localizer["ToBeginning"]</option> | ||||
|                                 @if (_children != null && _children.Count > 0) | ||||
|                                 { | ||||
|                                     <option value="<">@Localizer["Before"]</option> | ||||
|                                     <option value=">">@Localizer["After"]</option> | ||||
|                                 } | ||||
|                                 <option value=">>">@Localizer["ToEnd"]</option> | ||||
|                             </select> | ||||
|                             @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) | ||||
|                             { | ||||
|                                 <select class="form-select" @bind="@_childid"> | ||||
|                                     <option value="-1"><@Localizer["Page.Select"]></option> | ||||
|                                     @foreach (Page page in _children) | ||||
|                                     { | ||||
|                                         <option value="@(page.PageId)">@(page.Name)</option> | ||||
|                                     } | ||||
|                                 </select> | ||||
|                             } | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label> | ||||
|                         <Label Class="col-sm-3" For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Icon" class="form-control" @bind="@_icon" /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="Personalizable" class="form-select" @bind="@_ispersonalizable"> | ||||
|                             <select id="Navigation" class="form-select" @bind="@_isnavigation" required> | ||||
|                                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Clickablen" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <select id="Navigation" class="form-select" @bind="@_isclickable" required> | ||||
|                                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Path" class="form-control" @bind="@_path" /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <Label Class="col-sm-3" For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label> | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input id="Url" class="form-control" @bind="@_url" /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </Section> | ||||
|             <br /><br /> | ||||
|             <AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo> | ||||
|         } | ||||
|     </TabPanel> | ||||
|     <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|         @if (_permissions != null) | ||||
|         { | ||||
|             <div class="container"> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|         | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
|         } | ||||
|     </TabPanel> | ||||
|     @if (_themeSettingsType != null) | ||||
|     { | ||||
|         <TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings"> | ||||
|             @ThemeSettingsComponent | ||||
|                 <Section Name="Appearance" ResourceKey="Appearance"> | ||||
|                     <div class="container"> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <input id="Title" class="form-control" @bind="@_title" /> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <select id="Theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required> | ||||
|                                     @foreach (var theme in _themes) | ||||
|                                     { | ||||
|                                         <option value="@theme.TypeName">@theme.Name</option> | ||||
|                                     } | ||||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <select id="defaultContainer" class="form-select" @bind="@_containertype" required> | ||||
|                                     <option value="-"><@Localizer["Container.Select"]></option> | ||||
|                                     @foreach (var container in _containers) | ||||
|                                     { | ||||
|                                         <option value="@container.TypeName">@container.Name</option> | ||||
|                                     } | ||||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <input id="Icon" class="form-control" @bind="@_icon" /> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="row mb-1 align-items-center"> | ||||
|                             <Label Class="col-sm-3" For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label> | ||||
|                             <div class="col-sm-9"> | ||||
|                                 <select id="Personalizable" class="form-select" @bind="@_ispersonalizable" required> | ||||
|                                     <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                                     <option value="False">@SharedLocalizer["No"]</option> | ||||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </Section> | ||||
|                 <br /><br /> | ||||
|                 <AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo> | ||||
|             } | ||||
|         </TabPanel> | ||||
|     } | ||||
| </TabStrip> | ||||
| <button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button> | ||||
| <button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button> | ||||
|         <TabPanel Name="Permissions" ResourceKey="Permissions"> | ||||
|             @if (_permissions != null) | ||||
|             { | ||||
|                 <div class="container"> | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" /> | ||||
|  | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|             } | ||||
|         </TabPanel> | ||||
|         @if (_themeSettingsType != null) | ||||
|         { | ||||
|             <TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings"> | ||||
|                 @ThemeSettingsComponent | ||||
|             </TabPanel> | ||||
|         } | ||||
|     </TabStrip> | ||||
|     <button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button> | ||||
|     <button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button> | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|  | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|     private List<Theme> _themeList; | ||||
|     private List<ThemeControl> _themes = new List<ThemeControl>(); | ||||
|     private List<ThemeControl> _containers = new List<ThemeControl>(); | ||||
| @ -351,134 +355,143 @@ | ||||
|  | ||||
|     private async Task SavePage() | ||||
|     { | ||||
|         Page page = null; | ||||
|         try | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             if (_name != string.Empty && !string.IsNullOrEmpty(_themetype) && _containertype != "-") | ||||
|             Page page = null; | ||||
|             try | ||||
|             { | ||||
|                 page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId); | ||||
|                 string currentPath = page.Path; | ||||
|                 if (_name != string.Empty && !string.IsNullOrEmpty(_themetype) && _containertype != "-") | ||||
|                 { | ||||
|                     page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId); | ||||
|                     string currentPath = page.Path; | ||||
|  | ||||
|                 page.Name = _name; | ||||
|                 page.Title = _title; | ||||
|                 if (_path == "" && _name.ToLower() != "home") | ||||
|                     if (_path == string.Empty && _name.ToLower() != "home") | ||||
|                     page.Name = _name; | ||||
|                     page.Title = _title; | ||||
|                     if (_path == "" && _name.ToLower() != "home") | ||||
|                         if (_path == string.Empty && _name.ToLower() != "home") | ||||
|                         { | ||||
|                             _path = _name; | ||||
|                         } | ||||
|                     if (_path.Contains("/")) | ||||
|                     { | ||||
|                         _path = _name; | ||||
|                         _path = _path.Substring(_path.LastIndexOf("/") + 1); | ||||
|                     } | ||||
|                 if (_path.Contains("/")) | ||||
|                 { | ||||
|                     _path = _path.Substring(_path.LastIndexOf("/") + 1); | ||||
|                 } | ||||
|                 if (string.IsNullOrEmpty(_parentid) || _parentid == "-1") | ||||
|                 { | ||||
|                     page.ParentId = null; | ||||
|                     page.Path = Utilities.GetFriendlyUrl(_path); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     page.ParentId = Int32.Parse(_parentid); | ||||
|                     Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId); | ||||
|                     if (parent.Path == string.Empty) | ||||
|                     if (string.IsNullOrEmpty(_parentid) || _parentid == "-1") | ||||
|                     { | ||||
|                         page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         page.ParentId = null; | ||||
|                         page.Path = Utilities.GetFriendlyUrl(_path); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         page.ParentId = Int32.Parse(_parentid); | ||||
|                         Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId); | ||||
|                         if (parent.Path == string.Empty) | ||||
|                         { | ||||
|                             page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList)) | ||||
|                 { | ||||
|                     AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (_insert != "=") | ||||
|                 { | ||||
|                     Page child; | ||||
|                     switch (_insert) | ||||
|                     if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList)) | ||||
|                     { | ||||
|                         case "<<": | ||||
|                             page.Order = 0; | ||||
|                             break; | ||||
|                         case "<": | ||||
|                             child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid); | ||||
|                             if (child != null) page.Order = child.Order - 1; | ||||
|                             break; | ||||
|                         case ">": | ||||
|                             child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid); | ||||
|                             if (child != null) page.Order = child.Order + 1; | ||||
|                             break; | ||||
|                         case ">>": | ||||
|                             page.Order = int.MaxValue; | ||||
|                             break; | ||||
|                         AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation)); | ||||
|                 page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); | ||||
|                 page.Url = _url; | ||||
|                 page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; | ||||
|                 if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) | ||||
|                 { | ||||
|                     page.ThemeType = string.Empty; | ||||
|                 } | ||||
|                 page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty; | ||||
|                 if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType) | ||||
|                 { | ||||
|                     page.DefaultContainerType = string.Empty; | ||||
|                 } | ||||
|                 page.Icon = _icon ?? string.Empty; | ||||
|                 page.Permissions = _permissionGrid.GetPermissions(); | ||||
|                 page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable)); | ||||
|                 page.UserId = null; | ||||
|  | ||||
|                 page = await PageService.UpdatePageAsync(page); | ||||
|                 await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId); | ||||
|                 if (_currentparentid == string.Empty) | ||||
|                 { | ||||
|                     await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, null); | ||||
|                     if (_insert != "=") | ||||
|                     { | ||||
|                         Page child; | ||||
|                         switch (_insert) | ||||
|                         { | ||||
|                             case "<<": | ||||
|                                 page.Order = 0; | ||||
|                                 break; | ||||
|                             case "<": | ||||
|                                 child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid); | ||||
|                                 if (child != null) page.Order = child.Order - 1; | ||||
|                                 break; | ||||
|                             case ">": | ||||
|                                 child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid); | ||||
|                                 if (child != null) page.Order = child.Order + 1; | ||||
|                                 break; | ||||
|                             case ">>": | ||||
|                                 page.Order = int.MaxValue; | ||||
|                                 break; | ||||
|                         } | ||||
|                     } | ||||
|                     page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation)); | ||||
|                     page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); | ||||
|                     page.Url = _url; | ||||
|                     page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; | ||||
|                     if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) | ||||
|                     { | ||||
|                         page.ThemeType = string.Empty; | ||||
|                     } | ||||
|                     page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty; | ||||
|                     if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType) | ||||
|                     { | ||||
|                         page.DefaultContainerType = string.Empty; | ||||
|                     } | ||||
|                     page.Icon = _icon ?? string.Empty; | ||||
|                     page.Permissions = _permissionGrid.GetPermissions(); | ||||
|                     page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable)); | ||||
|                     page.UserId = null; | ||||
|  | ||||
|                     page = await PageService.UpdatePageAsync(page); | ||||
|                     await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId); | ||||
|                     if (_currentparentid == string.Empty) | ||||
|                     { | ||||
|                         await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, null); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, int.Parse(_currentparentid)); | ||||
|                     } | ||||
|  | ||||
|                     // update child paths | ||||
|                     if (_parentid != _currentparentid) | ||||
|                     { | ||||
|                         foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentPath))) | ||||
|                         { | ||||
|                             p.Path = p.Path.Replace(currentPath, page.Path); | ||||
|                             await PageService.UpdatePageAsync(p); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (_themeSettingsType != null && _themeSettings is ISettingsControl themeSettingsControl) | ||||
|                     { | ||||
|                         await themeSettingsControl.UpdateSettings(); | ||||
|                     } | ||||
|  | ||||
|                     await logger.LogInformation("Page Saved {Page}", page); | ||||
|                     if (PageState.QueryString.ContainsKey("cp")) | ||||
|                     { | ||||
|                         NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path)); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         NavigationManager.NavigateTo(NavigateUrl(page.Path)); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, int.Parse(_currentparentid)); | ||||
|                 } | ||||
|  | ||||
|                 // update child paths | ||||
|                 if (_parentid != _currentparentid) | ||||
|                 { | ||||
|                     foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentPath))) | ||||
|                     { | ||||
|                         p.Path = p.Path.Replace(currentPath, page.Path); | ||||
|                         await PageService.UpdatePageAsync(p); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (_themeSettingsType != null && _themeSettings is ISettingsControl themeSettingsControl) | ||||
|                 { | ||||
|                     await themeSettingsControl.UpdateSettings(); | ||||
|                 } | ||||
|  | ||||
|                 await logger.LogInformation("Page Saved {Page}", page); | ||||
|                 if (PageState.QueryString.ContainsKey("cp")) | ||||
|                 { | ||||
|                     NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path)); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     NavigationManager.NavigateTo(NavigateUrl(page.Path)); | ||||
|                     AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning); | ||||
|                 await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message); | ||||
|                 AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         else | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error); | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -5,86 +5,90 @@ | ||||
| @inject IStringLocalizer<Edit> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <div class="container"> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="name" HelpText="The name of this profile item" ResourceKey="Name">Name: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="name" class="form-control" @bind="@_name" /> | ||||
| <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> | ||||
|     <div class="container"> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="name" HelpText="The name of this profile item" ResourceKey="Name">Name: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="name" class="form-control" @bind="@_name" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="title" HelpText="The title of the profile item to display to the user" ResourceKey="Title">Title: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="title" class="form-control" @bind="@_title" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="description" HelpText="The help text displayed to the user for this profile item" ResourceKey="Description">Description: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <textarea id="description" class="form-control" @bind="@_description" rows="5" required></textarea> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="category" HelpText="The category of this profile item (for grouping)" ResourceKey="Category">Category: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="category" class="form-control" @bind="@_category" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="order" HelpText="The index order of where this profile item should be displayed" ResourceKey="Order">Order: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="order" class="form-control" @bind="@_vieworder" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="length" HelpText="The max number of characters this profile item should accept (enter zero for unlimited)" ResourceKey="Length">Length: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="length" class="form-control" @bind="@_maxlength" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="defaultVal" HelpText="The default value for this profile item" ResourceKey="DefaultValue">Default Value: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="defaultVal" class="form-control" @bind="@_defaultvalue" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="options" HelpText="A comma delimited list of options the user can select from" ResourceKey="Options">Options: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="options" class="form-control" @bind="@_options" required /> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="required" HelpText="Should a user be required to provide a value for this profile item?" ResourceKey="Required">Required? </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <select id="required" class="form-select" @bind="@_isrequired" required> | ||||
|                     <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                     <option value="False">@SharedLocalizer["No"]</option> | ||||
|                 </select> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <select id="private" class="form-select" @bind="@_isprivate" required> | ||||
|                     <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                     <option value="False">@SharedLocalizer["No"]</option> | ||||
|                 </select> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="title" HelpText="The title of the profile item to display to the user" ResourceKey="Title">Title: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="title" class="form-control" @bind="@_title" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="description" HelpText="The help text displayed to the user for this profile item" ResourceKey="Description">Description: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <textarea id="description" class="form-control" @bind="@_description" rows="5"></textarea> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="category" HelpText="The category of this profile item (for grouping)" ResourceKey="Category">Category: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="category" class="form-control" @bind="@_category" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="order" HelpText="The index order of where this profile item should be displayed" ResourceKey="Order">Order: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="order" class="form-control" @bind="@_vieworder" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="length" HelpText="The max number of characters this profile item should accept (enter zero for unlimited)" ResourceKey="Length">Length: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="length" class="form-control" @bind="@_maxlength" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="defaultVal" HelpText="The default value for this profile item" ResourceKey="DefaultValue">Default Value: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="defaultVal" class="form-control" @bind="@_defaultvalue" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="options" HelpText="A comma delimited list of options the user can select from" ResourceKey="Options">Options: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input id="options" class="form-control" @bind="@_options" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="required" HelpText="Should a user be required to provide a value for this profile item?" ResourceKey="Required">Required? </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <select id="required" class="form-select" @bind="@_isrequired"> | ||||
|                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <select id="private" class="form-select" @bind="@_isprivate"> | ||||
|                 <option value="True">@SharedLocalizer["Yes"]</option> | ||||
|                 <option value="False">@SharedLocalizer["No"]</option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| <br /> | ||||
| <button type="button" class="btn btn-success" @onclick="SaveProfile">@SharedLocalizer["Save"]</button> | ||||
| <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| @if (PageState.QueryString.ContainsKey("id")) | ||||
| { | ||||
|     <br /> | ||||
|     <br /> | ||||
|     <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo> | ||||
| } | ||||
|     <button type="button" class="btn btn-success" @onclick="SaveProfile">@SharedLocalizer["Save"]</button> | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
|     @if (PageState.QueryString.ContainsKey("id")) | ||||
|     { | ||||
|         <br /> | ||||
|         <br /> | ||||
|         <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo> | ||||
|     } | ||||
| </form> | ||||
|  | ||||
| @code { | ||||
|     private int _profileid = -1; | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
|     private string _name = string.Empty; | ||||
|     private string _title = string.Empty; | ||||
|     private string _description = string.Empty; | ||||
| @ -140,45 +144,54 @@ | ||||
|  | ||||
|     private async Task SaveProfile() | ||||
|     { | ||||
|         try | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             Profile profile; | ||||
|             if (_profileid != -1) | ||||
|             try | ||||
|             { | ||||
|                 profile = await ProfileService.GetProfileAsync(_profileid); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 profile = new Profile(); | ||||
|             } | ||||
|                 Profile profile; | ||||
|                 if (_profileid != -1) | ||||
|                 { | ||||
|                     profile = await ProfileService.GetProfileAsync(_profileid); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     profile = new Profile(); | ||||
|                 } | ||||
|  | ||||
|             profile.SiteId = PageState.Site.SiteId; | ||||
|             profile.Name = _name; | ||||
|             profile.Title = _title; | ||||
|             profile.Description = _description; | ||||
|             profile.Category = _category; | ||||
|             profile.ViewOrder = int.Parse(_vieworder); | ||||
|             profile.MaxLength = int.Parse(_maxlength); | ||||
|             profile.DefaultValue = _defaultvalue; | ||||
|             profile.Options = _options; | ||||
|             profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired)); | ||||
|             profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate)); | ||||
|             if (_profileid != -1) | ||||
|             { | ||||
|                 profile = await ProfileService.UpdateProfileAsync(profile); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 profile = await ProfileService.AddProfileAsync(profile); | ||||
|             } | ||||
|                 profile.SiteId = PageState.Site.SiteId; | ||||
|                 profile.Name = _name; | ||||
|                 profile.Title = _title; | ||||
|                 profile.Description = _description; | ||||
|                 profile.Category = _category; | ||||
|                 profile.ViewOrder = int.Parse(_vieworder); | ||||
|                 profile.MaxLength = int.Parse(_maxlength); | ||||
|                 profile.DefaultValue = _defaultvalue; | ||||
|                 profile.Options = _options; | ||||
|                 profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired)); | ||||
|                 profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate)); | ||||
|                 if (_profileid != -1) | ||||
|                 { | ||||
|                     profile = await ProfileService.UpdateProfileAsync(profile); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     profile = await ProfileService.AddProfileAsync(profile); | ||||
|                 } | ||||
|  | ||||
|             await logger.LogInformation("Profile Saved {Profile}", profile); | ||||
|             NavigationManager.NavigateTo(NavigateUrl()); | ||||
|                 await logger.LogInformation("Profile Saved {Profile}", profile); | ||||
|                 NavigationManager.NavigateTo(NavigateUrl()); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 await logger.LogError(ex, "Error Saving Profile {ProfleId} {Error}", _profileid, ex.Message); | ||||
|                 AddModuleMessage(Localizer["Error.Profile.Save"], MessageType.Error); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         else | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Saving Profile {ProfleId} {Error}", _profileid, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.Profile.Save"], MessageType.Error); | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Grayson Walker
					Grayson Walker