]> gitweb.hamatoma.de Git - exhibition.git/commitdiff
page list_xxx_custom works with paging managed by chips
authorHamatoma <author.hamatoma.de>
Fri, 22 Oct 2021 23:16:05 +0000 (01:16 +0200)
committerHamatoma <author.hamatoma.de>
Fri, 22 Oct 2021 23:16:05 +0000 (01:16 +0200)
34 files changed:
lib/page/benchmarks/create_benchmark_custom.dart
lib/page/benchmarks/create_benchmark_page.dart
lib/page/benchmarks/delete_benchmark_custom.dart
lib/page/benchmarks/delete_benchmark_page.dart
lib/page/benchmarks/edit_benchmark_custom.dart
lib/page/benchmarks/edit_benchmark_page.dart
lib/page/benchmarks/list_benchmark_custom.dart
lib/page/benchmarks/list_benchmark_page.dart
lib/page/roles/create_role_custom.dart
lib/page/roles/create_role_page.dart
lib/page/roles/edit_role_custom.dart
lib/page/roles/edit_role_page.dart
lib/page/roles/list_role_custom.dart
lib/page/roles/list_role_page.dart
lib/page/structures/create_structure_custom.dart
lib/page/structures/create_structure_page.dart
lib/page/structures/delete_structure_custom.dart
lib/page/structures/delete_structure_page.dart
lib/page/structures/edit_structure_custom.dart
lib/page/structures/edit_structure_page.dart
lib/page/structures/list_structure_custom.dart
lib/page/structures/list_structure_page.dart
lib/page/users/create_user_custom.dart
lib/page/users/create_user_page.dart
lib/page/users/delete_user_custom.dart
lib/page/users/delete_user_page.dart
lib/page/users/edit_user_custom.dart
lib/page/users/edit_user_page.dart
lib/page/users/list_user_custom.dart
lib/page/users/list_user_page.dart
lib/setting/global_data.dart
lib/widget/attended_page.dart
metatool/bin/page_generator.dart
rest_server/lib/rest_server.dart

index 8aa8fab53ec3009630ff7e65153eef69b7edd189..7c16160b84908863af0a10005154f409fa4c9969 100644 (file)
@@ -106,7 +106,8 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -153,7 +154,7 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
     super.initState();
   }
 
-  void store() {
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Benchmarks',
       'sql': 'insert',
@@ -175,10 +176,10 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index f69e701395fe931a7ea1a3177d8436dbfa5af042..2dc827211c30fbfb936cd4e0382e041e58fedcb8 100644 (file)
@@ -19,7 +19,8 @@ class CreateBenchmarkPage extends StatefulWidget {
         BenchmarkMeta.instance.pageByName('create')!,
         BenchmarkMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _CreateBenchmarkPageState extends CreateBenchmarkCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 35031504c5f19367bbf0f7c0103224b6e7cbf49a..17bce39fad0dd5c891192d2b81732a6c4ddcd6dd 100644 (file)
@@ -39,30 +39,14 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -134,7 +118,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndDelete(),
+              onPressed: () => onVerifyAndDelete(),
               child: Text(i18n.tr('Delete'))),
           weight: 8,
           gapAbove: 2 * padding),
@@ -167,9 +151,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -190,12 +172,16 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
     super.initState();
   }
 
-  void delete() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onDelete() {
     final parameters = <String, dynamic>{
       'module': 'Benchmarks',
       'sql': 'delete',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
@@ -203,10 +189,10 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
     });
   }
 
-  void verifyAndDelete() {
+  void onVerifyAndDelete() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      delete();
+      onDelete();
     }
   }
 }
index 4a4bff4dfd4412d4b21e12daae702123efbfdde3..9891dd61ce179429fbd2bc3be3a1700329fec10d 100644 (file)
@@ -20,7 +20,8 @@ class DeleteBenchmarkPage extends StatefulWidget {
         BenchmarkMeta.instance.pageByName('delete')!,
         BenchmarkMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _DeleteBenchmarkPageState extends DeleteBenchmarkCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 78664aee277432712e7a7ff9d30988b2629fbb93..147b64423b6f769f0fcce15f956e729007b40352 100644 (file)
@@ -38,30 +38,14 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -133,7 +117,8 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -165,9 +150,7 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -188,25 +171,30 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
     super.initState();
   }
 
-  void store() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Benchmarks',
       'sql': 'update',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     _fieldData.toMap(parameters);
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
+      requestRecord();
       attendedPage!.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index 5b0aeae45b96196fe3475f07b6c44e7938f2409d..32c93167338833b461a2cf89a4d28efbcecc05a3 100644 (file)
@@ -20,7 +20,8 @@ class EditBenchmarkPage extends StatefulWidget {
         BenchmarkMeta.instance.pageByName('edit')!,
         BenchmarkMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _EditBenchmarkPageState extends EditBenchmarkCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 0707e76ae8df3253afc67f3dce8e656ec7eac98f..2907e7e1cf989f94544e08732080504522cd06ab 100644 (file)
@@ -5,13 +5,11 @@ import 'package:flutter/material.dart';
 import '../../base/defines.dart';
 import '../../base/helper.dart';
 import '../../base/i18n.dart';
-import '../../base/validators.dart';
 import '../../services/global_widget.dart';
 import '../../setting/global_data.dart';
 import '../../widget/attended_page.dart';
 import '../../widget/widget_form.dart';
 import '../../persistence/persistence.dart';
-import '../../common/benchmark_actions.dart';
 import 'list_benchmark_page.dart';
 
 final i18n = I18N();
@@ -24,8 +22,6 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateBenchmark');
   final textController = TextEditingController();
-  final countController = TextEditingController();
-  final resultController = TextEditingController();
   ListBenchmarkCustom();
   @override
   Widget build(BuildContext context) {
@@ -54,7 +50,8 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
                   onDone: () => setState(() => 1),
                   routeEdit: '/Benchmarks/edit',
                   context: context);
-              rc = buildFrame(rows: rows);
+              rc = buildFrame(
+                  totalCount: snapshot.data?.count ?? rows.length, rows: rows);
             } else if (snapshot.hasError) {
               rc = Text('Backend problem: ${snapshot.error}');
             } else {
@@ -68,7 +65,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
     return rc;
   }
 
