Skip to content

Commit

Permalink
Merge pull request #318 from LiamMorrow/backup-alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
LiamMorrow authored Nov 16, 2024
2 parents 759182e + 1277a1e commit 470fbbc
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 24 deletions.
2 changes: 1 addition & 1 deletion LiftLog.Api/Db/UserDataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class UserDataContext(DbContextOptions<UserDataContext> options) : DbCont
/// <summary>
/// Used to register the user event filter tuple type as a DbSet for use in FromSqlRaw.
/// </summary>
public DbSet<UserEventFilter> UserEventFilterStubDbSet { get; set; }
public DbSet<UserEventFilter> UserEventFilterStubDbSet { get; set; } = null!;

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
Expand Down
2 changes: 2 additions & 0 deletions LiftLog.Ui/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ else
</TextContent>
</ConfirmationDialog>
<BackupAlert />
@code {
private ConfirmationDialog? replaceCurrentSesisonDialog;
Expand Down
18 changes: 18 additions & 0 deletions LiftLog.Ui/Pages/Settings/BackupAndRestorePage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
@inject IDispatcher Dispatcher
@inject IJSRuntime JSRuntime
@inject IDeviceService DeviceService
@inject IState<SettingsState> SettingsState

@inherits Fluxor.Blazor.Web.Components.FluxorComponent

Expand All @@ -26,6 +27,7 @@
<span slot="headline">Plaintext export</span>
<span slot="supporting-text">Export your data in a plaintext format such as CSV for use in other applications</span>
</md-list-item>
<ListSwitch Headline="Backup reminders" SupportingText="Periodically suggest a backup when you have not backed up in a while" Value="@SettingsState.Value.BackupReminder" OnSwitched="SetBackupReminder" />
</md-list>


Expand Down Expand Up @@ -58,6 +60,11 @@
private ConfirmationDialog? importFeedDialog;
private ConfirmationDialog? exportFeedDialog;
private InputFile? fileInput;

[Parameter]
[SupplyParameterFromQuery(Name = "backup")]
public bool Backup { get; set; }

protected override void OnInitialized()
{
Dispatcher.Dispatch(new SetPageTitleAction("Export, Backup and Restore"));
Expand All @@ -66,6 +73,15 @@
base.OnInitialized();
}

protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender && Backup)
{
exportFeedDialog?.Open();
}
}

private async Task LoadFiles(InputFileChangeEventArgs e)
{
using System.IO.Compression.GZipStream gzip = new(e.File.OpenReadStream(), System.IO.Compression.CompressionMode.Decompress);
Expand Down Expand Up @@ -97,6 +113,8 @@
importFeedDialog?.Open();
}

private void SetBackupReminder(bool value) => Dispatcher.Dispatch(new SetBackupReminderAction(value));

private void ImportFeedData()
{
if (importedFeedState is null)
Expand Down
27 changes: 27 additions & 0 deletions LiftLog.Ui/Repository/PreferencesRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,31 @@ public async Task SetLastSuccessfulRemoteBackupHashAsync(string hash)
{
return await preferenceStore.GetItemAsync("lastSuccessfulRemoteBackupHash");
}

public async Task SetLastBackupTimeAsync(DateTimeOffset time)
{
await preferenceStore.SetItemAsync("lastBackupTime", time.ToString("O"));
}

public async Task<DateTimeOffset> GetLastBackupTimeAsync()
{
var lastBackupTime = await preferenceStore.GetItemAsync("lastBackupTime");
if (DateTimeOffset.TryParse(lastBackupTime, out var time))
return time;
else
{
await SetLastBackupTimeAsync(DateTimeOffset.Now);
return DateTimeOffset.Now;
}
}

public async Task SetBackupReminderAsync(bool showReminder)
{
await preferenceStore.SetItemAsync("backupReminder", showReminder.ToString());
}

public async Task<bool> GetBackupReminderAsync()
{
return await preferenceStore.GetItemAsync("backupReminder") is "True" or null;
}
}
58 changes: 58 additions & 0 deletions LiftLog.Ui/Shared/Smart/BackupAlert.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

@inject IState<SettingsState> SettingsState
@inject IDispatcher Dispatcher

