@@ -48,12 +48,12 @@
private void ButtonClicked(EventArgs eventArgs)
{
- searchService.Show();
+ SearchService.Show();
}
protected override async Task OnInitializedAsync()
{
- userAgent = await jsRuntime.InvokeAsync
("getUserAgent");
+ userAgent = await JsRuntime.InvokeAsync("getUserAgent");
}
}
\ No newline at end of file
diff --git a/IGP/App.razor b/IGP/App.razor
index a28f294..68d92e5 100644
--- a/IGP/App.razor
+++ b/IGP/App.razor
@@ -1,4 +1,7 @@
-@inject IVariableService VariableService
+@using Microsoft.AspNetCore.Components.ProtectedBrowserStorage
+@inject IVariableService VariableService
+@inject IStorageService StorageService
+
@@ -76,6 +79,7 @@
protected override async Task OnInitializedAsync()
{
await VariableService.Load();
+ await StorageService.Load();
isLoaded = true;
StateHasChanged();
}
diff --git a/IGP/Database.db b/IGP/Database.db
index f2ea553..29f3f62 100644
Binary files a/IGP/Database.db and b/IGP/Database.db differ
diff --git a/IGP/IGP.csproj b/IGP/IGP.csproj
index 4282b55..71c0d12 100644
--- a/IGP/IGP.csproj
+++ b/IGP/IGP.csproj
@@ -20,6 +20,7 @@
+
diff --git a/IGP/Index.razor b/IGP/Index.razor
index 84e445d..e31ab73 100644
--- a/IGP/Index.razor
+++ b/IGP/Index.razor
@@ -3,7 +3,7 @@
@layout PageLayout
-
+
\ No newline at end of file
diff --git a/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor b/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor
index a9d80a4..8edf26e 100644
--- a/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor
+++ b/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor
@@ -1,15 +1,17 @@
-@inject IJSRuntime jsRuntime;
-@inject IKeyService keyService
-@inject IImmortalSelectionService filterService
-@inject IBuildOrderService buildOrderService
+@inject IJSRuntime JsRuntime
+@inject IKeyService KeyService
+@inject IImmortalSelectionService FilterService
+@inject IBuildOrderService BuildOrderService
+@inject IStorageService StorageService
+@using Services.Website
@implements IDisposable
-@if (entity != null)
+@if (_entity != null)
{
-
-
+
+
@@ -17,28 +19,39 @@
}
@code {
- private EntityModel? entity = default!;
- private string viewType = "Detailed";
+ private EntityModel? _entity = default!;
+ private string _viewType = EntityViewType.Detailed;
protected override void OnInitialized()
{
- keyService.Subscribe(HandleClick);
+ KeyService.Subscribe(HandleClick);
+ StorageService.Subscribe(RefreshDefaults);
+
+ RefreshDefaults();
}
void IDisposable.Dispose()
{
- keyService.Unsubscribe(HandleClick);
+ KeyService.Unsubscribe(HandleClick);
+
+ StorageService.Unsubscribe(RefreshDefaults);
+ }
+
+
+ void RefreshDefaults()
+ {
+ _viewType = StorageService.GetValue(StorageKeys.IsPlainView) ? EntityViewType.Plain : EntityViewType.Detailed;
}
protected override bool ShouldRender()
{
#if DEBUG
- jsRuntime.InvokeVoidAsync("console.time", "EntityClickViewComponent");
+ JsRuntime.InvokeVoidAsync("console.time", "EntityClickViewComponent");
#endif
return true;
}
@@ -46,23 +59,23 @@
protected override void OnAfterRender(bool firstRender)
{
#if DEBUG
- jsRuntime.InvokeVoidAsync("console.timeEnd", "EntityClickViewComponent");
+ JsRuntime.InvokeVoidAsync("console.timeEnd", "EntityClickViewComponent");
#endif
}
private void HandleClick()
{
- var hotkey = keyService.GetHotkey();
- var hotkeyGroup = keyService.GetHotkeyGroup();
- var isHoldSpace = keyService.IsHoldingSpace();
- var faction = filterService.GetFactionType();
- var immortal = filterService.GetImmortalType();
+ var hotkey = KeyService.GetHotkey();
+ var hotkeyGroup = KeyService.GetHotkeyGroup();
+ var isHoldSpace = KeyService.IsHoldingSpace();
+ var faction = FilterService.GetFactionType();
+ var immortal = FilterService.GetImmortalType();
var foundEntity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
- if (foundEntity != null && entity != foundEntity)
+ if (foundEntity != null && _entity != foundEntity)
{
- entity = foundEntity;
+ _entity = foundEntity;
StateHasChanged();
}
}
diff --git a/IGP/Pages/AnaltyicsPage.razor b/IGP/Pages/DataCollectionPage.razor
similarity index 83%
rename from IGP/Pages/AnaltyicsPage.razor
rename to IGP/Pages/DataCollectionPage.razor
index a638104..8d4fa5a 100644
--- a/IGP/Pages/AnaltyicsPage.razor
+++ b/IGP/Pages/DataCollectionPage.razor
@@ -1,4 +1,4 @@
-@page "/analytics"
+@page "/data-collection"
@layout PageLayout
diff --git a/IGP/Pages/PermissionsPage.razor b/IGP/Pages/PermissionsPage.razor
index ed68a87..04ead98 100644
--- a/IGP/Pages/PermissionsPage.razor
+++ b/IGP/Pages/PermissionsPage.razor
@@ -1,16 +1,27 @@
@page "/permissions"
+@inject IPermissionService PermissionService
@layout PageLayout
+@using Services.Website
+@inject Blazored.LocalStorage.ILocalStorageService LocalStorage
+@implements IDisposable
-
-
- Not Implemented
-
-
+
- TODO
+
+
+
+
@@ -41,4 +52,44 @@
Enable data tracking if you want the website maintainer to know how your using the website.
-
\ No newline at end of file
+
+
+
+@code {
+ private bool _storageEnabled = false;
+ private bool _dataCollectionEnabled = false;
+
+ protected override void OnInitialized()
+ {
+ PermissionService.Subscribe(Update);
+
+ Update();
+ }
+
+ void Update()
+ {
+ _storageEnabled = PermissionService.GetIsStorageEnabled();
+ _dataCollectionEnabled = PermissionService.GetIsDataCollectionEnabled();
+
+ StateHasChanged();
+ }
+
+ public void Dispose()
+ {
+ PermissionService.Unsubscribe(Update);
+ }
+
+
+
+ private void StoragePermissionChanged(ChangeEventArgs obj)
+ {
+ PermissionService.SetIsStorageEnabled((bool)obj.Value!);
+ }
+
+ private void DataCollectionPermissionChanged(ChangeEventArgs obj)
+ {
+ PermissionService.SetIsDataCollectionEnabled((bool)obj.Value!);
+ }
+
+
+}
\ No newline at end of file
diff --git a/IGP/Pages/StoragePage.razor b/IGP/Pages/StoragePage.razor
index 86886d9..c896551 100644
--- a/IGP/Pages/StoragePage.razor
+++ b/IGP/Pages/StoragePage.razor
@@ -1,20 +1,68 @@
@page "/storage"
+@inject IStorageService StorageService
+
+@using Services.Website
+@implements IDisposable
@layout PageLayout
-
- Not Implemented
-
-
-
- TODO
-
+ @if (!_enabledPermissions)
+ {
+
+ Storage Disabled
+ Enable Storage on the Permissions Page.
+
+ }
+ else
+ {
+
+
+
+
+
+ }
-
\ No newline at end of file
+
+
+@code {
+ bool _enabledPermissions;
+
+ protected override void OnInitialized()
+ {
+ _enabledPermissions = StorageService.GetValue(StorageKeys.EnabledStorage);
+
+ Update();
+
+ StorageService.Subscribe(Update);
+ }
+
+
+ public void Dispose()
+ {
+ StorageService.Unsubscribe(Update);
+ }
+
+ void Update()
+ {
+ _isEntityPlainView = StorageService.GetValue(StorageKeys.IsPlainView);
+
+ StateHasChanged();
+ }
+
+ private bool _isEntityPlainView;
+
+ private void EntityViewChanged(ChangeEventArgs obj)
+ {
+ StorageService.SetValue(StorageKeys.IsPlainView, obj.Value);
+ }
+}
\ No newline at end of file
diff --git a/IGP/Program.cs b/IGP/Program.cs
index 2ca70da..9215e57 100644
--- a/IGP/Program.cs
+++ b/IGP/Program.cs
@@ -1,8 +1,10 @@
using System.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Blazored.LocalStorage;
using IGP;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Services;
-using Model;
using Services;
using Services.Development;
using Services.Immortal;
@@ -17,11 +19,24 @@ builder.Logging.SetMinimumLevel(LogLevel.Warning);
builder.RootComponents.Add("#app");
builder.RootComponents.Add("head::after");
-builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
-builder.Services.AddScoped();
+builder.Services.AddSingleton(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
+builder.Services.AddSingleton();
+
+builder.Services.AddProtectedBrowserStorage();
builder.Services.AddLocalization();
+builder.Services.AddBlazoredLocalStorageAsSingleton(config =>
+{
+ config.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
+ config.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
+ config.JsonSerializerOptions.IgnoreReadOnlyProperties = true;
+ config.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
+ config.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ config.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
+ config.JsonSerializerOptions.WriteIndented = false;
+});
+
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
@@ -42,6 +57,9 @@ builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+
builder.Services.AddSingleton();
builder.Services.AddSingleton(new HttpClient
diff --git a/IGP/wwwroot/generated/AgileTaskModels.json b/IGP/wwwroot/generated/AgileTaskModels.json
index 4338f2f..51c246e 100644
--- a/IGP/wwwroot/generated/AgileTaskModels.json
+++ b/IGP/wwwroot/generated/AgileTaskModels.json
@@ -1 +1 @@
-[{"Id":1,"AgileSprintModelId":null,"Name":"Support Safari","Description":"Consider other web browsers.","Notes":"Added","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":2,"AgileSprintModelId":2,"Name":"Filter Patch Notes","Description":"You should be showing people what they really want to see in the patch notes.","Notes":"Added","Status":"Done","Priority":"Blocker","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":3,"AgileSprintModelId":5,"Name":"Consider Pyre","Description":"Add Pyre Income. Make it so you can take Pyre Camps and Pyre Miners","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":4,"AgileSprintModelId":5,"Name":"Optimizations","Description":"Build Calculator should be usable.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":5,"AgileSprintModelId":5,"Name":"Change Attack Timing Interval","Description":"Be able to set attack timing.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-15T00:00:00"},{"Id":6,"AgileSprintModelId":5,"Name":"Add Pyre Spells","Description":"Make Pyre Spells castable and consume Pyre on build order","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":7,"AgileSprintModelId":null,"Name":"Default builds (Rush Thrones)","Description":"Add a dropdown list of default builds.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":8,"AgileSprintModelId":null,"Name":"Load older builds","Description":"Be able to load older builds. How are you going to handle auto correct to current patch?","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":9,"AgileSprintModelId":null,"Name":"How to use Build Calculator step by step","Description":"Need docs","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":10,"AgileSprintModelId":null,"Name":"Compare Health and Damage","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":11,"AgileSprintModelId":null,"Name":"Compare Unit\u0027s Damage with it\u0027s own costs","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":12,"AgileSprintModelId":4,"Name":"View one unit stats from a link. Make YAML copy and paste","Description":"Design so people can easily copy and paste data into discord","Notes":"Ended up not using exact Yaml. Button in Database controls Detailed vs Plain display ","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":13,"AgileSprintModelId":2,"Name":"Look into SQL","Description":"You really should be using SQL.","Notes":"Agile and Change log pages now use SQL","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":14,"AgileSprintModelId":1,"Name":"Mobile Menu","Description":"You need a real mobile menu. Viewers don\u0027t scroll below the fold, so no one is going to know what happens when you click a button on phones.","Notes":"Added smaller menus for tablets and phones.","Status":"Done","Priority":"High","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":15,"AgileSprintModelId":2,"Name":"Acropolis Consume Mote","Description":"The Mote is suppose to be consumed when making a Town Hall.","Notes":"Fixed","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":16,"AgileSprintModelId":5,"Name":"Multiple Travel Time in Harass Calculator","Description":"Travel time should be based on the amount of bases used. 3 bases is 3 travel times.","Notes":"Add notes...","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":17,"AgileSprintModelId":1,"Name":"Update Database to 0.0.6.8375a","Description":"Xacal tech change, and Hallower damage change. Update Godhead text.","Notes":"Done","Status":"Done","Priority":"None","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":18,"AgileSprintModelId":null,"Name":"Patch History Viewer","Description":"Add an ability to compare patches, to see all nerfs and buffs made between them.","Notes":"Inspired by Zkay\u0027s post on discord, where he details a possible \u0027patch history viewer\u0027 implementation.","Status":"Fun_Idea","Priority":"None","Task":"Feature","OrderPriority":5,"Created":"2022-02-16T00:00:00","Finished":null},{"Id":19,"AgileSprintModelId":1,"Name":"Twitch Page","Description":"Did a ~3 hour test stream, and was personal quite happy with the quality. Make Twitch page, and stream patch, sprint planning and development on Sunday.","Notes":"Page added under General, and named \u0022Streams\u0022.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-16T00:00:00","Finished":"2022-02-16T00:00:00"},{"Id":20,"AgileSprintModelId":1,"Name":"Finish the database","Description":"Add more descriptions for everything. Reduce any data duplication with ids. Add upgrade connections. Add ability connections. Add passives and passives connections.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":21,"AgileSprintModelId":1,"Name":"Change Log View","Description":"Add a log to view last changes.","Notes":"Added changelog page. Shows Today, X Days Ago, or exact date if patch is over a week old.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-14T00:00:00","Finished":"2022-02-14T00:00:00"},{"Id":22,"AgileSprintModelId":1,"Name":"Agile View","Description":"Add the agile view.","Notes":"Finished.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-17T00:00:00"},{"Id":23,"AgileSprintModelId":1,"Name":"GUID for Ids","Description":"Stop using enums for ids, and start using guids. Enums are just too limited, I lose out on component and inheritance design with them. Replace all your enums with guids, rip off the bandaid.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":24,"AgileSprintModelId":1,"Name":"Co-op overview","Description":"Write some sort of blog on co-op gameplay so you have something the feels very content-ish. Maybe make it a video.","Notes":"Finished and released early.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-12T00:00:00"},{"Id":25,"AgileSprintModelId":1,"Name":"Mobile UI","Description":"Make website work on mobile.","Notes":"Should be good. Will test on phone later.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-15T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":26,"AgileSprintModelId":1,"Name":"Add Making Of View","Description":"View to reference UI designs. Nicely encourages the pratice of making the UI code a lot cleaner.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":27,"AgileSprintModelId":3,"Name":"Close Nav Menu on Navigation","Description":"Close Nav Menu on Navigation","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":28,"AgileSprintModelId":3,"Name":"Add Passive Descriptions and Passive","Description":"Have to guess on a bunch of passives","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-31T00:00:00"},{"Id":29,"AgileSprintModelId":3,"Name":"Tooltips that show referenced units","Description":"I should see any referenced unit by hovering over it","Notes":"Links can now go to links which can go to links.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":30,"AgileSprintModelId":null,"Name":"Update Logo for Website","Description":"After color scheme is picked","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":31,"AgileSprintModelId":3,"Name":"Documentation page","Description":"Add documents on how to maintain website","Notes":"Added start of documents","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":32,"AgileSprintModelId":6,"Name":"Test Automation","Description":"Selenium Tests","Notes":"Start adding IDs to everything","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":33,"AgileSprintModelId":null,"Name":"Unit Test","Description":"Add some unit tests","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":34,"AgileSprintModelId":4,"Name":"Fully Transfer everything to SQL","Description":"Need to regenerate the database once everthing is fully transfered","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-09T00:00:00"},{"Id":35,"AgileSprintModelId":3,"Name":"Adding a loading Component","Description":"For JSON loading","Notes":"Added loading component to Agile and Changelog screens","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":36,"AgileSprintModelId":3,"Name":"Optimize Loading of Data","Description":"Currently loading non Agile stuff on Agile page","Notes":"Moved SQL database injection to app root","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":37,"AgileSprintModelId":3,"Name":"Convert Notes to Markdown","Description":"Using Markdown and generating the Note pages seems like a better solution to SQL or hardcoding data","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":38,"AgileSprintModelId":3,"Name":"Improve Entity Filter Options","Description":"The options I give you is strange, given it filers on Faction type","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-01T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":39,"AgileSprintModelId":4,"Name":"Refresh Database Bug","Description":"Database dialog UI isn\u0027t refreshing enough","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":40,"AgileSprintModelId":4,"Name":"Branding Stuff","Description":"Add a schedule, improving branding, etc, ","Notes":"Only improved Twitch overlays","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":41,"AgileSprintModelId":4,"Name":"Improve Documents/Notes UI","Description":"Should have a left navigation menu. And prev/next buttons","Notes":"Updated UI. Will added prev/next and breadcrumbs later","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-05T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":42,"AgileSprintModelId":5,"Name":"Add GitHub links instead of showing code","Description":"For all code examples","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":43,"AgileSprintModelId":5,"Name":"Research More used RTS calculations","Description":"What other calculators like the Harass Page can be added","Notes":"Do amount of hits to kill, between two units. Maybe time to regen spell uses","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":44,"AgileSprintModelId":5,"Name":"Add Error Toasts to Calculator","Description":"Not enough \u0022Ether\u0022","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":45,"AgileSprintModelId":5,"Name":"Handle Divide by Zero in Harass Calculator","Description":"addDescription","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":46,"AgileSprintModelId":null,"Name":"Harass Calculator first client experience","Description":"Navigate player though the harass calculator steps","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":47,"AgileSprintModelId":5,"Name":"Training Queue","Description":"Add training queue times to the build calculator","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":48,"AgileSprintModelId":5,"Name":"Refresh Button for Build Calculator","Description":"Refresh to regenerate timeline and charts","Notes":"Adding a loading screen for charts. Remove redundant renders","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":49,"AgileSprintModelId":null,"Name":"Gameplay Warning State Toasts","Description":"\u0022You should upgrade your economy.\u0022 \u0022Your using too much ether, spend alloy\u0022","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":50,"AgileSprintModelId":5,"Name":"Make desktop navigation buttons","Description":"It popping up all the time is a tad tedious","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":51,"AgileSprintModelId":5,"Name":"Working Timers","Description":"Toast dismiss timers not making sense. Look into proper Timers","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":52,"AgileSprintModelId":5,"Name":"Clean up Build Calculator code","Description":"Code needs to be easily readable so it can be updated, maintained, and optimized","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-12T00:00:00","Finished":null},{"Id":53,"AgileSprintModelId":0,"Name":"Armor Types","Description":"Explain Light, Medium and Heavy armor types, and damage works","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":54,"AgileSprintModelId":0,"Name":"Economy Overview","Description":"How long it takes bases to mine out. How good natruals area","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":55,"AgileSprintModelId":0,"Name":"Timing and Scouting","Description":"Attacking and reacting to what the enemy is doing","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":56,"AgileSprintModelId":0,"Name":"Families, Factions, and Immortal Vanguards","Description":"How factions could be viewed.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":57,"AgileSprintModelId":0,"Name":"Immortals Spells and Pyre","Description":"Using your Immortal","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":58,"AgileSprintModelId":null,"Name":"Organize Sprint Order","Description":"Sprints should be ordered as, current sprint, previous sprint, backlog, easy tasks, future sprints, old sprints","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":59,"AgileSprintModelId":null,"Name":"Better Sorting Algorithms ","Description":"Be smarted with searching through and sorting lists","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":60,"AgileSprintModelId":6,"Name":"Settings Section","Description":"Add a settings area, for permission and cookie related content","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":61,"AgileSprintModelId":6,"Name":"Analytics","Description":"Track client going to each page.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":62,"AgileSprintModelId":6,"Name":"Cookies","Description":"Cookies to remember a the client permission options ","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":63,"AgileSprintModelId":6,"Name":"Permission Controls Page","Description":"Allow clients to enable cookies, analytics, and perhaps make things more granular. ","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":64,"AgileSprintModelId":6,"Name":"Defaults Page","Description":"Let clients set a cookie for Plain/Detailed view. Perhaps default Immortal. Etc.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":65,"AgileSprintModelId":6,"Name":"Analytics Page","Description":"Let\u0027s have a page that shows the analytics collected during a client\u0027s session","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":66,"AgileSprintModelId":5,"Name":"Economy Comparison","Description":"Compare different economies. Make this a page under resources","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-15T00:00:00","Finished":"2022-04-17T00:00:00"},{"Id":67,"AgileSprintModelId":5,"Name":"[Ctrl \u002B K] Search feature","Description":"WIP. Needs polish","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-16T00:00:00","Finished":"2022-04-16T00:00:00"},{"Id":68,"AgileSprintModelId":6,"Name":"Lighthouse Score","Description":"Lighthouse score is awful. Try to get to the green","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-16T00:00:00","Finished":null},{"Id":69,"AgileSprintModelId":6,"Name":"SEO","Description":"People might be trying to google this website instead of bookmarking it. Make sure its googleable","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":70,"AgileSprintModelId":6,"Name":"AttacksPerSecond Format Setting","Description":"Make SunSpear\u0027s DPS formatting the default, and allow people to turn it off in settings, for people that don\u0027t like the SBA/APS swapping","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":71,"AgileSprintModelId":5,"Name":"Fix Cancel Button Giving Money","Description":"Things can be built faster if you cancel","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":72,"AgileSprintModelId":5,"Name":"Calculations Change Answers Over Time","Description":"Obviously a bug in the calculation logic","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"}]
\ No newline at end of file
+[{"Id":1,"AgileSprintModelId":null,"Name":"Support Safari","Description":"Consider other web browsers.","Notes":"Added","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":2,"AgileSprintModelId":2,"Name":"Filter Patch Notes","Description":"You should be showing people what they really want to see in the patch notes.","Notes":"Added","Status":"Done","Priority":"Blocker","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":3,"AgileSprintModelId":5,"Name":"Consider Pyre","Description":"Add Pyre Income. Make it so you can take Pyre Camps and Pyre Miners","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":4,"AgileSprintModelId":5,"Name":"Optimizations","Description":"Build Calculator should be usable.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":5,"AgileSprintModelId":5,"Name":"Change Attack Timing Interval","Description":"Be able to set attack timing.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-15T00:00:00"},{"Id":6,"AgileSprintModelId":5,"Name":"Add Pyre Spells","Description":"Make Pyre Spells castable and consume Pyre on build order","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":7,"AgileSprintModelId":null,"Name":"Default builds (Rush Thrones)","Description":"Add a dropdown list of default builds.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":8,"AgileSprintModelId":null,"Name":"Load older builds","Description":"Be able to load older builds. How are you going to handle auto correct to current patch?","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":9,"AgileSprintModelId":null,"Name":"How to use Build Calculator step by step","Description":"Need docs","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":10,"AgileSprintModelId":null,"Name":"Compare Health and Damage","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":11,"AgileSprintModelId":null,"Name":"Compare Unit\u0027s Damage with it\u0027s own costs","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":12,"AgileSprintModelId":4,"Name":"View one unit stats from a link. Make YAML copy and paste","Description":"Design so people can easily copy and paste data into discord","Notes":"Ended up not using exact Yaml. Button in Database controls Detailed vs Plain display ","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":13,"AgileSprintModelId":2,"Name":"Look into SQL","Description":"You really should be using SQL.","Notes":"Agile and Change log pages now use SQL","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":14,"AgileSprintModelId":1,"Name":"Mobile Menu","Description":"You need a real mobile menu. Viewers don\u0027t scroll below the fold, so no one is going to know what happens when you click a button on phones.","Notes":"Added smaller menus for tablets and phones.","Status":"Done","Priority":"High","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":15,"AgileSprintModelId":2,"Name":"Acropolis Consume Mote","Description":"The Mote is suppose to be consumed when making a Town Hall.","Notes":"Fixed","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":16,"AgileSprintModelId":5,"Name":"Multiple Travel Time in Harass Calculator","Description":"Travel time should be based on the amount of bases used. 3 bases is 3 travel times.","Notes":"Add notes...","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":17,"AgileSprintModelId":1,"Name":"Update Database to 0.0.6.8375a","Description":"Xacal tech change, and Hallower damage change. Update Godhead text.","Notes":"Done","Status":"Done","Priority":"None","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":18,"AgileSprintModelId":null,"Name":"Patch History Viewer","Description":"Add an ability to compare patches, to see all nerfs and buffs made between them.","Notes":"Inspired by Zkay\u0027s post on discord, where he details a possible \u0027patch history viewer\u0027 implementation.","Status":"Fun_Idea","Priority":"None","Task":"Feature","OrderPriority":5,"Created":"2022-02-16T00:00:00","Finished":null},{"Id":19,"AgileSprintModelId":1,"Name":"Twitch Page","Description":"Did a ~3 hour test stream, and was personal quite happy with the quality. Make Twitch page, and stream patch, sprint planning and development on Sunday.","Notes":"Page added under General, and named \u0022Streams\u0022.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-16T00:00:00","Finished":"2022-02-16T00:00:00"},{"Id":20,"AgileSprintModelId":1,"Name":"Finish the database","Description":"Add more descriptions for everything. Reduce any data duplication with ids. Add upgrade connections. Add ability connections. Add passives and passives connections.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":21,"AgileSprintModelId":1,"Name":"Change Log View","Description":"Add a log to view last changes.","Notes":"Added changelog page. Shows Today, X Days Ago, or exact date if patch is over a week old.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-14T00:00:00","Finished":"2022-02-14T00:00:00"},{"Id":22,"AgileSprintModelId":1,"Name":"Agile View","Description":"Add the agile view.","Notes":"Finished.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-17T00:00:00"},{"Id":23,"AgileSprintModelId":1,"Name":"GUID for Ids","Description":"Stop using enums for ids, and start using guids. Enums are just too limited, I lose out on component and inheritance design with them. Replace all your enums with guids, rip off the bandaid.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":24,"AgileSprintModelId":1,"Name":"Co-op overview","Description":"Write some sort of blog on co-op gameplay so you have something the feels very content-ish. Maybe make it a video.","Notes":"Finished and released early.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-12T00:00:00"},{"Id":25,"AgileSprintModelId":1,"Name":"Mobile UI","Description":"Make website work on mobile.","Notes":"Should be good. Will test on phone later.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-15T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":26,"AgileSprintModelId":1,"Name":"Add Making Of View","Description":"View to reference UI designs. Nicely encourages the pratice of making the UI code a lot cleaner.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":27,"AgileSprintModelId":3,"Name":"Close Nav Menu on Navigation","Description":"Close Nav Menu on Navigation","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":28,"AgileSprintModelId":3,"Name":"Add Passive Descriptions and Passive","Description":"Have to guess on a bunch of passives","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-31T00:00:00"},{"Id":29,"AgileSprintModelId":3,"Name":"Tooltips that show referenced units","Description":"I should see any referenced unit by hovering over it","Notes":"Links can now go to links which can go to links.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":30,"AgileSprintModelId":null,"Name":"Update Logo for Website","Description":"After color scheme is picked","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":31,"AgileSprintModelId":3,"Name":"Documentation page","Description":"Add documents on how to maintain website","Notes":"Added start of documents","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":32,"AgileSprintModelId":6,"Name":"Test Automation","Description":"Selenium Tests","Notes":"Start adding IDs to everything","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":33,"AgileSprintModelId":6,"Name":"Unit Test","Description":"Add some unit tests","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":34,"AgileSprintModelId":4,"Name":"Fully Transfer everything to SQL","Description":"Need to regenerate the database once everthing is fully transfered","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-09T00:00:00"},{"Id":35,"AgileSprintModelId":3,"Name":"Adding a loading Component","Description":"For JSON loading","Notes":"Added loading component to Agile and Changelog screens","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":36,"AgileSprintModelId":3,"Name":"Optimize Loading of Data","Description":"Currently loading non Agile stuff on Agile page","Notes":"Moved SQL database injection to app root","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":37,"AgileSprintModelId":3,"Name":"Convert Notes to Markdown","Description":"Using Markdown and generating the Note pages seems like a better solution to SQL or hardcoding data","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":38,"AgileSprintModelId":3,"Name":"Improve Entity Filter Options","Description":"The options I give you is strange, given it filers on Faction type","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-01T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":39,"AgileSprintModelId":4,"Name":"Refresh Database Bug","Description":"Database dialog UI isn\u0027t refreshing enough","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":40,"AgileSprintModelId":4,"Name":"Branding Stuff","Description":"Add a schedule, improving branding, etc, ","Notes":"Only improved Twitch overlays","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":41,"AgileSprintModelId":4,"Name":"Improve Documents/Notes UI","Description":"Should have a left navigation menu. And prev/next buttons","Notes":"Updated UI. Will added prev/next and breadcrumbs later","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-05T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":42,"AgileSprintModelId":5,"Name":"Add GitHub links instead of showing code","Description":"For all code examples","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":43,"AgileSprintModelId":5,"Name":"Research More used RTS calculations","Description":"What other calculators like the Harass Page can be added","Notes":"Do amount of hits to kill, between two units. Maybe time to regen spell uses","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":44,"AgileSprintModelId":5,"Name":"Add Error Toasts to Calculator","Description":"Not enough \u0022Ether\u0022","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":45,"AgileSprintModelId":5,"Name":"Handle Divide by Zero in Harass Calculator","Description":"addDescription","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":46,"AgileSprintModelId":6,"Name":"Harass Calculator first client experience","Description":"Navigate player though the harass calculator steps","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":47,"AgileSprintModelId":5,"Name":"Training Queue","Description":"Add training queue times to the build calculator","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":48,"AgileSprintModelId":5,"Name":"Refresh Button for Build Calculator","Description":"Refresh to regenerate timeline and charts","Notes":"Adding a loading screen for charts. Remove redundant renders","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":49,"AgileSprintModelId":null,"Name":"Gameplay Warning State Toasts","Description":"\u0022You should upgrade your economy.\u0022 \u0022Your using too much ether, spend alloy\u0022","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":50,"AgileSprintModelId":5,"Name":"Make desktop navigation buttons","Description":"It popping up all the time is a tad tedious","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":51,"AgileSprintModelId":5,"Name":"Working Timers","Description":"Toast dismiss timers not making sense. Look into proper Timers","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":52,"AgileSprintModelId":5,"Name":"Clean up Build Calculator code","Description":"Code needs to be easily readable so it can be updated, maintained, and optimized","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-12T00:00:00","Finished":null},{"Id":53,"AgileSprintModelId":0,"Name":"Armor Types","Description":"Explain Light, Medium and Heavy armor types, and damage works","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":54,"AgileSprintModelId":0,"Name":"Economy Overview","Description":"How long it takes bases to mine out. How good natruals area","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":55,"AgileSprintModelId":0,"Name":"Timing and Scouting","Description":"Attacking and reacting to what the enemy is doing","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":56,"AgileSprintModelId":0,"Name":"Families, Factions, and Immortal Vanguards","Description":"How factions could be viewed.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":57,"AgileSprintModelId":0,"Name":"Immortals Spells and Pyre","Description":"Using your Immortal","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":58,"AgileSprintModelId":6,"Name":"Organize Sprint Order","Description":"Sprints should be ordered as, current sprint, previous sprint, backlog, easy tasks, future sprints, old sprints","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":59,"AgileSprintModelId":null,"Name":"Better Sorting Algorithms ","Description":"Be smarted with searching through and sorting lists","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":60,"AgileSprintModelId":6,"Name":"Settings Section","Description":"Add a settings area, for permission and cookie related content","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":61,"AgileSprintModelId":6,"Name":"Analytics","Description":"Track client going to each page.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":62,"AgileSprintModelId":6,"Name":"Cookies","Description":"Cookies to remember a the client permission options ","Notes":"addNotes","Status":"In_Progress","Priority":"Medium","Task":"Feature","OrderPriority":1,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":63,"AgileSprintModelId":6,"Name":"Permission Controls Page","Description":"Allow clients to enable cookies, analytics, and perhaps make things more granular. ","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":64,"AgileSprintModelId":6,"Name":"Defaults Page","Description":"Let clients set a cookie for Plain/Detailed view. Perhaps default Immortal. Etc.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":65,"AgileSprintModelId":6,"Name":"Analytics Page","Description":"Let\u0027s have a page that shows the analytics collected during a client\u0027s session","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":66,"AgileSprintModelId":5,"Name":"Economy Comparison","Description":"Compare different economies. Make this a page under resources","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-15T00:00:00","Finished":"2022-04-17T00:00:00"},{"Id":67,"AgileSprintModelId":5,"Name":"[Ctrl \u002B K] Search feature","Description":"WIP. Needs polish","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-16T00:00:00","Finished":"2022-04-16T00:00:00"},{"Id":68,"AgileSprintModelId":6,"Name":"Lighthouse Score","Description":"Lighthouse score is awful. Try to get to the green","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-16T00:00:00","Finished":null},{"Id":69,"AgileSprintModelId":6,"Name":"SEO","Description":"People might be trying to google this website instead of bookmarking it. Make sure its googleable","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":70,"AgileSprintModelId":6,"Name":"AttacksPerSecond Format Setting","Description":"Make SunSpear\u0027s DPS formatting the default, and allow people to turn it off in settings, for people that don\u0027t like the SBA/APS swapping","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":71,"AgileSprintModelId":5,"Name":"Fix Cancel Button Giving Money","Description":"Things can be built faster if you cancel","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":72,"AgileSprintModelId":5,"Name":"Calculations Change Answers Over Time","Description":"Obviously a bug in the calculation logic","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"}]
\ No newline at end of file
diff --git a/IGP/wwwroot/generated/WebPageModels.json b/IGP/wwwroot/generated/WebPageModels.json
index 24bed6f..752ac0d 100644
--- a/IGP/wwwroot/generated/WebPageModels.json
+++ b/IGP/wwwroot/generated/WebPageModels.json
@@ -1 +1 @@
-[{"Id":1,"WebSectionModelId":2,"Name":"Database","Description":"Database of game information","Href":"database","IsPrivate":"False"},{"Id":2,"WebSectionModelId":1,"Name":"Build Calculator","Description":"Build order calculator for determining army timings","Href":"build-calculator","IsPrivate":"False"},{"Id":3,"WebSectionModelId":1,"Name":"Harass Calculator","Description":"Alloy harassment calculator","Href":"harass-calculator","IsPrivate":"False"},{"Id":4,"WebSectionModelId":1,"Name":"Memory Tester","Description":"Testing memory","Href":"memory-tester","IsPrivate":"False"},{"Id":5,"WebSectionModelId":1,"Name":"Comparion Charts","Description":"Ecnomy charts to compare build orders","Href":"comparison-charts","IsPrivate":"True"},{"Id":6,"WebSectionModelId":2,"Name":"Notes","Description":"General player notes","Href":"notes","IsPrivate":"False"},{"Id":7,"WebSectionModelId":2,"Name":"Key Mapping","Description":"General key mapping info","Href":"keymapping","IsPrivate":"True"},{"Id":8,"WebSectionModelId":4,"Name":"Road Map","Description":"Plans for this website","Href":"roadmap","IsPrivate":"False"},{"Id":9,"WebSectionModelId":4,"Name":"Change Log","Description":"Past updates to the website","Href":"changelog","IsPrivate":"False"},{"Id":10,"WebSectionModelId":4,"Name":"Agile","Description":"Showing agile view of this website","Href":"agile","IsPrivate":"False"},{"Id":11,"WebSectionModelId":4,"Name":"Making Of","Description":"Explaining development details of this website","Href":"makingof","IsPrivate":"False"},{"Id":12,"WebSectionModelId":2,"Name":"Documentation","Description":"Explaining how to use this website","Href":"documentation","IsPrivate":"True"},{"Id":13,"WebSectionModelId":3,"Name":"About","Description":"Answering general questions on the website","Href":"about","IsPrivate":"False"},{"Id":14,"WebSectionModelId":3,"Name":"Contact","Description":"My contact info","Href":"contact","IsPrivate":"False"},{"Id":15,"WebSectionModelId":3,"Name":"Streams","Description":"Stream info","Href":"streams","IsPrivate":"False"},{"Id":16,"WebSectionModelId":4,"Name":"Documentation","Description":"Development information","Href":"docs","IsPrivate":"False"},{"Id":17,"WebSectionModelId":5,"Name":"Permissions","Description":"Permission Settings","Href":"permissions","IsPrivate":"False"},{"Id":18,"WebSectionModelId":5,"Name":"Analytics","Description":"Analytics Settings","Href":"analytics","IsPrivate":"False"},{"Id":19,"WebSectionModelId":5,"Name":"Storage","Description":"Storage Settings","Href":"storage","IsPrivate":"False"},{"Id":20,"WebSectionModelId":1,"Name":"Economy Comparison","Description":"Compare economies","Href":"economy-comparison","IsPrivate":"False"}]
\ No newline at end of file
+[{"Id":1,"WebSectionModelId":2,"Name":"Database","Description":"Database of game information","Href":"database","IsPrivate":"False"},{"Id":2,"WebSectionModelId":1,"Name":"Build Calculator","Description":"Build order calculator for determining army timings","Href":"build-calculator","IsPrivate":"False"},{"Id":3,"WebSectionModelId":1,"Name":"Harass Calculator","Description":"Alloy harassment calculator","Href":"harass-calculator","IsPrivate":"False"},{"Id":4,"WebSectionModelId":1,"Name":"Memory Tester","Description":"Testing memory","Href":"memory-tester","IsPrivate":"False"},{"Id":5,"WebSectionModelId":1,"Name":"Comparion Charts","Description":"Ecnomy charts to compare build orders","Href":"comparison-charts","IsPrivate":"True"},{"Id":6,"WebSectionModelId":2,"Name":"Notes","Description":"General player notes","Href":"notes","IsPrivate":"False"},{"Id":7,"WebSectionModelId":2,"Name":"Key Mapping","Description":"General key mapping info","Href":"keymapping","IsPrivate":"True"},{"Id":8,"WebSectionModelId":4,"Name":"Road Map","Description":"Plans for this website","Href":"roadmap","IsPrivate":"False"},{"Id":9,"WebSectionModelId":4,"Name":"Change Log","Description":"Past updates to the website","Href":"changelog","IsPrivate":"False"},{"Id":10,"WebSectionModelId":4,"Name":"Agile","Description":"Showing agile view of this website","Href":"agile","IsPrivate":"False"},{"Id":11,"WebSectionModelId":4,"Name":"Making Of","Description":"Explaining development details of this website","Href":"makingof","IsPrivate":"False"},{"Id":12,"WebSectionModelId":2,"Name":"Documentation","Description":"Explaining how to use this website","Href":"documentation","IsPrivate":"True"},{"Id":13,"WebSectionModelId":3,"Name":"About","Description":"Answering general questions on the website","Href":"about","IsPrivate":"False"},{"Id":14,"WebSectionModelId":3,"Name":"Contact","Description":"My contact info","Href":"contact","IsPrivate":"False"},{"Id":15,"WebSectionModelId":3,"Name":"Streams","Description":"Stream info","Href":"streams","IsPrivate":"False"},{"Id":16,"WebSectionModelId":4,"Name":"Documentation","Description":"Development information","Href":"docs","IsPrivate":"False"},{"Id":17,"WebSectionModelId":5,"Name":"Permissions","Description":"Permission Settings","Href":"permissions","IsPrivate":"False"},{"Id":18,"WebSectionModelId":5,"Name":"Data Collection","Description":"Data Collection Settings","Href":"data-collection","IsPrivate":"False"},{"Id":19,"WebSectionModelId":5,"Name":"Storage","Description":"Storage Settings","Href":"storage","IsPrivate":"False"},{"Id":20,"WebSectionModelId":1,"Name":"Economy Comparison","Description":"Compare economies","Href":"economy-comparison","IsPrivate":"False"}]
\ No newline at end of file
diff --git a/IGP/wwwroot/index.html b/IGP/wwwroot/index.html
index 53cc9d7..fbeb2d0 100644
--- a/IGP/wwwroot/index.html
+++ b/IGP/wwwroot/index.html
@@ -52,6 +52,7 @@
document.addEventListener("keydown", function (e) {
DotNetReference?.invokeMethodAsync('OnKeyPress', e.key, e.ctrlKey, e.shiftKey, e.altKey, e.metaKey)
});
+
diff --git a/Services/IServices.cs b/Services/IServices.cs
index 6787d8f..5f521cb 100644
--- a/Services/IServices.cs
+++ b/Services/IServices.cs
@@ -1,4 +1,5 @@
-using Model.BuildOrders;
+using Microsoft.AspNetCore.Components.ProtectedBrowserStorage;
+using Model.BuildOrders;
using Model.Doc;
using Model.Economy;
using Model.Entity;
@@ -10,6 +11,7 @@ using Model.Website;
using Model.Website.Enums;
using Model.Work.Tasks;
using Services.Immortal;
+using Services.Website;
namespace Services;
@@ -25,6 +27,30 @@ public interface IToastService
void ClearAllToasts();
}
+public interface IStorageService
+{
+ public void Subscribe(Action action);
+ public void Unsubscribe(Action action);
+ T GetValue(string forKey);
+ void SetValue(string key, T value);
+
+ Task Load();
+}
+
+public interface IPermissionService
+{
+ public void Subscribe(Action action);
+ public void Unsubscribe(Action action);
+
+ public bool GetIsStorageEnabled();
+ public bool GetIsDataCollectionEnabled();
+
+ public void SetIsStorageEnabled(bool isEnabled);
+ public void SetIsDataCollectionEnabled(bool isEnabled);
+
+ Task Load();
+}
+
public interface ISearchService
{
public List SearchPoints { get; set; }
diff --git a/Services/Immortal/EntityDisplayService.cs b/Services/Immortal/EntityDisplayService.cs
index 6531929..5b9cc54 100644
--- a/Services/Immortal/EntityDisplayService.cs
+++ b/Services/Immortal/EntityDisplayService.cs
@@ -1,12 +1,28 @@
-namespace Services.Immortal;
+using Services.Website;
+namespace Services.Immortal;
+
+public class EntityViewType
+{
+ public static string Detailed = "Detailed";
+ public static string Plain = "Plain";
+
+}
public class EntityDisplayService : IEntityDisplayService
{
- private string displayType = "Detailed";
+ private string _displayType;
+ public EntityDisplayService(IStorageService storageService)
+ {
+ _displayType = storageService.GetValue(StorageKeys.IsPlainView)
+ ? EntityViewType.Plain : EntityViewType.Detailed;
+ }
+
+
+
public List DefaultChoices()
{
- return new List { "Detailed", "Plain" };
+ return new List { EntityViewType.Detailed, EntityViewType.Plain };
}
public void Subscribe(Action action)
@@ -21,12 +37,12 @@ public class EntityDisplayService : IEntityDisplayService
public string GetDisplayType()
{
- return displayType;
+ return _displayType;
}
public void SetDisplayType(string displayType)
{
- this.displayType = displayType;
+ this._displayType = displayType;
NotifyDataChanged();
}
diff --git a/Services/Services.csproj b/Services/Services.csproj
index 5ced067..d10ad33 100644
--- a/Services/Services.csproj
+++ b/Services/Services.csproj
@@ -15,11 +15,14 @@
-
+
+
+
+
-
+
diff --git a/Services/Website/PermissionService.cs b/Services/Website/PermissionService.cs
new file mode 100644
index 0000000..07c7755
--- /dev/null
+++ b/Services/Website/PermissionService.cs
@@ -0,0 +1,64 @@
+using Blazored.LocalStorage;
+using Microsoft.JSInterop;
+
+namespace Services.Website;
+
+public class PermissionService : IPermissionService
+{
+ private bool isLoaded;
+
+
+ private IJSRuntime _jsRuntime;
+ private bool isStorageEnabled = false;
+ private IToastService _toastService;
+ private IStorageService _storageService;
+
+ public PermissionService(IJSRuntime jsRuntime, IToastService toastService, IStorageService storageService)
+ {
+ _jsRuntime = jsRuntime;
+ _toastService = toastService;
+ _storageService = storageService;
+ }
+
+ public void Subscribe(Action action)
+ {
+ OnChange += action;
+ }
+
+ public void Unsubscribe(Action action)
+ {
+ OnChange += action;
+ }
+
+ public bool GetIsStorageEnabled()
+ {
+ return _storageService.GetValue(StorageKeys.EnabledStorage);
+ }
+
+ public bool GetIsDataCollectionEnabled()
+ {
+ return _storageService.GetValue(StorageKeys.EnabledDataCollection);
+ }
+
+ public void SetIsStorageEnabled(bool isEnabled)
+ {
+ _storageService.SetValue(StorageKeys.EnabledStorage, isEnabled);
+ }
+
+ public void SetIsDataCollectionEnabled(bool isEnabled)
+ {
+ _storageService.SetValue(StorageKeys.EnabledDataCollection, isEnabled);
+ }
+
+ public Task Load()
+ {
+ throw new NotImplementedException();
+ }
+
+ private event Action OnChange = null!;
+
+ private void NotifyDataChanged()
+ {
+ OnChange();
+ }
+}
\ No newline at end of file
diff --git a/Services/Website/StorageService.cs b/Services/Website/StorageService.cs
new file mode 100644
index 0000000..29fd007
--- /dev/null
+++ b/Services/Website/StorageService.cs
@@ -0,0 +1,106 @@
+using Blazored.LocalStorage;
+using Microsoft.JSInterop;
+using Model.Feedback;
+
+namespace Services.Website;
+
+public class StorageKeys
+{
+ public static string EnabledStorage = "StorageEnabled";
+ public static string EnabledDataCollection = "StorageDataCollection";
+ public static string IsPlainView { get; set; } = "IsPlainView";
+}
+
+public class StorageService : IStorageService
+{
+ private readonly ISyncLocalStorageService _localStorageService;
+ private IJSRuntime _jsRuntime;
+ private readonly IToastService _toastService;
+ private bool isLoaded;
+ private bool isStorageEnabled;
+
+
+ public StorageService(IJSRuntime jsRuntime, IToastService toastService,
+ ISyncLocalStorageService localStorageService)
+ {
+ _jsRuntime = jsRuntime;
+ _toastService = toastService;
+ _localStorageService = localStorageService;
+ }
+
+ private string enabledKey => StorageKeys.EnabledStorage;
+
+ public void Subscribe(Action action)
+ {
+ OnChange += action;
+ }
+
+ public void Unsubscribe(Action action)
+ {
+ OnChange += action;
+ }
+
+ public T GetValue(string forKey)
+ {
+ return _localStorageService.GetItem(forKey);
+ }
+
+ public void SetValue(string key, T value)
+ {
+ if (key.Equals(StorageKeys.EnabledStorage) && value.Equals(true))
+ {
+ _localStorageService.SetItem(key, value);
+ NotifyDataChanged();
+ return;
+ }
+
+ if (key.Equals(StorageKeys.EnabledStorage))
+ {
+ _localStorageService.Clear();
+ NotifyDataChanged();
+ return;
+ }
+
+ var isEnabled = GetValue(StorageKeys.EnabledStorage);
+ if (!isEnabled)
+ {
+ _toastService.AddToast(new ToastModel
+ {
+ Title = "Permission Error",
+ SeverityType = SeverityType.Error,
+ Message = "Storage must be enabled before Storage can be used."
+ });
+ NotifyDataChanged();
+ return;
+ }
+
+ _localStorageService.SetItem(key, value);
+ NotifyDataChanged();
+ }
+
+ public async Task Load()
+ {
+ if (!isLoaded) return;
+
+
+ isLoaded = true;
+
+ isStorageEnabled = GetValue(enabledKey);
+
+ NotifyDataChanged();
+ }
+
+ private event Action OnChange = null!;
+
+ private void NotifyDataChanged()
+ {
+ try
+ {
+
+ OnChange();
+ }
+ catch (Exception e)
+ {
+ }
+ }
+}
\ No newline at end of file