Skip to content

Commit

Permalink
version 1.0.5 - ability to search, maintain state on summary and deta…
Browse files Browse the repository at this point in the history
…il transitions, use ResourceType in Settings, add missing RESX keys
  • Loading branch information
sbwalker committed Sep 19, 2022
1 parent 0add91b commit fcc040d
Show file tree
Hide file tree
Showing 15 changed files with 131 additions and 68 deletions.
4 changes: 2 additions & 2 deletions Client/Edit.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</div>
<br /><br />
<button type="button" class="btn btn-success" @onclick="@SaveBlog">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@Localizer["Cancel"]</NavLink>
@if (_id != -1)
{
<br /><br />
Expand Down Expand Up @@ -133,7 +133,7 @@
}
}

NavigationManager.NavigateTo(NavigateUrl());
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
catch (Exception ex)
{
Expand Down
111 changes: 83 additions & 28 deletions Client/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,66 @@
@inject NavigationManager NavigationManager
@inject ISettingService SettingService
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer

@if (_blogs != null)
@if (_blog != null)
{
if (!string.IsNullOrEmpty(PageState.UrlParameters))
<div class="text-center"><NavLink class="btn btn-secondary" href="@NavigateUrl(PageState.Page.Path, $"?page={_page}&search={_search}")">@Localizer["View All Blogs"]</NavLink></div>
<br />
<div class="text-center">
<ActionLink Action="Edit" Parameters="@($"id=" + _blog.BlogId.ToString())" ReturnUrl="@(NavigateUrl(PageState.Page.Path, $"?page={_page}&search={_search}"))" ResourceKey="EditBlog" Text="Edit" />
<ActionDialog Header="Delete Blog" Message="Are You Sure You Wish To Delete This Blog?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" ResourceKey="DeleteBlog" OnClick="@(async () => await DeleteBlog(_blog.BlogId))" />
</div>
@((MarkupString)Utilities.FormatContent(FormatTemplate(_detail, _blog), PageState.Alias, "render"))
<br />
<div class="text-center"><NavLink class="btn btn-secondary" href="@NavigateUrl(PageState.Page.Path, $"?page={_page}&search={_search}")">@Localizer["View All Blogs"]</NavLink></div>
}
else
{
@if (_blogs != null)
{
<div class="text-center"><NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["View All Blogs"]</NavLink></div>
<br />
if (_blogs.Count > 0)
{
<div class="text-center">
<ActionLink Action="Edit" Parameters="@($"id=" + _blogs[0].BlogId.ToString())" ResourceKey="EditBlog" Text="Edit" />
<ActionDialog Header="Delete Blog" Message="Are You Sure You Wish To Delete This Blog?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" ResourceKey="DeleteBlog" OnClick="@(async () => await DeleteBlog(_blogs[0].BlogId))" />
<div class="container">
<div class="row mb-1 align-items-center">
<div class="col-sm-4">
<ActionLink Action="Add" Security="SecurityAccessLevel.Edit" ResourceKey="AddBlog" Text="Add Blog" />
</div>
<div class="col-sm-4">
<input class="form-control" @bind="@_search" />
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-secondary" @onclick="Search">@SharedLocalizer["Search"]</button>
<button type="button" class="btn btn-secondary" @onclick="Reset">@SharedLocalizer["Reset"]</button>
</div>
</div>
@((MarkupString)Utilities.FormatContent(FormatTemplate(_detail, _blogs[0]), PageState.Alias, "render"))
}
</div>
<br />
<div class="text-center"><NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["View All Blogs"]</NavLink></div>
}
else
{
<ActionLink Action="Add" Security="SecurityAccessLevel.Edit" ResourceKey="AddBlog" Text="Add Blog" />
<br />
<Pager Format="Grid" Items="@_blogs" DisplayPages="1" PageSize="@_items.ToString()" ColumnClass="col-lg-4 col-md-6">
<Pager Format="Grid" Items="@_blogs" DisplayPages="1" PageSize="@_items.ToString()" CurrentPage="@_page.ToString()" OnPageChange="OnPageChange" ColumnClass="col-lg-4 col-md-6">
<Row>
@((MarkupString)Utilities.FormatContent(FormatTemplate(_summary, context), PageState.Alias, "render"))
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
{
<div>
<NavLink class="btn btn-secondary" href="@FormatUrl(context)">@Localizer["Details"]</NavLink>
<ActionLink Action="Edit" Parameters="@($"id=" + context.BlogId.ToString())" ResourceKey="EditBlog" Text="Edit" />
<ActionLink Action="Edit" Parameters="@($"id=" + context.BlogId.ToString())" ReturnUrl="@(NavigateUrl(PageState.Page.Path, $"?page={_page}&search={_search}"))" ResourceKey="EditBlog" Text="Edit" />
<ActionDialog Header="Delete Blog" Message="Are You Sure You Wish To Delete This Blog?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" ResourceKey="DeleteBlog" OnClick="@(async () => await DeleteBlog(context.BlogId))" />
</div>
}
</Row>
</Pager>
}
<br />
}
<br />

@code {
public override string UrlParametersTemplate => "/{id}/{slug}";

private List<Blog> _blogs;
private Blog _blog;
private int _items;
private string _summary;
private string _detail;
private int _page = 1;
private string _search = "";

protected override async Task OnParametersSetAsync()
{
Expand All @@ -60,15 +76,22 @@
_summary = SettingService.GetSetting(ModuleState.Settings, "Summary", "<a href=\"[URL]\"><h2>[TITLE]</h2></a><p>[SUMMARY]</p>");
_detail = SettingService.GetSetting(ModuleState.Settings, "Detail", "<h2>[TITLE]</h2><p>[CONTENT]</p>");

if (PageState.QueryString.ContainsKey("page"))
{
_page = int.Parse(PageState.QueryString["page"]);
}
if (PageState.QueryString.ContainsKey("search"))
{
_search = PageState.QueryString["search"];
}

if (!string.IsNullOrEmpty(PageState.UrlParameters))
{
_blogs = new List<Blog>();
_blogs.Add(await BlogService.GetBlogAsync(int.Parse(PageState.UrlParameters.Split('/')[0]), ModuleState.ModuleId));
_blog = await BlogService.GetBlogAsync(int.Parse(UrlParameters["id"]), ModuleState.ModuleId);
}
else
{
_blogs = await BlogService.GetBlogsAsync(ModuleState.ModuleId);
_blogs = _blogs.OrderByDescending(item => item.CreatedOn).ToList();
await GetBlogs();
}
}
catch (Exception ex)
Expand All @@ -78,27 +101,39 @@
}
}