<Dialog @ref="dialog" @ondialog-cancel="No" type="alert">
<span slot="headline">Back up data</span>
<span slot="content" class="block text-left">
It has been a while since you last created a backup. It is HIGHLY recommended you back up your data regularly to prevent data loss.
Would you like to back up your data now?
</span>
<div slot="actions">
<AppButton Type="AppButtonType.Text" OnClick="DontAsk">Don't ask again</AppButton>
<AppButton Type="AppButtonType.Text" OnClick="No">No</AppButton>
<AppButton Type="AppButtonType.Text" OnClick="BackUp">Yes</AppButton>
</div>
</Dialog>

@code {
private Dialog? dialog;

protected override void OnInitialized()
{
base.OnInitialized();

}

protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
var lastBackupTime = SettingsState.Value.LastBackupTime;
var timeSinceLastBackup = DateTimeOffset.Now - lastBackupTime;
if (SettingsState.Value.BackupReminder && timeSinceLastBackup.TotalDays > 7)
{
dialog?.Open();
}
}
}

private void DontAsk()
{
Dispatcher.Dispatch(new SetBackupReminderAction(false));
dialog?.Close();
}

private void No()
{
dialog?.Close();
}

private async Task BackUp()
{
await dialog!.CloseWait();
Dispatcher.Dispatch(new NavigateAction("/settings/backup-and-restore?backup=true"));
}
}
4 changes: 4 additions & 0 deletions LiftLog.Ui/Store/Settings/SettingsActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ public record UpdateRemoteBackupSettingsAction(RemoteBackupSettings Settings);

public record SetLastSuccessfulRemoteBackupHashAction(string Hash);

public record SetLastBackupTimeAction(DateTimeOffset Time);

public record SetBackupReminderAction(bool ShowReminder);

