Merge remote-tracking branch 'upstream/dev' into Bootstrap
This commit is contained in:
@ -54,6 +54,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ILocalizationCookieService, LocalizationCookieService>();
|
||||
services.AddScoped<ICookieConsentService, CookieConsentService>();
|
||||
services.AddScoped<IOutputCacheService, OutputCacheService>();
|
||||
services.AddScoped<ITimeZoneService, TimeZoneService>();
|
||||
|
||||
// providers
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||
|
@ -15,22 +15,34 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent folder" ResourceKey="Parent">Parent: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="parent" class="form-select" @bind="@_parentId" required>
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
@if (_parentId == -1)
|
||||
{
|
||||
<select id="parent" class="form-select" @bind="@_parentId" required>
|
||||
<option value="-1"><@Localizer["NoParent"]></option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
else
|
||||
{
|
||||
<select id="parent" class="form-select" @bind="@_parentId" required>
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
|
||||
@if (_isSystem)
|
||||
{
|
||||
<input id="name" class="form-control" @bind="@_name" readonly />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
@ -229,7 +241,6 @@
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
||||
await logger.LogInformation("Folder Saved {Folder}", folder);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
@ -265,17 +276,9 @@
|
||||
}
|
||||
if (!isparent)
|
||||
{
|
||||
var files = await FileService.GetFilesAsync(_folderId);
|
||||
if (files.Count == 0)
|
||||
{
|
||||
await FolderService.DeleteFolderAsync(_folderId);
|
||||
await logger.LogInformation("Folder Deleted {Folder}", _folderId);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Folder.Files.InvalidDelete"], MessageType.Warning);
|
||||
}
|
||||
await FolderService.DeleteFolderAsync(_folderId);
|
||||
await logger.LogInformation("Folder Deleted {Folder}", _folderId);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ else
|
||||
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" ResourceKey="Details" /></td>
|
||||
<td><ActionDialog Header="Delete File" Message="@string.Format(Localizer["Confirm.File.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" ResourceKey="DeleteFile" /></td>
|
||||
<td><a href="@context.Url" target="_new">@context.Name</a></td>
|
||||
<td>@context.ModifiedOn</td>
|
||||
<td>@UtcToLocal(context.ModifiedOn)</td>
|
||||
<td>@context.Extension.ToUpper() @SharedLocalizer["File"]</td>
|
||||
<td>@string.Format("{0:0.00}", ((decimal)context.Size / 1000)) KB</td>
|
||||
</Row>
|
||||
|
@ -132,13 +132,13 @@
|
||||
_isEnabled = job.IsEnabled.ToString();
|
||||
_interval = job.Interval.ToString();
|
||||
_frequency = job.Frequency;
|
||||
_startDate = Utilities.UtcAsLocalDate(job.StartDate);
|
||||
_startTime = Utilities.UtcAsLocalDateTime(job.StartDate);
|
||||
_endDate = Utilities.UtcAsLocalDate(job.EndDate);
|
||||
_endTime = Utilities.UtcAsLocalDateTime(job.EndDate);
|
||||
_startDate = UtcToLocal(job.StartDate);
|
||||
_startTime = UtcToLocal(job.StartDate);
|
||||
_endDate = UtcToLocal(job.EndDate);
|
||||
_endTime = UtcToLocal(job.EndDate);
|
||||
_retentionHistory = job.RetentionHistory.ToString();
|
||||
_nextDate = Utilities.UtcAsLocalDate(job.NextExecution);
|
||||
_nextTime = Utilities.UtcAsLocalDateTime(job.NextExecution);
|
||||
_nextDate = UtcToLocal(job.NextExecution);
|
||||
_nextTime = UtcToLocal(job.NextExecution);
|
||||
createdby = job.CreatedBy;
|
||||
createdon = job.CreatedOn;
|
||||
modifiedby = job.ModifiedBy;
|
||||
@ -176,10 +176,10 @@
|
||||
{
|
||||
job.Interval = int.Parse(_interval);
|
||||
}
|
||||
job.StartDate = Utilities.LocalDateAndTimeAsUtc(_startDate, _startTime);
|
||||
job.EndDate = Utilities.LocalDateAndTimeAsUtc(_endDate, _endTime);
|
||||
job.StartDate = LocalToUtc(_startDate.Value.Date.Add(_startTime.Value.TimeOfDay));
|
||||
job.EndDate = LocalToUtc(_endDate.Value.Date.Add(_endTime.Value.TimeOfDay));
|
||||
job.RetentionHistory = int.Parse(_retentionHistory);
|
||||
job.NextExecution = Utilities.LocalDateAndTimeAsUtc(_nextDate, _nextTime);
|
||||
job.NextExecution = LocalToUtc(_nextDate.Value.Date.Add(_nextTime.Value.TimeOfDay));
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ else
|
||||
<td>@context.Name</td>
|
||||
<td>@DisplayStatus(context.IsEnabled, context.IsExecuting)</td>
|
||||
<td>@DisplayFrequency(context.Interval, context.Frequency)</td>
|
||||
<td>@context.NextExecution?.ToLocalTime()</td>
|
||||
<td>@UtcToLocal(context.NextExecution)</td>
|
||||
<td>
|
||||
@if (context.IsStarted)
|
||||
{
|
||||
|
@ -23,8 +23,8 @@ else
|
||||
<Row>
|
||||
<td>@context.Job.Name</td>
|
||||
<td>@DisplayStatus(context.Job.IsExecuting, context.Succeeded)</td>
|
||||
<td>@context.StartDate</td>
|
||||
<td>@context.FinishDate</td>
|
||||
<td>@UtcToLocal(context.StartDate)</td>
|
||||
<td>@UtcToLocal(context.FinishDate)</td>
|
||||
</Row>
|
||||
<Detail>
|
||||
<td colspan="4">@((MarkupString)context.Notes)</td>
|
||||
|
@ -141,7 +141,7 @@
|
||||
var log = await LogService.GetLogAsync(_logId);
|
||||
if (log != null)
|
||||
{
|
||||
_logDate = log.LogDate.ToString(CultureInfo.CurrentCulture);
|
||||
_logDate = UtcToLocal(log.LogDate).Value.ToString(CultureInfo.CurrentCulture);
|
||||
_level = log.Level;
|
||||
_feature = log.Feature;
|
||||
_function = log.Function;
|
||||
|
@ -64,7 +64,7 @@ else
|
||||
</Header>
|
||||
<Row>
|
||||
<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Text="Details" Parameters="@($"/{context.LogId}")" ReturnUrl="@(NavigateUrl(PageState.Page.Path, AddUrlParameters(_level, _function, _rows, _page)))" ResourceKey="LogDetails" /></td>
|
||||
<td class="@GetClass(context.Function)">@context.LogDate</td>
|
||||
<td class="@GetClass(context.Function)">@UtcToLocal(context.LogDate)</td>
|
||||
<td class="@GetClass(context.Function)">@context.Level</td>
|
||||
<td class="@GetClass(context.Function)">@context.Feature</td>
|
||||
<td class="@GetClass(context.Function)">@context.Function</td>
|
||||
|
@ -97,6 +97,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<Section Name="ModuleContent" Heading="Content" ResourceKey="ModuleContent">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="header" HelpText="Optionally provide content to be injected above the module instance" ResourceKey="Header">Header: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="header" class="form-control" @bind="@_header" rows="3" maxlength="4000"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="footer" HelpText="Optionally provide content to be injected below the module instance" ResourceKey="Footer">Footer: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="footer" class="form-control" @bind="@_footer" rows="3" maxlength="4000"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Permissions" Heading="Permissions" ResourceKey="Permissions">
|
||||
@ -144,6 +161,8 @@
|
||||
private string _pane;
|
||||
private string _containerType;
|
||||
private string _allPages = "false";
|
||||
private string _header = "";
|
||||
private string _footer = "";
|
||||
private string _permissionNames = "";
|
||||
private List<Permission> _permissions = null;
|
||||
private string _pageId;
|
||||
@ -167,37 +186,47 @@
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
SetModuleTitle(Localizer["ModuleSettings.Title"]);
|
||||
|
||||
_title = ModuleState.Title;
|
||||
_moduleSettingsTitle = Localizer["ModuleSettings.Heading"];
|
||||
_pane = ModuleState.Pane;
|
||||
|
||||
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
|
||||
_containerType = ModuleState.ContainerType;
|
||||
_allPages = ModuleState.AllPages.ToString();
|
||||
_permissions = ModuleState.PermissionList;
|
||||
_pageId = ModuleState.PageId.ToString();
|
||||
createdby = ModuleState.CreatedBy;
|
||||
createdon = ModuleState.CreatedOn;
|
||||
modifiedby = ModuleState.ModifiedBy;
|
||||
modifiedon = ModuleState.ModifiedOn;
|
||||
_effectivedate = Utilities.UtcAsLocalDate(ModuleState.EffectiveDate);
|
||||
_expirydate = Utilities.UtcAsLocalDate(ModuleState.ExpiryDate);
|
||||
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||
|
||||
if (ModuleState.ModuleDefinition != null)
|
||||
{
|
||||
_module = ModuleState.ModuleDefinition.Name;
|
||||
_permissionNames = ModuleState.ModuleDefinition?.PermissionNames;
|
||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
|
||||
if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
|
||||
_pageId = pagemodule.PageId.ToString();
|
||||
_title = pagemodule.Title;
|
||||
_pane = pagemodule.Pane;
|
||||
_containerType = pagemodule.ContainerType;
|
||||
if (string.IsNullOrEmpty(_containerType))
|
||||
{
|
||||
_containerType = (!string.IsNullOrEmpty(PageState.Page.DefaultContainerType)) ? PageState.Page.DefaultContainerType : PageState.Site.DefaultContainerType;
|
||||
}
|
||||
_header = pagemodule.Header;
|
||||
_footer = pagemodule.Footer;
|
||||
_effectivedate = Utilities.UtcAsLocalDate(pagemodule.EffectiveDate);
|
||||
_expirydate = Utilities.UtcAsLocalDate(pagemodule.ExpiryDate);
|
||||
|
||||
_allPages = pagemodule.Module.AllPages.ToString();
|
||||
createdby = pagemodule.Module.CreatedBy;
|
||||
createdon = pagemodule.Module.CreatedOn;
|
||||
modifiedby = pagemodule.Module.ModifiedBy;
|
||||
modifiedon = pagemodule.Module.ModifiedOn;
|
||||
_permissions = pagemodule.Module.PermissionList;
|
||||
|
||||
if (pagemodule.Module.ModuleDefinition != null)
|
||||
{
|
||||
_module = pagemodule.Module.ModuleDefinition.Name;
|
||||
_permissionNames = pagemodule.Module.ModuleDefinition?.PermissionNames;
|
||||
|
||||
if (!string.IsNullOrEmpty(pagemodule.Module.ModuleDefinition.SettingsType))
|
||||
{
|
||||
// module settings type explicitly declared in IModule interface
|
||||
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
|
||||
_moduleSettingsType = Type.GetType(pagemodule.Module.ModuleDefinition.SettingsType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
|
||||
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
|
||||
_moduleSettingsType = Type.GetType(pagemodule.Module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
|
||||
}
|
||||
if (_moduleSettingsType != null)
|
||||
{
|
||||
@ -218,7 +247,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
|
||||
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], pagemodule.Module.ModuleDefinitionName), MessageType.Error);
|
||||
}
|
||||
|
||||
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
||||
@ -270,10 +299,12 @@
|
||||
{
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
pagemodule.Header = _header;
|
||||
pagemodule.Footer = _footer;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
|
||||
var module = ModuleState;
|
||||
var module = await ModuleService.GetModuleAsync(ModuleState.ModuleId);
|
||||
module.AllPages = bool.Parse(_allPages);
|
||||
module.PageModuleId = ModuleState.PageModuleId;
|
||||
module.PermissionList = _permissionGrid.GetPermissionList();
|
||||
|
@ -30,16 +30,16 @@
|
||||
<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))" required>
|
||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||
@foreach (Page page in _pages)
|
||||
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||
@foreach (Page page in _pages)
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList) && page.PageId != _pageId)
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList) && page.PageId != _pageId)
|
||||
{
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
}
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
@ -217,6 +217,9 @@
|
||||
</div>
|
||||
</Section>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
</TabPanel>
|
||||
@ -225,15 +228,28 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<PermissionGrid EntityName="@EntityNames.Page" PermissionList="@_permissions" @ref="_permissionGrid" />
|
||||
</div>
|
||||
<br /><br />
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="updatemodulepermissions" HelpText="Specify if changes made to page permissions should be propagated to the modules on this page" ResourceKey="UpdateModulePermissions">Update Module Permissions? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="updatemodulepermissions" class="form-select" @bind="@_updatemodulepermissions" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
</TabPanel>
|
||||
<TabPanel Name="PageModules" Heading="Modules" ResourceKey="PageModules">
|
||||
<Pager Items="_pageModules">
|
||||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@Localizer["ModuleTitle"]</th>
|
||||
<th>@Localizer["ModuleDefinition"]</th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@Localizer["ModuleTitle"]</th>
|
||||
<th>@Localizer["ModuleDefinition"]</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Settings" Text="Edit" Path="@_actualpath" ModuleId="@context.ModuleId" Security="SecurityAccessLevel.Edit" PermissionList="@context.PermissionList" ResourceKey="ModuleSettings" /></td>
|
||||
@ -247,8 +263,10 @@
|
||||
{
|
||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||
@_themeSettingsComponent
|
||||
<br />
|
||||
<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>
|
||||
<br />
|
||||
}
|
||||
</TabStrip>
|
||||
}
|
||||
@ -299,19 +317,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<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>
|
||||
@if (_themeSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||
@_themeSettingsComponent
|
||||
<br />
|
||||
<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>
|
||||
<br />
|
||||
}
|
||||
</TabStrip>
|
||||
}
|
||||
<br />
|
||||
<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>
|
||||
}
|
||||
|
||||
@ -348,6 +368,7 @@
|
||||
private string _bodycontent;
|
||||
private List<Permission> _permissions = null;
|
||||
private PermissionGrid _permissionGrid;
|
||||
private string _updatemodulepermissions;
|
||||
private List<Module> _pageModules;
|
||||
private string _createdby;
|
||||
private DateTime _createdon;
|
||||
@ -436,6 +457,7 @@
|
||||
|
||||
// permissions
|
||||
_permissions = _page.PermissionList;
|
||||
_updatemodulepermissions = "True";
|
||||
|
||||
// page modules
|
||||
var modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
|
||||
@ -651,6 +673,7 @@
|
||||
if (_page.UserId == null)
|
||||
{
|
||||
_page.PermissionList = _permissionGrid.GetPermissionList();
|
||||
_page.UpdateModulePermissions = bool.Parse(_updatemodulepermissions);
|
||||
}
|
||||
|
||||
_page = await PageService.UpdatePageAsync(_page);
|
||||
|
@ -3,6 +3,7 @@
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
@inject ITimeZoneService TimeZoneService
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
@inject ISettingService SettingService
|
||||
@ -56,6 +57,18 @@
|
||||
<input id="displayname" class="form-control" @bind="@_displayname" maxlength="50" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="timezone" HelpText="Your time zone" ResourceKey="TimeZone">Time Zone:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="timezone" class="form-select" @bind="@_timezoneid">
|
||||
<option value=""><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var timezone in _timezones)
|
||||
{
|
||||
<option value="@timezone.Id">@timezone.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-primary" @onclick="Register">@Localizer["Register"]</button>
|
||||
@ -77,6 +90,7 @@ else
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Models.TimeZone> _timezones;
|
||||
private string _passwordrequirements;
|
||||
private string _username = string.Empty;
|
||||
private ElementReference form;
|
||||
@ -87,6 +101,7 @@ else
|
||||
private string _confirm = string.Empty;
|
||||
private string _email = string.Empty;
|
||||
private string _displayname = string.Empty;
|
||||
private string _timezoneid = string.Empty;
|
||||
private bool _userCreated = false;
|
||||
private bool _allowsitelogin = true;
|
||||
|
||||
@ -96,6 +111,8 @@ else
|
||||
{
|
||||
_passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId);
|
||||
_allowsitelogin = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:AllowSiteLogin", "true"));
|
||||
_timezones = await TimeZoneService.GetTimeZonesAsync();
|
||||
_timezoneid = PageState.Site.TimeZoneId;
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
@ -124,6 +141,7 @@ else
|
||||
Password = _password,
|
||||
Email = _email,
|
||||
DisplayName = (_displayname == string.Empty ? _username : _displayname),
|
||||
TimeZoneId = _timezoneid,
|
||||
PhotoFileId = null
|
||||
};
|
||||
user = await UserService.AddUserAsync(user);
|
||||
|
@ -10,6 +10,7 @@
|
||||
@inject IAliasService AliasService
|
||||
@inject IThemeService ThemeService
|
||||
@inject ISettingService SettingService
|
||||
@inject ITimeZoneService TimeZoneService
|
||||
@inject IServiceProvider ServiceProvider
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
@inject INotificationService NotificationService
|
||||
@ -41,6 +42,18 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="timezone" HelpText="Your time zone" ResourceKey="TimeZone">Time Zone:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="timezone" class="form-select" @bind="@_timezoneid">
|
||||
<option value=""><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var timezone in _timezones)
|
||||
{
|
||||
<option value="@timezone.Id">@timezone.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Deleted? </Label>
|
||||
<div class="col-sm-9">
|
||||
@ -133,7 +146,7 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@_logofileid" Filter="@_imageFiles" @ref="_logofilemanager" />
|
||||
<FileManager FileId="@_logofileid" Filter="@_imagefiles" @ref="_logofilemanager" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
@ -416,9 +429,11 @@
|
||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||
private List<Page> _pages;
|
||||
private List<Models.TimeZone> _timezones;
|
||||
|
||||
private string _name = string.Empty;
|
||||
private string _homepageid = "-";
|
||||
private string _timezoneid = string.Empty;
|
||||
private string _isdeleted;
|
||||
private string _sitemap = "";
|
||||
private string _siteguid = "";
|
||||
@ -435,7 +450,7 @@
|
||||
|
||||
private Dictionary<string, string> _textEditors = new Dictionary<string, string>();
|
||||
private string _textEditor = "";
|
||||
private string _imageFiles = string.Empty;
|
||||
private string _imagefiles = string.Empty;
|
||||
|
||||
private string _headcontent = string.Empty;
|
||||
private string _bodycontent = string.Empty;
|
||||
@ -493,11 +508,13 @@
|
||||
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||
if (site != null)
|
||||
{
|
||||
_timezones = await TimeZoneService.GetTimeZonesAsync();
|
||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||
|
||||
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||
|
||||
_name = site.Name;
|
||||
_timezoneid = site.TimeZoneId;
|
||||
if (site.HomePageId != null)
|
||||
{
|
||||
_homepageid = site.HomePageId.Value.ToString();
|
||||
@ -531,8 +548,8 @@
|
||||
_textEditors.Add(textEditor.Name, Utilities.GetFullTypeName(textEditor.GetType().AssemblyQualifiedName));
|
||||
}
|
||||
_textEditor = SettingService.GetSetting(settings, "TextEditor", Constants.DefaultTextEditor);
|
||||
_imageFiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
|
||||
_imageFiles = (string.IsNullOrEmpty(_imageFiles)) ? Constants.ImageFiles : _imageFiles;
|
||||
_imagefiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
|
||||
_imagefiles = (string.IsNullOrEmpty(_imagefiles)) ? Constants.ImageFiles : _imagefiles;
|
||||
|
||||
// page content
|
||||
_headcontent = site.HeadContent;
|
||||
@ -650,6 +667,7 @@
|
||||
if (site != null)
|
||||
{
|
||||
site.Name = _name;
|
||||
site.TimeZoneId = _timezoneid;
|
||||
site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null);
|
||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||
|
||||
|
@ -48,7 +48,7 @@ else
|
||||
}
|
||||
</td>
|
||||
<td>@context.Requests</td>
|
||||
<td>@context.RequestedOn</td>
|
||||
<td>@UtcToLocal(context.RequestedOn)</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</TabPanel>
|
||||
|
@ -9,6 +9,7 @@
|
||||
@inject INotificationService NotificationService
|
||||
@inject IFileService FileService
|
||||
@inject IFolderService FolderService
|
||||
@inject ITimeZoneService TimeZoneService
|
||||
@inject IJSRuntime jsRuntime
|
||||
@inject IServiceProvider ServiceProvider
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
@ -16,9 +17,9 @@
|
||||
|
||||
@if (_initialized)
|
||||
{
|
||||
@if (PageState.User != null && photo != null)
|
||||
@if (PageState.User != null && _photo != null)
|
||||
{
|
||||
<img src="@ImageUrl(photofileid, 400, 400)" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||
<img src="@ImageUrl(_photofileid, 400, 400)" alt="@_displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -31,7 +32,7 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="Your username. Note that this field can not be modified." ResourceKey="Username"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@username" readonly />
|
||||
<input id="username" class="form-control" @bind="@_username" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
@ -47,17 +48,17 @@
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="If you are changing your password you must enter it again to confirm it matches" ResourceKey="Confirm"></Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" />
|
||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (allowtwofactor)
|
||||
@if (_allowtwofactor)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="twofactor" HelpText="Indicates if you are using two factor authentication. Two factor authentication requires you to enter a verification code sent via email after you sign in." ResourceKey="TwoFactor"></Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="twofactor" class="form-select" @bind="@twofactor" required>
|
||||
<select id="twofactor" class="form-select" @bind="@_twofactor" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
@ -67,19 +68,31 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="email" class="form-control" @bind="@email" />
|
||||
<input id="email" class="form-control" @bind="@_email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="displayname" HelpText="Your full name" ResourceKey="DisplayName"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="displayname" class="form-control" @bind="@displayname" />
|
||||
<input id="displayname" class="form-control" @bind="@_displayname" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@photofileid.ToString()" HelpText="A photo of yourself" ResourceKey="Photo"></Label>
|
||||
<Label Class="col-sm-3" For="timezone" HelpText="Your time zone" ResourceKey="TimeZone">Time Zone:</Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@photofileid" Filter="@PageState.Site.ImageFiles" ShowFolders="false" ShowFiles="true" UploadMultiple="false" FolderId="@folderid" @ref="filemanager" />
|
||||
<select id="timezone" class="form-select" @bind="@_timezoneid">
|
||||
<option value=""><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var timezone in _timezones)
|
||||
{
|
||||
<option value="@timezone.Id">@timezone.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@_photofileid.ToString()" HelpText="A photo of yourself" ResourceKey="Photo"></Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@_photofileid" Filter="@PageState.Site.ImageFiles" ShowFolders="false" ShowFiles="true" UploadMultiple="false" FolderId="@_folderid" @ref="_filemanager" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -91,17 +104,17 @@
|
||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@foreach (Profile profile in profiles)
|
||||
@foreach (Profile profile in _profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (!p.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
if (p.Category != category)
|
||||
if (p.Category != _category)
|
||||
{
|
||||
<div class="col text-center pb-2">
|
||||
@p.Category
|
||||
</div>
|
||||
category = p.Category;
|
||||
_category = p.Category;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
@ -150,12 +163,12 @@
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<input id="@p.Name" class="form-control" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="@p.Name" class="form-control" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -163,12 +176,12 @@
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<input id="@p.Name" class="form-control" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="@p.Name" class="form-control" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)" />
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,12 +192,12 @@
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -192,12 +205,12 @@
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))"
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
@attributes="@(p.MaxLength > 0 ? new Dictionary<string, object> {{"maxlength", p.MaxLength }} : null)"></textarea>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -220,11 +233,11 @@
|
||||
<option value="from">@Localizer["Items.Sent"]</option>
|
||||
</select>
|
||||
<br />
|
||||
@if (filter == "to")
|
||||
@if (_filter == "to")
|
||||
{
|
||||
@if (notifications.Any())
|
||||
@if (_notifications.Any())
|
||||
{
|
||||
<Pager Items="@notifications">
|
||||
<Pager Items="@_notifications">
|
||||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
@ -260,15 +273,15 @@
|
||||
context.Body = context.Body.Replace("\n", "");
|
||||
context.Body = context.Body.Replace("\r", "");
|
||||
}
|
||||
notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
|
||||
_notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
|
||||
}
|
||||
@if (context.IsRead)
|
||||
{
|
||||
@notificationSummary
|
||||
@_notificationSummary
|
||||
}
|
||||
else
|
||||
{
|
||||
<b>@notificationSummary</b>
|
||||
<b>@_notificationSummary</b>
|
||||
}
|
||||
</td>
|
||||
</Detail>
|
||||
@ -285,9 +298,9 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (notifications.Any())
|
||||
@if (_notifications.Any())
|
||||
{
|
||||
<Pager Items="@notifications">
|
||||
<Pager Items="@_notifications">
|
||||
<Header>
|
||||
<th style="width: 1px;"></th>
|
||||
<th style="width: 1px;"></th>
|
||||
@ -324,15 +337,15 @@
|
||||
context.Body = context.Body.Replace("\n", "");
|
||||
context.Body = context.Body.Replace("\r", "");
|
||||
}
|
||||
notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
|
||||
_notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
|
||||
}
|
||||
@if (context.IsRead)
|
||||
{
|
||||
@notificationSummary
|
||||
@_notificationSummary
|
||||
}
|
||||
else
|
||||
{
|
||||
<b>@notificationSummary</b>
|
||||
<b>@_notificationSummary</b>
|
||||
}
|
||||
</td>
|
||||
</Detail>
|
||||
@ -354,29 +367,32 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Models.TimeZone> _timezones;
|
||||
private bool _initialized = false;
|
||||
private string _passwordrequirements;
|
||||
private string username = string.Empty;
|
||||
private string _username = string.Empty;
|
||||
private string _password = string.Empty;
|
||||
private string _passwordtype = "password";
|
||||
private string _togglepassword = string.Empty;
|
||||
private string confirm = string.Empty;
|
||||
private bool allowtwofactor = false;
|
||||
private string twofactor = "False";
|
||||
private string email = string.Empty;
|
||||
private string displayname = string.Empty;
|
||||
private FileManager filemanager;
|
||||
private int folderid = -1;
|
||||
private int photofileid = -1;
|
||||
private File photo = null;
|
||||
private string _ImageFiles = string.Empty;
|
||||
private List<Profile> profiles;
|
||||
private Dictionary<string, string> userSettings;
|
||||
private string category = string.Empty;
|
||||
private string _confirm = string.Empty;
|
||||
private bool _allowtwofactor = false;
|
||||
private string _twofactor = "False";
|
||||
private string _email = string.Empty;
|
||||
private string _displayname = string.Empty;
|
||||
private FileManager _filemanager;
|
||||
private int _folderid = -1;
|
||||
private string _timezoneid = string.Empty;
|
||||
private int _photofileid = -1;
|
||||
private File _photo = null;
|
||||
private string _imagefiles = string.Empty;
|
||||
|
||||
private string filter = "to";
|
||||
private List<Notification> notifications;
|
||||
private string notificationSummary = string.Empty;
|
||||
private List<Profile> _profiles;
|
||||
private Dictionary<string, string> _userSettings;
|
||||
private string _category = string.Empty;
|
||||
|
||||
private string _filter = "to";
|
||||
private List<Notification> _notifications;
|
||||
private string _notificationSummary = string.Empty;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||
|
||||
@ -386,17 +402,19 @@
|
||||
{
|
||||
_passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId);
|
||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||
allowtwofactor = (SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:TwoFactor", "false") == "true");
|
||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||
_allowtwofactor = (SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:TwoFactor", "false") == "true");
|
||||
_profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||
_timezones = await TimeZoneService.GetTimeZonesAsync();
|
||||
|
||||
if (PageState.User != null)
|
||||
{
|
||||
username = PageState.User.Username;
|
||||
twofactor = PageState.User.TwoFactorRequired.ToString();
|
||||
email = PageState.User.Email;
|
||||
displayname = PageState.User.DisplayName;
|
||||
_username = PageState.User.Username;
|
||||
_twofactor = PageState.User.TwoFactorRequired.ToString();
|
||||
_email = PageState.User.Email;
|
||||
_displayname = PageState.User.DisplayName;
|
||||
_timezoneid = PageState.User.TimeZoneId;
|
||||
|
||||
if (string.IsNullOrEmpty(email))
|
||||
if (string.IsNullOrEmpty(_email))
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.User.NoEmail"], MessageType.Warning);
|
||||
}
|
||||
@ -405,24 +423,24 @@
|
||||
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
||||
if (folder != null)
|
||||
{
|
||||
folderid = folder.FolderId;
|
||||
_folderid = folder.FolderId;
|
||||
}
|
||||
|
||||
if (PageState.User.PhotoFileId != null)
|
||||
{
|
||||
photofileid = PageState.User.PhotoFileId.Value;
|
||||
photo = await FileService.GetFileAsync(photofileid);
|
||||
_photofileid = PageState.User.PhotoFileId.Value;
|
||||
_photo = await FileService.GetFileAsync(_photofileid);
|
||||
}
|
||||
else
|
||||
{
|
||||
photofileid = -1;
|
||||
photo = null;
|
||||
_photofileid = -1;
|
||||
_photo = null;
|
||||
}
|
||||
|
||||
userSettings = PageState.User.Settings;
|
||||
_userSettings = PageState.User.Settings;
|
||||
var sitesettings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
||||
_ImageFiles = SettingService.GetSetting(userSettings, "ImageFiles", Constants.ImageFiles);
|
||||
_ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
|
||||
_imagefiles = SettingService.GetSetting(_userSettings, "ImageFiles", Constants.ImageFiles);
|
||||
_imagefiles = (string.IsNullOrEmpty(_imagefiles)) ? Constants.ImageFiles : _imagefiles;
|
||||
|
||||
await LoadNotificationsAsync();
|
||||
|
||||
@ -442,13 +460,13 @@
|
||||
|
||||
private async Task LoadNotificationsAsync()
|
||||
{
|
||||
notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
|
||||
notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
|
||||
_notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, _filter, PageState.User.UserId);
|
||||
_notifications = _notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
|
||||
}
|
||||
|
||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||
{
|
||||
string value = SettingService.GetSetting(userSettings, SettingName, DefaultValue);
|
||||
string value = SettingService.GetSetting(_userSettings, SettingName, DefaultValue);
|
||||
if (value.Contains("]"))
|
||||
{
|
||||
value = value.Substring(value.IndexOf("]") + 1);
|
||||
@ -460,38 +478,39 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
if (username != string.Empty && email != string.Empty)
|
||||
if (_username != string.Empty && _email != string.Empty)
|
||||
{
|
||||
if (_password == confirm)
|
||||
if (_password == _confirm)
|
||||
{
|
||||
if (ValidateProfiles())
|
||||
{
|
||||
var user = PageState.User;
|
||||
user.Username = username;
|
||||
user.Username = _username;
|
||||
user.Password = _password;
|
||||
user.TwoFactorRequired = bool.Parse(twofactor);
|
||||
user.Email = email;
|
||||
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
||||
user.PhotoFileId = filemanager.GetFileId();
|
||||
user.TwoFactorRequired = bool.Parse(_twofactor);
|
||||
user.Email = _email;
|
||||
user.DisplayName = (_displayname == string.Empty ? _username : _displayname);
|
||||
user.TimeZoneId = _timezoneid;
|
||||
user.PhotoFileId = _filemanager.GetFileId();
|
||||
if (user.PhotoFileId == -1)
|
||||
{
|
||||
user.PhotoFileId = null;
|
||||
}
|
||||
if (user.PhotoFileId != null)
|
||||
{
|
||||
photofileid = user.PhotoFileId.Value;
|
||||
photo = await FileService.GetFileAsync(photofileid);
|
||||
_photofileid = user.PhotoFileId.Value;
|
||||
_photo = await FileService.GetFileAsync(_photofileid);
|
||||
}
|
||||
else
|
||||
{
|
||||
photofileid = -1;
|
||||
photo = null;
|
||||
_photofileid = -1;
|
||||
_photo = null;
|
||||
}
|
||||
|
||||
user = await UserService.UpdateUserAsync(user);
|
||||
if (user != null)
|
||||
{
|
||||
await SettingService.UpdateUserSettingsAsync(userSettings, PageState.User.UserId);
|
||||
await SettingService.UpdateUserSettingsAsync(_userSettings, PageState.User.UserId);
|
||||
await logger.LogInformation("User Profile Saved");
|
||||
|
||||
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||
@ -557,12 +576,12 @@
|
||||
|
||||
private bool ValidateProfiles()
|
||||
{
|
||||
foreach (Profile profile in profiles)
|
||||
foreach (Profile profile in _profiles)
|
||||
{
|
||||
var value = GetProfileValue(profile.Name, string.Empty);
|
||||
if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(profile.DefaultValue))
|
||||
{
|
||||
userSettings = SettingService.SetSetting(userSettings, profile.Name, profile.DefaultValue);
|
||||
_userSettings = SettingService.SetSetting(_userSettings, profile.Name, profile.DefaultValue);
|
||||
}
|
||||
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
@ -594,7 +613,7 @@
|
||||
private void ProfileChanged(ChangeEventArgs e, string SettingName)
|
||||
{
|
||||
var value = (string)e.Value;
|
||||
userSettings = SettingService.SetSetting(userSettings, SettingName, value);
|
||||
_userSettings = SettingService.SetSetting(_userSettings, SettingName, value);
|
||||
}
|
||||
|
||||
private async Task Delete(Notification Notification)
|
||||
@ -624,7 +643,7 @@
|
||||
|
||||
private async void FilterChanged(ChangeEventArgs e)
|
||||
{
|
||||
filter = (string)e.Value;
|
||||
_filter = (string)e.Value;
|
||||
await LoadNotificationsAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
@ -634,7 +653,7 @@
|
||||
try
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
foreach(var Notification in notifications)
|
||||
foreach(var Notification in _notifications)
|
||||
{
|
||||
if (!Notification.IsDeleted)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@
|
||||
@inject IUserService UserService
|
||||
@inject IProfileService ProfileService
|
||||
@inject ISettingService SettingService
|
||||
@inject ITimeZoneService TimeZoneService
|
||||
@inject IStringLocalizer<Add> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
@ -12,7 +13,7 @@
|
||||
{
|
||||
<TabStrip>
|
||||
<TabPanel Name="Identity" ResourceKey="Identity">
|
||||
@if (profiles != null)
|
||||
@if (_profiles != null)
|
||||
{
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@ -33,6 +34,18 @@
|
||||
<input id="displayname" class="form-control" @bind="@_displayname" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="timezone" HelpText="Your time zone" ResourceKey="TimeZone">Time Zone:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="timezone" class="form-select" @bind="@_timezoneid">
|
||||
<option value=""><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var timezone in _timezones)
|
||||
{
|
||||
<option value="@timezone.Id">@timezone.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="notify" HelpText="Indicate if new users should receive an email notification" ResourceKey="Notify">Notify? </Label>
|
||||
<div class="col-sm-9">
|
||||
@ -48,20 +61,20 @@
|
||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@foreach (Profile profile in profiles)
|
||||
@foreach (Profile profile in _profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
if (p.Category != _category)
|
||||
{
|
||||
<div class="col text-center pb-2">
|
||||
<strong>@p.Category</strong>
|
||||
</div>
|
||||
category = p.Category;
|
||||
_category = p.Category;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
<div class="col-sm-9">
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
<div class="col-sm-9">
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
{
|
||||
<select id="@p.Name" class="form-select" @onchange="@(e => ProfileChanged(e, p.Name))">
|
||||
@foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
@ -103,14 +116,16 @@
|
||||
|
||||
|
||||
@code {
|
||||
private List<Models.TimeZone> _timezones;
|
||||
private bool _initialized = false;
|
||||
private string _username = string.Empty;
|
||||
private string _email = string.Empty;
|
||||
private string _displayname = string.Empty;
|
||||
private string _timezoneid = string.Empty;
|
||||
private string _notify = "True";
|
||||
private List<Profile> profiles;
|
||||
private Dictionary<string, string> settings;
|
||||
private string category = string.Empty;
|
||||
private List<Profile> _profiles;
|
||||
private Dictionary<string, string> _settings;
|
||||
private string _category = string.Empty;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||
|
||||
@ -118,8 +133,10 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||
settings = new Dictionary<string, string>();
|
||||
_timezones = await TimeZoneService.GetTimeZonesAsync();
|
||||
_profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||
_settings = new Dictionary<string, string>();
|
||||
_timezoneid = PageState.Site.TimeZoneId;
|
||||
_initialized = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -131,7 +148,7 @@
|
||||
|
||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||
{
|
||||
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||
string value = SettingService.GetSetting(_settings, SettingName, DefaultValue);
|
||||
if (value.Contains("]"))
|
||||
{
|
||||
value = value.Substring(value.IndexOf("]") + 1);
|
||||
@ -153,6 +170,7 @@
|
||||
user.Password = ""; // will be auto generated
|
||||
user.Email = _email;
|
||||
user.DisplayName = string.IsNullOrWhiteSpace(_displayname) ? _username : _displayname;
|
||||
user.TimeZoneId = _timezoneid;
|
||||
user.PhotoFileId = null;
|
||||
user.SuppressNotification = !bool.Parse(_notify);
|
||||
|
||||
@ -160,7 +178,7 @@
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
||||
await SettingService.UpdateUserSettingsAsync(_settings, user.UserId);
|
||||
await logger.LogInformation("User Created {User}", user);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
@ -185,12 +203,12 @@
|
||||
|
||||
private bool ValidateProfiles()
|
||||
{
|
||||
foreach (Profile profile in profiles)
|
||||
foreach (Profile profile in _profiles)
|
||||
{
|
||||
var value = GetProfileValue(profile.Name, string.Empty);
|
||||
if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(profile.DefaultValue))
|
||||
{
|
||||
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
|
||||
_settings = SettingService.SetSetting(_settings, profile.Name, profile.DefaultValue);
|
||||
}
|
||||
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
@ -217,6 +235,6 @@
|
||||
private void ProfileChanged(ChangeEventArgs e, string SettingName)
|
||||
{
|
||||
var value = (string)e.Value;
|
||||
settings = SettingService.SetSetting(settings, SettingName, value);
|
||||
_settings = SettingService.SetSetting(_settings, SettingName, value);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
@inject IProfileService ProfileService
|
||||
@inject ISettingService SettingService
|
||||
@inject IFileService FileService
|
||||
@inject ITimeZoneService TimeZoneService
|
||||
@inject IServiceProvider ServiceProvider
|
||||
@inject IStringLocalizer<Edit> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
@ -19,7 +20,7 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="The unique username for a user. Note that this field can not be modified." ResourceKey="Username"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@username" readonly />
|
||||
<input id="username" class="form-control" @bind="@_username" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
@ -35,7 +36,7 @@
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" />
|
||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -43,13 +44,25 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="The email address where the user will receive notifications" ResourceKey="Email"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="email" class="form-control" @bind="@email" />
|
||||
<input id="email" class="form-control" @bind="@_email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="displayname" class="form-control" @bind="@displayname" />
|
||||
<input id="displayname" class="form-control" @bind="@_displayname" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="timezone" HelpText="Your time zone" ResourceKey="TimeZone">Time Zone:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="timezone" class="form-select" @bind="@_timezoneid">
|
||||
<option value=""><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var timezone in _timezones)
|
||||
{
|
||||
<option value="@timezone.Id">@timezone.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
@ -57,7 +70,7 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isdeleted" HelpText="Indicate if the user is active" ResourceKey="IsDeleted"></Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="isdeleted" class="form-select" @bind="@isdeleted">
|
||||
<select id="isdeleted" class="form-select" @bind="@_isdeleted">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
@ -67,13 +80,13 @@
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="lastlogin" HelpText="The date and time when the user last signed in" ResourceKey="LastLogin"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="lastlogin" class="form-control" @bind="@lastlogin" readonly />
|
||||
<input id="lastlogin" class="form-control" @bind="@_lastlogin" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="lastipaddress" HelpText="The IP Address of the user recorded during their last login" ResourceKey="LastIPAddress"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="lastipaddress" class="form-control" @bind="@lastipaddress" readonly />
|
||||
<input id="lastipaddress" class="form-control" @bind="@_lastipaddress" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -81,15 +94,15 @@
|
||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@foreach (Profile profile in profiles)
|
||||
@foreach (Profile profile in _profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
if (p.Category != _category)
|
||||
{
|
||||
<div class="col text-center pb-2">
|
||||
<strong>@p.Category</strong>
|
||||
</div>
|
||||
category = p.Category;
|
||||
_category = p.Category;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
@ -128,47 +141,49 @@
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveUser">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) && PageState.Runtime != Shared.Runtime.Hybrid && !ishost)
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) && PageState.Runtime != Shared.Runtime.Hybrid && !_ishost)
|
||||
{
|
||||
<button type="button" class="btn btn-primary ms-1" @onclick="ImpersonateUser">@Localizer["Impersonate"]</button>
|
||||
}
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && isdeleted == "True")
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _isdeleted == "True")
|
||||
{
|
||||
<ActionDialog Header="Delete User" Message="Are You Sure You Wish To Permanently Delete This User?" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteUser())" ResourceKey="DeleteUser" />
|
||||
}
|
||||
<br /><br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Models.TimeZone> _timezones;
|
||||
private bool _initialized = false;
|
||||
private string _passwordrequirements;
|
||||
private int userid;
|
||||
private string username = string.Empty;
|
||||
private int _userid;
|
||||
private string _username = string.Empty;
|
||||
private string _password = string.Empty;
|
||||
private string _passwordtype = "password";
|
||||
private string _togglepassword = string.Empty;
|
||||
private string confirm = string.Empty;
|
||||
private string email = string.Empty;
|
||||
private string displayname = string.Empty;
|
||||
private string isdeleted;
|
||||
private string lastlogin;
|
||||
private string lastipaddress;
|
||||
private bool ishost = false;
|
||||
private string _confirm = string.Empty;
|
||||
private string _email = string.Empty;
|
||||
private string _displayname = string.Empty;
|
||||
private string _timezoneid = string.Empty;
|
||||
private string _isdeleted;
|
||||
private string _lastlogin;
|
||||
private string _lastipaddress;
|
||||
private bool _ishost = false;
|
||||
|
||||
private List<Profile> profiles;
|
||||
private Dictionary<string, string> userSettings;
|
||||
private string category = string.Empty;
|
||||
private List<Profile> _profiles;
|
||||
private Dictionary<string, string> _settings;
|
||||
private string _category = string.Empty;
|
||||
|
||||
private string createdby;
|
||||
private DateTime createdon;
|
||||
private string modifiedby;
|
||||
private DateTime modifiedon;
|
||||
private string deletedby;
|
||||
private DateTime? deletedon;
|
||||
private string _createdby;
|
||||
private DateTime _createdon;
|
||||
private string _modifiedby;
|
||||
private DateTime _modifiedon;
|
||||
private string _deletedby;
|
||||
private DateTime? _deletedon;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||
|
||||
@ -178,29 +193,31 @@
|
||||
{
|
||||
_passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId);
|
||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||
profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
||||
_profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
||||
_timezones = await TimeZoneService.GetTimeZonesAsync();
|
||||
|
||||
if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int UserId))
|
||||
{
|
||||
userid = UserId;
|
||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||
_userid = UserId;
|
||||
var user = await UserService.GetUserAsync(_userid, PageState.Site.SiteId);
|
||||
if (user != null)
|
||||
{
|
||||
username = user.Username;
|
||||
email = user.Email;
|
||||
displayname = user.DisplayName;
|
||||
isdeleted = user.IsDeleted.ToString();
|
||||
lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", user.LastLoginOn);
|
||||
lastipaddress = user.LastIPAddress;
|
||||
ishost = UserSecurity.ContainsRole(user.Roles, RoleNames.Host);
|
||||
_username = user.Username;
|
||||
_email = user.Email;
|
||||
_displayname = user.DisplayName;
|
||||
_timezoneid = PageState.User.TimeZoneId;
|
||||
_isdeleted = user.IsDeleted.ToString();
|
||||
_lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", UtcToLocal(user.LastLoginOn));
|
||||
_lastipaddress = user.LastIPAddress;
|
||||
_ishost = UserSecurity.ContainsRole(user.Roles, RoleNames.Host);
|
||||
|
||||
userSettings = user.Settings;
|
||||
createdby = user.CreatedBy;
|
||||
createdon = user.CreatedOn;
|
||||
modifiedby = user.ModifiedBy;
|
||||
modifiedon = user.ModifiedOn;
|
||||
deletedby = user.DeletedBy;
|
||||
deletedon = user.DeletedOn;
|
||||
_settings = user.Settings;
|
||||
_createdby = user.CreatedBy;
|
||||
_createdon = user.CreatedOn;
|
||||
_modifiedby = user.ModifiedBy;
|
||||
_modifiedon = user.ModifiedOn;
|
||||
_deletedby = user.DeletedBy;
|
||||
_deletedon = user.DeletedOn;
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,14 +225,14 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
|
||||
await logger.LogError(ex, "Error Loading User {UserId} {Error}", _userid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||
{
|
||||
string value = SettingService.GetSetting(userSettings, SettingName, DefaultValue);
|
||||
string value = SettingService.GetSetting(_settings, SettingName, DefaultValue);
|
||||
if (value.Contains("]"))
|
||||
{
|
||||
value = value.Substring(value.IndexOf("]") + 1);
|
||||
@ -227,27 +244,28 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
if (username != string.Empty && email != string.Empty)
|
||||
if (_username != string.Empty && _email != string.Empty)
|
||||
{
|
||||
if (_password == confirm)
|
||||
if (_password == _confirm)
|
||||
{
|
||||
if (ValidateProfiles())
|
||||
{
|
||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||
var user = await UserService.GetUserAsync(_userid, PageState.Site.SiteId);
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = username;
|
||||
user.Username = _username;
|
||||
user.Password = _password;
|
||||
user.Email = email;
|
||||
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
||||
user.Email = _email;
|
||||
user.DisplayName = string.IsNullOrWhiteSpace(_displayname) ? _username : _displayname;
|
||||
user.TimeZoneId = _timezoneid;
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
||||
user.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||
}
|
||||
|
||||
user = await UserService.UpdateUserAsync(user);
|
||||
if (user != null)
|
||||
{
|
||||
await SettingService.UpdateUserSettingsAsync(userSettings, user.UserId);
|
||||
await SettingService.UpdateUserSettingsAsync(_settings, user.UserId);
|
||||
await logger.LogInformation("User Saved {User}", user);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
@ -269,7 +287,7 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving User {Username} {Email} {Error}", username, email, ex.Message);
|
||||
await logger.LogError(ex, "Error Saving User {Username} {Email} {Error}", _username, _email, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
@ -278,17 +296,17 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
await logger.LogInformation(LogFunction.Security, "User {Username} Impersonated By Administrator {Administrator}", username, PageState.User.Username);
|
||||
await logger.LogInformation(LogFunction.Security, "User {Username} Impersonated By Administrator {Administrator}", _username, PageState.User.Username);
|
||||
|
||||
// post back to the server so that the cookies are set correctly
|
||||
var interop = new Interop(JSRuntime);
|
||||
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = username, returnurl = PageState.Alias.Path };
|
||||
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, returnurl = PageState.Alias.Path };
|
||||
string url = Utilities.TenantUrl(PageState.Alias, "/pages/impersonate/");
|
||||
await interop.SubmitForm(url, fields);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Impersonating User {Username} {Error}", username, ex.Message);
|
||||
await logger.LogError(ex, "Error Impersonating User {Username} {Error}", _username, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.Impersonate"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
@ -297,9 +315,9 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && userid != PageState.User.UserId)
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _userid != PageState.User.UserId)
|
||||
{
|
||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||
var user = await UserService.GetUserAsync(_userid, PageState.Site.SiteId);
|
||||
await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId);
|
||||
await logger.LogInformation("User Permanently Deleted {User}", user);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
@ -307,19 +325,19 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Permanently Deleting User {UserId} {Error}", userid, ex.Message);
|
||||
await logger.LogError(ex, "Error Permanently Deleting User {UserId} {Error}", _userid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.DeleteUser"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ValidateProfiles()
|
||||
{
|
||||
foreach (Profile profile in profiles)
|
||||
foreach (Profile profile in _profiles)
|
||||
{
|
||||
var value = GetProfileValue(profile.Name, string.Empty);
|
||||
if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(profile.DefaultValue))
|
||||
{
|
||||
userSettings = SettingService.SetSetting(userSettings, profile.Name, profile.DefaultValue);
|
||||
_settings = SettingService.SetSetting(_settings, profile.Name, profile.DefaultValue);
|
||||
}
|
||||
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
@ -346,7 +364,7 @@
|
||||
private void ProfileChanged(ChangeEventArgs e, string SettingName)
|
||||
{
|
||||
var value = (string)e.Value;
|
||||
userSettings = SettingService.SetSetting(userSettings, SettingName, value);
|
||||
_settings = SettingService.SetSetting(_settings, SettingName, value);
|
||||
}
|
||||
|
||||
private void TogglePassword()
|
||||
|
@ -43,7 +43,7 @@ else
|
||||
<td>@context.User.Username</td>
|
||||
<td>@context.User.DisplayName</td>
|
||||
<td>@((MarkupString)string.Format("<a href=\"mailto:{0}\">{1}</a>", @context.User.Email, @context.User.Email))</td>
|
||||
<td>@((context.User.LastLoginOn != DateTime.MinValue) ? string.Format("{0:dd-MMM-yyyy HH:mm:ss}", context.User.LastLoginOn) : "")</td>
|
||||
<td>@((context.User.LastLoginOn != DateTime.MinValue) ? string.Format("{0:dd-MMM-yyyy HH:mm:ss}", UtcToLocal(context.User.LastLoginOn)) : "")</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</TabPanel>
|
||||
|
@ -101,8 +101,8 @@
|
||||
_url = visitor.Url;
|
||||
_referrer = visitor.Referrer;
|
||||
_visits = visitor.Visits.ToString();
|
||||
_visited = visitor.VisitedOn.ToString(CultureInfo.CurrentCulture);
|
||||
_created = visitor.CreatedOn.ToString(CultureInfo.CurrentCulture);
|
||||
_visited = UtcToLocal(visitor.VisitedOn).Value.ToString(CultureInfo.CurrentCulture);
|
||||
_created = UtcToLocal(visitor.CreatedOn).Value.ToString(CultureInfo.CurrentCulture);
|
||||
|
||||
if (visitor.UserId != null)
|
||||
{
|
||||
|
@ -53,8 +53,8 @@ else
|
||||
</td>
|
||||
<td>@context.Language</td>
|
||||
<td>@context.Visits</td>
|
||||
<td>@context.VisitedOn</td>
|
||||
<td>@context.CreatedOn</td>
|
||||
<td>@UtcToLocal(context.VisitedOn)</td>
|
||||
<td>@UtcToLocal(context.CreatedOn)</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</TabPanel>
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
if (CreatedOn != null)
|
||||
{
|
||||
_text += $" {Localizer["On"]} <b>{CreatedOn.Value.ToString(DateTimeFormat)}</b>";
|
||||
_text += $" {Localizer["On"]} <b>{UtcToLocal(CreatedOn).Value.ToString(DateTimeFormat)}</ b >";
|
||||
}
|
||||
|
||||
_text += "</p>";
|
||||
@ -69,7 +69,7 @@
|
||||
|
||||
if (ModifiedOn != null)
|
||||
{
|
||||
_text += $" {Localizer["On"]} <b>{ModifiedOn.Value.ToString(DateTimeFormat)}</b>";
|
||||
_text += $" {Localizer["On"]} <b>{UtcToLocal(ModifiedOn).Value.ToString(DateTimeFormat)}</ b >";
|
||||
}
|
||||
|
||||
_text += "</p>";
|
||||
@ -86,7 +86,7 @@
|
||||
|
||||
if (DeletedOn != null)
|
||||
{
|
||||
_text += $" {Localizer["On"]} <b>{DeletedOn.Value.ToString(DateTimeFormat)}</b>";
|
||||
_text += $" {Localizer["On"]} <b>{UtcToLocal(DeletedOn).Value.ToString(DateTimeFormat)}</ b >";
|
||||
}
|
||||
|
||||
_text += "</p>";
|
||||
|
@ -487,6 +487,35 @@ namespace Oqtane.Modules
|
||||
return content;
|
||||
}
|
||||
|
||||
// date methods
|
||||
public DateTime? UtcToLocal(DateTime? datetime)
|
||||
{
|
||||
TimeZoneInfo timezone = null;
|
||||
if (PageState.User != null && !string.IsNullOrEmpty(PageState.User.TimeZoneId))
|
||||
{
|
||||
timezone = TimeZoneInfo.FindSystemTimeZoneById(PageState.User.TimeZoneId);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(PageState.Site.TimeZoneId))
|
||||
{
|
||||
timezone = TimeZoneInfo.FindSystemTimeZoneById(PageState.Site.TimeZoneId);
|
||||
}
|
||||
return Utilities.UtcAsLocalDateTime(datetime, timezone);
|
||||
}
|
||||
|
||||
public DateTime? LocalToUtc(DateTime? datetime)
|
||||
{
|
||||
TimeZoneInfo timezone = null;
|
||||
if (PageState.User != null && !string.IsNullOrEmpty(PageState.User.TimeZoneId))
|
||||
{
|
||||
timezone = TimeZoneInfo.FindSystemTimeZoneById(PageState.User.TimeZoneId);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(PageState.Site.TimeZoneId))
|
||||
{
|
||||
timezone = TimeZoneInfo.FindSystemTimeZoneById(PageState.Site.TimeZoneId);
|
||||
}
|
||||
return Utilities.LocalDateAndTimeAsUtc(datetime, timezone);
|
||||
}
|
||||
|
||||
// logging methods
|
||||
public async Task Log(Alias alias, LogLevel level, string function, Exception exception, string message, params object[] args)
|
||||
{
|
||||
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -12,7 +12,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
@ -22,10 +22,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -135,9 +135,6 @@
|
||||
<data name="Error.Folder.Save" xml:space="preserve">
|
||||
<value>Error Saving Folder</value>
|
||||
</data>
|
||||
<data name="Message.Folder.Files.InvalidDelete" xml:space="preserve">
|
||||
<value>Folder Has Files And Cannot Be Deleted</value>
|
||||
</data>
|
||||
<data name="Message.Folder.Subfolders.InvalidDelete" xml:space="preserve">
|
||||
<value>Folder Has Subfolders And Cannot Be Deleted</value>
|
||||
</data>
|
||||
|
@ -160,12 +160,12 @@
|
||||
<value>Enabled?</value>
|
||||
</data>
|
||||
<data name="Synchronize" xml:space="preserve">
|
||||
<value>Synchronize</value>
|
||||
<value>Check For Updates</value>
|
||||
</data>
|
||||
<data name="Success.Module.Synchronize" xml:space="preserve">
|
||||
<value>Modules Have Been Successfully Synchronized With The Marketplace</value>
|
||||
<value>Module Information Has Been Retrieved From The Marketplace</value>
|
||||
</data>
|
||||
<data name="Error.Module.Synchronize" xml:space="preserve">
|
||||
<value>Error Synchronizing Modules With The Marketplace</value>
|
||||
<value>Error Retrieving Module Information From The Marketplace</value>
|
||||
</data>
|
||||
</root>
|
@ -189,4 +189,19 @@
|
||||
<data name="ModuleSettings.Title" xml:space="preserve">
|
||||
<value>Module Settings</value>
|
||||
</data>
|
||||
<data name="Header.Text" xml:space="preserve">
|
||||
<value>Header:</value>
|
||||
</data>
|
||||
<data name="Header.HelpText" xml:space="preserve">
|
||||
<value>Optionally provide content to be injected above the module instance</value>
|
||||
</data>
|
||||
<data name="Footer.Text" xml:space="preserve">
|
||||
<value>Footer:</value>
|
||||
</data>
|
||||
<data name="Footer.HelpText" xml:space="preserve">
|
||||
<value>Optionally provide content to be injected below the module instance</value>
|
||||
</data>
|
||||
<data name="ModuleContent.Heading" xml:space="preserve">
|
||||
<value>Content</value>
|
||||
</data>
|
||||
</root>
|
@ -303,4 +303,10 @@
|
||||
<data name="PersonalizedUrlPath.HelpText" xml:space="preserve">
|
||||
<value>Provide a url path for your personalized page. Please note that spaces and punctuation will be replaced by a dash.</value>
|
||||
</data>
|
||||
<data name="UpdateModulePermissions.Text" xml:space="preserve">
|
||||
<value>Update Module Permissions?</value>
|
||||
</data>
|
||||
<data name="UpdateModulePermissions.HelpText" xml:space="preserve">
|
||||
<value>Specify if changes made to page permissions should be propagated to the modules on this page</value>
|
||||
</data>
|
||||
</root>
|
@ -180,4 +180,10 @@
|
||||
<data name="Login" xml:space="preserve">
|
||||
<value>Already have account? Login now.</value>
|
||||
</data>
|
||||
<data name="TimeZone.Text" xml:space="preserve">
|
||||
<value>Time Zone:</value>
|
||||
</data>
|
||||
<data name="TimeZone.HelpText" xml:space="preserve">
|
||||
<value>Your time zone</value>
|
||||
</data>
|
||||
</root>
|
@ -447,4 +447,10 @@
|
||||
<data name="Success.SiteMap.CacheEvicted" xml:space="preserve">
|
||||
<value>Site Map Cache Cleared</value>
|
||||
</data>
|
||||
<data name="TimeZone.Text" xml:space="preserve">
|
||||
<value>Time Zone:</value>
|
||||
</data>
|
||||
<data name="TimeZone.HelpText" xml:space="preserve">
|
||||
<value>The default time zone for the site</value>
|
||||
</data>
|
||||
</root>
|
@ -160,12 +160,12 @@
|
||||
<value>Assign</value>
|
||||
</data>
|
||||
<data name="Synchronize" xml:space="preserve">
|
||||
<value>Synchronize</value>
|
||||
<value>Check For Updates</value>
|
||||
</data>
|
||||
<data name="Success.Theme.Synchronize" xml:space="preserve">
|
||||
<value>Themes Have Been Successfully Synchronized With The Marketplace</value>
|
||||
<value>Theme Information Has Been Retrieved From The Marketplace</value>
|
||||
</data>
|
||||
<data name="Error.Theme.Synchronize" xml:space="preserve">
|
||||
<value>Error Synchronizing Themes With The Marketplace</value>
|
||||
<value>Error Retrieving Theme Information From The Marketplace</value>
|
||||
</data>
|
||||
</root>
|
@ -246,4 +246,10 @@
|
||||
<data name="Logout Everywhere" xml:space="preserve">
|
||||
<value>Logout Everywhere</value>
|
||||
</data>
|
||||
<data name="TimeZone.Text" xml:space="preserve">
|
||||
<value>Time Zone:</value>
|
||||
</data>
|
||||
<data name="TimeZone.HelpText" xml:space="preserve">
|
||||
<value>Your time zone</value>
|
||||
</data>
|
||||
</root>
|
@ -156,4 +156,10 @@
|
||||
<data name="Notify.Text" xml:space="preserve">
|
||||
<value>Notify?</value>
|
||||
</data>
|
||||
<data name="TimeZone.Text" xml:space="preserve">
|
||||
<value>Time Zone:</value>
|
||||
</data>
|
||||
<data name="TimeZone.HelpText" xml:space="preserve">
|
||||
<value>The user's time zone</value>
|
||||
</data>
|
||||
</root>
|
@ -210,4 +210,10 @@
|
||||
<data name="Error.User.Impersonate" xml:space="preserve">
|
||||
<value>Unable To Impersonate User</value>
|
||||
</data>
|
||||
<data name="TimeZone.Text" xml:space="preserve">
|
||||
<value>Time Zone:</value>
|
||||
</data>
|
||||
<data name="TimeZone.HelpText" xml:space="preserve">
|
||||
<value>The user's time zone</value>
|
||||
</data>
|
||||
</root>
|
@ -42,14 +42,6 @@ namespace Oqtane.Services
|
||||
return await PutJsonAsync<Folder>($"{ApiUrl}/{folder.FolderId}", folder);
|
||||
}
|
||||
|
||||
public async Task UpdateFolderOrderAsync(int siteId, int folderId, int? parentId)
|
||||
{
|
||||
var parent = parentId == null
|
||||
? string.Empty
|
||||
: parentId.ToString();
|
||||
await PutAsync($"{ApiUrl}/?siteid={siteId}&folderid={folderId}&parentid={parent}");
|
||||
}
|
||||
|
||||
public async Task DeleteFolderAsync(int folderId)
|
||||
{
|
||||
await DeleteAsync($"{ApiUrl}/{folderId}");
|
||||
|
@ -39,15 +39,6 @@ namespace Oqtane.Services
|
||||
/// <returns></returns>
|
||||
Task<Folder> UpdateFolderAsync(Folder folder);
|
||||
|
||||
/// <summary>
|
||||
/// Update the internal Folder-Order within the list of Folders.
|
||||
/// </summary>
|
||||
/// <param name="siteId">Reference to the <see cref="Site"/></param>
|
||||
/// <param name="folderId">Reference to a <see cref="Folder"/> for the security check</param>
|
||||
/// <param name="parentId">Reference to the Parent <see cref="Folder"/> or null - this Folders children will be re-sorted.</param>
|
||||
/// <returns></returns>
|
||||
Task UpdateFolderOrderAsync(int siteId, int folderId, int? parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a <see cref="Folder"/>
|
||||
/// </summary>
|
||||
|
18
Oqtane.Client/Services/Interfaces/ITimeZoneService.cs
Normal file
18
Oqtane.Client/Services/Interfaces/ITimeZoneService.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retrieve <see cref="TimeZone"/> entries
|
||||
/// </summary>
|
||||
public interface ITimeZoneService
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the list of time zones
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<TimeZone>> GetTimeZonesAsync();
|
||||
}
|
||||
}
|
22
Oqtane.Client/Services/TimeZoneService.cs
Normal file
22
Oqtane.Client/Services/TimeZoneService.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Oqtane.Documentation;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||
public class TimeZoneService : ServiceBase, ITimeZoneService
|
||||
{
|
||||
public TimeZoneService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||
|
||||
private string Apiurl => CreateApiUrl("TimeZone");
|
||||
|
||||
public async Task<List<TimeZone>> GetTimeZonesAsync()
|
||||
{
|
||||
return await GetJsonAsync<List<TimeZone>>($"{Apiurl}");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,10 @@
|
||||
@namespace Oqtane.UI
|
||||
@inject SiteState SiteState
|
||||
|
||||
@if (PageState.ModuleId == -1)
|
||||
{
|
||||
@((MarkupString)ModuleState.Header)
|
||||
}
|
||||
@if (_comment != null)
|
||||
{
|
||||
@((MarkupString)_comment)
|
||||
@ -13,6 +17,11 @@
|
||||
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, _prerender)" />
|
||||
}
|
||||
}
|
||||
@if (PageState.ModuleId == -1)
|
||||
{
|
||||
@((MarkupString)ModuleState.Footer)
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -10,7 +10,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -10,7 +10,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.5" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -10,7 +10,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
@ -33,7 +33,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -10,7 +10,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
@ -33,7 +33,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<!-- <TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks> -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -14,7 +14,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane.Maui</RootNamespace>
|
||||
@ -30,7 +30,7 @@
|
||||
<ApplicationId>com.oqtane.maui</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>6.1.2</ApplicationDisplayVersion>
|
||||
<ApplicationDisplayVersion>6.1.3</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||
@ -67,14 +67,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.50" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.50" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.50" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.5" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.61" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.61" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.61" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Client</id>
|
||||
<version>6.1.2</version>
|
||||
<version>6.1.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -12,7 +12,7 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Framework</id>
|
||||
<version>6.1.2</version>
|
||||
<version>6.1.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -11,8 +11,8 @@
|
||||
<copyright>.NET Foundation</copyright>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v6.1.2/Oqtane.Framework.6.1.2.Upgrade.zip</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</releaseNotes>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v6.1.3/Oqtane.Framework.6.1.3.Upgrade.zip</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane framework</tags>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Server</id>
|
||||
<version>6.1.2</version>
|
||||
<version>6.1.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -12,7 +12,7 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Shared</id>
|
||||
<version>6.1.2</version>
|
||||
<version>6.1.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -12,7 +12,7 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Updater</id>
|
||||
<version>6.1.2</version>
|
||||
<version>6.1.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -12,7 +12,7 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
|
@ -1 +1 @@
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net9.0\publish\*" -DestinationPath "Oqtane.Framework.6.1.2.Install.zip" -Force
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net9.0\publish\*" -DestinationPath "Oqtane.Framework.6.1.3.Install.zip" -Force
|
||||
|
@ -1 +1 @@
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net9.0\publish\*" -DestinationPath "Oqtane.Framework.6.1.2.Upgrade.zip" -Force
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net9.0\publish\*" -DestinationPath "Oqtane.Framework.6.1.3.Upgrade.zip" -Force
|
||||
|
@ -20,14 +20,16 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
private readonly IFolderRepository _folders;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly IFileRepository _files;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public FolderController(IFolderRepository folders, IUserPermissions userPermissions, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
|
||||
public FolderController(IFolderRepository folders, IUserPermissions userPermissions, IFileRepository files, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
|
||||
{
|
||||
_folders = folders;
|
||||
_userPermissions = userPermissions;
|
||||
_files = files;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
@ -41,7 +43,8 @@ namespace Oqtane.Controllers
|
||||
int SiteId;
|
||||
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
||||
{
|
||||
foreach (Folder folder in _folders.GetFolders(SiteId))
|
||||
var hierarchy = GetFoldersHierarchy(_folders.GetFolders(SiteId).ToList());
|
||||
foreach (Folder folder in hierarchy)
|
||||
{
|
||||
// note that Browse permission is used for this method
|
||||
if (_userPermissions.IsAuthorized(User, PermissionNames.Browse, folder.PermissionList))
|
||||
@ -49,7 +52,6 @@ namespace Oqtane.Controllers
|
||||
folders.Add(folder);
|
||||
}
|
||||
}
|
||||
folders = GetFoldersHierarchy(folders);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -244,34 +246,6 @@ namespace Oqtane.Controllers
|
||||
return folder;
|
||||
}
|
||||
|
||||
// PUT api/<controller>/?siteid=x&folderid=y&parentid=z
|
||||
[HttpPut]
|
||||
[Authorize(Roles = RoleNames.Registered)]
|
||||
public void Put(int siteid, int folderid, int? parentid)
|
||||
{
|
||||
if (siteid == _alias.SiteId && _folders.GetFolder(folderid, false) != null && _userPermissions.IsAuthorized(User, siteid, EntityNames.Folder, folderid, PermissionNames.Edit))
|
||||
{
|
||||
int order = 1;
|
||||
List<Folder> folders = _folders.GetFolders(siteid).ToList();
|
||||
foreach (Folder folder in folders.Where(item => item.ParentId == parentid).OrderBy(item => item.Order))
|
||||
{
|
||||
if (folder.Order != order)
|
||||
{
|
||||
folder.Order = order;
|
||||
_folders.UpdateFolder(folder);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.Folder, folder.FolderId, SyncEventActions.Update);
|
||||
}
|
||||
order += 2;
|
||||
}
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Order Updated {SiteId} {FolderId} {ParentId}", siteid, folderid, parentid);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Update, "Unauthorized Folder Put Attempt {SiteId} {FolderId} {ParentId}", siteid, folderid, parentid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/5
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Roles = RoleNames.Registered)]
|
||||
@ -283,12 +257,20 @@ namespace Oqtane.Controllers
|
||||
var folderPath = _folders.GetFolderPath(folder);
|
||||
if (Directory.Exists(folderPath))
|
||||
{
|
||||
// remove all files from disk (including thumbnails, etc...)
|
||||
foreach (var filePath in Directory.GetFiles(folderPath))
|
||||
{
|
||||
System.IO.File.Delete(filePath);
|
||||
}
|
||||
Directory.Delete(folderPath);
|
||||
}
|
||||
|
||||
// remove files from database
|
||||
foreach (var file in _files.GetFiles(id))
|
||||
{
|
||||
_files.DeleteFile(file.FileId);
|
||||
}
|
||||
|
||||
_folders.DeleteFolder(id);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.Folder, folder.FolderId, SyncEventActions.Delete);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Folder Deleted {FolderId}", id);
|
||||
@ -304,7 +286,6 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
List<Folder> hierarchy = new List<Folder>();
|
||||
Action<List<Folder>, Folder> getPath = null;
|
||||
var folders1 = folders;
|
||||
getPath = (folderList, folder) =>
|
||||
{
|
||||
IEnumerable<Folder> children;
|
||||
@ -312,23 +293,23 @@ namespace Oqtane.Controllers
|
||||
if (folder == null)
|
||||
{
|
||||
level = -1;
|
||||
children = folders1.Where(item => item.ParentId == null);
|
||||
children = folders.Where(item => item.ParentId == null);
|
||||
}
|
||||
else
|
||||
{
|
||||
level = folder.Level;
|
||||
children = folders1.Where(item => item.ParentId == folder.FolderId);
|
||||
children = folders.Where(item => item.ParentId == folder.FolderId);
|
||||
}
|
||||
|
||||
foreach (Folder child in children)
|
||||
{
|
||||
child.Level = level + 1;
|
||||
child.HasChildren = folders1.Any(item => item.ParentId == child.FolderId);
|
||||
child.HasChildren = folders.Any(item => item.ParentId == child.FolderId);
|
||||
hierarchy.Add(child);
|
||||
if (getPath != null) getPath(folderList, child);
|
||||
getPath(folderList, child);
|
||||
}
|
||||
};
|
||||
folders = folders.OrderBy(item => item.Order).ToList();
|
||||
folders = folders.OrderBy(item => item.Name).ToList();
|
||||
getPath(folders, null);
|
||||
|
||||
// add any non-hierarchical items to the end of the list
|
||||
|
@ -76,6 +76,8 @@ namespace Oqtane.Controllers
|
||||
module.ContainerType = pagemodule.ContainerType;
|
||||
module.EffectiveDate = pagemodule.EffectiveDate;
|
||||
module.ExpiryDate = pagemodule.ExpiryDate;
|
||||
module.Header = pagemodule.Header;
|
||||
module.Footer = pagemodule.Footer;
|
||||
|
||||
module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
|
||||
|
||||
|
@ -246,6 +246,10 @@ namespace Oqtane.Controllers
|
||||
pagemodule.Pane = pm.Pane;
|
||||
pagemodule.Order = pm.Order;
|
||||
pagemodule.ContainerType = pm.ContainerType;
|
||||
pagemodule.EffectiveDate = pm.EffectiveDate;
|
||||
pagemodule.ExpiryDate = pm.ExpiryDate;
|
||||
pagemodule.Header = pm.Header;
|
||||
pagemodule.Footer = pm.Footer;
|
||||
|
||||
_pageModules.AddPageModule(pagemodule);
|
||||
}
|
||||
@ -295,38 +299,43 @@ namespace Oqtane.Controllers
|
||||
var removed = GetPermissionsDifferences(currentPermissions, page.PermissionList);
|
||||
|
||||
// synchronize module permissions
|
||||
if (added.Count > 0 || removed.Count > 0)
|
||||
if (page.UpdateModulePermissions && (added.Count > 0 || removed.Count > 0))
|
||||
{
|
||||
foreach (PageModule pageModule in _pageModules.GetPageModules(page.SiteId).Where(item => item.PageId == page.PageId).ToList())
|
||||
var pageModules = _pageModules.GetPageModules(page.SiteId);
|
||||
foreach (PageModule pageModule in pageModules.Where(item => item.PageId == page.PageId).ToList())
|
||||
{
|
||||
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
||||
// permissions added
|
||||
foreach (Permission permission in added)
|
||||
// ignore "shared" modules
|
||||
if (!pageModules.Any(item => item.ModuleId == pageModule.ModuleId && item.PageId != pageModule.PageId))
|
||||
{
|
||||
if (!modulePermissions.Any(item => item.PermissionName == permission.PermissionName
|
||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized))
|
||||
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
||||
// permissions added
|
||||
foreach (Permission permission in added)
|
||||
{
|
||||
_permissionRepository.AddPermission(new Permission
|
||||
if (!modulePermissions.Any(item => item.PermissionName == permission.PermissionName
|
||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized))
|
||||
{
|
||||
SiteId = page.SiteId,
|
||||
EntityName = EntityNames.Module,
|
||||
EntityId = pageModule.ModuleId,
|
||||
PermissionName = permission.PermissionName,
|
||||
RoleId = permission.RoleId,
|
||||
UserId = permission.UserId,
|
||||
IsAuthorized = permission.IsAuthorized
|
||||
});
|
||||
_permissionRepository.AddPermission(new Permission
|
||||
{
|
||||
SiteId = page.SiteId,
|
||||
EntityName = EntityNames.Module,
|
||||
EntityId = pageModule.ModuleId,
|
||||
PermissionName = permission.PermissionName,
|
||||
RoleId = permission.RoleId,
|
||||
UserId = permission.UserId,
|
||||
IsAuthorized = permission.IsAuthorized
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// permissions removed
|
||||
foreach (Permission permission in removed)
|
||||
{
|
||||
var modulePermission = modulePermissions.FirstOrDefault(item => item.PermissionName == permission.PermissionName
|
||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized);
|
||||
if (modulePermission != null)
|
||||
// permissions removed
|
||||
foreach (Permission permission in removed)
|
||||
{
|
||||
_permissionRepository.DeletePermission(modulePermission.PermissionId);
|
||||
var modulePermission = modulePermissions.FirstOrDefault(item => item.PermissionName == permission.PermissionName
|
||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized);
|
||||
if (modulePermission != null)
|
||||
{
|
||||
_permissionRepository.DeletePermission(modulePermission.PermissionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
29
Oqtane.Server/Controllers/TimeZoneController.cs
Normal file
29
Oqtane.Server/Controllers/TimeZoneController.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class TimeZoneController : Controller
|
||||
{
|
||||
public TimeZoneController() {}
|
||||
|
||||
// GET: api/<controller>
|
||||
[HttpGet]
|
||||
public IEnumerable<Models.TimeZone> Get()
|
||||
{
|
||||
return TimeZoneInfo.GetSystemTimeZones()
|
||||
.Select(item => new Models.TimeZone
|
||||
{
|
||||
Id = item.Id,
|
||||
DisplayName = item.DisplayName
|
||||
})
|
||||
.OrderBy(item => item.DisplayName);
|
||||
}
|
||||
}
|
||||
}
|
@ -135,6 +135,7 @@ namespace Oqtane.Controllers
|
||||
if (_userPermissions.IsAuthorized(User, user.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin) || _userPermissions.GetUser(User).UserId == user.UserId)
|
||||
{
|
||||
filtered.Email = user.Email;
|
||||
filtered.TimeZoneId = user.TimeZoneId;
|
||||
filtered.PhotoFileId = user.PhotoFileId;
|
||||
filtered.LastLoginOn = user.LastLoginOn;
|
||||
filtered.LastIPAddress = user.LastIPAddress;
|
||||
|
@ -104,6 +104,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ISearchProvider, DatabaseSearchProvider>();
|
||||
services.AddScoped<IImageService, ImageService>();
|
||||
services.AddScoped<ICookieConsentService, ServerCookieConsentService>();
|
||||
services.AddScoped<ITimeZoneService, TimeZoneService>();
|
||||
|
||||
// providers
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||
|
31
Oqtane.Server/Migrations/Tenant/06010301_AddTimeZone.cs
Normal file
31
Oqtane.Server/Migrations/Tenant/06010301_AddTimeZone.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Migrations.EntityBuilders;
|
||||
using Oqtane.Repository;
|
||||
|
||||
namespace Oqtane.Migrations.Tenant
|
||||
{
|
||||
[DbContext(typeof(TenantDBContext))]
|
||||
[Migration("Tenant.06.01.03.01")]
|
||||
public class AddTimeZone : MultiDatabaseMigration
|
||||
{
|
||||
public AddTimeZone(IDatabase database) : base(database)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
siteEntityBuilder.AddStringColumn("TimeZoneId", 50, true);
|
||||
|
||||
var userEntityBuilder = new UserEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
userEntityBuilder.AddStringColumn("TimeZoneId", 50, true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Migrations.EntityBuilders;
|
||||
using Oqtane.Repository;
|
||||
|
||||
namespace Oqtane.Migrations.Tenant
|
||||
{
|
||||
[DbContext(typeof(TenantDBContext))]
|
||||
[Migration("Tenant.06.01.03.02")]
|
||||
public class AddModuleHeaderFooter : MultiDatabaseMigration
|
||||
{
|
||||
public AddModuleHeaderFooter(IDatabase database) : base(database)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
pageModuleEntityBuilder.AddMaxStringColumn("Header", true);
|
||||
pageModuleEntityBuilder.AddMaxStringColumn("Footer", true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -11,7 +11,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
@ -34,19 +34,19 @@
|
||||
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.5" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.11" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.8" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.12.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
|
||||
</ItemGroup>
|
||||
|
@ -442,6 +442,8 @@ namespace Oqtane.Repository
|
||||
pageModule.Pane = (string.IsNullOrEmpty(pageTemplateModule.Pane)) ? PaneNames.Default : pageTemplateModule.Pane;
|
||||
pageModule.Order = (pageTemplateModule.Order == 0) ? 1 : pageTemplateModule.Order;
|
||||
pageModule.ContainerType = pageTemplateModule.ContainerType;
|
||||
pageModule.Header = pageTemplateModule.Header;
|
||||
pageModule.Footer = pageTemplateModule.Footer;
|
||||
pageModule.IsDeleted = pageTemplateModule.IsDeleted;
|
||||
pageModule.Module.PermissionList = new List<Permission>();
|
||||
foreach (var permission in pageTemplateModule.PermissionList)
|
||||
|
@ -285,6 +285,8 @@ namespace Oqtane.Services
|
||||
ContainerType = pagemodule.ContainerType,
|
||||
EffectiveDate = pagemodule.EffectiveDate,
|
||||
ExpiryDate = pagemodule.ExpiryDate,
|
||||
Header = pagemodule.Header,
|
||||
Footer = pagemodule.Footer,
|
||||
|
||||
ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == pagemodule.Module.ModuleDefinitionName)),
|
||||
|
||||
|
@ -225,6 +225,9 @@ namespace Oqtane
|
||||
app.UseAuthorization();
|
||||
app.UseAntiforgery();
|
||||
|
||||
// execute any IServerStartup logic
|
||||
app.ConfigureOqtaneAssemblies(env);
|
||||
|
||||
if (_useSwagger)
|
||||
{
|
||||
app.UseSwagger();
|
||||
@ -245,9 +248,6 @@ namespace Oqtane
|
||||
.AddAdditionalAssemblies(typeof(SiteRouter).Assembly);
|
||||
});
|
||||
|
||||
// execute any IServerStartup logic
|
||||
app.ConfigureOqtaneAssemblies(env);
|
||||
|
||||
// simulate the fallback routing approach of traditional Blazor - allowing the custom SiteRouter to handle all routing concerns
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
|
@ -13,11 +13,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.4" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
4
Oqtane.Server/wwwroot/Modules/Templates/External/Server/AssemblyInfo.cs
vendored
Normal file
4
Oqtane.Server/wwwroot/Modules/Templates/External/Server/AssemblyInfo.cs
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
using System.Resources;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
[assembly: RootNamespace("[Owner].Module.[Module].Server")]
|
@ -19,10 +19,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -13,9 +13,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -113,6 +113,18 @@ namespace Oqtane.Models
|
||||
[NotMapped]
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Header content to include at the top of a module instance in the UI
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Footer content to include below a module instance in the UI
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string Footer { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region SiteRouter properties
|
||||
@ -218,6 +230,8 @@ namespace Oqtane.Models
|
||||
ContainerType = ContainerType,
|
||||
EffectiveDate = EffectiveDate,
|
||||
ExpiryDate = ExpiryDate,
|
||||
Header = Header,
|
||||
Footer = Footer,
|
||||
CreatedBy = CreatedBy,
|
||||
CreatedOn = CreatedOn,
|
||||
ModifiedBy = ModifiedBy,
|
||||
|
@ -122,6 +122,12 @@ namespace Oqtane.Models
|
||||
[NotMapped]
|
||||
public bool HasChildren { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if module permissions should be updated to be consistent with page permissions
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public bool UpdateModulePermissions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of permissions for this page
|
||||
/// </summary>
|
||||
|
@ -41,14 +41,27 @@ namespace Oqtane.Models
|
||||
/// Reference to a Razor Container which wraps this module instance.
|
||||
/// </summary>
|
||||
public string ContainerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start of when this assignment is valid. See also <see cref="ExpiryDate"/>
|
||||
/// </summary>
|
||||
public DateTime? EffectiveDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End of when this assignment is valid. See also <see cref="EffectiveDate"/>
|
||||
/// </summary>
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Header content to include above the module instance in the UI
|
||||
/// </summary>
|
||||
public string Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Footer content to include below the module instance in the UI
|
||||
/// </summary>
|
||||
public string Footer { get; set; }
|
||||
|
||||
#region IDeletable Properties
|
||||
|
||||
public string DeletedBy { get; set; }
|
||||
|
@ -26,6 +26,11 @@ namespace Oqtane.Models
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default time zone for the site
|
||||
/// </summary>
|
||||
public string TimeZoneId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to a <see cref="File"/> which has the Logo for this site.
|
||||
/// Should be an image.
|
||||
@ -200,6 +205,7 @@ namespace Oqtane.Models
|
||||
SiteId = SiteId,
|
||||
TenantId = TenantId,
|
||||
Name = Name,
|
||||
TimeZoneId = TimeZoneId,
|
||||
LogoFileId = LogoFileId,
|
||||
FaviconFileId = FaviconFileId,
|
||||
DefaultThemeType = DefaultThemeType,
|
||||
|
@ -95,6 +95,8 @@ namespace Oqtane.Models
|
||||
Pane = PaneNames.Default;
|
||||
Order = 1;
|
||||
ContainerType = "";
|
||||
Header = "";
|
||||
Footer = "";
|
||||
IsDeleted = false;
|
||||
PermissionList = new List<Permission>()
|
||||
{
|
||||
@ -110,6 +112,8 @@ namespace Oqtane.Models
|
||||
public string Pane { get; set; }
|
||||
public int Order { get; set; }
|
||||
public string ContainerType { get; set; }
|
||||
public string Header { get; set; }
|
||||
public string Footer { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
public List<Permission> PermissionList { get; set; }
|
||||
public List<Setting> Settings { get; set; }
|
||||
|
10
Oqtane.Shared/Models/TimeZone.cs
Normal file
10
Oqtane.Shared/Models/TimeZone.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
public class TimeZone
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
}
|
||||
}
|
@ -29,6 +29,11 @@ namespace Oqtane.Models
|
||||
/// </summary>
|
||||
public string Email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User time zone
|
||||
/// </summary>
|
||||
public string TimeZoneId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to a <see cref="File"/> containing the users photo.
|
||||
/// </summary>
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using Oqtane.Models;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Oqtane.Documentation;
|
||||
|
||||
namespace Oqtane.Modules.HtmlText.Models
|
||||
|
@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -11,7 +11,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
@ -19,11 +19,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.5" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.4" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -4,8 +4,8 @@ namespace Oqtane.Shared
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
public static readonly string Version = "6.1.2";
|
||||
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1,5.1.2,5.2.0,5.2.1,5.2.2,5.2.3,5.2.4,6.0.0,6.0.1,6.1.0,6.1.1,6.1.2";
|
||||
public static readonly string Version = "6.1.3";
|
||||
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1,5.1.2,5.2.0,5.2.1,5.2.2,5.2.3,5.2.4,6.0.0,6.0.1,6.1.0,6.1.1,6.1.2,6.1.3";
|
||||
public const string PackageId = "Oqtane.Framework";
|
||||
public const string ClientId = "Oqtane.Client";
|
||||
public const string UpdaterPackageId = "Oqtane.Updater";
|
||||
|
@ -68,7 +68,7 @@ namespace Oqtane.Shared
|
||||
Name = "Facebook",
|
||||
Settings = new Dictionary<string, string>()
|
||||
{
|
||||
{ "ExternalLogin:ProviderUrl", "https://developers.facebook.com/apps/" },
|
||||
{ "ExternalLogin:ProviderUrl", "https://developers.facebook.com" },
|
||||
{ "ExternalLogin:ProviderType", "oauth2" },
|
||||
{ "ExternalLogin:ProviderName", "Facebook" },
|
||||
{ "ExternalLogin:AuthorizationUrl", "https://www.facebook.com/v18.0/dialog/oauth" },
|
||||
|
@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>6.1.2</Version>
|
||||
<Version>6.1.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -11,7 +11,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.2</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.1.3</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
|
Reference in New Issue
Block a user