private async Task GetBlogs()
{
_blog = null;
_blogs = await BlogService.GetBlogsAsync(ModuleState.ModuleId, _search);
_blogs = _blogs.OrderByDescending(item => item.CreatedOn).ToList();
}

private string FormatSlug(string title)
{
string slug = "";
foreach(var character in title.ToLower())
{
for (int i = 0; i < title.Length; i++)
{
var character = title.ToLower()[i];
int ascii = (int)character;
if ((ascii >= (int)'a' && ascii <= (int)'z') || (ascii >= (int)'0' && ascii <= (int)'9'))
{
slug += character;
}
else
{
slug += "-";
if (character != '\'' && (i < title.Length - 1) && slug.Length > 0 && slug[slug.Length - 1] != '-')
{
slug += "-";
}
}

}
return slug;
}

private string FormatUrl(Blog blog)
{
return NavigateUrl(PageState.Page.Path + "/" + Constants.UrlParametersDelimiter + "/" + blog.BlogId.ToString() + "/" + FormatSlug(blog.Title));
return NavigateUrl(PageState.Page.Path, AddUrlParameters(blog.BlogId, FormatSlug(blog.Title) + $"?page={_page}&search={_search}"));
}

private string FormatTemplate(string template, Blog blog)
Expand Down Expand Up @@ -127,4 +162,24 @@
ModuleInstance.AddModuleMessage(Localizer["Error Deleting Blog"], MessageType.Error);
}
}

private async Task Search()
{
_page = 1;
await GetBlogs();
StateHasChanged();
}

private async Task Reset()
{
_page = 1;
_search = "";
await GetBlogs();
StateHasChanged();
}

private void OnPageChange(int page)
{
_page = page;
}
}
4 changes: 2 additions & 2 deletions Client/ModuleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public class ModuleInfo : IModule
{
Name = "Blog",
Description = "Blog",
Version = "1.0.4",
Version = "1.0.5",
ServerManagerType = "Oqtane.Blogs.Manager.BlogManager, Oqtane.Blogs.Server.Oqtane",
ReleaseVersions = "1.0.0,1.0.1,1.0.3,1.0.4",
ReleaseVersions = "1.0.0,1.0.1,1.0.3,1.0.4,1.0.5",
Dependencies = "Oqtane.Blogs.Shared.Oqtane",
SettingsType = "Oqtane.Blogs.Settings, Oqtane.Blogs.Client.Oqtane"
};
Expand Down
10 changes: 5 additions & 5 deletions Client/Oqtane.Blogs.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
<Version>1.0.4</Version>
<Version>1.0.5</Version>
<Authors>Oqtane</Authors>
<Company>Oqtane</Company>
<Description>A Blog Module for the Oqtane Framework</Description>
Expand All @@ -13,10 +13,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.3" />
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
</ItemGroup>

Expand Down
22 changes: 14 additions & 8 deletions Client/Resources/Oqtane.Blogs.Settings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,22 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MaximumBlogEntries.Text" xml:space="preserve">
<value>Maximum Blog Entries:</value>
<data name="Items.Text" xml:space="preserve">
<value>Items Per Page:</value>
</data>
<data name="MaximumBlogEntries.HelpText" xml:space="preserve">
<value>Enter the maximum number of blogs to display on a page</value>
<data name="Items.HelpText" xml:space="preserve">
<value>Enter the maximum items per page</value>
</data>
<data name="SummaryLength.Text" xml:space="preserve">
<value>Summary Length (Characters):</value>
<data name="Summary.Text" xml:space="preserve">
<value>Summary Template:</value>
</data>
<data name="SummaryLength.HelpText" xml:space="preserve">
<value>Enter the maximum length of the blog to display in the summary view</value>
<data name="Summary.HelpText" xml:space="preserve">
<value>Enter the summary blog template</value>
</data>
<data name="Detail.HelpText" xml:space="preserve">
<value>Enter the detail blog template</value>
</data>
<data name="Detail.Text" xml:space="preserve">
<value>Detail Template:</value>
</data>
</root>
5 changes: 2 additions & 3 deletions Client/Services/BlogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ public BlogService(HttpClient http, SiteState siteState) : base(http)

