Commit db39351

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2023-11-25 10:52:23
add ExportColumnsManager field to database
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 3e90cc7
Changed files (5)
lib/model/storage/db/config_dao.dart
@@ -1,5 +1,6 @@
 import 'package:blood_pressure_app/model/export_import/legacy_column.dart';
 import 'package:blood_pressure_app/model/storage/db/config_db.dart';
+import 'package:blood_pressure_app/model/storage/export_columns_store.dart';
 import 'package:blood_pressure_app/model/storage/export_csv_settings_store.dart';
 import 'package:blood_pressure_app/model/storage/export_pdf_settings_store.dart';
 import 'package:blood_pressure_app/model/storage/export_settings_store.dart';
@@ -260,6 +261,54 @@ class ConfigDao {
         conflictAlgorithm: ConflictAlgorithm.replace
     );
   }
+  
+  /// Loads the profiles [ExportColumnsManager] object from the database.
+  ///
+  /// If any errors occur or the object is not present, a default one will be created. Changes in the object
+  /// will save to the database automatically (a listener gets attached).
+  ///
+  /// Changes to the database will not propagate to the object.
+  Future<ExportColumnsManager> loadExportColumnsManager(int profileID) async {
+    final dbEntry = await _configDB.database.query(
+        ConfigDB.exportColumnsTable,
+        columns: ['json'],
+        where: 'profile_id = ?',
+        whereArgs: [profileID]
+    );
+
+    late final ExportColumnsManager columnsManager;
+    if (dbEntry.isEmpty) {
+      columnsManager = ExportColumnsManager();
+    } else {
+      assert(dbEntry.length == 1, 'The profile_id should be unique.');
+      final json = dbEntry.first['json'];
+      if (json == null) {
+        columnsManager = ExportColumnsManager();
+      } else {
+        columnsManager = ExportColumnsManager.fromJson(json.toString());
+      }
+    }
+    _updateExportColumnsManager(profileID, columnsManager);
+    columnsManager.addListener(() {
+      _updateExportColumnsManager(profileID, columnsManager);
+    });
+    return columnsManager;
+  }
+
+  /// Update [ExportColumnsManager] for a profile in the database.
+  ///
+  /// Adds an entry if necessary.
+  Future<void> _updateExportColumnsManager(int profileID, ExportColumnsManager manager) async {
+    if (!_configDB.database.isOpen) return;
+    await _configDB.database.insert(
+        ConfigDB.exportColumnsTable,
+        {
+          'profile_id': profileID,
+          'json': manager.toJson()
+        },
+        conflictAlgorithm: ConflictAlgorithm.replace
+    );
+  }
 
   /// Loads the current export columns from the database.
   ///
lib/model/storage/db/config_db.dart
@@ -76,10 +76,19 @@ class ConfigDB {
   ///
   /// Format:
   /// `CREATE TABLE exportStrings(internalColumnName STRING PRIMARY KEY, columnTitle STRING, formatPattern STRING)`
+  @Deprecated('removed after all usages are replaced by export_columns_store')
   static const String exportStringsTable = 'exportStrings';
   static const String _exportStringsTableCreationString =
       'CREATE TABLE exportStrings(internalColumnName STRING PRIMARY KEY, columnTitle STRING, formatPattern STRING)';
 
+  /// Name of table of storing [ExportColumnsManager] objects
+  ///
+  /// Format:
+  /// `CREATE TABLE exportColumns(profile_id INTEGER PRIMARY KEY, json STRING)`
+  static const String exportColumnsTable = 'exportColumns';
+  static const String _exportColumnsTableCreationString =
+      'CREATE TABLE exportColumns(profile_id INTEGER PRIMARY KEY, json STRING)';
+
   late final Database _database;
 
   /// [dbPath] is the path to the folder the database is in. When [dbPath] is left empty the default database file is
@@ -95,7 +104,7 @@ class ConfigDB {
       onCreate: _onDBCreate,
       onUpgrade: _onDBUpgrade,
       // When increasing the version an update procedure from every other possible version is needed
-      version: 2,
+      version: 3,
     );
   }
 
@@ -106,18 +115,23 @@ class ConfigDB {
     await db.execute(_exportCsvSettingsTableCreationString);
     await db.execute(_exportPdfSettingsTableCreationString);
     await db.execute(_selectedIntervallStorageCreationString);
+    await db.execute(_exportColumnsTableCreationString);
   }
 
   FutureOr<void> _onDBUpgrade(Database db, int oldVersion, int newVersion) async {
     // When adding more versions the upgrade procedure proposed in https://stackoverflow.com/a/75153875/21489239
     // might be useful, to avoid duplicated code. Currently this would only lead to complexity without benefits.
-    if (oldVersion == 1 && newVersion == 2) {
+    assert(newVersion == 3);
+    if (oldVersion == 1) { // TODO: migrate data, delete old table and test update
       await db.execute(_settingsTableCreationString);
       await db.execute(_exportSettingsTableCreationString);
       await db.execute(_exportCsvSettingsTableCreationString);
       await db.execute(_exportPdfSettingsTableCreationString);
       await db.execute(_selectedIntervallStorageCreationString);
+      await db.execute(_exportColumnsTableCreationString);
       await db.database.setVersion(2);
+    } else if (oldVersion == 2) {
+      await db.execute(_exportColumnsTableCreationString);
     } else {
       assert(false, 'Unexpected version upgrade from $oldVersion to $newVersion.');
     }
lib/model/storage/export_columns_store.dart
@@ -37,6 +37,7 @@ class ExportColumnsManager extends ChangeNotifier {
   void deleteUserColumn(String identifier) {
     assert(_userColumns.containsKey(identifier), 'Don\'t call for non user columns');
     _userColumns.remove(identifier);
+    notifyListeners();
   }
 
   String toJson() {
lib/main.dart
@@ -40,6 +40,7 @@ Future<Widget> _loadApp() async {
   final csvExportSettings = await configDao.loadCsvExportSettings(0);
   final pdfExportSettings = await configDao.loadPdfExportSettings(0);
   final intervalStorageManager = await IntervallStoreManager.load(configDao, 0);
+  final exportColumnsManager = await configDao.loadExportColumnsManager(0);
 
   await updateLegacySettings(settings, exportSettings, csvExportSettings, pdfExportSettings, intervalStorageManager);
 
@@ -55,6 +56,7 @@ Future<Widget> _loadApp() async {
     ChangeNotifierProvider(create: (context) => csvExportSettings),
     ChangeNotifierProvider(create: (context) => pdfExportSettings),
     ChangeNotifierProvider(create: (context) => intervalStorageManager),
+    ChangeNotifierProvider(create: (context) => exportColumnsManager),
   ], child: const AppRoot());
 }
 
test/model/export_import/columns_store_test.dart
@@ -16,7 +16,7 @@ void main() {
       expect(manager.userColumns['test2']?.csvTitle, 'test2');
     });
 
-    test('should be restoreable from json', () async {
+    test('should be restoreable from json', () async { // TODO: consider moving to json_serialization_test and adding crash tests
       final init = ExportColumnsManager();
       init.addOrUpdate(UserColumn('test', 'test', '\$SYS'));
       init.addOrUpdate(UserColumn('test2', 'test2', '234'));