public record ExportPlainTextAction(PlaintextExportFormat Format);
16 changes: 15 additions & 1 deletion LiftLog.Ui/Store/Settings/SettingsEffects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ HttpClient httpClient
)
{
[EffectMethod]
public async Task ExportData(ExportBackupDataAction action, IDispatcher __)
public async Task ExportData(ExportBackupDataAction action, IDispatcher dispatcher)
{
await textExporter.ExportBytesAsync(
(await GetDataExportAsync(action.ExportFeed)).ToByteArray()
);
dispatcher.Dispatch(new SetLastBackupTimeAction(DateTimeOffset.Now));
}

[EffectMethod]
Expand Down Expand Up @@ -257,6 +258,7 @@ public async Task ExecuteRemoteBackup(ExecuteRemoteBackupAction action, IDispatc
result.EnsureSuccessStatusCode();
dispatcher.Dispatch(new SetLastSuccessfulRemoteBackupHashAction(hashString));
dispatcher.Dispatch(new RemoteBackupSucceededEvent());
dispatcher.Dispatch(new SetLastBackupTimeAction(DateTimeOffset.Now));
}
catch (HttpRequestException ex) when (ex.StatusCode is null)
{
Expand Down Expand Up @@ -294,6 +296,18 @@ IDispatcher __
await preferencesRepository.SetRemoteBackupSettingsAsync(action.Settings);
}

[EffectMethod]
public async Task SetLastBackupTime(SetLastBackupTimeAction action, IDispatcher __)
{
await preferencesRepository.SetLastBackupTimeAsync(action.Time);
}

[EffectMethod]
public async Task SetBackupReminder(SetBackupReminderAction action, IDispatcher __)
{
await preferencesRepository.SetBackupReminderAsync(action.ShowReminder);
}

private async Task<ExportedDataDaoV2> GetDataExportAsync(bool includeFeed)
{
var sessions = await progressRepository.GetOrderedSessions().ToListAsync();
Expand Down
18 changes: 1 addition & 17 deletions LiftLog.Ui/Store/Settings/SettingsFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,5 @@ public class SettingsFeature : Feature<SettingsState>
{
public override string GetName() => nameof(SettingsFeature);

protected override SettingsState GetInitialState() =>
new(
IsHydrated: false,
AiWorkoutAttributes: null,
IsGeneratingAiPlan: false,
AiPlanError: null,
AiPlan: null,
UseImperialUnits: false,
ShowBodyweight: true,
ShowTips: true,
TipToShow: 1,
ShowFeed: true,
StatusBarFix: false,
RestNotifications: true,
RemoteBackupSettings: new RemoteBackupSettings(string.Empty, string.Empty, false),
LastSuccessfulRemoteBackupHash: string.Empty
);
protected override SettingsState GetInitialState() => SettingsState.Default;
}
12 changes: 12 additions & 0 deletions LiftLog.Ui/Store/Settings/SettingsReducers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ public static SettingsState UpdateRemoteBackupSettings(
UpdateRemoteBackupSettingsAction action
) => state with { RemoteBackupSettings = action.Settings };

[ReducerMethod]
public static SettingsState SetLastBackupTime(
SettingsState state,
SetLastBackupTimeAction action
) => state with { LastBackupTime = action.Time };

[ReducerMethod]
public static SettingsState SetBackupReminder(
SettingsState state,
SetBackupReminderAction action
) => state with { BackupReminder = action.ShowReminder };

[ReducerMethod]
public static SettingsState SetLastSuccessfulRemoteBackupHash(
SettingsState state,
Expand Down
27 changes: 25 additions & 2 deletions LiftLog.Ui/Store/Settings/SettingsState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,31 @@ public record SettingsState(
bool StatusBarFix,
bool RestNotifications,
RemoteBackupSettings RemoteBackupSettings,
string LastSuccessfulRemoteBackupHash
);
string LastSuccessfulRemoteBackupHash,
DateTimeOffset LastBackupTime,
bool BackupReminder
)
{
public static SettingsState Default =>
new(
IsHydrated: false,
AiWorkoutAttributes: null,
IsGeneratingAiPlan: false,
AiPlanError: null,
AiPlan: null,
UseImperialUnits: false,
ShowBodyweight: true,
ShowTips: true,
TipToShow: 1,
ShowFeed: true,
StatusBarFix: false,
RestNotifications: true,
RemoteBackupSettings: new RemoteBackupSettings(string.Empty, string.Empty, false),
LastSuccessfulRemoteBackupHash: string.Empty,
LastBackupTime: DateTimeOffset.MinValue,
BackupReminder: true
);
}

public record RemoteBackupSettings(string Endpoint, string ApiKey, bool IncludeFeedAccount)
{
Expand Down
11 changes: 8 additions & 3 deletions LiftLog.Ui/Store/Settings/SettingsStateInitMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Fluxor;
using LiftLog.Ui.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;

namespace LiftLog.Ui.Store.Settings;
Expand All @@ -24,7 +23,9 @@ public override async Task InitializeAsync(IDispatcher dispatch, IStore store)
statusBarFix,
restNotifications,
remoteBackupSettings,
lastSuccessfulRemoteBackupHash
lastSuccessfulRemoteBackupHash,
lastBackupTime,
backupReminder
) = await (
preferencesRepository.GetUseImperialUnitsAsync(),
preferencesRepository.GetShowBodyweightAsync(),
Expand All @@ -34,7 +35,9 @@ public override async Task InitializeAsync(IDispatcher dispatch, IStore store)
preferencesRepository.GetStatusBarFixAsync(),
preferencesRepository.GetRestNotificationsAsync(),
preferencesRepository.GetRemoteBackupSettingsAsync(),
preferencesRepository.GetLastSuccessfulRemoteBackupHashAsync()
preferencesRepository.GetLastSuccessfulRemoteBackupHashAsync(),
preferencesRepository.GetLastBackupTimeAsync(),
preferencesRepository.GetBackupReminderAsync()
);

var state = (SettingsState)store.Features[nameof(SettingsFeature)].GetState() with
Expand All @@ -49,6 +52,8 @@ public override async Task InitializeAsync(IDispatcher dispatch, IStore store)
RestNotifications = restNotifications,
RemoteBackupSettings = remoteBackupSettings,
LastSuccessfulRemoteBackupHash = lastSuccessfulRemoteBackupHash,
LastBackupTime = lastBackupTime,
BackupReminder = backupReminder,
};
store.Features[nameof(SettingsFeature)].RestoreState(state);
sw.Stop();
Expand Down

0 comments on commit 470fbbc

Please sign in to comment.