private string Apiurl=> CreateApiUrl("Blog", _siteState.Alias);

public async Task<List<Blog>> GetBlogsAsync(int ModuleId)
public async Task<List<Blog>> GetBlogsAsync(int ModuleId, string Search)
{
List<Blog> Blogs = await GetJsonAsync<List<Blog>>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId));
return Blogs.OrderBy(item => item.Title).ToList();
return await GetJsonAsync<List<Blog>>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}&search={Search}", EntityNames.Module, ModuleId));
}

public async Task<Blog> GetBlogAsync(int BlogId, int ModuleId)
Expand Down
2 changes: 1 addition & 1 deletion Client/Services/IBlogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Oqtane.Blogs.Services
{
public interface IBlogService
{
Task<List<Blog>> GetBlogsAsync(int ModuleId);
Task<List<Blog>> GetBlogsAsync(int ModuleId, string Search);

Task<Blog> GetBlogAsync(int BlogId, int ModuleId);

Expand Down
8 changes: 5 additions & 3 deletions Client/Settings.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label For="items" ResourceKey="Items" HelpText="Enter the maximum items per page">Items Per Page: </Label>
<Label For="items" ResourceKey="Items" ResourceType="@resourceType" HelpText="Enter the maximum items per page">Items Per Page: </Label>
<div class="col-sm-9">
<input id="items" type="text" class="form-control" @bind="@_items" maxlength="1" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label For="summary" ResourceKey="Summary" HelpText="Enter the summary blog template">Summary Template: </Label>
<Label For="summary" ResourceKey="Summary" ResourceType="@resourceType" HelpText="Enter the summary blog template">Summary Template: </Label>
<div class="col-sm-9">
<textarea id="summary" class="form-control" @bind="@_summary" rows="5" required></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label For="detail" ResourceKey="Detail" HelpText="Enter the detail blog template">Detail Template: </Label>
<Label For="detail" ResourceKey="Detail" ResourceType="@resourceType" HelpText="Enter the detail blog template">Detail Template: </Label>
<div class="col-sm-9">
<textarea id="detail" class="form-control" @bind="@_detail" rows="5" required></textarea>
</div>
Expand All @@ -28,6 +28,8 @@
</form>

@code {
private string resourceType = "Oqtane.Blogs.Settings, Oqtane.Blogs.Client.Oqtane"; // for localization
private ElementReference form;
private bool validated = false;

Expand Down
4 changes: 2 additions & 2 deletions Package/Oqtane.Blogs.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Blogs</id>
<version>1.0.4</version>
<version>1.0.5</version>
<authors>Oqtane</authors>
<owners>Oqtane</owners>
<title>Blogs</title>
Expand All @@ -16,7 +16,7 @@
<releaseNotes></releaseNotes>
<summary></summary>
<dependencies>
<dependency id="Oqtane.Framework" version="3.0.3" />
<dependency id="Oqtane.Framework" version="3.2.0" />
</dependencies>
</metadata>
<files>
Expand Down
6 changes: 3 additions & 3 deletions Server/Controllers/BlogController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ public BlogController(IBlogRepository BlogRepository, ILogManager logger, IHttpC
_BlogRepository = BlogRepository;
}

// GET: api/<controller>?moduleid=x
// GET: api/<controller>?moduleid=x&search=y
[HttpGet]
[Authorize(Policy = "ViewModule")]
public IEnumerable<Blog> Get(string moduleid)
public IEnumerable<Blog> Get(string moduleid, string search)
{
if (int.Parse(moduleid) == _authEntityId[EntityNames.Module])
{
return _BlogRepository.GetBlogs(int.Parse(moduleid));
return _BlogRepository.GetBlogs(int.Parse(moduleid), search);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion Server/Manager/BlogManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public bool Uninstall(Tenant tenant)
public string ExportModule(Module module)
{
string content = "";
List<Blog> Blogs = _Blogs.GetBlogs(module.ModuleId).ToList();
List<Blog> Blogs = _Blogs.GetBlogs(module.ModuleId, "").ToList();
if (Blogs != null)
{
content = JsonSerializer.Serialize(Blogs);
Expand Down
10 changes: 5 additions & 5 deletions Server/Oqtane.Blogs.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<Version>1.0.4</Version>
<Version>1.0.5</Version>
<Product>Oqtane.Blogs</Product>
<Authors>Oqtane</Authors>
<Company>Oqtane</Company>
Expand All @@ -13,10 +13,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="6.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit fcc040d

Please sign in to comment.