-  Widget buildFrame({required JsonList rows}) {
+  Widget buildFrame({required JsonList rows, required int totalCount}) {
     final padding = GlobalThemeData.padding;
     final formItems = <FormItem>[
       FormItem(
@@ -83,57 +80,19 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
           weight: 12,
           gapAbove: padding),
     ];
-    final belowForm = Padding(
-        padding: EdgeInsets.symmetric(vertical: padding, horizontal: padding),
-        child: Column(children: [
-          SizedBox(
-            height: padding,
-          ),
-          Row(children: [
-            Expanded(
-                child: TextFormField(
-              controller: countController,
-              decoration: InputDecoration(labelText: i18n.tr('Count')),
-              onSaved: (value) => _fieldData.count = value ?? '',
-              validator: (input) => isNat(input),
-            )),
-            SizedBox(width: padding),
-            Expanded(
-                child: ElevatedButton(
-                    onPressed: () => createNew(),
-                    child: Text(i18n.tr('Create new elements')))),
-            SizedBox(width: padding),
-            Expanded(
-                child: ElevatedButton(
-                    onPressed: () => readItems(),
-                    child: Text(i18n.tr('Read existing elements')))),
-          ]),
-          SizedBox(height: padding),
-          Row(children: [
-            Expanded(
-                child: TextFormField(
-              controller: resultController,
-              decoration: InputDecoration(labelText: i18n.tr('Message')),
-              readOnly: true,
-            ))
-          ])
-        ]));
     final form = Form(
         key: _formKey,
-        child: Column(children: [
-          Card(
-              color: GlobalThemeData.formBackgroundColor,
-              elevation: GlobalThemeData.formElevation,
-              margin:
-                  EdgeInsets.symmetric(vertical: padding, horizontal: padding),
-              child: Padding(
-                  padding: EdgeInsets.symmetric(
-                      vertical: padding, horizontal: padding),
-                  child: WidgetForm.flexibleGrid(formItems,
-                      screenWidth: attendedPage!.pageStates.screenWidth,
-                      padding: padding))),
-          belowForm,
-        ]));
+        child: Card(
+            color: GlobalThemeData.formBackgroundColor,
+            elevation: GlobalThemeData.formElevation,
+            margin:
+                EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+            child: Padding(
+                padding: EdgeInsets.symmetric(
+                    vertical: padding, horizontal: padding),
+                child: WidgetForm.flexibleGrid(formItems,
+                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
         DataColumn(
@@ -157,8 +116,15 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar =
-        attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+    Widget? tabBar = attendedPage!.buildChipBar(
+        totalCount: totalCount,
+        offset: _fieldData.theOffset,
+        pageSize: _fieldData.thePageSize,
+        onTap: (offset) {
+          _fieldData.theOffset = offset;
+          requestRecords();
+          setState(() => 1);
+        });
     final frameWidget = ListView(children: [
       form,
       if (tabBar != null) tabBar,
@@ -171,20 +137,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
-      'module': 'Benchmarks',
-      'sql': 'list',
-      'offset': _fieldData.theOffset,
-      'size': _fieldData.thePageSize,
-      ':text': asPattern(_fieldData.text),
-    });
-  }
-
-  void createNew() {
-    final benchMark = BenchmarkActions(globalData);
-    benchMark
-        .createMultiple(int.tryParse(countController.text) ?? 1)
-        .then((message) => setState(() => resultController.text = message));
+    requestRecords();
   }
 
   @override
@@ -192,8 +145,6 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
     helperDummyUsage(DataType.string);
     globalWidgetDummyUsage();
     textController.dispose();
-    countController.dispose();
-    resultController.dispose();
     super.dispose();
   }
 
@@ -202,17 +153,20 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
     super.initState();
   }
 
-  void readItems() {
-    final benchMark = BenchmarkActions(globalData);
-    // resultController.text = benchMark.createMultiple(
-    //    int.tryParse(_fieldData.count) ?? 1);
-    setState(() => 1);
-  }
+  void requestRecords() =>
+      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+        'module': 'Benchmarks',
+        'sql': 'list',
+        'offset': _fieldData.theOffset,
+        'size': _fieldData.thePageSize,
+        ':text': asPattern(_fieldData.text),
+      });
 
   void search() {
     attendedPage!.pageStates.dbDataState.clear();
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
+      requestRecords();
       setState(() => 1);
     }
   }
@@ -222,5 +176,4 @@ class _FieldData {
   int thePageSize = 10;
   int theOffset = 0;
   String text = '';
-  String count = '';
 }
index bad001348e1729299b52189ba2d744d6eed050b5..1f6410f8a96caf4e1ea779729df50a53297e8818 100644 (file)
@@ -19,7 +19,8 @@ class ListBenchmarkPage extends StatefulWidget {
         BenchmarkMeta.instance.pageByName('list')!,
         BenchmarkMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _ListBenchmarkPageState extends ListBenchmarkCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index a55c6a8cbdab59374d8581a05e4cef4d3508047c..3929279e667648488524f654546cc073d9a8a7d5 100644 (file)
@@ -45,7 +45,8 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -87,7 +88,7 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
     super.initState();
   }
 
