Hangover. WinForms. Restore deleted books
This commit is contained in:
parent
7ad0ab566a
commit
b2cf837de7
@ -9,7 +9,6 @@ using Dinah.Core;
|
|||||||
using DtoImporterService;
|
using DtoImporterService;
|
||||||
using LibationFileManager;
|
using LibationFileManager;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using static System.Reflection.Metadata.BlobBuilder;
|
|
||||||
using static DtoImporterService.PerfLogger;
|
using static DtoImporterService.PerfLogger;
|
||||||
|
|
||||||
namespace ApplicationServices
|
namespace ApplicationServices
|
||||||
@ -336,7 +335,7 @@ namespace ApplicationServices
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region remove books
|
#region remove/restore books
|
||||||
public static Task<int> RemoveBooksAsync(List<string> idsToRemove) => Task.Run(() => removeBooks(idsToRemove));
|
public static Task<int> RemoveBooksAsync(List<string> idsToRemove) => Task.Run(() => removeBooks(idsToRemove));
|
||||||
public static int RemoveBook(string idToRemove) => removeBooks(new() { idToRemove });
|
public static int RemoveBook(string idToRemove) => removeBooks(new() { idToRemove });
|
||||||
private static int removeBooks(List<string> idsToRemove)
|
private static int removeBooks(List<string> idsToRemove)
|
||||||
@ -368,11 +367,40 @@ namespace ApplicationServices
|
|||||||
Log.Logger.Error(ex, "Error removing books");
|
Log.Logger.Error(ex, "Error removing books");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
// call this whenever books are added or removed from library
|
public static int RestoreBooks(this List<LibraryBook> libraryBooks)
|
||||||
private static void finalizeLibrarySizeChange() => LibrarySizeChanged?.Invoke(null, null);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (libraryBooks is null || !libraryBooks.Any())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
using var context = DbContexts.GetContext();
|
||||||
|
|
||||||
|
// Attach() NoTracking entities before SaveChanges()
|
||||||
|
foreach (var lb in libraryBooks)
|
||||||
|
{
|
||||||
|
lb.IsDeleted = false;
|
||||||
|
context.Attach(lb).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
var qtyChanges = context.SaveChanges();
|
||||||
|
if (qtyChanges > 0)
|
||||||
|
finalizeLibrarySizeChange();
|
||||||
|
|
||||||
|
return qtyChanges;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Logger.Error(ex, "Error restoring books");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// call this whenever books are added or removed from library
|
||||||
|
private static void finalizeLibrarySizeChange() => LibrarySizeChanged?.Invoke(null, null);
|
||||||
|
|
||||||
/// <summary>Occurs when the size of the library changes. ie: books are added or removed</summary>
|
/// <summary>Occurs when the size of the library changes. ie: books are added or removed</summary>
|
||||||
public static event EventHandler LibrarySizeChanged;
|
public static event EventHandler LibrarySizeChanged;
|
||||||
|
|||||||
@ -39,6 +39,19 @@ namespace DataLayer
|
|||||||
public static IQueryable<LibraryBook> GetLibrary(this IQueryable<LibraryBook> library)
|
public static IQueryable<LibraryBook> GetLibrary(this IQueryable<LibraryBook> library)
|
||||||
=> library
|
=> library
|
||||||
.Where(lb => !lb.IsDeleted)
|
.Where(lb => !lb.IsDeleted)
|
||||||
|
.getLibrary();
|
||||||
|
|
||||||
|
public static List<LibraryBook> GetDeletedLibraryBooks(this LibationContext context)
|
||||||
|
=> context
|
||||||
|
.LibraryBooks
|
||||||
|
.AsNoTrackingWithIdentityResolution()
|
||||||
|
.Where(lb => lb.IsDeleted)
|
||||||
|
.getLibrary()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
/// <summary>This is still IQueryable. YOU MUST CALL ToList() YOURSELF</summary>
|
||||||
|
private static IQueryable<LibraryBook> getLibrary(this IQueryable<LibraryBook> library)
|
||||||
|
=> library
|
||||||
// owned items are always loaded. eg: book.UserDefinedItem, book.Supplements
|
// owned items are always loaded. eg: book.UserDefinedItem, book.Supplements
|
||||||
.Include(le => le.Book).ThenInclude(b => b.SeriesLink).ThenInclude(sb => sb.Series)
|
.Include(le => le.Book).ThenInclude(b => b.SeriesLink).ThenInclude(sb => sb.Series)
|
||||||
.Include(le => le.Book).ThenInclude(b => b.ContributorsLink).ThenInclude(c => c.Contributor)
|
.Include(le => le.Book).ThenInclude(b => b.ContributorsLink).ThenInclude(c => c.Contributor)
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using AppScaffolding;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using HangoverAvalonia.ViewModels;
|
using HangoverAvalonia.ViewModels;
|
||||||
|
|
||||||
@ -9,7 +10,11 @@ namespace HangoverAvalonia.Views
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
|
||||||
|
var config = LibationScaffolding.RunPreConfigMigrations();
|
||||||
|
LibationScaffolding.RunPostConfigMigrations(config);
|
||||||
|
LibationScaffolding.RunPostMigrationScaffolding(config);
|
||||||
|
}
|
||||||
|
|
||||||
public void Execute_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
public void Execute_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -11,7 +11,7 @@ namespace HangoverWinForms
|
|||||||
|
|
||||||
private void cliTab_VisibleChanged(object sender, EventArgs e)
|
private void cliTab_VisibleChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (!databaseTab.Visible)
|
if (!cliTab.Visible)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
Source/HangoverWinForms/Form1.Deleted.cs
Normal file
73
Source/HangoverWinForms/Form1.Deleted.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using ApplicationServices;
|
||||||
|
using DataLayer;
|
||||||
|
|
||||||
|
namespace HangoverWinForms
|
||||||
|
{
|
||||||
|
public partial class Form1
|
||||||
|
{
|
||||||
|
private string deletedCheckedTemplate;
|
||||||
|
|
||||||
|
private void Load_deletedTab()
|
||||||
|
{
|
||||||
|
deletedCheckedTemplate = deletedCheckedLbl.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deletedTab_VisibleChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!deletedTab.Visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (deletedCbl.Items.Count == 0)
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deletedCbl_ItemCheck(object sender, ItemCheckEventArgs e)
|
||||||
|
{
|
||||||
|
// CheckedItems.Count is not updated until after the event fires
|
||||||
|
setLabel(e.NewValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAllBtn_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < deletedCbl.Items.Count; i++)
|
||||||
|
deletedCbl.SetItemChecked(i, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uncheckAllBtn_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < deletedCbl.Items.Count; i++)
|
||||||
|
deletedCbl.SetItemChecked(i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveBtn_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var libraryBooksToRestore = deletedCbl.CheckedItems.Cast<LibraryBook>().ToList();
|
||||||
|
var qtyChanges = libraryBooksToRestore.RestoreBooks();
|
||||||
|
if (qtyChanges > 0)
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reload()
|
||||||
|
{
|
||||||
|
deletedCbl.Items.Clear();
|
||||||
|
var deletedBooks = DbContexts.GetContext().GetDeletedLibraryBooks();
|
||||||
|
foreach (var lb in deletedBooks)
|
||||||
|
deletedCbl.Items.Add(lb);
|
||||||
|
|
||||||
|
setLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLabel(CheckState? checkedState = null)
|
||||||
|
{
|
||||||
|
var pre = deletedCbl.CheckedItems.Count;
|
||||||
|
int count = checkedState switch
|
||||||
|
{
|
||||||
|
CheckState.Checked => pre + 1,
|
||||||
|
CheckState.Unchecked => pre - 1,
|
||||||
|
_ => pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
deletedCheckedLbl.Text = string.Format(deletedCheckedTemplate, count, deletedCbl.Items.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
98
Source/HangoverWinForms/Form1.Designer.cs
generated
98
Source/HangoverWinForms/Form1.Designer.cs
generated
@ -36,14 +36,23 @@
|
|||||||
this.sqlTb = new System.Windows.Forms.TextBox();
|
this.sqlTb = new System.Windows.Forms.TextBox();
|
||||||
this.sqlLbl = new System.Windows.Forms.Label();
|
this.sqlLbl = new System.Windows.Forms.Label();
|
||||||
this.databaseFileLbl = new System.Windows.Forms.Label();
|
this.databaseFileLbl = new System.Windows.Forms.Label();
|
||||||
|
this.deletedTab = new System.Windows.Forms.TabPage();
|
||||||
|
this.deletedCheckedLbl = new System.Windows.Forms.Label();
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.saveBtn = new System.Windows.Forms.Button();
|
||||||
|
this.uncheckAllBtn = new System.Windows.Forms.Button();
|
||||||
|
this.checkAllBtn = new System.Windows.Forms.Button();
|
||||||
|
this.deletedCbl = new System.Windows.Forms.CheckedListBox();
|
||||||
this.cliTab = new System.Windows.Forms.TabPage();
|
this.cliTab = new System.Windows.Forms.TabPage();
|
||||||
this.tabControl1.SuspendLayout();
|
this.tabControl1.SuspendLayout();
|
||||||
this.databaseTab.SuspendLayout();
|
this.databaseTab.SuspendLayout();
|
||||||
|
this.deletedTab.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// tabControl1
|
// tabControl1
|
||||||
//
|
//
|
||||||
this.tabControl1.Controls.Add(this.databaseTab);
|
this.tabControl1.Controls.Add(this.databaseTab);
|
||||||
|
this.tabControl1.Controls.Add(this.deletedTab);
|
||||||
this.tabControl1.Controls.Add(this.cliTab);
|
this.tabControl1.Controls.Add(this.cliTab);
|
||||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.tabControl1.Location = new System.Drawing.Point(0, 0);
|
this.tabControl1.Location = new System.Drawing.Point(0, 0);
|
||||||
@ -119,6 +128,86 @@
|
|||||||
this.databaseFileLbl.TabIndex = 0;
|
this.databaseFileLbl.TabIndex = 0;
|
||||||
this.databaseFileLbl.Text = "Database file: ";
|
this.databaseFileLbl.Text = "Database file: ";
|
||||||
//
|
//
|
||||||
|
// deletedTab
|
||||||
|
//
|
||||||
|
this.deletedTab.Controls.Add(this.deletedCheckedLbl);
|
||||||
|
this.deletedTab.Controls.Add(this.label1);
|
||||||
|
this.deletedTab.Controls.Add(this.saveBtn);
|
||||||
|
this.deletedTab.Controls.Add(this.uncheckAllBtn);
|
||||||
|
this.deletedTab.Controls.Add(this.checkAllBtn);
|
||||||
|
this.deletedTab.Controls.Add(this.deletedCbl);
|
||||||
|
this.deletedTab.Location = new System.Drawing.Point(4, 24);
|
||||||
|
this.deletedTab.Name = "deletedTab";
|
||||||
|
this.deletedTab.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.deletedTab.Size = new System.Drawing.Size(792, 422);
|
||||||
|
this.deletedTab.TabIndex = 2;
|
||||||
|
this.deletedTab.Text = "Deleted Books";
|
||||||
|
this.deletedTab.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// deletedCheckedLbl
|
||||||
|
//
|
||||||
|
this.deletedCheckedLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.deletedCheckedLbl.AutoSize = true;
|
||||||
|
this.deletedCheckedLbl.Location = new System.Drawing.Point(233, 395);
|
||||||
|
this.deletedCheckedLbl.Name = "deletedCheckedLbl";
|
||||||
|
this.deletedCheckedLbl.Size = new System.Drawing.Size(104, 15);
|
||||||
|
this.deletedCheckedLbl.TabIndex = 6;
|
||||||
|
this.deletedCheckedLbl.Text = "Checked: {0} of {1}";
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.AutoSize = true;
|
||||||
|
this.label1.Location = new System.Drawing.Point(8, 3);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(239, 15);
|
||||||
|
this.label1.TabIndex = 0;
|
||||||
|
this.label1.Text = "To restore deleted book, check box and save";
|
||||||
|
//
|
||||||
|
// saveBtn
|
||||||
|
//
|
||||||
|
this.saveBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.saveBtn.Location = new System.Drawing.Point(709, 391);
|
||||||
|
this.saveBtn.Name = "saveBtn";
|
||||||
|
this.saveBtn.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.saveBtn.TabIndex = 5;
|
||||||
|
this.saveBtn.Text = "Save";
|
||||||
|
this.saveBtn.UseVisualStyleBackColor = true;
|
||||||
|
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
|
||||||
|
//
|
||||||
|
// uncheckAllBtn
|
||||||
|
//
|
||||||
|
this.uncheckAllBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.uncheckAllBtn.Location = new System.Drawing.Point(129, 391);
|
||||||
|
this.uncheckAllBtn.Name = "uncheckAllBtn";
|
||||||
|
this.uncheckAllBtn.Size = new System.Drawing.Size(98, 23);
|
||||||
|
this.uncheckAllBtn.TabIndex = 4;
|
||||||
|
this.uncheckAllBtn.Text = "Uncheck All";
|
||||||
|
this.uncheckAllBtn.UseVisualStyleBackColor = true;
|
||||||
|
this.uncheckAllBtn.Click += new System.EventHandler(this.uncheckAllBtn_Click);
|
||||||
|
//
|
||||||
|
// checkAllBtn
|
||||||
|
//
|
||||||
|
this.checkAllBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.checkAllBtn.Location = new System.Drawing.Point(8, 391);
|
||||||
|
this.checkAllBtn.Name = "checkAllBtn";
|
||||||
|
this.checkAllBtn.Size = new System.Drawing.Size(98, 23);
|
||||||
|
this.checkAllBtn.TabIndex = 3;
|
||||||
|
this.checkAllBtn.Text = "Check All";
|
||||||
|
this.checkAllBtn.UseVisualStyleBackColor = true;
|
||||||
|
this.checkAllBtn.Click += new System.EventHandler(this.checkAllBtn_Click);
|
||||||
|
//
|
||||||
|
// deletedCbl
|
||||||
|
//
|
||||||
|
this.deletedCbl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.deletedCbl.FormattingEnabled = true;
|
||||||
|
this.deletedCbl.Location = new System.Drawing.Point(8, 21);
|
||||||
|
this.deletedCbl.Name = "deletedCbl";
|
||||||
|
this.deletedCbl.Size = new System.Drawing.Size(776, 364);
|
||||||
|
this.deletedCbl.TabIndex = 2;
|
||||||
|
this.deletedCbl.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.deletedCbl_ItemCheck);
|
||||||
|
//
|
||||||
// cliTab
|
// cliTab
|
||||||
//
|
//
|
||||||
this.cliTab.Location = new System.Drawing.Point(4, 24);
|
this.cliTab.Location = new System.Drawing.Point(4, 24);
|
||||||
@ -140,6 +229,8 @@
|
|||||||
this.tabControl1.ResumeLayout(false);
|
this.tabControl1.ResumeLayout(false);
|
||||||
this.databaseTab.ResumeLayout(false);
|
this.databaseTab.ResumeLayout(false);
|
||||||
this.databaseTab.PerformLayout();
|
this.databaseTab.PerformLayout();
|
||||||
|
this.deletedTab.ResumeLayout(false);
|
||||||
|
this.deletedTab.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -154,5 +245,12 @@
|
|||||||
private Label sqlLbl;
|
private Label sqlLbl;
|
||||||
private Button sqlExecuteBtn;
|
private Button sqlExecuteBtn;
|
||||||
private TabPage cliTab;
|
private TabPage cliTab;
|
||||||
|
private TabPage deletedTab;
|
||||||
|
private CheckedListBox deletedCbl;
|
||||||
|
private Label label1;
|
||||||
|
private Button saveBtn;
|
||||||
|
private Button uncheckAllBtn;
|
||||||
|
private Button checkAllBtn;
|
||||||
|
private Label deletedCheckedLbl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
namespace HangoverWinForms
|
using AppScaffolding;
|
||||||
|
|
||||||
|
namespace HangoverWinForms
|
||||||
{
|
{
|
||||||
public partial class Form1 : Form
|
public partial class Form1 : Form
|
||||||
{
|
{
|
||||||
@ -6,11 +8,17 @@
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
var config = LibationScaffolding.RunPreConfigMigrations();
|
||||||
|
LibationScaffolding.RunPostConfigMigrations(config);
|
||||||
|
LibationScaffolding.RunPostMigrationScaffolding(config);
|
||||||
|
|
||||||
databaseTab.VisibleChanged += databaseTab_VisibleChanged;
|
databaseTab.VisibleChanged += databaseTab_VisibleChanged;
|
||||||
cliTab.VisibleChanged += cliTab_VisibleChanged;
|
cliTab.VisibleChanged += cliTab_VisibleChanged;
|
||||||
|
deletedTab.VisibleChanged += deletedTab_VisibleChanged;
|
||||||
|
|
||||||
Load_databaseTab();
|
Load_databaseTab();
|
||||||
Load_cliTab();
|
Load_cliTab();
|
||||||
|
Load_deletedTab();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -383,8 +383,7 @@ namespace LibationWinForms.GridView
|
|||||||
|
|
||||||
if (visibleCount != bindingList.Count)
|
if (visibleCount != bindingList.Count)
|
||||||
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
|
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user