From adff4da0fbfbd07698f46692494f8051d7fdc5b3 Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Sat, 23 Oct 2021 01:16:05 +0200 Subject: [PATCH] page list_xxx_custom works with paging managed by chips --- .../benchmarks/create_benchmark_custom.dart | 9 +- .../benchmarks/create_benchmark_page.dart | 23 +++- .../benchmarks/delete_benchmark_custom.dart | 50 +++---- .../benchmarks/delete_benchmark_page.dart | 23 +++- .../benchmarks/edit_benchmark_custom.dart | 52 +++----- lib/page/benchmarks/edit_benchmark_page.dart | 23 +++- .../benchmarks/list_benchmark_custom.dart | 113 +++++----------- lib/page/benchmarks/list_benchmark_page.dart | 23 +++- lib/page/roles/create_role_custom.dart | 9 +- lib/page/roles/create_role_page.dart | 23 +++- lib/page/roles/edit_role_custom.dart | 52 +++----- lib/page/roles/edit_role_page.dart | 23 +++- lib/page/roles/list_role_custom.dart | 33 +++-- lib/page/roles/list_role_page.dart | 23 +++- .../structures/create_structure_custom.dart | 9 +- .../structures/create_structure_page.dart | 23 +++- .../structures/delete_structure_custom.dart | 50 +++---- .../structures/delete_structure_page.dart | 23 +++- .../structures/edit_structure_custom.dart | 52 +++----- lib/page/structures/edit_structure_page.dart | 23 +++- .../structures/list_structure_custom.dart | 33 +++-- lib/page/structures/list_structure_page.dart | 23 +++- lib/page/users/create_user_custom.dart | 9 +- lib/page/users/create_user_page.dart | 23 +++- lib/page/users/delete_user_custom.dart | 50 +++---- lib/page/users/delete_user_page.dart | 23 +++- lib/page/users/edit_user_custom.dart | 52 +++----- lib/page/users/edit_user_page.dart | 23 +++- lib/page/users/list_user_custom.dart | 35 +++-- lib/page/users/list_user_page.dart | 23 +++- lib/setting/global_data.dart | 13 +- lib/widget/attended_page.dart | 76 ++++++----- metatool/bin/page_generator.dart | 124 ++++++++++-------- rest_server/lib/rest_server.dart | 14 +- 34 files changed, 662 insertions(+), 518 deletions(-) diff --git a/lib/page/benchmarks/create_benchmark_custom.dart b/lib/page/benchmarks/create_benchmark_custom.dart index 8aa8fab..7c16160 100644 --- a/lib/page/benchmarks/create_benchmark_custom.dart +++ b/lib/page/benchmarks/create_benchmark_custom.dart @@ -106,7 +106,8 @@ class CreateBenchmarkCustom extends State 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 super.initState(); } - void store() { + void onStore() { final parameters = { 'module': 'Benchmarks', 'sql': 'insert', @@ -175,10 +176,10 @@ class CreateBenchmarkCustom extends State }); } - void verifyAndStore() { + void onVerifyAndStore() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - store(); + onStore(); } } } diff --git a/lib/page/benchmarks/create_benchmark_page.dart b/lib/page/benchmarks/create_benchmark_page.dart index f69e701..2dc8272 100644 --- a/lib/page/benchmarks/create_benchmark_page.dart +++ b/lib/page/benchmarks/create_benchmark_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/benchmarks/delete_benchmark_custom.dart b/lib/page/benchmarks/delete_benchmark_custom.dart index 3503150..17bce39 100644 --- a/lib/page/benchmarks/delete_benchmark_custom.dart +++ b/lib/page/benchmarks/delete_benchmark_custom.dart @@ -39,30 +39,14 @@ class DeleteBenchmarkCustom extends State drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 @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 super.initState(); } - void delete() { + void requestRecord() => _futureDbData = globalData.restPersistence!.query( + what: 'query', + data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey}); + + void onDelete() { final parameters = { '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 }); } - void verifyAndDelete() { + void onVerifyAndDelete() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - delete(); + onDelete(); } } } diff --git a/lib/page/benchmarks/delete_benchmark_page.dart b/lib/page/benchmarks/delete_benchmark_page.dart index 4a4bff4..9891dd6 100644 --- a/lib/page/benchmarks/delete_benchmark_page.dart +++ b/lib/page/benchmarks/delete_benchmark_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/benchmarks/edit_benchmark_custom.dart b/lib/page/benchmarks/edit_benchmark_custom.dart index 78664ae..147b644 100644 --- a/lib/page/benchmarks/edit_benchmark_custom.dart +++ b/lib/page/benchmarks/edit_benchmark_custom.dart @@ -38,30 +38,14 @@ class EditBenchmarkCustom extends State with MessageLine { drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 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 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 = { '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(); } } } diff --git a/lib/page/benchmarks/edit_benchmark_page.dart b/lib/page/benchmarks/edit_benchmark_page.dart index 5b0aeae..32c9316 100644 --- a/lib/page/benchmarks/edit_benchmark_page.dart +++ b/lib/page/benchmarks/edit_benchmark_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/benchmarks/list_benchmark_custom.dart b/lib/page/benchmarks/list_benchmark_custom.dart index 0707e76..2907e7e 100644 --- a/lib/page/benchmarks/list_benchmark_custom.dart +++ b/lib/page/benchmarks/list_benchmark_custom.dart @@ -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 { final GlobalKey _formKey = GlobalKey(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 { 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 { return rc; } - Widget buildFrame({required JsonList rows}) { + Widget buildFrame({required JsonList rows, required int totalCount}) { final padding = GlobalThemeData.padding; final formItems = [ FormItem( @@ -83,57 +80,19 @@ class ListBenchmarkCustom extends State { 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( @@ -157,8 +116,15 @@ class ListBenchmarkCustom extends State { ], rows: rows as List, ); - 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 { @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 { helperDummyUsage(DataType.string); globalWidgetDummyUsage(); textController.dispose(); - countController.dispose(); - resultController.dispose(); super.dispose(); } @@ -202,17 +153,20 @@ class ListBenchmarkCustom extends State { 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 = ''; } diff --git a/lib/page/benchmarks/list_benchmark_page.dart b/lib/page/benchmarks/list_benchmark_page.dart index bad0013..1f6410f 100644 --- a/lib/page/benchmarks/list_benchmark_page.dart +++ b/lib/page/benchmarks/list_benchmark_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/roles/create_role_custom.dart b/lib/page/roles/create_role_custom.dart index a55c6a8..3929279 100644 --- a/lib/page/roles/create_role_custom.dart +++ b/lib/page/roles/create_role_custom.dart @@ -45,7 +45,8 @@ class CreateRoleCustom extends State 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 with MessageLine { super.initState(); } - void store() { + void onStore() { final parameters = { 'module': 'Roles', 'sql': 'insert', @@ -109,10 +110,10 @@ class CreateRoleCustom extends State with MessageLine { }); } - void verifyAndStore() { + void onVerifyAndStore() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - store(); + onStore(); } } } diff --git a/lib/page/roles/create_role_page.dart b/lib/page/roles/create_role_page.dart index 6df1eae..d6cf4ee 100644 --- a/lib/page/roles/create_role_page.dart +++ b/lib/page/roles/create_role_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/roles/edit_role_custom.dart b/lib/page/roles/edit_role_custom.dart index 9008ce0..c853b7a 100644 --- a/lib/page/roles/edit_role_custom.dart +++ b/lib/page/roles/edit_role_custom.dart @@ -33,30 +33,14 @@ class EditRoleCustom extends State with MessageLine { drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 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 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 = { '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(); } } } diff --git a/lib/page/roles/edit_role_page.dart b/lib/page/roles/edit_role_page.dart index 2c88a6f..8ce66cb 100644 --- a/lib/page/roles/edit_role_page.dart +++ b/lib/page/roles/edit_role_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/roles/list_role_custom.dart b/lib/page/roles/list_role_custom.dart index c179cdf..d2c3c8d 100644 --- a/lib/page/roles/list_role_custom.dart +++ b/lib/page/roles/list_role_custom.dart @@ -49,7 +49,8 @@ class ListRoleCustom extends State { 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 { return rc; } - Widget buildFrame({required JsonList rows}) { + Widget buildFrame({required JsonList rows, required int totalCount}) { final padding = GlobalThemeData.padding; final formItems = [ FormItem( @@ -99,8 +100,14 @@ class ListRoleCustom extends State { ], rows: rows as List, ); - 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 { @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 { 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); } } diff --git a/lib/page/roles/list_role_page.dart b/lib/page/roles/list_role_page.dart index c4b1172..91335a8 100644 --- a/lib/page/roles/list_role_page.dart +++ b/lib/page/roles/list_role_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/structures/create_structure_custom.dart b/lib/page/structures/create_structure_custom.dart index d0f90df..df1e153 100644 --- a/lib/page/structures/create_structure_custom.dart +++ b/lib/page/structures/create_structure_custom.dart @@ -73,7 +73,8 @@ class CreateStructureCustom extends State 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 super.initState(); } - void store() { + void onStore() { final parameters = { 'module': 'Structures', 'sql': 'insert', @@ -140,10 +141,10 @@ class CreateStructureCustom extends State }); } - void verifyAndStore() { + void onVerifyAndStore() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - store(); + onStore(); } } } diff --git a/lib/page/structures/create_structure_page.dart b/lib/page/structures/create_structure_page.dart index 0773962..3eec391 100644 --- a/lib/page/structures/create_structure_page.dart +++ b/lib/page/structures/create_structure_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/structures/delete_structure_custom.dart b/lib/page/structures/delete_structure_custom.dart index 272fbb9..f20a98b 100644 --- a/lib/page/structures/delete_structure_custom.dart +++ b/lib/page/structures/delete_structure_custom.dart @@ -37,30 +37,14 @@ class DeleteStructureCustom extends State drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 @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 super.initState(); } - void delete() { + void requestRecord() => _futureDbData = globalData.restPersistence!.query( + what: 'query', + data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey}); + + void onDelete() { final parameters = { '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 }); } - void verifyAndDelete() { + void onVerifyAndDelete() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - delete(); + onDelete(); } } } diff --git a/lib/page/structures/delete_structure_page.dart b/lib/page/structures/delete_structure_page.dart index ed32671..fc458a6 100644 --- a/lib/page/structures/delete_structure_page.dart +++ b/lib/page/structures/delete_structure_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/structures/edit_structure_custom.dart b/lib/page/structures/edit_structure_custom.dart index bc38798..c96e9ba 100644 --- a/lib/page/structures/edit_structure_custom.dart +++ b/lib/page/structures/edit_structure_custom.dart @@ -36,30 +36,14 @@ class EditStructureCustom extends State with MessageLine { drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 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 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 = { '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(); } } } diff --git a/lib/page/structures/edit_structure_page.dart b/lib/page/structures/edit_structure_page.dart index df271e3..8baf89c 100644 --- a/lib/page/structures/edit_structure_page.dart +++ b/lib/page/structures/edit_structure_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/structures/list_structure_custom.dart b/lib/page/structures/list_structure_custom.dart index 7f09d04..04f0d64 100644 --- a/lib/page/structures/list_structure_custom.dart +++ b/lib/page/structures/list_structure_custom.dart @@ -50,7 +50,8 @@ class ListStructureCustom extends State { 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 { return rc; } - Widget buildFrame({required JsonList rows}) { + Widget buildFrame({required JsonList rows, required int totalCount}) { final padding = GlobalThemeData.padding; final formItems = [ FormItem( @@ -100,8 +101,14 @@ class ListStructureCustom extends State { ], rows: rows as List, ); - 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 { @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 { 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); } } diff --git a/lib/page/structures/list_structure_page.dart b/lib/page/structures/list_structure_page.dart index efeb5d7..c60cda3 100644 --- a/lib/page/structures/list_structure_page.dart +++ b/lib/page/structures/list_structure_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/users/create_user_custom.dart b/lib/page/users/create_user_custom.dart index 33570bf..5efce7c 100644 --- a/lib/page/users/create_user_custom.dart +++ b/lib/page/users/create_user_custom.dart @@ -78,7 +78,8 @@ class CreateUserCustom extends State 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 with MessageLine { super.initState(); } - void store() { + void onStore() { final parameters = { 'module': 'Users', 'sql': 'insert', @@ -144,10 +145,10 @@ class CreateUserCustom extends State with MessageLine { }); } - void verifyAndStore() { + void onVerifyAndStore() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - store(); + onStore(); } } } diff --git a/lib/page/users/create_user_page.dart b/lib/page/users/create_user_page.dart index 3048fa1..8f11c94 100644 --- a/lib/page/users/create_user_page.dart +++ b/lib/page/users/create_user_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/users/delete_user_custom.dart b/lib/page/users/delete_user_custom.dart index 1380cc4..9b01b61 100644 --- a/lib/page/users/delete_user_custom.dart +++ b/lib/page/users/delete_user_custom.dart @@ -35,30 +35,14 @@ class DeleteUserCustom extends State with MessageLine { drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 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 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 = { '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 with MessageLine { }); } - void verifyAndDelete() { + void onVerifyAndDelete() { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - delete(); + onDelete(); } } } diff --git a/lib/page/users/delete_user_page.dart b/lib/page/users/delete_user_page.dart index 98871a5..6b563ac 100644 --- a/lib/page/users/delete_user_page.dart +++ b/lib/page/users/delete_user_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/users/edit_user_custom.dart b/lib/page/users/edit_user_custom.dart index 311e124..c38e348 100644 --- a/lib/page/users/edit_user_custom.dart +++ b/lib/page/users/edit_user_custom.dart @@ -35,30 +35,14 @@ class EditUserCustom extends State with MessageLine { drawer: globalData.drawerBuilder(context), body: SafeArea( child: FutureBuilder( - 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 ?? ''}'); - } - _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 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 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 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 = { '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(); } } } diff --git a/lib/page/users/edit_user_page.dart b/lib/page/users/edit_user_page.dart index 230fe4a..b1ca38c 100644 --- a/lib/page/users/edit_user_page.dart +++ b/lib/page/users/edit_user_page.dart @@ -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(); + } + }); } } } diff --git a/lib/page/users/list_user_custom.dart b/lib/page/users/list_user_custom.dart index c23310e..330f896 100644 --- a/lib/page/users/list_user_custom.dart +++ b/lib/page/users/list_user_custom.dart @@ -50,7 +50,8 @@ class ListUserCustom extends State { 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 { 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 { ], rows: rows as List, ); - 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 { @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 { 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); } } diff --git a/lib/page/users/list_user_page.dart b/lib/page/users/list_user_page.dart index 67ac443..186994f 100644 --- a/lib/page/users/list_user_page.dart +++ b/lib/page/users/list_user_page.dart @@ -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(); + } + }); } } } diff --git a/lib/setting/global_data.dart b/lib/setting/global_data.dart index fce281d..618cfef 100644 --- a/lib/setting/global_data.dart +++ b/lib/setting/global_data.dart @@ -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( diff --git a/lib/widget/attended_page.dart b/lib/widget/attended_page.dart index 46f42f3..104ab17 100644 --- a/lib/widget/attended_page.dart +++ b/lib/widget/attended_page.dart @@ -31,7 +31,7 @@ class AttendedPage extends ChangeNotifier { final StatefulWidget statefulWidget; final State 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 ?? []; } + /// 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 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 ?? ''}'); + } + 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]. diff --git a/metatool/bin/page_generator.dart b/metatool/bin/page_generator.dart index aa41bba..9252dad 100644 --- a/metatool/bin/page_generator.dart +++ b/metatool/bin/page_generator.dart @@ -15,27 +15,12 @@ class PageGenerator extends SqlGenerator { child: FutureBuilder( 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 ?? ''}'); - } - _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 { 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 { return rc; } - Widget buildFrame({required JsonList rows}){ + Widget buildFrame({required JsonList rows, required int totalCount}){ final padding = GlobalThemeData.padding; #INIT_COMBOS final formItems = [ #FORM_ITEMS FormItem( @@ -194,8 +192,15 @@ class ListUserCustom extends State { #TABLE_HEADER ], rows: rows as List, ); - 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 { @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 { 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 with MessageLine { super.initState(); } - void #ACTION1() { +#REQ_RECORD void #ACTION1() { final parameters = { '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 _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; } diff --git a/rest_server/lib/rest_server.dart b/rest_server/lib/rest_server.dart index 4f6228e..4c8ce98 100644 --- a/rest_server/lib/rest_server.dart +++ b/rest_server/lib/rest_server.dart @@ -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 -- 2.39.5