-  void store() {
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Roles',
       'sql': 'insert',
@@ -109,10 +110,10 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index 6df1eae3ca692a005d1e6c20bb3ddc147c79617e..d6cf4eed1bd17193a2ed010503a1e155091a9f01 100644 (file)
@@ -19,7 +19,8 @@ class CreateRolePage extends StatefulWidget {
         RoleMeta.instance.pageByName('create')!,
         RoleMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _CreateRolePageState extends CreateRoleCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 9008ce040a0f2d687da86910c9ab0dd7f9c9fa2a..c853b7a2fa22cdee4601c9d3ca9eae2debc1a1bf 100644 (file)
@@ -33,30 +33,14 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -73,7 +57,8 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -105,9 +90,7 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -123,25 +106,30 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
     super.initState();
   }
 
-  void store() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Roles',
       'sql': 'update',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     _fieldData.toMap(parameters);
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
+      requestRecord();
       attendedPage!.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index 2c88a6fcfb3df23fa123813c81866788eb854c38..8ce66cb7a5584bedea8c2c74e0222777137386f4 100644 (file)
@@ -20,7 +20,8 @@ class EditRolePage extends StatefulWidget {
         RoleMeta.instance.pageByName('edit')!,
         RoleMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _EditRolePageState extends EditRoleCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index c179cdfb41905896be192d4e3f2cb606455819ee..d2c3c8d7785472b25781491c0e32012322a3a36a 100644 (file)
@@ -49,7 +49,8 @@ class ListRoleCustom extends State<ListRolePage> {
                   onDone: () => setState(() => 1),
                   routeEdit: '/Roles/edit',
                   context: context);
-              rc = buildFrame(rows: rows);
+              rc = buildFrame(
+                  totalCount: snapshot.data?.count ?? rows.length, rows: rows);
             } else if (snapshot.hasError) {
               rc = Text('Backend problem: ${snapshot.error}');
             } else {
@@ -63,7 +64,7 @@ class ListRoleCustom extends State<ListRolePage> {
     return rc;
   }
 
-  Widget buildFrame({required JsonList rows}) {
+  Widget buildFrame({required JsonList rows, required int totalCount}) {
     final padding = GlobalThemeData.padding;
     final formItems = <FormItem>[
       FormItem(
@@ -99,8 +100,14 @@ class ListRoleCustom extends State<ListRolePage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar =
-        attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+    Widget? tabBar = attendedPage!.buildChipBar(
+        totalCount: totalCount,
+        offset: _fieldData.theOffset,
+        pageSize: _fieldData.thePageSize,
+        onTap: (offset) {
+          _fieldData.theOffset = offset;
+          requestRecords();
+        });
     final frameWidget = ListView(children: [
       form,
       if (tabBar != null) tabBar,
@@ -113,13 +120,7 @@ class ListRoleCustom extends State<ListRolePage> {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
-      'module': 'Roles',
-      'sql': 'list',
-      'offset': _fieldData.theOffset,
-      'size': _fieldData.thePageSize,
-      ':text': _fieldData.text,
-    });
+    requestRecords();
   }
 
   @override
@@ -135,10 +136,20 @@ class ListRoleCustom extends State<ListRolePage> {
     super.initState();
   }
 
+  void requestRecords() =>
+      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+        'module': 'Roles',
+        'sql': 'list',
+        'offset': _fieldData.theOffset,
+        'size': _fieldData.thePageSize,
+        ':text': _fieldData.text,
+      });
+
   void search() {
     attendedPage!.pageStates.dbDataState.clear();
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
+      requestRecords();
       setState(() => 1);
     }
   }
index c4b1172f655c38ef69ed9de9d8c0ec6ae51b83ca..91335a8873159ae251477dca3f283f364a01f46b 100644 (file)
@@ -19,7 +19,8 @@ class ListRolePage extends StatefulWidget {
         RoleMeta.instance.pageByName('list')!,
         RoleMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _ListRolePageState extends ListRoleCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index d0f90dfafd97d5fd8318916a44bb48dabdfe4f1e..df1e1533fffaff3ea73c54f944c9d95a2e0b2a9f 100644 (file)
@@ -73,7 +73,8 @@ class CreateStructureCustom extends State<CreateStructurePage>
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -118,7 +119,7 @@ class CreateStructureCustom extends State<CreateStructurePage>
     super.initState();
   }
 
-  void store() {
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Structures',
       'sql': 'insert',
@@ -140,10 +141,10 @@ class CreateStructureCustom extends State<CreateStructurePage>
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index 0773962bd78b64903ba7209738d4729c7ba4b0cb..3eec391222f90ff2fe7ceed21a9ea461caef4738 100644 (file)
@@ -19,7 +19,8 @@ class CreateStructurePage extends StatefulWidget {
         StructureMeta.instance.pageByName('create')!,
         StructureMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _CreateStructurePageState extends CreateStructureCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 272fbb9f3b23893cd59d6f5d622a7cdb319a6354..f20a98b07f5deb980f03fa8837ec6ab3766c4963 100644 (file)
@@ -37,30 +37,14 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -101,7 +85,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndDelete(),
+              onPressed: () => onVerifyAndDelete(),
               child: Text(i18n.tr('Delete'))),
           weight: 8,
           gapAbove: 2 * padding),
@@ -134,9 +118,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -155,12 +137,16 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
     super.initState();
   }
 
-  void delete() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onDelete() {
     final parameters = <String, dynamic>{
       'module': 'Structures',
       'sql': 'delete',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
@@ -168,10 +154,10 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
     });
   }
 
-  void verifyAndDelete() {
+  void onVerifyAndDelete() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      delete();
+      onDelete();
     }
   }
 }
