Implemented local setting persistence and fixed main page search bug.
This commit is contained in:
parent
04f6657ed3
commit
11fa15fe62
@ -1,11 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
using MultiShop.Client.Module;
|
||||
using MultiShop.Client.Shared;
|
||||
using MultiShop.Shared.Models;
|
||||
using MultiShop.Shop.Framework;
|
||||
|
||||
@ -13,19 +15,26 @@ namespace MultiShop.Client
|
||||
{
|
||||
public partial class App
|
||||
{
|
||||
[Inject]
|
||||
private IJSRuntime JS { get; set; }
|
||||
[Inject]
|
||||
private IHttpClientFactory HttpClientFactory {get; set;}
|
||||
private IJSObjectReference localStorageManager;
|
||||
private ICollection<RuntimeDependencyManager.Dependency> dependencies = new List<RuntimeDependencyManager.Dependency>();
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
dependencies.Add(new RuntimeDependencyManager.Dependency(typeof(IReadOnlyDictionary<string, IShop>), "Shops", DownloadShops));
|
||||
dependencies.Add(new RuntimeDependencyManager.Dependency(typeof(IJSObjectReference), "JS Modules", (pHttp, http, auth, logger) => new ValueTask<object>(localStorageManager), "LocalStorageManager"));
|
||||
dependencies.Add(new RuntimeDependencyManager.Dependency(typeof(IJSObjectReference), "JS Modules", async (pHttp, http, auth, logger) => await JS.InvokeAsync<IJSObjectReference>("import", "./js/Components/ComponentSupport.js"), "ComponentSupport"));
|
||||
dependencies.Add(new RuntimeDependencyManager.Dependency(typeof(IReadOnlyDictionary<string, IShop>), "Shops", async (publicHttp, authenticatedHttp, auth, logger) => await (new ShopModuleLoader(publicHttp, logger)).GetShops()));
|
||||
dependencies.Add(new RuntimeDependencyManager.Dependency(typeof(ApplicationProfile), "Application Profile", DownloadApplicationProfile));
|
||||
}
|
||||
|
||||
private async ValueTask<object> DownloadShops(HttpClient publicHttp, HttpClient http, AuthenticationState authState, ILogger logger)
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ShopModuleLoader loader = new ShopModuleLoader(publicHttp, logger);
|
||||
return await loader.GetShops();
|
||||
await base.OnInitializedAsync();
|
||||
localStorageManager = await JS.InvokeAsync<IJSObjectReference>("import", "./js/LocalStorageManager.js");
|
||||
}
|
||||
|
||||
private async ValueTask<object> DownloadApplicationProfile(HttpClient publicHttp, HttpClient http, AuthenticationState authState, ILogger logger)
|
||||
@ -39,7 +48,10 @@ namespace MultiShop.Client
|
||||
return await response.Content.ReadFromJsonAsync<ApplicationProfile>();
|
||||
}
|
||||
}
|
||||
ApplicationProfile profile = await localStorageManager.InvokeAsync<ApplicationProfile>("retrieve", "ApplicationProfile");
|
||||
if (profile != null) return profile;
|
||||
return new ApplicationProfile();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
using MultiShop.Client.Services;
|
||||
using MultiShop.Shared.Models;
|
||||
|
||||
@ -70,6 +71,7 @@ namespace MultiShop.Client.Pages
|
||||
Logger.LogDebug($"User is authenticated. Attempting to save configuration to server.");
|
||||
await Http.PutAsJsonAsync("Profile/Application", ApplicationProfile);
|
||||
}
|
||||
await RuntimeDependencyManager.Get<IJSObjectReference>("LocalStorageManager").InvokeVoidAsync("save", "ApplicationProfile", ApplicationProfile);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
using MultiShop.Client.Extensions;
|
||||
using MultiShop.Client.Listing;
|
||||
using MultiShop.Client.Services;
|
||||
@ -17,9 +18,6 @@ namespace MultiShop.Client.Pages
|
||||
{
|
||||
public partial class Search : IAsyncDisposable
|
||||
{
|
||||
[Inject]
|
||||
private LayoutStateChangeNotifier LayoutStateChangeNotifier { get; set; }
|
||||
|
||||
[Inject]
|
||||
private ILogger<Search> Logger { get; set; }
|
||||
|
||||
@ -53,7 +51,6 @@ namespace MultiShop.Client.Pages
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
LayoutStateChangeNotifier.Notify += UpdateState;
|
||||
Shops = RuntimeDependencyManager.Get<IReadOnlyDictionary<string, IShop>>();
|
||||
}
|
||||
|
||||
@ -71,36 +68,24 @@ namespace MultiShop.Client.Pages
|
||||
{
|
||||
activeSearchProfile = await searchProfileResponse.Content.ReadFromJsonAsync<SearchProfile>();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Could not load search profile from server. Using default.");
|
||||
activeSearchProfile = new SearchProfile();
|
||||
}
|
||||
|
||||
HttpResponseMessage resultsProfileResponse = await Http.GetAsync("Profile/Results");
|
||||
if (resultsProfileResponse.IsSuccessStatusCode)
|
||||
{
|
||||
activeResultsProfile = await resultsProfileResponse.Content.ReadFromJsonAsync<ResultsProfile>();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Could not load results profile from server. Using default.");
|
||||
activeResultsProfile = new ResultsProfile();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
activeSearchProfile = new SearchProfile();
|
||||
activeResultsProfile = new ResultsProfile();
|
||||
}
|
||||
activeSearchProfile.ShopStates.TotalShops = Shops.Count;
|
||||
}
|
||||
IJSObjectReference localStorageManager = RuntimeDependencyManager.Get<IJSObjectReference>("LocalStorageManager");
|
||||
if (activeSearchProfile == null) activeSearchProfile = await localStorageManager.InvokeAsync<SearchProfile>("retrieve", "SearchProfile");
|
||||
if (activeResultsProfile == null) activeResultsProfile = await localStorageManager.InvokeAsync<ResultsProfile>("retrieve", "ResultsProfile");
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await base.OnParametersSetAsync();
|
||||
if (!string.IsNullOrEmpty(Query))
|
||||
if (activeSearchProfile == null) activeSearchProfile = new SearchProfile();
|
||||
if (activeResultsProfile == null) activeResultsProfile = new ResultsProfile();
|
||||
activeSearchProfile.ShopStates.TotalShops = Shops.Count;
|
||||
|
||||
if (Query != null)
|
||||
{
|
||||
searchBar.Searching = true;
|
||||
await PerformSearch(Query);
|
||||
}
|
||||
}
|
||||
@ -111,9 +96,6 @@ namespace MultiShop.Client.Pages
|
||||
if (firstRender)
|
||||
{
|
||||
searchBar.Query = Query;
|
||||
searchBar.Searching = true;
|
||||
await PerformSearch(Query);
|
||||
searchBar.Searching = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,6 +103,7 @@ namespace MultiShop.Client.Pages
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(query)) return;
|
||||
if (status.Searching) return;
|
||||
searchBar.Searching = true;
|
||||
SearchProfile searchProfile = activeSearchProfile.DeepCopy();
|
||||
status.Searching = true;
|
||||
Logger.LogDebug($"Received search request for \"{query}\".");
|
||||
@ -187,6 +170,7 @@ namespace MultiShop.Client.Pages
|
||||
}
|
||||
status.Searching = false;
|
||||
status.Searched = true;
|
||||
searchBar.Searching = false;
|
||||
|
||||
int tagsAdded = 0;
|
||||
foreach (ResultsProfile.Category c in greatest.Keys)
|
||||
@ -272,12 +256,6 @@ namespace MultiShop.Client.Pages
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task UpdateState() {
|
||||
await InvokeAsync(() => {
|
||||
StateHasChanged();
|
||||
});
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
AuthenticationState authState = await AuthenticationStateTask;
|
||||
@ -286,7 +264,9 @@ namespace MultiShop.Client.Pages
|
||||
await Http.PutAsJsonAsync("Profile/Search", activeSearchProfile);
|
||||
await Http.PutAsJsonAsync("Profile/Results", activeResultsProfile);
|
||||
}
|
||||
LayoutStateChangeNotifier.Notify -= UpdateState;
|
||||
IJSObjectReference localStorageManager = RuntimeDependencyManager.Get<IJSObjectReference>("LocalStorageManager");
|
||||
await localStorageManager.InvokeVoidAsync("save", "SearchProfile", activeSearchProfile);
|
||||
await localStorageManager.InvokeVoidAsync("save", "ResultsProfile", activeResultsProfile);
|
||||
}
|
||||
|
||||
public class Status
|
||||
|
38
src/MultiShop/Client/wwwroot/js/LocalStorageManager.js
Normal file
38
src/MultiShop/Client/wwwroot/js/LocalStorageManager.js
Normal file
@ -0,0 +1,38 @@
|
||||
const APP_STORAGE_KEY = "MultiShop"
|
||||
|
||||
export function save(key, value) {
|
||||
try {
|
||||
localStorage.setItem(APP_STORAGE_KEY + "/" + key, JSON.stringify(value));
|
||||
} catch (error) {
|
||||
console.warn("Failed to save value with key: " + key);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function retrieve(key) {
|
||||
let value = localStorage.getItem(APP_STORAGE_KEY + "/" + key);
|
||||
if (value == null) return null;
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
if (error instanceof SyntaxError) {
|
||||
console.warn("Unable to parse value for key \"" + key + "\". Removing.");
|
||||
remove(key);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function remove(key) {
|
||||
localStorage.removeItem(APP_STORAGE_KEY + "/" + key);
|
||||
}
|
||||
|
||||
export function clear() {
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
let name = localStorage.key(i);
|
||||
if (name.startsWith(APP_STORAGE_KEY + "/")) {
|
||||
localStorage.removeItem(name);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user