index ed326715b5fb0588039f24deadf3184736a67fe2..fc458a6ed4b3400fadd504413e59ebe1aad2013a 100644 (file)
@@ -20,7 +20,8 @@ class DeleteStructurePage extends StatefulWidget {
         StructureMeta.instance.pageByName('delete')!,
         StructureMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _DeleteStructurePageState extends DeleteStructureCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index bc3879888c2b658bd91d625d871610cf44d61e3a..c96e9ba4057518da886042ac8431089278c676a4 100644 (file)
@@ -36,30 +36,14 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -100,7 +84,8 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -132,9 +117,7 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -153,25 +136,30 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
     super.initState();
   }
 
-  void store() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Structures',
       'sql': 'update',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     _fieldData.toMap(parameters);
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
+      requestRecord();
       attendedPage!.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index df271e30058102561059b2dd26885178495932d5..8baf89cf63ff720d76a850377da40f67ce4c3d9a 100644 (file)
@@ -20,7 +20,8 @@ class EditStructurePage extends StatefulWidget {
         StructureMeta.instance.pageByName('edit')!,
         StructureMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _EditStructurePageState extends EditStructureCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 7f09d04bcdfe7d5710a3a823f224a3bf94fc365c..04f0d643380fbdf434c90ac78557fc4af93b51c8 100644 (file)
@@ -50,7 +50,8 @@ class ListStructureCustom extends State<ListStructurePage> {
                   onDone: () => setState(() => 1),
                   routeEdit: '/Structures/edit',
                   context: context);
-              rc = buildFrame(rows: rows);
+              rc = buildFrame(
+                  totalCount: snapshot.data?.count ?? rows.length, rows: rows);
             } else if (snapshot.hasError) {
               rc = Text('Backend problem: ${snapshot.error}');
             } else {
@@ -64,7 +65,7 @@ class ListStructureCustom extends State<ListStructurePage> {
     return rc;
   }
 
-  Widget buildFrame({required JsonList rows}) {
+  Widget buildFrame({required JsonList rows, required int totalCount}) {
     final padding = GlobalThemeData.padding;
     final formItems = <FormItem>[
       FormItem(
@@ -100,8 +101,14 @@ class ListStructureCustom extends State<ListStructurePage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar =
-        attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+    Widget? tabBar = attendedPage!.buildChipBar(
+        totalCount: totalCount,
+        offset: _fieldData.theOffset,
+        pageSize: _fieldData.thePageSize,
+        onTap: (offset) {
+          _fieldData.theOffset = offset;
+          requestRecords();
+        });
     final frameWidget = ListView(children: [
       form,
       if (tabBar != null) tabBar,
@@ -114,13 +121,7 @@ class ListStructureCustom extends State<ListStructurePage> {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
-      'module': 'Structures',
-      'sql': 'list',
-      'offset': _fieldData.theOffset,
-      'size': _fieldData.thePageSize,
-      ':text': _fieldData.text,
-    });
+    requestRecords();
   }
 
   @override
@@ -136,10 +137,20 @@ class ListStructureCustom extends State<ListStructurePage> {
     super.initState();
   }
 
+  void requestRecords() =>
+      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+        'module': 'Structures',
+        'sql': 'list',
+        'offset': _fieldData.theOffset,
+        'size': _fieldData.thePageSize,
+        ':text': _fieldData.text,
+      });
+
   void search() {
     attendedPage!.pageStates.dbDataState.clear();
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
+      requestRecords();
       setState(() => 1);
     }
   }
index efeb5d71332449e3c4af6fb069881e1babd46f00..c60cda366bea073996f4e5da9c78ec94e2261178 100644 (file)
@@ -19,7 +19,8 @@ class ListStructurePage extends StatefulWidget {
         StructureMeta.instance.pageByName('list')!,
         StructureMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _ListStructurePageState extends ListStructureCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 33570bf09f5d692609e57f8c26f42f634472110e..5efce7c6c6a060ec1a4ee51a5e0d41c0e881a7e6 100644 (file)
@@ -78,7 +78,8 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -122,7 +123,7 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
     super.initState();
   }
 
-  void store() {
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Users',
       'sql': 'insert',
@@ -144,10 +145,10 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index 3048fa1feb9eeb424229f9908fd98087bc2761bf..8f11c9419884bc4dcadc23bb2a1d859c91153784 100644 (file)
@@ -19,7 +19,8 @@ class CreateUserPage extends StatefulWidget {
         UserMeta.instance.pageByName('create')!,
         UserMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _CreateUserPageState extends CreateUserCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 1380cc410213672226882ca67238bc47991fe769..9b01b618b6c6aba2006f85d6e081319a3738d88a 100644 (file)
@@ -35,30 +35,14 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -106,7 +90,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndDelete(),
+              onPressed: () => onVerifyAndDelete(),
               child: Text(i18n.tr('Delete'))),
           weight: 8,
           gapAbove: 2 * padding),
@@ -139,9 +123,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -159,12 +141,16 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
     super.initState();
   }
 
-  void delete() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onDelete() {
     final parameters = <String, dynamic>{
       'module': 'Users',
       'sql': 'delete',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
@@ -172,10 +158,10 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
     });
   }
 
-  void verifyAndDelete() {
+  void onVerifyAndDelete() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      delete();
+      onDelete();
     }
   }
 }
index 98871a5a43bad45711c0dedd93207c75bf6d716f..6b563ac2291d0c69d74ede9694c93a5652154e9d 100644 (file)
@@ -20,7 +20,8 @@ class DeleteUserPage extends StatefulWidget {
         UserMeta.instance.pageByName('delete')!,
         UserMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _DeleteUserPageState extends DeleteUserCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index 311e124e338b82c7013188697f6894abbfe44ffc..c38e348decaf5ff3f9537e013146254f9a52d322 100644 (file)
@@ -35,30 +35,14 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
         drawer: globalData.drawerBuilder(context),
         body: SafeArea(
             child: FutureBuilder<DbData>(
-          future: _futureDbData,
-          builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null) {
-                  rc =
-                      Text('backend problem: ${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: ${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
-            return rc;
-          },
-        )));
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
     return rc;
   }
 
@@ -106,7 +90,8 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
           weight: 6),
       FormItem(
           ElevatedButton(
-              onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
           weight: 8,
           gapAbove: 2 * padding),
       FormItem(
@@ -138,9 +123,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }
 
   @override
@@ -158,25 +141,30 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
     super.initState();
   }
 
-  void store() {
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onStore() {
     final parameters = <String, dynamic>{
       'module': 'Users',
       'sql': 'update',
+      ':id': primaryKey
     };
-    parameters[':id'] = primaryKey;
     _fieldData.toMap(parameters);
     globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {
+      requestRecord();
       attendedPage!.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
-  void verifyAndStore() {
+  void onVerifyAndStore() {
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
-      store();
+      onStore();
     }
   }
 }
index 230fe4a008068fa053a1183e5a8c86558adc12a7..b1ca38cd459f254d527e4e040600fb90ce330d2b 100644 (file)
@@ -20,7 +20,8 @@ class EditUserPage extends StatefulWidget {
         UserMeta.instance.pageByName('edit')!,
         UserMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -37,11 +38,25 @@ class _EditUserPageState extends EditUserCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index c23310e610c2d122f496e0197d393a45193a31c3..330f896923311d9c0318f4e3ab0289fff47f1cb8 100644 (file)
@@ -50,7 +50,8 @@ class ListUserCustom extends State<ListUserPage> {
                   onDone: () => setState(() => 1),
                   routeEdit: '/Users/edit',
                   context: context);
-              rc = buildFrame(rows: rows);
+              rc = buildFrame(
+                  totalCount: snapshot.data?.count ?? rows.length, rows: rows);
             } else if (snapshot.hasError) {
               rc = Text('Backend problem: ${snapshot.error}');
             } else {
@@ -64,7 +65,7 @@ class ListUserCustom extends State<ListUserPage> {
     return rc;
   }
 
-  Widget buildFrame({required JsonList rows}) {
+  Widget buildFrame({required JsonList rows, required int totalCount}) {
     final padding = GlobalThemeData.padding;
     comboRolesFromBackend(
         attendedPage: attendedPage!, onDone: () => setState(() => 1));
@@ -127,8 +128,14 @@ class ListUserCustom extends State<ListUserPage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar =
-        attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+    Widget? tabBar = attendedPage!.buildChipBar(
+        totalCount: totalCount,
+        offset: _fieldData.theOffset,
+        pageSize: _fieldData.thePageSize,
+        onTap: (offset) {
+          _fieldData.theOffset = offset;
+          requestRecords();
+        });
     final frameWidget = ListView(children: [
       form,
       if (tabBar != null) tabBar,
@@ -141,14 +148,7 @@ class ListUserCustom extends State<ListUserPage> {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
-      'module': 'Users',
-      'sql': 'list',
-      'offset': _fieldData.theOffset,
-      'size': _fieldData.thePageSize,
-      ':text': asPattern(_fieldData.text),
-      ':role': _fieldData.role.toString(),
-    });
+    requestRecords();
   }
 
   @override
@@ -164,10 +164,21 @@ class ListUserCustom extends State<ListUserPage> {
     super.initState();
   }
 
+  void requestRecords() =>
+      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+        'module': 'Users',
+        'sql': 'list',
+        'offset': _fieldData.theOffset,
+        'size': _fieldData.thePageSize,
+        ':text': asPattern(_fieldData.text),
+        ':role': _fieldData.role.toString(),
+      });
+
   void search() {
     attendedPage!.pageStates.dbDataState.clear();
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
+      requestRecords();
       setState(() => 1);
     }
   }
index 67ac443b4d43867f4fc636de7f72ba25bcfe10cd..186994f2303729a907928eeb204ac164618af112 100644 (file)
@@ -19,7 +19,8 @@ class ListUserPage extends StatefulWidget {
         UserMeta.instance.pageByName('list')!,
         UserMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -36,11 +37,25 @@ class _ListUserPageState extends ListUserCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload) {
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
     if (afterReload == null) {
-      setState(() => 1);
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
 }
index fce281d8cea82b893cf1c721f36bda52362979f8..618cfef5dd5c8660cd7aad3d4ad9b20c30ea647b 100644 (file)
@@ -139,18 +139,16 @@ class NavigatorStack {
   void goto(BuildContext context, String route,
       {bool popIfPossible = true, bool registerWithParent = false}) {
     final ix = route.indexOf(';');
-    if (ix > 0) {
-      route = route.substring(0, ix);
-    }
+    final route2 = ix > 0 ? route.substring(0, ix) : route;
     if (popIfPossible &&
         stack.length >= 2 &&
-        stack[stack.length - 2].route == route) {
+        stack[stack.length - 2].route == route2) {
       pop(context);
     } else {
       /// Note: constructor of AttendedPage calls supplyTopOfStack()
       /// to set NavigatorStackEntry.attendedPage.
       stack.add(NavigatorStackEntry(
-          route: route, registerWithParent: registerWithParent));
+          route: route2, registerWithParent: registerWithParent));
       Navigator.pushNamed(context, route);
     }
   }
@@ -176,7 +174,8 @@ class NavigatorStack {
         globalData!.logger
             .error('informAboutChanges(): parent ${route!} not found');
       } else {
-        parent.noticeChange();
+        // parent.noticeChange();
+        parent.reload(rebuild: true);
       }
     }
   }
@@ -208,7 +207,7 @@ class NavigatorStack {
       if (last.registerWithParent && stack.length >= 2) {
         stack[stack.length - 2]
             .attendedPage
-            ?.addListener(() => attendedPage.reload());
+            ?.addListener(() => attendedPage.reload(rebuild: true));
       }
     } else {
       globalData!.logger.error(
index 46f42f31c4d4986737ab15d7ea553f9904e57465..104ab1729f797087dd3cf293234acb55277971d7 100644 (file)
@@ -31,7 +31,7 @@ class AttendedPage extends ChangeNotifier {
   final StatefulWidget statefulWidget;
   final State<StatefulWidget> state;
   final PageStates pageStates;
-  final void Function(Function? afterReload)? reloadFunction;
+  final void Function(Function? afterReload, bool rebuild)? reloadFunction;
   AttendedPage(
       this.statefulWidget,
       this.state,
@@ -76,23 +76,26 @@ class AttendedPage extends ChangeNotifier {
   ///
   /// If [afterReload] is not null this function is used as parameter of
   /// setState().
-  void reload({Function? afterReload}) {
-    reloadFunction!(afterReload);
+  void reload({Function? afterReload, bool rebuild = false}) {
+    reloadFunction!(afterReload, rebuild);
   }
 
   /// Creates a chip bar: a row of ChoiceChip instances (special buttons).
   ///
   /// That chips allow to change the page of the db result.
   ///
+  /// [totalCount]: the number of records matching the filters.
+  ///
+  /// [offset]: the offset of the result in the result set.
+  ///
+  /// [pageSize]: the page size defining the  maximal entries in the result set.
+  ///
   /// [onTap]: a function which is called if another chip is selected.
-  Widget? buildChipBar({required Function(int offset) onTap}) {
-    final dbData = pageStates.dbDataState.dataOf('rows');
-    final pageSize = dbData?.pageSize ?? 10;
-    //pageSize = 10;
-    final totalCount = dbData?.count ?? pageSize;
-    //totalCount = 1;
-    final offset = dbData?.offset ?? 0;
-    // offset = 30;
+  Widget? buildChipBar(
+      {required int totalCount,
+      required int offset,
+      required int pageSize,
+      required Function(int offset) onTap}) {
     final pageCount = (totalCount + pageSize - 1) ~/ pageSize;
     final currentPage = 1 + offset ~/ pageSize;
     int currentIndex;
@@ -223,44 +226,45 @@ class AttendedPage extends ChangeNotifier {
     return rc ?? <DataRow>[];
   }
 
+  /// Informs the listeners of [ChangeNotifier] about a change.
   void noticeChange() {
     notifyListeners();
   }
 
+  /// Informs a parent about changes.
+  ///
+  /// See [globalData.navigatorStack.informAboutChanges()]
   void informAboutChanges({String? route}) {
     globalData.navigatorStack.informAboutChanges(route);
   }
 
   /// Loads a record from the backend.
   ///
-  /// [name]: a unique name over all backend data requests.
-  ///
-  /// [reload]: a function calling setState().
+  /// [onSuccess]: this function must convert the Json format to the native
+  /// object and must return the (complex) widget displaying the record.
   ///
-  /// [onDone]: a function storing the record fetched from the backend.
-  ///
-  /// [parameters]: a map specifying the request.
-  /// Example: { 'module': 'Roles', 'sql': 'byId', ':id': primaryKey}.///
-  void loadRecord(
-      {required String name,
-      required void Function() reload,
-      required void Function(JsonMap) onDone,
-      required Map<String, dynamic> parameters}) {
-    if (!pageStates.dbDataState.hasEntry(name)) {
-      pageStates.dbDataState.addRequest(name).then((_) => globalData
-              .restPersistence!
-              .query(what: 'query', data: parameters)
-              .then((value) {
-            pageStates.dbDataState
-                .storeDbResult(name, value)
-                .then((_) => reload());
-          }));
-    } else if (pageStates.dbDataState.dataOf('record') != null) {
-      final dbData = pageStates.dbDataState.dataOf('record');
-      if (dbData != null && dbData.singleRecord != null) {
-        onDone(dbData.singleRecord!);
+  /// Returns: An error text on network errors, a progress indicator while data
+  /// is not available or the widget displaying the record on success.
+  Widget loadRecord(
+      AsyncSnapshot snapshot, Widget Function(JsonMap record) onSuccess) {
+    Widget rc;
+    if (snapshot.connectionState != ConnectionState.done) {
+      rc = const CircularProgressIndicator();
+    } else {
+      if (snapshot.hasData) {
+        final dbData = snapshot.data!;
+        final record = dbData.singleRecord;
+        if (record == null) {
+          rc = Text('backend problem: ${dbData.message ?? '<unknown>'}');
+        }
+        rc = onSuccess(record as JsonMap);
+      } else if (snapshot.hasError) {
+        rc = Text('Backend problem: ${snapshot.error}');
+      } else {
+        rc = const CircularProgressIndicator();
       }
     }
+    return rc;
   }
 
   /// Validates the text [value] of the [textAttended].
index aa41bbabf0a25bbefa6c93b7428d2538aaffc341..9252dadffff9014ad9935f52ae99ba2e9db5a8ff 100644 (file)
@@ -15,27 +15,12 @@ class PageGenerator extends SqlGenerator {
         child: FutureBuilder<DbData>(
           future: _futureDbData,
           builder: (context, snapshot) {
-            Widget rc;
-            if (snapshot.connectionState != ConnectionState.done) {
-              rc = const CircularProgressIndicator();
-            } else {
-              if (snapshot.hasData) {
-                final dbData = snapshot.data!;
-                final record = dbData.singleRecord;
-                if (record == null){
-                  rc = Text('backend problem: \${dbData.message ?? '<unknown>'}');
-                }
-                _fieldData.fromMap(record as JsonMap);
-                rc = buildFrame();
-              } else if (snapshot.hasError) {
-                rc = Text('Backend problem: \${snapshot.error}');
-              } else {
-                rc = const CircularProgressIndicator();
-              }
-            }
+            final rc = attendedPage!.loadRecord(snapshot, (record) {
+              _fieldData.fromMap(record);
+              return buildFrame();
+            });
             return rc;
-          },
-        )));''';
+          })));''';
   static final templateBodySimple = '''SafeArea(
             child: buildFrame()));''';
   static final templateDidChangeDependencies = '''
@@ -43,9 +28,7 @@ class PageGenerator extends SqlGenerator {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(
-        what: 'query',
-        data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+    requestRecord();
   }''';
 
   static final templatePage = '''
@@ -70,7 +53,8 @@ DEF_PRIMARY  final PageStates pageStates = PageStates();
         UserMeta.instance.pageByName('edit')!,
         UserMeta.instance,
         pageStates,
-        (afterReload) => rc.reload(afterReload));
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
     pageStates.attendedPage = rc.attendedPage;
     return rc;
   }
@@ -87,15 +71,28 @@ class _EditUserPageState extends EditUserCustom {
   }
 
   /// Renders the widget tree again.
-  void reload(Function? afterReload){
-    if (afterReload == null){
-      setState(() => 1);
+  ///
+  /// [afterReload] is a function used as parameter of setState().
+  ///
+  /// If [rebuild] is true the state has been changed and didChangeDependencies()
+  /// will be called.
+  void reload({Function? afterReload, bool rebuild = false}) {
+    if (afterReload == null) {
+      if (rebuild) {
+        setState(() => didChangeDependencies());
+      } else {
+        setState(() => 1);
+      }
     } else {
-      setState(() => afterReload());
+      setState(() {
+        afterReload();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
     }
   }
-}
-''';
+}''';
 
   static final templateGlobalComboBox = '''    comboRolesFromBackend(
         attendedPage: attendedPage!, onDone: () => setState(() => 1));
@@ -152,7 +149,8 @@ class ListUserCustom extends State<ListUserPage> {
                   onDone: () => setState(() => 1),
                   route#EDIT1: '/Users/#EDIT2',
                   context: context);
-              rc = buildFrame(rows: rows);
+              rc = buildFrame(totalCount: snapshot.data?.count ?? rows.length,
+                rows: rows);
             } else if (snapshot.hasError) {
               rc = Text('Backend problem: \${snapshot.error}');
             } else {
@@ -166,7 +164,7 @@ class ListUserCustom extends State<ListUserPage> {
     return rc;
   }
 
-  Widget buildFrame({required JsonList rows}){
+  Widget buildFrame({required JsonList rows, required int totalCount}){
     final padding = GlobalThemeData.padding;
 #INIT_COMBOS    final formItems = <FormItem>[
 #FORM_ITEMS      FormItem(
@@ -194,8 +192,15 @@ class ListUserCustom extends State<ListUserPage> {
 #TABLE_HEADER      ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar =
-    attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+    Widget? tabBar = attendedPage!.buildChipBar(
+        totalCount: totalCount,
+        offset: _fieldData.theOffset,
+        pageSize: _fieldData.thePageSize,
+        onTap: (offset) {
+          _fieldData.theOffset = offset;
+          requestRecords();
+          setState(() => 1);
+        });
     final frameWidget = ListView(children: [
       form,
       if (tabBar != null) tabBar,
@@ -208,12 +213,7 @@ class ListUserCustom extends State<ListUserPage> {
   @override
   void didChangeDependencies() {
     super.didChangeDependencies();
-    _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
-      'module': 'Users',
-      'sql': 'list',
-      'offset': _fieldData.theOffset,
-      'size': _fieldData.thePageSize,
-#PARAM_DEF    });
+    requestRecords();
   }
 
   @override
@@ -228,10 +228,19 @@ class ListUserCustom extends State<ListUserPage> {
     super.initState();
   }
 
+  void requestRecords() =>  _futureDbData = globalData.restPersistence!.query(
+    what: 'query', data: {
+      'module': 'Users',
+      'sql': 'list',
+      'offset': _fieldData.theOffset,
+      'size': _fieldData.thePageSize,
+#PARAM_DEF    });
+
   void search() {
     attendedPage!.pageStates.dbDataState.clear();
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
+      requestRecords();
       setState(() => 1);
     }
   }
@@ -324,12 +333,12 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
     super.initState();
   }
 
-  void #ACTION1() {
+#REQ_RECORD  void #ACTION1() {
     final parameters = <String, dynamic>{
       'module': 'Users',
       'sql': '#SQL_TYPE',
-    };
-#SET_PRIMARY#CALL_TO_MAP    globalData.restPersistence!
+#SET_PRIMARY    };
+#CALL_TO_MAP    globalData.restPersistence!
         .store(what: 'store', map: parameters)
         .then((answer) {#STORAGE_DONE});
   }
@@ -346,6 +355,13 @@ class _FieldData {
 #DEF_FIELD
 #FROM_MAP#TO_MAP}
 ''';
+  static final templateRequestRecord = '''
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+''';
+
   static final templateStorageDoneCreate = '''
 
       if (answer.startsWith('id:')) {
@@ -361,6 +377,7 @@ class _FieldData {
     ''';
   static final templateStorageDoneEdit = '''
 
+      requestRecord();
       attendedPage!.pageStates.dbDataState.clear();
       setState(() => 1);
     ''';
@@ -831,17 +848,19 @@ StatefulWidget? customPageByRoute(String route) {
   String createRecordCustomized(PageMetaData page) {
     var hasPrimary = false;
     page.pageType == PageType.edit || page.pageType == PageType.delete;
-    var action1 = 'store';
-    var action2 = 'verifyAndStore';
+    var action1 = 'onStore';
+    var action2 = 'onVerifyAndStore';
     var storageDone = '';
     var buttonText = 'Save';
     var sqlType = '';
-    var setPrimary = '';
+    var setPrimary = "      ':id': primaryKey\n";
     var callToMap = '';
     var body = templateBodyLoadData;
     var didChangeDependencies = templateDidChangeDependencies;
     var definitionFuture = '  late Future<DbData> _futureDbData;';
     var importPersistence = "import '../../persistence/persistence.dart';\n";
+    var informAboutChanges = '    attendedPage!.informAboutChanges();';
+    var requestRecord = templateRequestRecord;
     page.pageType == PageType.edit
         ? 'update'
         : (page.pageType == PageType.delete ? 'delete' : 'insert');
@@ -853,23 +872,20 @@ StatefulWidget? customPageByRoute(String route) {
         storageDone = templateStorageDoneCreate.replaceFirst(
             '#MODULE', page.module.moduleName);
         body = templateBodySimple;
-        didChangeDependencies = '';
-        definitionFuture = '';
-        importPersistence = '';
+        didChangeDependencies = definitionFuture = importPersistence
+        = informAboutChanges = setPrimary = requestRecord = '';
         break;
       case PageType.edit:
         callToMap = '    _fieldData.toMap(parameters);\n';
-        setPrimary = "    parameters[':id'] = primaryKey;\n";
         sqlType = 'update';
         storageDone = templateStorageDoneEdit;
         hasPrimary = true;
         break;
       case PageType.delete:
-        setPrimary = "    parameters[':id'] = primaryKey;\n";
         sqlType = 'delete';
         buttonText = 'Delete';
-        action1 = 'delete';
-        action2 = 'verifyAndDelete';
+        action1 = 'onDelete';
+        action2 = 'onVerifyAndDelete';
         storageDone = templateStorageDoneDelete.replaceFirst(
             '#MODULE', page.module.moduleName);
         hasPrimary = true;
@@ -880,6 +896,7 @@ StatefulWidget? customPageByRoute(String route) {
         break;
     }
     var rc = replaceVariables(templateRecordCustom, page)
+        .replaceFirst('#REQ_RECORD', requestRecord)
         .replaceFirst('#DIDCHANGE', didChangeDependencies)
         .replaceFirst('#DEF_CONTROLLER', buildDefinitionControllers(page))
         .replaceFirst('#INIT_COMBO', buildInitializeComboBoxes(page))
@@ -903,6 +920,7 @@ StatefulWidget? customPageByRoute(String route) {
         .replaceFirst('#TO_MAP', buildToMap(page))
         .replaceFirst('#FROM_MAP', buildFromMap(page))
         .replaceFirst('#DEF_FUTURE', definitionFuture)
+        .replaceFirst('#INFORM', informAboutChanges)
         .replaceFirst('#IMP_PERSISTENCE', importPersistence);
     return rc;
   }
index 4f6228e2cbf1001baa43fc3260c49aee5743a017..4c8ce98ee4a2acd27b456deefbf885bc255cfacf 100644 (file)
@@ -584,12 +584,8 @@ class ServiceWorker {
         sql2 = sql;
       } else {
         final ix = sql.lastIndexOf(';');
-        if (ix > 0) {
-          sql2 = sql.substring(0, ix) +
-              ' limit ${parameters["offset"]},${parameters["size"]};';
-        } else {
-          sql2 = sql + ' limit ${parameters["offset"]},${parameters["size"]};';
-        }
+        final limit = ' limit ${parameters["offset"]},${parameters["size"]};';
+        sql2 = (ix > 0 ? sql.substring(0, ix) : sql) + limit;
         final fromPart = 'FROM ${module.toLowerCase()} t0';
         final ix2 = sql.indexOf(fromPart);
         if (ix2 > 0) {
@@ -601,9 +597,11 @@ class ServiceWorker {
                   : positionalParameters
                       .skip(positionalParameters.length - countParams)
                       .toList();
-          prefix =
-              '#${await db!.readOneInt(sqlCount, params: positionalParameters2)}';
+          prefix = '#' +
+              (await db!.readOneInt(sqlCount, params: positionalParameters2))
+                  .toString();
         }
+        logger.log('(offset, pagesize): ($limit)', LEVEL_DETAIL);
       }
       final records = await db!.readAll(sql2, params: positionalParameters);
       rc = records == null