]> gitweb.hamatoma.de Git - exhibition.git/commitdiff
Refactoring
authorHamatoma <author.hamatoma.de>
Sun, 24 Oct 2021 17:36:48 +0000 (19:36 +0200)
committerHamatoma <author.hamatoma.de>
Sun, 24 Oct 2021 17:36:48 +0000 (19:36 +0200)
* Refactoring:
** usage of the dart feature "late": many "Type? x;" replaced by "late TYPE x;"

* module_meta_data:
** new module attribute needsSqlAll:
   creates a "all" section of the module with no WHERE condition
** Fix in pageByName(): "nothing found" is handled now correctly
** Fix in primaryOf(): "nothing found" is handled now correctly

* rest_server:
** logging of the using configuration file

69 files changed:
dart_tools/bin/i18n_text_parser.dart
lib/base/i18n.dart
lib/common/benchmark_actions.dart
lib/meta/module_meta_data.dart
lib/meta/roles_meta.dart
lib/meta/rolestarter_meta.dart
lib/meta/starters_meta.dart
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/info_page.dart
lib/page/log_page.dart
lib/page/page_manager.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/rolestarter/list_rolestarter_custom.dart [new file with mode: 0644]
lib/page/rolestarter/list_rolestarter_page.dart [new file with mode: 0644]
lib/page/rolestarter/mapping_rolestarter_custom.dart [new file with mode: 0644]
lib/page/rolestarter/mapping_rolestarter_page.dart [new file with mode: 0644]
lib/page/rolestarter/role_starter_data.dart [new file with mode: 0644]
lib/page/start_page.dart
lib/page/starters/create_starter_custom.dart
lib/page/starters/create_starter_page.dart
lib/page/starters/delete_starter_custom.dart
lib/page/starters/delete_starter_page.dart
lib/page/starters/edit_starter_custom.dart
lib/page/starters/edit_starter_page.dart
lib/page/starters/list_starter_custom.dart
lib/page/starters/list_starter_page.dart
lib/page/starters/starter_data.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/services/global_widget.dart
lib/setting/global_data.dart
lib/setting/structure.dart
lib/widget/attended_page.dart
metatool/bin/page_generator.dart
metatool/bin/sql_generator.dart
rest_server/data/sql/benchmarks.sql.yaml
rest_server/data/sql/roles.sql.yaml
rest_server/data/sql/rolestarter.sql.yaml [new file with mode: 0644]
rest_server/data/sql/starters.sql.yaml
rest_server/data/sql/structures.sql.yaml
rest_server/data/sql/users.sql.yaml
rest_server/lib/rest_server.dart
rest_server/lib/sql_storage.dart

index 48928cad923a6c995934328ac9df18828a1a3a78..bcfca05c6e0192c14042274aea426b26efd8387e 100644 (file)
@@ -59,7 +59,7 @@ void parse(List<String> args) {
         excluded = RegExp.escape(excluded).replaceAll(';', '|');
       }
       parser.regExpExcluded = RegExp('^($excluded)\$');
-      logger.log('excluding: ' + parser.regExpExcluded!.pattern, LEVEL_FINE);
+      logger.log('excluding: ' + parser.regExpExcluded.pattern, LEVEL_FINE);
     }
     parser.scanDirectory(args[0], 0);
     parser.writePot(args[1]);
@@ -103,7 +103,7 @@ class I18nTextParser {
   List<String> lines = [];
   int currentLineNo = 0;
   int currentIxLines = 0;
-  RegExp? regExpExcluded;
+  late RegExp regExpExcluded;
   // ...........................1.............1.........2
   final regExpModule =
       RegExp(r'''(\w+) = (I18N\(\)|i18n)\.module\(["'](.*?)['"]\);''');
@@ -474,8 +474,7 @@ msgstr ""
     }
     for (var node in subDirs) {
       if (depth == 0 &&
-          regExpExcluded != null &&
-          regExpExcluded!.firstMatch(node) != null) {
+          regExpExcluded.firstMatch(node) != null) {
         logger.log('ignoring $node');
       } else {
         scanDirectory(
index e0ccf448944964fa546f1029d55538377fe33400..528f67f6ad05f7e99e88f01a5d37a083c302b10e 100644 (file)
@@ -36,8 +36,8 @@ class I18N {
       rc = removeInvisibleTag(count == 1 ? keySingular : keyPlural);
     } else {
       if (map.containsKey(keySingular)) {
-        final info = map[keySingular];
-        if (info!.list != null && count < info.list!.length) {
+        final info = map[keySingular]!;
+        if (info.list != null && count < info.list!.length) {
           rc = info.list![count];
         } else {
           rc = count == 1 ? info.singular : info.plural;
index 970351167d1dbbc3f15e71a70673749722348a5b..c3290a2b96411717b71c8a028bb3f316a2dd9159 100644 (file)
@@ -68,7 +68,7 @@ class BenchmarkActions {
         ':active': 'T',
         ':createdBy': 'benchmark'
       };
-      final answer = await globalData.restPersistence!
+      final answer = await globalData.restPersistence
           .store(what: 'store', map: parameters);
       if (!answer.startsWith('id:')) {
         rc = '+++ storage failed: $answer';
index 2634f5298373c050c2b8753cf26c5237378e0c6f..80f924b73ad24085b45569de91950cad1f057be4 100644 (file)
@@ -157,6 +157,8 @@ class ModuleMetaData {
   /// The related database table.
   String tableName = '';
 
+  final needsSqlAll;
+
   /// If true the fields create, createdBy ... have the same ("short") column name
   /// instead of prefix and name.
   bool shortModifiedLabel = false;
@@ -168,7 +170,8 @@ class ModuleMetaData {
       {String tableName = '',
       String moduleNameSingular = '',
       String columnPrefix = '',
-      bool shortModifiedLabel = false}) {
+      bool shortModifiedLabel = false,
+      bool this.needsSqlAll = false}) {
     this.tableName = tableName.isEmpty ? moduleName.toLowerCase() : tableName;
     this.shortModifiedLabel = shortModifiedLabel;
     if (moduleNameSingular.isEmpty) {
@@ -307,16 +310,37 @@ class ModuleMetaData {
 
   /// Returns the meta data of a page given by its [name] or null if missing.
   PageMetaData? pageByName(String name) {
-    final rc =
-        pageList.firstWhere((element) => element.name == name, orElse: null);
+    PageMetaData? rc;
+    for (var item in pageList) {
+      if (item.name == name) {
+        rc = item;
+        break;
+      }
+    }
+    return rc;
+  }
+
+  /// Returns the list of pages with a given [pageType]. May be empty.
+  List<PageMetaData> pagesByType(PageType pageType) {
+    final rc = <PageMetaData>[];
+    for (var item in pageList) {
+      if (item.pageType == pageType) {
+        rc.add(item);
+        break;
+      }
+    }
     return rc;
   }
 
   /// Returns the primary key of the relation.
   PropertyMetaData? primaryOf() {
-    final rc = propertyList.firstWhere(
-        (element) => element.options.contains('primary'),
-        orElse: null);
+    PropertyMetaData? rc;
+    for (var item in propertyList) {
+      if (item.options.contains('primary')) {
+        rc = item;
+        break;
+      }
+    }
     return rc;
   }
 
index ed494696ecac1aee9276f9c5481f515a9c5960da..e3f1eaf164c2db03cc05b8280267d5f3fb932226 100644 (file)
@@ -11,39 +11,44 @@ class RolesMeta extends ModuleMetaData {
     return instance;
   }
   RolesMeta.internal()
-      : super('Roles', [
-          PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
-              displayType: DisplayType.combobox),
-          PropertyMetaData(
-              'name', i18n.tr('Name'), DataType.string, ':notnull:',
-              size: 64),
-          PropertyMetaData('createdAt', i18n.tr('Created at'),
-              DataType.datetime, ':hidden:'),
-          PropertyMetaData(
-              'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
-              size: 32),
-          PropertyMetaData(
-              'changedAt', i18n.tr('ChangedAt'), DataType.datetime, ':hidden:'),
-          PropertyMetaData(
-              'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
-              size: 32),
-        ], [
-          PageMetaData('New Role', PageType.create,
-              fields: [CopyDbFields('fields')]),
-          PageMetaData('Change Role', PageType.edit,
-              fields: [CopyDbFields('fields')]),
-          ListPageMetaData(
-            'Roles Overview',
-            fields: [
-              PropertyMetaData('text', i18n.tr('Text'), DataType.string,
-                  ':where=!text IS NONE OR (role_name like !text):',
+      : super(
+            'Roles',
+            [
+              PropertyMetaData(
+                  'id', i18n.tr('Id'), DataType.reference, ':primary:',
+                  displayType: DisplayType.combobox),
+              PropertyMetaData(
+                  'name', i18n.tr('Name'), DataType.string, ':notnull:',
                   size: 64),
+              PropertyMetaData('createdAt', i18n.tr('Created at'),
+                  DataType.datetime, ':hidden:'),
+              PropertyMetaData('createdBy', i18n.tr('Created by'),
+                  DataType.string, ':hidden:',
+                  size: 32),
+              PropertyMetaData('changedAt', i18n.tr('ChangedAt'),
+                  DataType.datetime, ':hidden:'),
+              PropertyMetaData('changedBy', i18n.tr('Changed by'),
+                  DataType.string, ':hidden:',
+                  size: 32),
             ],
-            toolTipAddButton: i18n.tr('Add a new role'),
-            tableColumns: 'role_id;role_name',
-            tableHeaders: i18n.tr(';Id;Name'),
-          ),
-        ]);
+            [
+              PageMetaData('New Role', PageType.create,
+                  fields: [CopyDbFields('fields')]),
+              PageMetaData('Change Role', PageType.edit,
+                  fields: [CopyDbFields('fields')]),
+              ListPageMetaData(
+                'Roles Overview',
+                fields: [
+                  PropertyMetaData('text', i18n.tr('Text'), DataType.string,
+                      ':where=!text IS NONE OR (role_name like !text):',
+                      size: 64),
+                ],
+                toolTipAddButton: i18n.tr('Add a new role'),
+                tableColumns: 'role_id;role_name',
+                tableHeaders: i18n.tr(';Id;Name'),
+              ),
+            ],
+            needsSqlAll: true);
   @override
   void onInitialized() {
     super.onInitialized();
index 35c71448d5591ae588d259e62eabc85a67190e24..2fac6a81f0534ee777cf93de7938bfdf27b3f807 100644 (file)
@@ -13,32 +13,45 @@ class RoleStarterMeta extends ModuleMetaData {
     return instance;
   }
   RoleStarterMeta.internal()
-      : super('RoleStarter', [
-          PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
-              displayType: DisplayType.combobox),
-          PropertyMetaData(
-              'role', i18n.tr('Role'), DataType.reference, ':notnull:',
-              displayType: DisplayType.combobox,
-              foreignKey: 'roles.role_id;role_name;role'),
-          PropertyMetaData(
-              'starter', i18n.tr('Starter'), DataType.reference, ':notnull:',
-              displayType: DisplayType.combobox,
-              foreignKey: 'starters.starter_id;starter_name;starter'),
-          PropertyMetaData('createdAt', i18n.tr('Created at'),
-              DataType.datetime, ':hidden:'),
-          PropertyMetaData(
-              'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
-              size: 32),
-          PropertyMetaData('changedAt', i18n.tr('Changed at'),
-              DataType.datetime, ':hidden:'),
-          PropertyMetaData(
-              'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
-              size: 32),
-        ], [
-          MappingPageMetaData(
-            i18n.tr('Role-Starter Assignment'),
-          ),
-        ]);
+      : super(
+            'RoleStarter',
+            [
+              PropertyMetaData(
+                  'id', i18n.tr('Id'), DataType.reference, ':primary:',
+                  displayType: DisplayType.combobox),
+              PropertyMetaData(
+                  'role', i18n.tr('Role'), DataType.reference, ':notnull:',
+                  displayType: DisplayType.combobox,
+                  foreignKey: 'roles.role_id;role_name;role'),
+              PropertyMetaData('starter', i18n.tr('Starter'),
+                  DataType.reference, ':notnull:',
+                  displayType: DisplayType.combobox,
+                  foreignKey: 'starters.starter_id;starter_name;starter'),
+              PropertyMetaData('order', i18n.tr('Order'), DataType.int, ''),
+              PropertyMetaData('createdAt', i18n.tr('Created at'),
+                  DataType.datetime, ':hidden:'),
+              PropertyMetaData('createdBy', i18n.tr('Created by'),
+                  DataType.string, ':hidden:',
+                  size: 32),
+              PropertyMetaData('changedAt', i18n.tr('Changed at'),
+                  DataType.datetime, ':hidden:'),
+              PropertyMetaData('changedBy', i18n.tr('Changed by'),
+                  DataType.string, ':hidden:',
+                  size: 32),
+            ],
+            [
+              MappingPageMetaData(
+                i18n.tr('Role-Starter Assignment'),
+              ),
+              ListPageMetaData(
+                'Role/Starter Assignment Overview',
+                fields: [],
+                tableColumns:
+                    'rolestarter_id;rolestarter_position;role;starter',
+                tableHeaders: i18n.tr(';Id;Position;Role;Starter'),
+              ),
+            ],
+            needsSqlAll: true);
   @override
   void onInitialized() {
     super.onInitialized();
index 150ab1f4b5dbafba63a81a1e2fdb9231679cd971..8da2dc7cdfd506898e45c2f849fa962f51149cab 100644 (file)
@@ -11,47 +11,53 @@ class StartersMeta extends ModuleMetaData {
     return instance;
   }
   StartersMeta.internal()
-      : super('Starters', [
-          PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
-              displayType: DisplayType.combobox),
-          PropertyMetaData(
-              'name', i18n.tr('Name'), DataType.string, ':notnull:',
-              size: 64),
-          PropertyMetaData(
-              'link', i18n.tr('Link'), DataType.string, ':notnull:',
-              size: 64),
-          PropertyMetaData(
-              'icon', i18n.tr('Icon'), DataType.string, ':notnull:',
-              size: 64),
-          PropertyMetaData('createdAt', i18n.tr('Created at'),
-              DataType.datetime, ':hidden:'),
-          PropertyMetaData(
-              'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
-              size: 32),
-          PropertyMetaData('changedAt', i18n.tr('Changed at'),
-              DataType.datetime, ':hidden:'),
-          PropertyMetaData(
-              'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
-              size: 32),
-        ], [
-          PageMetaData('New Starter', PageType.create,
-              fields: [CopyDbFields('fields')]),
-          PageMetaData('Change Starter', PageType.edit,
-              fields: [CopyDbFields('fields')]),
-          PageMetaData('Delete Starter', PageType.delete,
-              fields: [CopyDbFields('fields')]),
-          ListPageMetaData(
-            'Starters Overview',
-            fields: [
-              PropertyMetaData('text', i18n.tr('Text'), DataType.string,
-                  ':where=!text IS NONE OR starter_name like !text OR starter_link like !text:',
+      : super(
+            'Starters',
+            [
+              PropertyMetaData(
+                  'id', i18n.tr('Id'), DataType.reference, ':primary:',
+                  displayType: DisplayType.combobox),
+              PropertyMetaData(
+                  'name', i18n.tr('Name'), DataType.string, ':notnull:',
                   size: 64),
+              PropertyMetaData(
+                  'route', i18n.tr('Route'), DataType.string, ':notnull:',
+                  size: 128),
+              PropertyMetaData(
+                  'icon', i18n.tr('Icon'), DataType.string, ':notnull:',
+                  size: 64),
+              PropertyMetaData('createdAt', i18n.tr('Created at'),
+                  DataType.datetime, ':hidden:'),
+              PropertyMetaData('createdBy', i18n.tr('Created by'),
+                  DataType.string, ':hidden:',
+                  size: 32),
+              PropertyMetaData('changedAt', i18n.tr('Changed at'),
+                  DataType.datetime, ':hidden:'),
+              PropertyMetaData('changedBy', i18n.tr('Changed by'),
+                  DataType.string, ':hidden:',
+                  size: 32),
+            ],
+            [
+              PageMetaData('New Starter', PageType.create,
+                  fields: [CopyDbFields('fields')]),
+              PageMetaData('Change Starter', PageType.edit,
+                  fields: [CopyDbFields('fields')]),
+              PageMetaData('Delete Starter', PageType.delete,
+                  fields: [CopyDbFields('fields')]),
+              ListPageMetaData(
+                'Starters Overview',
+                fields: [
+                  PropertyMetaData('text', i18n.tr('Text'), DataType.string,
+                      ':where=!text IS NONE OR starter_name like !text OR starter_route like !text:',
+                      size: 64),
+                ],
+                toolTipAddButton: i18n.tr('Add a new starter'),
+                tableColumns:
+                    'starter_id;starter_name;starter_route;starter_icon',
+                tableHeaders: i18n.tr(';Id;Name;Route;Icon'),
+              ),
             ],
-            toolTipAddButton: i18n.tr('Add a new starter'),
-            tableColumns: 'starter_id;starter_name;starter_link;starter_icon',
-            tableHeaders: i18n.tr(';Id;Name;Link;Icon'),
-          ),
-        ]);
+            needsSqlAll: true);
   @override
   void onInitialized() {
     super.onInitialized();
index 7c16160b84908863af0a10005154f409fa4c9969..bb56856f4256770a7df6ec3f8093b321b65ee2ac 100644 (file)
@@ -18,7 +18,7 @@ final i18n = I18N();
 class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
     with MessageLine {
   final globalData = GlobalData();
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateBenchmark');
@@ -113,7 +113,7 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Benchmarks/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -130,7 +130,7 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -160,7 +160,7 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
       'sql': 'insert',
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       if (answer.startsWith('id:')) {
@@ -169,7 +169,7 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
           setError(i18n.tr('Saving data failed: $answer'));
           setState(() => 1);
         } else {
-          attendedPage!.pageStates.dbDataState.clear();
+          attendedPage.pageStates.dbDataState.clear();
           globalData.navigate(context, '/Benchmarks/edit;$id');
         }
       }
@@ -177,7 +177,7 @@ class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index bac42c040b39c8b8c9d3e280c494892bbc652382..3933f0eb54603950951fa12b8b2dce2b745e88d5 100644 (file)
@@ -31,8 +31,8 @@ class _CreateBenchmarkPageState extends CreateBenchmarkCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 17bce39fad0dd5c891192d2b81732a6c4ddcd6dd..beefab168cf83657c079933a1429da604c1adcdf 100644 (file)
@@ -21,7 +21,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'DeleteBenchmark');
@@ -41,7 +41,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -125,7 +125,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Benchmarks/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -142,7 +142,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -172,7 +172,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -182,7 +182,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
       'sql': 'delete',
       ':id': primaryKey
     };
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       globalData.navigate(context, '/Benchmarks/list');
@@ -190,7 +190,7 @@ class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
   }
 
   void onVerifyAndDelete() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onDelete();
     }
index d521ed4bfa12678cd9f4761392b7741b709a81e5..e11e7011131d48725cc1525940f4359c4b9f7eb4 100644 (file)
@@ -32,8 +32,8 @@ class _DeleteBenchmarkPageState extends DeleteBenchmarkCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 147b64423b6f769f0fcce15f956e729007b40352..de6c688a2a2f20bad8c4bbc1e8590951181864ef 100644 (file)
@@ -20,7 +20,7 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'EditBenchmark');
@@ -40,7 +40,7 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -124,7 +124,7 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Benchmarks/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -141,7 +141,7 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -171,7 +171,7 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -182,17 +182,17 @@ class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
       ':id': primaryKey
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       requestRecord();
-      attendedPage!.pageStates.dbDataState.clear();
+      attendedPage.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index 43e540f00d2a2a71255b0a0a76758ed7523b67bf..53f305c2e6716b6f78d55762258a4a27ecb513aa 100644 (file)
@@ -32,8 +32,8 @@ class _EditBenchmarkPageState extends EditBenchmarkCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index b20bc85dd2c3a91b1b66fa7c894fca4e787a6537..3dfcc0ee15c192342ec7de8cf884be9c767d61a0 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 class ListBenchmarkCustom extends State<ListBenchmarkPage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateBenchmark');
@@ -43,7 +43,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(
+              final rows = attendedPage.getRows(
                   dbData: snapshot.data!,
                   columnList:
                       'benchmark_id;benchmark_lastname;benchmark_firstname;benchmark_birthday;benchmark_active;benchmark_income',
@@ -91,7 +91,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
@@ -116,7 +116,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -154,7 +154,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
   }
 
   void requestRecords() =>
-      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+      _futureDbData = globalData.restPersistence.query(what: 'query', data: {
         'module': 'Benchmarks',
         'sql': 'list',
         'offset': _fieldData.theOffset,
@@ -163,7 +163,7 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
       });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
+    attendedPage.pageStates.dbDataState.clear();
     if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
index 6e1c6afc54266239ac45c5b65bc93c4153e2b054..6a65fa05934b2e5890627061e831e0e940ec7d01 100644 (file)
@@ -31,8 +31,8 @@ class _ListBenchmarkPageState extends ListBenchmarkCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 9ae2ed8ec26c042428da223d44c354fedb22d739..e721ba2633974b9bf0dc56ceddcdef984ab2a9fd 100644 (file)
@@ -63,14 +63,16 @@ Zur Entwicklung wurden einige **Opensource-Pakete** verwendet:
     String? href,
     String? title,
   ) async {
-    if (href!.startsWith('file:')) {
-      if (++clickCounter > 3) {
-        // globalData.navigate(context, '/configurations/base');
+    if (href != null) {
+      if (href.startsWith('file:')) {
+        if (++clickCounter > 3) {
+          // globalData.navigate(context, '/configurations/base');
+        }
+      } else {
+        await canLaunch(href)
+            ? await launch(href)
+            : globalData.logger.error('Could not launch $href');
       }
-    } else {
-      await canLaunch(href)
-          ? await launch(href)
-          : globalData.logger.error('Could not launch $href');
     }
   }
 
index 81782e3b950b973bffddbfe093291a3064f1c8fd..7028e220f044ded20cd88c880683656cb331741e 100644 (file)
@@ -47,7 +47,7 @@ class LogPageState extends State<LogPage> {
   }
 
   void store(context) async {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
     }
   }
index 581a5e4818a260b9e1943f98bdfd9901895cc596..c4d5ff0a9311434422e81ce9c64a17203b9badab 100644 (file)
@@ -10,6 +10,7 @@ import 'roles/create_role_page.dart';
 import 'roles/edit_role_page.dart';
 import 'roles/list_role_page.dart';
 import 'rolestarter/mapping_rolestarter_page.dart';
+import 'rolestarter/list_rolestarter_page.dart';
 import 'starters/create_starter_page.dart';
 import 'starters/edit_starter_page.dart';
 import 'starters/delete_starter_page.dart';
@@ -63,6 +64,9 @@ class PageManager {
       case '/RoleStarter/mapping':
         rc = MappingRoleStarterPage();
         break;
+      case '/RoleStarter/list':
+        rc = ListRoleStarterPage();
+        break;
       case '/Starters/create':
         rc = CreateStarterPage();
         break;
index 3929279e667648488524f654546cc073d9a8a7d5..0de70da26eb214fdcdc41def1a07b9d3bd65d598 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 
 class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
   final globalData = GlobalData();
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateRole');
@@ -52,7 +52,7 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Roles/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -69,7 +69,7 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -94,7 +94,7 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
       'sql': 'insert',
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       if (answer.startsWith('id:')) {
@@ -103,7 +103,7 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
           setError(i18n.tr('Saving data failed: $answer'));
           setState(() => 1);
         } else {
-          attendedPage!.pageStates.dbDataState.clear();
+          attendedPage.pageStates.dbDataState.clear();
           globalData.navigate(context, '/Roles/edit;$id');
         }
       }
@@ -111,7 +111,7 @@ class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index 2601a43b78ee66c87aefd31a8ae5f18ba43e3df5..57426c9aebd0ff34466dbafebfff52f84db3d4c5 100644 (file)
@@ -31,8 +31,8 @@ class _CreateRolePageState extends CreateRoleCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index c853b7a2fa22cdee4601c9d3ca9eae2debc1a1bf..5b6d134871b8f4f3d93c94b79ffc425862dea415 100644 (file)
@@ -20,7 +20,7 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'EditRole');
@@ -35,7 +35,7 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -64,7 +64,7 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Roles/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -81,7 +81,7 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -106,7 +106,7 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -117,17 +117,17 @@ class EditRoleCustom extends State<EditRolePage> with MessageLine {
       ':id': primaryKey
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       requestRecord();
-      attendedPage!.pageStates.dbDataState.clear();
+      attendedPage.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index 9a7a3d3b8fda7cbf43a3e862d6a9dfb76ab5527c..c720ac87b60aa961121539324c6179168524dff4 100644 (file)
@@ -32,8 +32,8 @@ class _EditRolePageState extends EditRoleCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 9f190cd465ecba1f38ff078fe9cbf29eddabdc1a..97c0f4b32c11dcc78bfcc8d9c6a5e46257669846 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 class ListRoleCustom extends State<ListRolePage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateRole');
@@ -43,7 +43,7 @@ class ListRoleCustom extends State<ListRolePage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(
+              final rows = attendedPage.getRows(
                   dbData: snapshot.data!,
                   columnList: 'role_id;role_name',
                   onDone: () => setState(() => 1),
@@ -90,7 +90,7 @@ class ListRoleCustom extends State<ListRolePage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
@@ -103,7 +103,7 @@ class ListRoleCustom extends State<ListRolePage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -141,7 +141,7 @@ class ListRoleCustom extends State<ListRolePage> {
   }
 
   void requestRecords() =>
-      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+      _futureDbData = globalData.restPersistence.query(what: 'query', data: {
         'module': 'Roles',
         'sql': 'list',
         'offset': _fieldData.theOffset,
@@ -150,8 +150,8 @@ class ListRoleCustom extends State<ListRolePage> {
       });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
-    if (_formKey.currentState!.validate()) {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
       setState(() => 1);
index 41a4331c51f3a2c254f4a7d394904e9de8842ddc..fee466d10761ea6c4d66c9c173a07aef321bf9b7 100644 (file)
@@ -31,8 +31,8 @@ class _ListRolePageState extends ListRoleCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
diff --git a/lib/page/rolestarter/list_rolestarter_custom.dart b/lib/page/rolestarter/list_rolestarter_custom.dart
new file mode 100644 (file)
index 0000000..cf515f5
--- /dev/null
@@ -0,0 +1,163 @@
+// This file is created by the meta_tool. But it can be customized.
+// It will never overridden by the meta_tool.
+import 'package:flutter/material.dart';
+
+import '../../base/defines.dart';
+import '../../base/helper.dart';
+import '../../base/i18n.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 'list_rolestarter_page.dart';
+
+final i18n = I18N();
+
+class ListRoleStarterCustom extends State<ListRoleStarterPage> {
+  final globalData = GlobalData();
+  late Future<DbData> _futureDbData;
+  late AttendedPage attendedPage;
+  final _fieldData = _FieldData();
+  final GlobalKey<FormState> _formKey =
+      GlobalKey<FormState>(debugLabel: 'CreateRoleStarter');
+  ListRoleStarterCustom();
+  @override
+  Widget build(BuildContext context) {
+    final rc = Scaffold(
+      appBar: globalData.appBarBuilder(i18n.tr('Overview rolestarter')),
+      drawer: globalData.drawerBuilder(context),
+      floatingActionButton: FloatingActionButton(
+          onPressed: () {
+            globalData.navigate(context, '/RoleStarter/create');
+          },
+          child: const Icon(Icons.add),
+          tooltip: null),
+      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 rows = attendedPage.getRows(
+                  dbData: snapshot.data!,
+                  columnList:
+                      'rolestarter_id;rolestarter_position;role;starter',
+                  onDone: () => setState(() => 1),
+                  routeEdit: '/RoleStarter/edit',
+                  context: context);
+              rc = buildFrame(
+                  totalCount: snapshot.data?.count ?? rows.length, rows: rows);
+            } else if (snapshot.hasError) {
+              rc = Text('Backend problem: ${snapshot.error}');
+            } else {
+              rc = const CircularProgressIndicator();
+            }
+          }
+          return rc;
+        },
+      )),
+    );
+    return rc;
+  }
+
+  Widget buildFrame({required JsonList rows, required int totalCount}) {
+    final padding = GlobalThemeData.padding;
+    final formItems = <FormItem>[
+      FormItem(
+          ElevatedButton(
+              onPressed: () => search(), child: Text(i18n.tr('Search'))),
+          weight: 12,
+          gapAbove: padding),
+    ];
+    final form = Form(
+        key: _formKey,
+        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(
+          label: Text(i18n.tr('Id')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Position')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Role')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Starter')),
+        ),
+      ],
+      rows: rows as List<DataRow>,
+    );
+    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,
+      SizedBox(height: padding),
+      SizedBox(width: double.infinity, child: table),
+    ]);
+    return frameWidget;
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+    requestRecords();
+  }
+
+  @override
+  void dispose() {
+    helperDummyUsage(DataType.string);
+    globalWidgetDummyUsage();
+    super.dispose();
+  }
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  void requestRecords() =>
+      _futureDbData = globalData.restPersistence.query(what: 'query', data: {
+        'module': 'RoleStarter',
+        'sql': 'list',
+        'offset': _fieldData.theOffset,
+        'size': _fieldData.thePageSize,
+      });
+
+  void search() {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
+      _formKey.currentState!.save();
+      requestRecords();
+      setState(() => 1);
+    }
+  }
+}
+
+class _FieldData {
+  int thePageSize = 10;
+  int theOffset = 0;
+}
diff --git a/lib/page/rolestarter/list_rolestarter_page.dart b/lib/page/rolestarter/list_rolestarter_page.dart
new file mode 100644 (file)
index 0000000..0d1b5b9
--- /dev/null
@@ -0,0 +1,61 @@
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/rolestarter_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'list_rolestarter_custom.dart';
+
+class ListRoleStarterPage extends StatefulWidget {
+  final PageStates pageStates = PageStates();
+  ListRoleStarterPage() : super();
+  @override
+  _ListRoleStarterPageState createState() {
+    final rc = _ListRoleStarterPageState();
+    rc.attendedPage = AttendedPage(
+        this,
+        rc,
+        GlobalData(),
+        RoleStarterMeta.instance.pageByName('list')!,
+        RoleStarterMeta.instance,
+        pageStates,
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
+    pageStates.attendedPage = rc.attendedPage;
+    return rc;
+  }
+}
+
+class _ListRoleStarterPageState extends ListRoleStarterCustom {
+  _ListRoleStarterPageState() : super();
+  @override
+  void didChangeDependencies() {
+    final size = MediaQuery.of(context).size;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
+    super.didChangeDependencies();
+  }
+
+  /// Renders the widget tree again.
+  ///
+  /// [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();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
+    }
+  }
+}
diff --git a/lib/page/rolestarter/mapping_rolestarter_custom.dart b/lib/page/rolestarter/mapping_rolestarter_custom.dart
new file mode 100644 (file)
index 0000000..c03e7da
--- /dev/null
@@ -0,0 +1,304 @@
+// This file is created by the meta_tool. But it can be customized.
+// It will never overridden by the meta_tool.
+import 'package:flutter/material.dart';
+
+import '../../base/defines.dart';
+import '../../base/helper.dart';
+import '../../base/i18n.dart';
+import '../../persistence/persistence.dart';
+import '../../services/global_widget.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import '../../widget/widget_form.dart';
+import 'mapping_rolestarter_page.dart';
+
+final i18n = I18N();
+
+class CommonInfo {
+  final List<String> columns;
+  final List<MemberInfo> members = [];
+  CommonInfo({required this.columns});
+}
+
+class MappingRoleStarterCustom extends State<MappingRoleStarterPage> {
+  final globalData = GlobalData();
+  late Future<DbData> _futureDbDataCommon;
+  late Future<DbData> _futureDbDataMember;
+  late Future<DbData> _futureDbDataConnection;
+  var membersOfCommon = <int, List<int>>{};
+  late AttendedPage attendedPage;
+  final _fieldData = _FieldData();
+  final GlobalKey<FormState> _formKey =
+      GlobalKey<FormState>(debugLabel: 'CreateRole');
+  final textController = TextEditingController();
+  final commonColumns = ['role_name'];
+  final memberColumns = ['starter_name', 'starter_route'];
+  final commonInfos = <int, CommonInfo>{};
+
+  /// Members of the current common module:
+  final memberInfos = <MemberInfo>[];
+
+  final notMemberInfos = <MemberInfo>[];
+  JsonList membersRows = [];
+  JsonList commonRows = [];
+  JsonList connectionRows = [];
+  MappingRoleStarterCustom();
+
+  @override
+  Widget build(BuildContext context) {
+    final rc = Scaffold(
+      appBar: globalData.appBarBuilder(i18n.tr('Role/Starter Assignment')),
+      drawer: globalData.drawerBuilder(context),
+      body: SafeArea(
+          child: FutureBuilder<List<DbData>>(
+        future: Future.wait([
+          _futureDbDataMember,
+          _futureDbDataCommon,
+          _futureDbDataConnection
+        ]),
+        builder: (context, AsyncSnapshot<List<DbData>> snapshot) {
+          Widget rc;
+          if (snapshot.connectionState != ConnectionState.done) {
+            rc = const CircularProgressIndicator();
+          } else {
+            if (snapshot.hasData) {
+              commonRows = snapshot.data![0].recordList ?? [];
+              membersRows = snapshot.data![1].recordList ?? [];
+              connectionRows = snapshot.data![2].recordList ?? [];
+              handleConnectionRows();
+              rc = buildFrame();
+            } else if (snapshot.hasError) {
+              rc = Text('Backend problem: ${snapshot.error}');
+            } else {
+              rc = const CircularProgressIndicator();
+            }
+          }
+          return rc;
+        },
+      )),
+    );
+    return rc;
+  }
+
+  /// Builds the items of the common module combobox from the database records.
+  List<DropdownMenuItem<int>> buildCommonItems() {
+    final rc = <DropdownMenuItem<int>>[];
+    for (var record in commonRows) {
+      rc.add(DropdownMenuItem<int>(
+          value: record['role_id'], child: Text(record['role_name'])));
+    }
+    return rc;
+  }
+
+  Widget buildFrame() {
+    final padding = GlobalThemeData.padding;
+    final itemsRoles = <DropdownMenuItem<int>>[];
+    final formItems = <FormItem>[
+      FormItem(
+          DropdownButtonFormField<int>(
+            value: itemsRoles.length == 1 ? 0 : _fieldData.role,
+            items: buildCommonItems(),
+            isExpanded: true,
+            decoration: InputDecoration(labelText: i18n.tr('Role')),
+            onChanged: (value) => _fieldData.role = value ?? 0,
+          ),
+          weight: 6),
+      FormItem(
+          ElevatedButton(onPressed: () => save(), child: Text(i18n.tr('Save'))),
+          weight: 12,
+          gapAbove: padding),
+    ];
+    final form = Form(
+        key: _formKey,
+        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 tableMembers = buildMemberTable();
+    final tableNotMembers = buildNotMemberTable();
+    final frameWidget = ListView(children: [
+      form,
+      Text(i18n.tr('The following items are assigned. Click it to remove.')),
+      SizedBox(height: padding),
+      tableMembers,
+      SizedBox(height: padding),
+      Text(
+          i18n.tr('The following items are not assigned. Click it to assign.')),
+      SizedBox(height: padding),
+      tableNotMembers,
+    ]);
+    return frameWidget;
+  }
+
+  buildMemberTable() {
+    final rows = buildTableItems(
+        commonInfos[_fieldData.role]!.members, 'rolestarter_id');
+    final headers = <DataColumn>[];
+    for (var column in commonInfos[_fieldData.role]!.columns) {
+      final label =
+          attendedPage.moduleMetaData.propertyByColumnName(column)?.label ??
+              i18n.tr('Info');
+      headers.add(DataColumn(label: Text(label)));
+    }
+    final rc = DataTable(
+      columns: headers,
+      rows: rows,
+    );
+    return rc;
+  }
+
+  buildNotMemberTable() {
+    final rows = buildTableItems(
+        commonInfos[_fieldData.role]!.members, 'rolestarter_id');
+    final headers = <DataColumn>[];
+    for (var column in commonInfos[_fieldData.role]!.columns) {
+      final label =
+          attendedPage.moduleMetaData.propertyByColumnName(column)?.label ??
+              i18n.tr('Info');
+      headers.add(DataColumn(label: Text(label)));
+    }
+    final rc = DataTable(
+      columns: headers,
+      rows: rows,
+    );
+    return rc;
+  }
+
+  /// Build the [notMemberInfos] list of items not being members of the common
+  /// module with [commonId].
+  void buildNotMembers(int commonId) {
+    notMemberInfos.clear();
+    int order = 10;
+    for (var record in membersRows) {
+      final id = record['rolestarter_starter'];
+      if (record['rolestarter_role'] == commonId && !hasMember(id)) {
+        notMemberInfos.add(MemberInfo(
+            memberId: id, position: order++, columns: memberColumns));
+      }
+    }
+  }
+
+  buildTableItems(List<MemberInfo> members, String primary) {
+    members.map((MemberInfo element) {
+      final cells = <DataCell>[];
+      final record = findRecord(membersRows, primary, element.memberId);
+      if (record != null) {
+        for (var column in element.columns) {
+          cells.add(DataCell(Text(record[column])));
+        }
+      }
+      return DataRow(cells: cells);
+    });
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+    requestRecords();
+  }
+
+  @override
+  void dispose() {
+    helperDummyUsage(DataType.string);
+    globalWidgetDummyUsage();
+    textController.dispose();
+    super.dispose();
+  }
+
+  /// Finds a record in a list of records by a given [id] in a given [column].
+  JsonMap? findRecord(JsonList rows, String column, int id) {
+    JsonMap? rc;
+    for (var record in rows) {
+      if (record[column] == id) {
+        rc = record;
+        break;
+      }
+    }
+    return rc;
+  }
+
+  /// Inspects the [connectionRows] and build the internal structures.
+  void handleConnectionRows() {
+    commonInfos.clear();
+    for (var record in commonRows) {
+      int common = record['role_id'];
+      commonInfos[common] = CommonInfo(columns: commonColumns);
+    }
+    for (var record in connectionRows) {
+      int common = record['rolestarter_role'];
+      if (!commonInfos.containsKey(common)) {
+        commonInfos[common] = CommonInfo(columns: commonColumns);
+      }
+      commonInfos[common]!.members.add(MemberInfo(
+          memberId: record['rolestarter_starter'],
+          columns: memberColumns,
+          position: record['rolestarter_position']));
+    }
+    for (var key in commonInfos.keys) {
+      commonInfos[key]!.members.sort((a, b) => a.position - b.position);
+    }
+  }
+
+  /// Returns whether the given [memberId] is part of [memberInfos].
+  bool hasMember(int memberId) {
+    bool rc = false;
+    for (var item in memberInfos) {
+      if (item.memberId == memberId) {
+        rc = true;
+        break;
+      }
+    }
+    return rc;
+  }
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  void requestRecords() {
+    _futureDbDataMember =
+        globalData.restPersistence.query(what: 'query', data: {
+      'module': 'Starters',
+      'sql': 'all',
+    });
+    _futureDbDataCommon =
+        globalData.restPersistence.query(what: 'query', data: {
+      'module': 'Roles',
+      'sql': 'all',
+    });
+    _futureDbDataConnection =
+        globalData.restPersistence.query(what: 'query', data: {
+      'module': 'RoleStarter',
+      'sql': 'all',
+    });
+  }
+
+  void save() {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState!.validate()) {
+      _formKey.currentState!.save();
+      requestRecords();
+      setState(() => 1);
+    }
+  }
+}
+
+class MemberInfo {
+  final int memberId;
+  final int position;
+  final List<String> columns;
+  MemberInfo(
+      {required this.memberId, required this.position, required this.columns});
+}
+
+class _FieldData {
+  int role = 0;
+}
diff --git a/lib/page/rolestarter/mapping_rolestarter_page.dart b/lib/page/rolestarter/mapping_rolestarter_page.dart
new file mode 100644 (file)
index 0000000..4c97680
--- /dev/null
@@ -0,0 +1,61 @@
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/rolestarter_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'mapping_rolestarter_custom.dart';
+
+class MappingRoleStarterPage extends StatefulWidget {
+  final PageStates pageStates = PageStates();
+  MappingRoleStarterPage() : super();
+  @override
+  _MappingRoleStarterPageState createState() {
+    final rc = _MappingRoleStarterPageState();
+    rc.attendedPage = AttendedPage(
+        this,
+        rc,
+        GlobalData(),
+        RoleStarterMeta.instance.pageByName('mapping')!,
+        RoleStarterMeta.instance,
+        pageStates,
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
+    pageStates.attendedPage = rc.attendedPage;
+    return rc;
+  }
+}
+
+class _MappingRoleStarterPageState extends MappingRoleStarterCustom {
+  _MappingRoleStarterPageState() : super();
+  @override
+  void didChangeDependencies() {
+    final size = MediaQuery.of(context).size;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
+    super.didChangeDependencies();
+  }
+
+  /// Renders the widget tree again.
+  ///
+  /// [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();
+        if (rebuild) {
+          didChangeDependencies();
+        }
+      });
+    }
+  }
+}
diff --git a/lib/page/rolestarter/role_starter_data.dart b/lib/page/rolestarter/role_starter_data.dart
new file mode 100644 (file)
index 0000000..2e761f3
--- /dev/null
@@ -0,0 +1,114 @@
+// DO NOT CHANGE. This file is created by the meta_tool
+import '../../base/defines.dart';
+import '../../base/helper.dart';
+import '../../persistence/data_record.dart';
+
+class RoleStarterData extends DataRecord<int> {
+  int? id;
+  int? role;
+  int? starter;
+  int? order;
+  DateTime? createdAt;
+  String? createdBy;
+  DateTime? changedAt;
+  String? changedBy;
+  RoleStarterData(
+      {this.id,
+      this.role,
+      this.starter,
+      this.order,
+      this.createdAt,
+      this.createdBy,
+      this.changedAt,
+      this.changedBy});
+  RoleStarterData.createFromMap(DataMap map) {
+    fromMap(map);
+  }
+  @override
+  void fromMap(DataMap map) {
+    id = map.containsKey('rolestarter_id')
+        ? fromString(map['rolestarter_id'], dataType: DataType.reference)
+        : null;
+    role = map.containsKey('rolestarter_role')
+        ? fromString(map['rolestarter_role'], dataType: DataType.reference)
+        : null;
+    starter = map.containsKey('rolestarter_starter')
+        ? fromString(map['rolestarter_starter'], dataType: DataType.reference)
+        : null;
+    order = map.containsKey('rolestarter_order')
+        ? fromString(map['rolestarter_order'], dataType: DataType.int)
+        : null;
+    createdAt = map.containsKey('rolestarter_createdat')
+        ? fromString(map['rolestarter_createdat'], dataType: DataType.datetime)
+        : null;
+    createdBy = map.containsKey('rolestarter_createdby')
+        ? fromString(map['rolestarter_createdby'], dataType: DataType.string)
+        : null;
+    changedAt = map.containsKey('rolestarter_changedat')
+        ? fromString(map['rolestarter_changedat'], dataType: DataType.datetime)
+        : null;
+    changedBy = map.containsKey('rolestarter_changedby')
+        ? fromString(map['rolestarter_changedby'], dataType: DataType.string)
+        : null;
+  }
+
+  @override
+  int keyOf() {
+    return id ?? 0;
+  }
+
+  @override
+  String nameOfKey() {
+    return 'rolestarter_id';
+  }
+
+  static DataType? dataTypeOf(String name) {
+    DataType? rc;
+    switch (name) {
+      case 'id':
+        rc = DataType.reference;
+        break;
+      case 'role':
+        rc = DataType.reference;
+        break;
+      case 'starter':
+        rc = DataType.reference;
+        break;
+      case 'order':
+        rc = DataType.int;
+        break;
+      case 'createdAt':
+        rc = DataType.datetime;
+        break;
+      case 'createdBy':
+        rc = DataType.string;
+        break;
+      case 'changedAt':
+        rc = DataType.datetime;
+        break;
+      case 'changedBy':
+        rc = DataType.string;
+        break;
+      default:
+        break;
+    }
+    return rc;
+  }
+
+  @override
+  DataMap toMap({DataMap? map, bool clear = true}) {
+    map ??= DataMap();
+    if (clear) {
+      map.clear();
+    }
+    map['rolestarter_id'] = id;
+    map['rolestarter_role'] = role;
+    map['rolestarter_starter'] = starter;
+    map['rolestarter_order'] = order;
+    map['rolestarter_createdat'] = createdAt;
+    map['rolestarter_createdby'] = createdBy;
+    map['rolestarter_changedat'] = changedAt;
+    map['rolestarter_changedby'] = changedBy;
+    return map;
+  }
+}
index ab5b3b077da49f4c32c5e1e569f61c5baf125985..845dc5c65cceb07f85e111efdf32b3546491c589 100644 (file)
@@ -96,7 +96,7 @@ class StartPageState extends State<StartPage> {
                     RestPersistence.fromConfig(configuration, logger),
                     logger);
                 globalData.initializeAsync().then((value) {
-                  globalData.navigate(context, '/Starters/list');
+                  globalData.navigate(context, '/RoleStarter/mapping');
                 });
               }
             });
index fffaf2f487f6fa86a9a88522c953474b0f8291d1..bfe2ccbd9da18ae5b66c343ac0b8952cbe507bfb 100644 (file)
@@ -17,12 +17,12 @@ final i18n = I18N();
 
 class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
   final globalData = GlobalData();
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateStarter');
   final nameController = TextEditingController();
-  final linkController = TextEditingController();
+  final routeController = TextEditingController();
   final iconController = TextEditingController();
   CreateStarterCustom();
   @override
@@ -37,7 +37,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
   Widget buildFrame() {
     final padding = GlobalThemeData.padding;
     nameController.text = _fieldData.name;
-    linkController.text = _fieldData.link;
+    routeController.text = _fieldData.route;
     iconController.text = _fieldData.icon;
     final formItems = <FormItem>[
       FormItem(
@@ -49,10 +49,10 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
           weight: 6),
       FormItem(
           TextFormField(
-              controller: linkController,
-              decoration: InputDecoration(labelText: i18n.tr('Link')),
+              controller: routeController,
+              decoration: InputDecoration(labelText: i18n.tr('Route')),
               validator: (input) => notEmpty(input),
-              onSaved: (value) => _fieldData.link = value ?? ''),
+              onSaved: (value) => _fieldData.route = value ?? ''),
           weight: 6),
       FormItem(
           TextFormField(
@@ -70,7 +70,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Starters/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -87,7 +87,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -98,7 +98,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
     helperDummyUsage(DataType.int);
     globalWidgetDummyUsage();
     nameController.dispose();
-    linkController.dispose();
+    routeController.dispose();
     iconController.dispose();
     super.dispose();
   }
@@ -114,7 +114,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
       'sql': 'insert',
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       if (answer.startsWith('id:')) {
@@ -123,7 +123,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
           setError(i18n.tr('Saving data failed: $answer'));
           setState(() => 1);
         } else {
-          attendedPage!.pageStates.dbDataState.clear();
+          attendedPage.pageStates.dbDataState.clear();
           globalData.navigate(context, '/Starters/edit;$id');
         }
       }
@@ -131,7 +131,7 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
@@ -140,12 +140,12 @@ class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
 
 class _FieldData {
   String name = '';
-  String link = '';
+  String route = '';
   String icon = '';
 
   void toMap(Map<String, dynamic> map) {
     map[':name'] = name;
-    map[':link'] = link;
+    map[':route'] = route;
     map[':icon'] = icon;
     map[':createdBy'] = GlobalData.loginUserName;
   }
index 29fc58b1c2897b0ae64e33357e4a52f252df76ca..58346477b65c9d87d5e1e5c4f02c3d9fa46869e9 100644 (file)
@@ -31,8 +31,8 @@ class _CreateStarterPageState extends CreateStarterCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index c99708d1684525c7bc93ac09f9cc555c8e660f6a..77d91f93cea6dee71fbab7cbd10792a506f0b0ab 100644 (file)
@@ -20,12 +20,12 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'DeleteStarter');
   final nameController = TextEditingController();
-  final linkController = TextEditingController();
+  final routeController = TextEditingController();
   final iconController = TextEditingController();
   DeleteStarterCustom(this.primaryKey);
   @override
@@ -37,7 +37,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -49,7 +49,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
   Widget buildFrame() {
     final padding = GlobalThemeData.padding;
     nameController.text = _fieldData.name;
-    linkController.text = _fieldData.link;
+    routeController.text = _fieldData.route;
     iconController.text = _fieldData.icon;
     final formItems = <FormItem>[
       FormItem(
@@ -61,10 +61,10 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
           weight: 6),
       FormItem(
           TextFormField(
-              controller: linkController,
-              decoration: InputDecoration(labelText: i18n.tr('Link')),
+              controller: routeController,
+              decoration: InputDecoration(labelText: i18n.tr('Route')),
               validator: (input) => notEmpty(input),
-              onSaved: (value) => _fieldData.link = value ?? ''),
+              onSaved: (value) => _fieldData.route = value ?? ''),
           weight: 6),
       FormItem(
           TextFormField(
@@ -82,7 +82,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Starters/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -99,7 +99,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -116,7 +116,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
     helperDummyUsage(DataType.int);
     globalWidgetDummyUsage();
     nameController.dispose();
-    linkController.dispose();
+    routeController.dispose();
     iconController.dispose();
     super.dispose();
   }
@@ -126,7 +126,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -136,7 +136,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
       'sql': 'delete',
       ':id': primaryKey
     };
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       globalData.navigate(context, '/Starters/list');
@@ -144,7 +144,7 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
   }
 
   void onVerifyAndDelete() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onDelete();
     }
@@ -153,12 +153,12 @@ class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
 
 class _FieldData {
   String name = '';
-  String link = '';
+  String route = '';
   String icon = '';
 
   void fromMap(Map<String, dynamic> map) {
     name = map['starter_name'];
-    link = map['starter_link'];
+    route = map['starter_route'];
     icon = map['starter_icon'];
   }
 }
index 9d872e68ee11b87f070cbe17e26de0309a12da87..0d16fe3ea31e72e54bd383d6dc0dbdae12732829 100644 (file)
@@ -32,8 +32,8 @@ class _DeleteStarterPageState extends DeleteStarterCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 60c5384dee41232efdff3d40c97a63e42eeb6d9b..2dd6b6a35acee1f83e9e9d13fd6547d2a0c0e520 100644 (file)
@@ -20,12 +20,12 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'EditStarter');
   final nameController = TextEditingController();
-  final linkController = TextEditingController();
+  final routeController = TextEditingController();
   final iconController = TextEditingController();
   EditStarterCustom(this.primaryKey);
   @override
@@ -37,7 +37,7 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -49,7 +49,7 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
   Widget buildFrame() {
     final padding = GlobalThemeData.padding;
     nameController.text = _fieldData.name;
-    linkController.text = _fieldData.link;
+    routeController.text = _fieldData.route;
     iconController.text = _fieldData.icon;
     final formItems = <FormItem>[
       FormItem(
@@ -61,10 +61,10 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
           weight: 6),
       FormItem(
           TextFormField(
-              controller: linkController,
-              decoration: InputDecoration(labelText: i18n.tr('Link')),
+              controller: routeController,
+              decoration: InputDecoration(labelText: i18n.tr('Route')),
               validator: (input) => notEmpty(input),
-              onSaved: (value) => _fieldData.link = value ?? ''),
+              onSaved: (value) => _fieldData.route = value ?? ''),
           weight: 6),
       FormItem(
           TextFormField(
@@ -82,7 +82,7 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Starters/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -99,7 +99,7 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -116,7 +116,7 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
     helperDummyUsage(DataType.int);
     globalWidgetDummyUsage();
     nameController.dispose();
-    linkController.dispose();
+    routeController.dispose();
     iconController.dispose();
     super.dispose();
   }
@@ -126,7 +126,7 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -137,17 +137,17 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
       ':id': primaryKey
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       requestRecord();
-      attendedPage!.pageStates.dbDataState.clear();
+      attendedPage.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
@@ -156,19 +156,19 @@ class EditStarterCustom extends State<EditStarterPage> with MessageLine {
 
 class _FieldData {
   String name = '';
-  String link = '';
+  String route = '';
   String icon = '';
 
   void fromMap(Map<String, dynamic> map) {
     name = map['starter_name'];
-    link = map['starter_link'];
+    route = map['starter_route'];
     icon = map['starter_icon'];
   }
 
   void toMap(Map<String, dynamic> map) {
     // please set outside: map[':id'] = primaryKey;
     map[':name'] = name;
-    map[':link'] = link;
+    map[':route'] = route;
     map[':icon'] = icon;
     map[':changedBy'] = GlobalData.loginUserName;
   }
index a1022aeb7209e76045fed5d88af334f4d9df02f5..2768e2587174fc2372cde82ac00213b634ed5212 100644 (file)
@@ -32,8 +32,8 @@ class _EditStarterPageState extends EditStarterCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index e2cce7e9b183e251143d2ea6dac0f4d03e9f3cb2..e9de7ab40a8c7f585848d5619090372b2fc6b8cb 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 class ListStarterCustom extends State<ListStarterPage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateStarter');
@@ -43,10 +43,10 @@ class ListStarterCustom extends State<ListStarterPage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(
+              final rows = attendedPage.getRows(
                   dbData: snapshot.data!,
                   columnList:
-                      'starter_id;starter_name;starter_link;starter_icon',
+                      'starter_id;starter_name;starter_route;starter_icon',
                   onDone: () => setState(() => 1),
                   routeEdit: '/Starters/edit',
                   context: context);
@@ -91,7 +91,7 @@ class ListStarterCustom extends State<ListStarterPage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
@@ -102,7 +102,7 @@ class ListStarterCustom extends State<ListStarterPage> {
           label: Text(i18n.tr('Name')),
         ),
         DataColumn(
-          label: Text(i18n.tr('Link')),
+          label: Text(i18n.tr('Route')),
         ),
         DataColumn(
           label: Text(i18n.tr('Icon')),
@@ -110,7 +110,7 @@ class ListStarterCustom extends State<ListStarterPage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -148,7 +148,7 @@ class ListStarterCustom extends State<ListStarterPage> {
   }
 
   void requestRecords() =>
-      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+      _futureDbData = globalData.restPersistence.query(what: 'query', data: {
         'module': 'Starters',
         'sql': 'list',
         'offset': _fieldData.theOffset,
@@ -157,8 +157,8 @@ class ListStarterCustom extends State<ListStarterPage> {
       });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
-    if (_formKey.currentState!.validate()) {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
       setState(() => 1);
index a0849ef99004ef1003209d381af161ddeccb73d3..795a7d2e8e65a758a13dbae8c00e5acc38f82067 100644 (file)
@@ -31,8 +31,8 @@ class _ListStarterPageState extends ListStarterCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index cf9a8844521d79508ec653d58be1f7badca9e116..46c80855e7912746981fa823e4f1c32dd759220b 100644 (file)
@@ -6,7 +6,7 @@ import '../../persistence/data_record.dart';
 class StarterData extends DataRecord<int> {
   int? id;
   String? name;
-  String? link;
+  String? route;
   String? icon;
   DateTime? createdAt;
   String? createdBy;
@@ -15,7 +15,7 @@ class StarterData extends DataRecord<int> {
   StarterData(
       {this.id,
       this.name,
-      this.link,
+      this.route,
       this.icon,
       this.createdAt,
       this.createdBy,
@@ -32,8 +32,8 @@ class StarterData extends DataRecord<int> {
     name = map.containsKey('starter_name')
         ? fromString(map['starter_name'], dataType: DataType.string)
         : null;
-    link = map.containsKey('starter_link')
-        ? fromString(map['starter_link'], dataType: DataType.string)
+    route = map.containsKey('starter_route')
+        ? fromString(map['starter_route'], dataType: DataType.string)
         : null;
     icon = map.containsKey('starter_icon')
         ? fromString(map['starter_icon'], dataType: DataType.string)
@@ -71,7 +71,7 @@ class StarterData extends DataRecord<int> {
       case 'name':
         rc = DataType.string;
         break;
-      case 'link':
+      case 'route':
         rc = DataType.string;
         break;
       case 'icon':
@@ -103,7 +103,7 @@ class StarterData extends DataRecord<int> {
     }
     map['starter_id'] = id;
     map['starter_name'] = name;
-    map['starter_link'] = link;
+    map['starter_route'] = route;
     map['starter_icon'] = icon;
     map['starter_createdat'] = createdAt;
     map['starter_createdby'] = createdBy;
index df1e1533fffaff3ea73c54f944c9d95a2e0b2a9f..13de279f82340d9e0a057050901590f0f7a39b76 100644 (file)
@@ -18,7 +18,7 @@ final i18n = I18N();
 class CreateStructureCustom extends State<CreateStructurePage>
     with MessageLine {
   final globalData = GlobalData();
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateStructure');
@@ -80,7 +80,7 @@ class CreateStructureCustom extends State<CreateStructurePage>
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Structures/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -97,7 +97,7 @@ class CreateStructureCustom extends State<CreateStructurePage>
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -125,7 +125,7 @@ class CreateStructureCustom extends State<CreateStructurePage>
       'sql': 'insert',
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       if (answer.startsWith('id:')) {
@@ -134,7 +134,7 @@ class CreateStructureCustom extends State<CreateStructurePage>
           setError(i18n.tr('Saving data failed: $answer'));
           setState(() => 1);
         } else {
-          attendedPage!.pageStates.dbDataState.clear();
+          attendedPage.pageStates.dbDataState.clear();
           globalData.navigate(context, '/Structures/edit;$id');
         }
       }
@@ -142,7 +142,7 @@ class CreateStructureCustom extends State<CreateStructurePage>
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index a46570beeb8feb21de7b8cf3110380c7dbf8b5a9..ab007e19603459ec57ccfe8b9bdf9e3d6686282b 100644 (file)
@@ -31,8 +31,8 @@ class _CreateStructurePageState extends CreateStructureCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index f20a98b07f5deb980f03fa8837ec6ab3766c4963..043bc26e5ccfbd9394faeaa78ab1e9aa763b5bbf 100644 (file)
@@ -21,7 +21,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'DeleteStructure');
@@ -39,7 +39,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -92,7 +92,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Structures/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -109,7 +109,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -137,7 +137,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -147,7 +147,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
       'sql': 'delete',
       ':id': primaryKey
     };
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       globalData.navigate(context, '/Structures/list');
@@ -155,7 +155,7 @@ class DeleteStructureCustom extends State<DeleteStructurePage>
   }
 
   void onVerifyAndDelete() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onDelete();
     }
index b974f29b5c9e555b8fd547d1aa6a3f69614fac28..dda553597bff1165d61bc28a38276e719e27c4d5 100644 (file)
@@ -32,8 +32,8 @@ class _DeleteStructurePageState extends DeleteStructureCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index c96e9ba4057518da886042ac8431089278c676a4..309734d2045f05926aa6e70b026ce8972c0e371f 100644 (file)
@@ -20,7 +20,7 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'EditStructure');
@@ -38,7 +38,7 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -91,7 +91,7 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Structures/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -108,7 +108,7 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -136,7 +136,7 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -147,17 +147,17 @@ class EditStructureCustom extends State<EditStructurePage> with MessageLine {
       ':id': primaryKey
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       requestRecord();
-      attendedPage!.pageStates.dbDataState.clear();
+      attendedPage.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index b8c92b97bc888d9b45dcc52bc0d9700a303f4c7e..5c4ef5ffdc102e28c55aab8296985bf09200bb75 100644 (file)
@@ -32,8 +32,8 @@ class _EditStructurePageState extends EditStructureCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 952c08ce54205dccffe6e42f38cbe5395e68e8f1..4cec578eeebfccd60f20ede2418a528114f13f9e 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 class ListStructureCustom extends State<ListStructurePage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateStructure');
@@ -43,7 +43,7 @@ class ListStructureCustom extends State<ListStructurePage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(
+              final rows = attendedPage.getRows(
                   dbData: snapshot.data!,
                   columnList:
                       'structure_id;structure_scope;structure_name;structure_value;structure_position',
@@ -91,7 +91,7 @@ class ListStructureCustom extends State<ListStructurePage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
@@ -113,7 +113,7 @@ class ListStructureCustom extends State<ListStructurePage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -151,7 +151,7 @@ class ListStructureCustom extends State<ListStructurePage> {
   }
 
   void requestRecords() =>
-      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+      _futureDbData = globalData.restPersistence.query(what: 'query', data: {
         'module': 'Structures',
         'sql': 'list',
         'offset': _fieldData.theOffset,
@@ -160,8 +160,8 @@ class ListStructureCustom extends State<ListStructurePage> {
       });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
-    if (_formKey.currentState!.validate()) {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
       setState(() => 1);
index cc03dc12396c4d4cabddfead75a5143030fe8055..4b6d716eb34197c3a7d4d4961ee0578d5d31f1e9 100644 (file)
@@ -31,8 +31,8 @@ class _ListStructurePageState extends ListStructureCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 5efce7c6c6a060ec1a4ee51a5e0d41c0e881a7e6..8265748a8fc1130252980a7c20cbce49e1f2a830 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 
 class CreateUserCustom extends State<CreateUserPage> with MessageLine {
   final globalData = GlobalData();
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateUser');
@@ -37,9 +37,9 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
   Widget buildFrame() {
     final padding = GlobalThemeData.padding;
     comboRolesFromBackend(
-        attendedPage: attendedPage!, onDone: () => setState(() => 1));
-    final itemsRoles = comboRoles(
-        i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage!);
+        attendedPage: attendedPage, onDone: () => setState(() => 1));
+    final itemsRoles =
+        comboRoles(i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage);
     nameController.text = _fieldData.name;
     displayNameController.text = _fieldData.displayName;
     emailController.text = _fieldData.email;
@@ -85,7 +85,7 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Users/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -102,7 +102,7 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -129,7 +129,7 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
       'sql': 'insert',
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       if (answer.startsWith('id:')) {
@@ -138,7 +138,7 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
           setError(i18n.tr('Saving data failed: $answer'));
           setState(() => 1);
         } else {
-          attendedPage!.pageStates.dbDataState.clear();
+          attendedPage.pageStates.dbDataState.clear();
           globalData.navigate(context, '/Users/edit;$id');
         }
       }
@@ -146,7 +146,7 @@ class CreateUserCustom extends State<CreateUserPage> with MessageLine {
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index a4763713cd512d45a3a3e8fb1dcab506919b4dd9..9428ee756ed0e88059468566b00134570708df95 100644 (file)
@@ -31,8 +31,8 @@ class _CreateUserPageState extends CreateUserCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 9b01b618b6c6aba2006f85d6e081319a3738d88a..75c7808930925383d484fb8a3e9940d2aa108382 100644 (file)
@@ -20,7 +20,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'DeleteUser');
@@ -37,7 +37,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -49,9 +49,9 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
   Widget buildFrame() {
     final padding = GlobalThemeData.padding;
     comboRolesFromBackend(
-        attendedPage: attendedPage!, onDone: () => setState(() => 1));
-    final itemsRoles = comboRoles(
-        i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage!);
+        attendedPage: attendedPage, onDone: () => setState(() => 1));
+    final itemsRoles =
+        comboRoles(i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage);
     nameController.text = _fieldData.name;
     displayNameController.text = _fieldData.displayName;
     emailController.text = _fieldData.email;
@@ -97,7 +97,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Users/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -114,7 +114,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -141,7 +141,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -151,7 +151,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
       'sql': 'delete',
       ':id': primaryKey
     };
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       globalData.navigate(context, '/Users/list');
@@ -159,7 +159,7 @@ class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
   }
 
   void onVerifyAndDelete() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onDelete();
     }
index d87137a01ef0bfe58d3df5e713570be4568e4b21..5b627576e2b59de43ca4c795b5382d70c442070a 100644 (file)
@@ -32,8 +32,8 @@ class _DeleteUserPageState extends DeleteUserCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index c38e348decaf5ff3f9537e013146254f9a52d322..e79c56cef8f23c1da378d8f3fefbd1b44191f6fe 100644 (file)
@@ -20,7 +20,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
   final int primaryKey;
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'EditUser');
@@ -37,7 +37,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
             child: FutureBuilder<DbData>(
                 future: _futureDbData,
                 builder: (context, snapshot) {
-                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                  final rc = attendedPage.loadRecord(snapshot, (record) {
                     _fieldData.fromMap(record);
                     return buildFrame();
                   });
@@ -49,9 +49,9 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
   Widget buildFrame() {
     final padding = GlobalThemeData.padding;
     comboRolesFromBackend(
-        attendedPage: attendedPage!, onDone: () => setState(() => 1));
-    final itemsRoles = comboRoles(
-        i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage!);
+        attendedPage: attendedPage, onDone: () => setState(() => 1));
+    final itemsRoles =
+        comboRoles(i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage);
     nameController.text = _fieldData.name;
     displayNameController.text = _fieldData.displayName;
     emailController.text = _fieldData.email;
@@ -97,7 +97,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Users/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -114,7 +114,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -141,7 +141,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
     super.initState();
   }
 
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -152,17 +152,17 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
       ':id': primaryKey
     };
     _fieldData.toMap(parameters);
-    globalData.restPersistence!
+    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {
       requestRecord();
-      attendedPage!.pageStates.dbDataState.clear();
+      attendedPage.pageStates.dbDataState.clear();
       setState(() => 1);
     });
   }
 
   void onVerifyAndStore() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       onStore();
     }
index 9b0c24f67e88d28efa1b524dfc79034dba0e7e01..18ae325a906338e7afa7c20051909cb4e46bd2ec 100644 (file)
@@ -32,8 +32,8 @@ class _EditUserPageState extends EditUserCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index 4d5be2f151ff1fb02f833f98fe6d665e07e1fc69..4c41337b6e4b84725e48caba47470196506cb8be 100644 (file)
@@ -17,7 +17,7 @@ final i18n = I18N();
 class ListUserCustom extends State<ListUserPage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateUser');
@@ -43,7 +43,7 @@ class ListUserCustom extends State<ListUserPage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(
+              final rows = attendedPage.getRows(
                   dbData: snapshot.data!,
                   columnList:
                       'user_id;user_name;user_displayname;user_email;role',
@@ -68,9 +68,9 @@ class ListUserCustom extends State<ListUserPage> {
   Widget buildFrame({required JsonList rows, required int totalCount}) {
     final padding = GlobalThemeData.padding;
     comboRolesFromBackend(
-        attendedPage: attendedPage!, onDone: () => setState(() => 1));
+        attendedPage: attendedPage, onDone: () => setState(() => 1));
     final itemsRoles = comboRoles(
-        i18n.trDyn(GlobalTranslations.comboboxItemAll), attendedPage!);
+        i18n.trDyn(GlobalTranslations.comboboxItemAll), attendedPage);
     final formItems = <FormItem>[
       FormItem(
           TextFormField(
@@ -106,7 +106,7 @@ class ListUserCustom extends State<ListUserPage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
@@ -128,7 +128,7 @@ class ListUserCustom extends State<ListUserPage> {
       ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -166,7 +166,7 @@ class ListUserCustom extends State<ListUserPage> {
   }
 
   void requestRecords() =>
-      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+      _futureDbData = globalData.restPersistence.query(what: 'query', data: {
         'module': 'Users',
         'sql': 'list',
         'offset': _fieldData.theOffset,
@@ -176,8 +176,8 @@ class ListUserCustom extends State<ListUserPage> {
       });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
-    if (_formKey.currentState!.validate()) {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
       setState(() => 1);
index 41a1c6c7391d179182e4c928036245f2b1cc1196..b4f014c39aaa74367ebe640b02712fc0d3755837 100644 (file)
@@ -31,8 +31,8 @@ class _ListUserPageState extends ListUserCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
index b3261a3c744f2b5df1d9c8e4031fc12afae60514..8449761e7d9e318e2bf8c074a9796672e183f4bb 100644 (file)
@@ -60,7 +60,7 @@ void _requestData(String name, AttendedPage attendedPage,
   if (!attendedPage.pageStates.dbDataState.hasEntry(name)) {
     attendedPage.pageStates.dbDataState.addRequest(name).then((_) =>
         GlobalData()
-            .restPersistence!
+            .restPersistence
             .query(what: 'query', data: parameters)
             .then((value) {
           attendedPage.pageStates.dbDataState
index 9c1215cb00fad413fd95bbc729653c3f943844be..00f403134c2d0131fa2a946bcd761592e0d19b34 100644 (file)
@@ -24,7 +24,7 @@ abstract class FooterInterface {
 /// Storage for  global resources. This is a singleton.
 class GlobalData {
   static const version = '2021.08.24.00';
-  static GlobalData? _instance;
+  static late GlobalData _instance;
   static String baseDirectory = '';
   static var serverEnvironment = ServerEnvironment.productive;
   static final String applicationName = theApplicationName;
@@ -36,11 +36,11 @@ class GlobalData {
   final DrawerBuilder drawerBuilder;
   final FooterBuilder footerBuilder;
   final BaseConfiguration configuration;
-  final RestPersistence? restPersistence;
+  late final RestPersistence restPersistence;
   late HomeDirectories homeDirectories;
 
   final navigatorStack = NavigatorStack();
-  factory GlobalData() => _instance ?? GlobalData();
+  factory GlobalData() => _instance;
 
   /// [configuration]: general settings.
   /// [appBarBuilder]: a factory to create the Hamburger menu.
@@ -108,7 +108,7 @@ class HomeDirectories {
 /// This allows to access the calling page from the current page,
 /// e.g. to inform about changes.
 class NavigatorStack {
-  GlobalData? globalData;
+  late GlobalData globalData;
   final stack = <NavigatorStackEntry>[];
 
   /// Switches the page given by a [route].
@@ -156,7 +156,7 @@ class NavigatorStack {
         }
       }
       if (parent == null) {
-        globalData!.logger
+        globalData.logger
             .error('informAboutChanges(): parent ${route!} not found');
       } else {
         // parent.noticeChange();
@@ -170,7 +170,7 @@ class NavigatorStack {
   /// [context]: the context of the calling page.
   void pop(BuildContext context) {
     if (stack.isEmpty) {
-      globalData!.logger.error('NavigatorStack.pop(): empty stack');
+      globalData.logger.error('NavigatorStack.pop(): empty stack');
     } else {
       stack.removeLast();
       Navigator.pop(context);
@@ -195,7 +195,7 @@ class NavigatorStack {
             ?.addListener(() => attendedPage.reload(rebuild: true));
       }
     } else {
-      globalData!.logger.error(
+      globalData.logger.error(
           'supplyTopOfStack(): route $route not found. TOS: ' +
               (last == null ? '<none>' : last.route));
     }
index 79f25f2a46b94f654fb31594df9f7d93d9fbcfcb..514fb0efeb6a7873e2bbbef2302c74945f01242c 100644 (file)
@@ -22,13 +22,13 @@ class Structure {
 
 /// Manages a list of [Structure] items.
 class Structures {
-  static Structures? _instance;
-  GlobalData? globalData;
+  static late Structures _instance;
+  late GlobalData globalData;
   final structures = <Structure>[];
   final scopes = <String, List<Structure>>{};
 
   /// Returns the singleton instance.
-  factory Structures() => _instance!;
+  factory Structures() => _instance;
 
   /// Builds the singleton instance with items from a JSon file.
   ///
@@ -38,7 +38,7 @@ class Structures {
     this.globalData = GlobalData();
     final file = File(filename);
     if (!file.existsSync()) {
-      globalData!.logger.error('cannot read structures from $filename');
+      globalData.logger.error('cannot read structures from $filename');
     } else {
       final content = file.readAsStringSync();
       final data = convert.jsonDecode(content);
index 104ab1729f797087dd3cf293234acb55277971d7..7ddf1d1c044a7ed032543addf9d89cff8d7bb15b 100644 (file)
@@ -175,7 +175,7 @@ class AttendedPage extends ChangeNotifier {
     String name = 'record';
     if (!pageStates.dbDataState.hasEntry(name)) {
       pageStates.dbDataState.addRequest(name).then((_) => globalData
-              .restPersistence!
+              .restPersistence
               .query(what: what, data: parameters)
               .then((value) {
             pageStates.dbDataState
index 37af3dc0a5256779ea22cf4c025b3461c7465e33..982d8c9f962e52ce5e12798bf2240bbe2efb5616 100644 (file)
@@ -15,7 +15,7 @@ class PageGenerator extends SqlGenerator {
         child: FutureBuilder<DbData>(
           future: _futureDbData,
           builder: (context, snapshot) {
-            final rc = attendedPage!.loadRecord(snapshot, (record) {
+            final rc = attendedPage.loadRecord(snapshot, (record) {
               _fieldData.fromMap(record);
               return buildFrame();
             });
@@ -65,8 +65,8 @@ class _EditUserPageState extends EditUserCustom {
   @override
   void didChangeDependencies() {
     final size = MediaQuery.of(context).size;
-    attendedPage!.pageStates.screenWidth = size.width;
-    attendedPage!.pageStates.screenHeight = size.height;
+    attendedPage.pageStates.screenWidth = size.width;
+    attendedPage.pageStates.screenHeight = size.height;
     super.didChangeDependencies();
   }
 
@@ -95,9 +95,9 @@ class _EditUserPageState extends EditUserCustom {
 }''';
 
   static final templateGlobalComboBox = '''    comboRolesFromBackend(
-        attendedPage: attendedPage!, onDone: () => setState(() => 1));
+        attendedPage: attendedPage, onDone: () => setState(() => 1));
     final itemsRoles = comboRoles(
-        i18n.trDyn(GlobalTranslations.combobox#UNDEF), attendedPage!);''';
+        i18n.trDyn(GlobalTranslations.combobox#UNDEF), attendedPage);''';
 
   static final templateListCustom =
       '''// This file is created by the meta_tool. But it can be customized.
@@ -119,7 +119,7 @@ final i18n = I18N();
 class ListUserCustom extends State<ListUserPage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateUser');
@@ -145,7 +145,7 @@ class ListUserCustom extends State<ListUserPage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(dbData: snapshot.data!,
+              final rows = attendedPage.getRows(dbData: snapshot.data!,
                   columnList: '#ROW_COLUMNS',
                   onDone: () => setState(() => 1),
                   route#EDIT1: '/Users/#EDIT2',
@@ -186,14 +186,14 @@ class ListUserCustom extends State<ListUserPage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
 #TABLE_HEADER      ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -229,7 +229,7 @@ class ListUserCustom extends State<ListUserPage> {
     super.initState();
   }
 
-  void requestRecords() =>  _futureDbData = globalData.restPersistence!.query(
+  void requestRecords() =>  _futureDbData = globalData.restPersistence.query(
     what: 'query', data: {
       'module': 'Users',
       'sql': 'list',
@@ -238,8 +238,8 @@ class ListUserCustom extends State<ListUserPage> {
 #PARAM_DEF    });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
-    if (_formKey.currentState!.validate()) {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
       setState(() => 1);
@@ -273,7 +273,7 @@ final i18n = I18N();
 class MappingUserCustom extends State<MappingUserPage> {
   final globalData = GlobalData();
   late Future<DbData> _futureDbData;
-  AttendedPage? attendedPage;
+  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'CreateUser');
@@ -299,7 +299,7 @@ class MappingUserCustom extends State<MappingUserPage> {
             rc = const CircularProgressIndicator();
           } else {
             if (snapshot.hasData) {
-              final rows = attendedPage!.getRows(dbData: snapshot.data!,
+              final rows = attendedPage.getRows(dbData: snapshot.data!,
                   columnList: '#ROW_COLUMNS',
                   onDone: () => setState(() => 1),
                   route#EDIT1: '/Users/#EDIT2',
@@ -340,14 +340,14 @@ class MappingUserCustom extends State<MappingUserPage> {
                 padding: EdgeInsets.symmetric(
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(formItems,
-                    screenWidth: attendedPage!.pageStates.screenWidth,
+                    screenWidth: attendedPage.pageStates.screenWidth,
                     padding: padding))));
     final table = DataTable(
       columns: <DataColumn>[
 #TABLE_HEADER      ],
       rows: rows as List<DataRow>,
     );
-    Widget? tabBar = attendedPage!.buildChipBar(
+    Widget? tabBar = attendedPage.buildChipBar(
         totalCount: totalCount,
         offset: _fieldData.theOffset,
         pageSize: _fieldData.thePageSize,
@@ -383,7 +383,7 @@ class MappingUserCustom extends State<MappingUserPage> {
     super.initState();
   }
 
-  void requestRecords() =>  _futureDbData = globalData.restPersistence!.query(
+  void requestRecords() =>  _futureDbData = globalData.restPersistence.query(
     what: 'query', data: {
       'module': 'Users',
       'sql': 'list',
@@ -392,8 +392,8 @@ class MappingUserCustom extends State<MappingUserPage> {
 #PARAM_DEF    });
 
   void search() {
-    attendedPage!.pageStates.dbDataState.clear();
-    if (_formKey.currentState!.validate()) {
+    attendedPage.pageStates.dbDataState.clear();
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       requestRecords();
       setState(() => 1);
@@ -427,7 +427,7 @@ final i18n = I18N();
 
 class EditUserCustom extends State<EditUserPage> with MessageLine {
 #DEF_PRIMARY  final globalData = GlobalData();
-#DEF_FUTURE  AttendedPage? attendedPage;
+#DEF_FUTURE  late AttendedPage attendedPage;
   final _fieldData = _FieldData();
   final GlobalKey<FormState> _formKey =
       GlobalKey<FormState>(debugLabel: 'EditUser');
@@ -453,7 +453,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
       FormItem(
           ElevatedButton(
             onPressed: () {
-              attendedPage!.pageStates.dbDataState.clear();
+              attendedPage.pageStates.dbDataState.clear();
               globalData.navigate(context, '/Users/list');
             },
             child: Text(i18n.tr('Cancel')),
@@ -470,7 +470,7 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
                     vertical: padding, horizontal: padding),
                 child: WidgetForm.flexibleGrid(
                   formItems,
-                  screenWidth: attendedPage!.pageStates.screenWidth,
+                  screenWidth: attendedPage.pageStates.screenWidth,
                   padding: padding,
                 ))));
     return rc;
@@ -493,13 +493,13 @@ class EditUserCustom extends State<EditUserPage> with MessageLine {
       'module': 'Users',
       'sql': '#SQL_TYPE',
 #SET_PRIMARY    };
-#CALL_TO_MAP    globalData.restPersistence!
+#CALL_TO_MAP    globalData.restPersistence
         .store(what: 'store', map: parameters)
         .then((answer) {#STORAGE_DONE});
   }
 
   void #ACTION2() {
-    if (_formKey.currentState!.validate()) {
+    if (_formKey.currentState != null && _formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       #ACTION1();
     }
@@ -511,7 +511,7 @@ class _FieldData {
 #FROM_MAP#TO_MAP}
 ''';
   static final templateRequestRecord = '''
-  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+  void requestRecord() => _futureDbData = globalData.restPersistence.query(
       what: 'query',
       data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
 
@@ -525,7 +525,7 @@ class _FieldData {
           setError(i18n.tr('Saving data failed: \$answer'));
           setState(() => 1);
         } else {
-          attendedPage!.pageStates.dbDataState.clear();
+          attendedPage.pageStates.dbDataState.clear();
           globalData.navigate(context, '/#MODULE/edit;\$id');
         }
       }
@@ -533,7 +533,7 @@ class _FieldData {
   static final templateStorageDoneEdit = '''
 
       requestRecord();
-      attendedPage!.pageStates.dbDataState.clear();
+      attendedPage.pageStates.dbDataState.clear();
       setState(() => 1);
     ''';
   static final templateStorageDoneDelete =
@@ -1031,7 +1031,7 @@ StatefulWidget? customPageByRoute(String route) {
     var didChangeDependencies = templateDidChangeDependencies;
     var definitionFuture = '  late Future<DbData> _futureDbData;';
     var importPersistence = "import '../../persistence/persistence.dart';\n";
-    var informAboutChanges = '    attendedPage!.informAboutChanges();';
+    var informAboutChanges = '    attendedPage.informAboutChanges();';
     var requestRecord = templateRequestRecord;
     page.pageType == PageType.edit
         ? 'update'
index 106d2eb46436d643948f61d1ef6d878bb5186504..9826a6d29df570f012ab4ea2958ec5e11fccbc67 100644 (file)
@@ -37,59 +37,60 @@ class SqlGenerator extends GeneratorBase {
   /// Creates the sections for pages with PageType.list of the [module].
   String createListSections(ModuleMetaData module) {
     final buffer = StringBuffer();
-    List<PageMetaData>? listPages;
-    try {
-      listPages = module.pageList
-          .where((element) => element.pageType == PageType.list)
-          .toList(growable: false);
-    } on Exception catch (exc) {
-      logger.error('no page with list type: $exc');
-      listPages = null;
+    final listPages = module.pagesByType(PageType.list);
+    final tableName = module.tableName;
+    for (var page in listPages) {
+      if (page is ListPageMetaData) {
+        var whereCondition = page.whereCondition;
+        if (whereCondition.endsWith('\n')) {
+          whereCondition =
+              whereCondition.substring(0, whereCondition.length - 1);
+        }
+        addListSql(page.name, page, whereCondition, tableName, buffer);
+      }
     }
-    if (listPages != null) {
-      final tableName = module.tableName;
-      for (var page in listPages) {
-        if (page is ListPageMetaData) {
-          var whereCondition = page.whereCondition;
-          if (whereCondition.endsWith('\n')) {
-            whereCondition =
-                whereCondition.substring(0, whereCondition.length - 1);
-          }
-          String selectItems2 = '';
-          var selectItems =
-              page.selectItems.isEmpty ? '' : indent(page.selectItems, '    ');
-          var joins = findReferences(module, (x) => selectItems2 = x);
-          if (page.joinItems.isNotEmpty) {
-            joins += indent(page.joinItems, '    ');
-            if (!joins.endsWith('\n')) {
-              joins += '\n';
-            }
-          }
-          var parameters = '';
-          if (whereCondition.isNotEmpty) {
-            parameters = findParameters(whereCondition, page.fields);
-            whereCondition = '    WHERE\n' + indent(whereCondition, '    ');
-          }
-          final order = page.orderBy.isNotEmpty
-              ? page.orderBy
-              : module.primaryOf()!.columnName;
-          buffer.writeln(page.name + ':');
-          buffer.writeln('''  type: list
+    if (module.needsSqlAll) {
+      PageMetaData? page = module.pageByName('list');
+      if (page != null) {
+        addListSql('all', page as ListPageMetaData, '1', tableName, buffer);
+      }
+    }
+    return buffer.toString();
+  }
+
+  void addListSql(String sqlName, ListPageMetaData page, String whereCondition,
+      String tableName, StringBuffer buffer) {
+    String selectItems2 = '';
+    var selectItems =
+        page.selectItems.isEmpty ? '' : indent(page.selectItems, '    ');
+    var joins = findReferences(page.module, (x) => selectItems2 = x);
+    if (page.joinItems.isNotEmpty) {
+      joins += indent(page.joinItems, '    ');
+      if (!joins.endsWith('\n')) {
+        joins += '\n';
+      }
+    }
+    var parameters = '';
+    if (whereCondition.isNotEmpty) {
+      parameters = findParameters(whereCondition, page.fields);
+      whereCondition = '    WHERE\n' + indent(whereCondition, '    ');
+    }
+    final order = page.orderBy.isNotEmpty
+        ? page.orderBy
+        : page.module.primaryOf()!.columnName;
+    buffer.writeln(sqlName + ':');
+    buffer.writeln('''  type: list
   parameters: [$parameters]
   order: "$order"
   sql: |
     SELECT''');
-          if (selectItems.isNotEmpty) {
-            addToBuffer(selectItems, maxLength: 80, buffer: buffer, indent: 6);
-          }
-          addToBuffer('    t0.*$selectItems2',
-              maxLength: 80, buffer: buffer, indent: 6);
-          buffer.writeln('    FROM $tableName t0');
-          buffer.write('$joins$whereCondition');
-        }
-      }
+    if (selectItems.isNotEmpty) {
+      addToBuffer(selectItems, maxLength: 80, buffer: buffer, indent: 6);
     }
-    return buffer.toString();
+    addToBuffer('    t0.*$selectItems2',
+        maxLength: 80, buffer: buffer, indent: 6);
+    buffer.writeln('\n    FROM $tableName t0');
+    buffer.write('$joins$whereCondition');
   }
 
   /// Returns the SQL statements for insert, update, delete...
@@ -135,7 +136,7 @@ update:
       }
     }
     parameters.write(']');
-    if (! module.properties.containsKey('changedAt')){
+    if (!module.properties.containsKey('changedAt')) {
       logger.error('Module $moduleName misses changedAt');
     }
     var item = module.properties['changedAt']!;
@@ -191,6 +192,10 @@ update:
     buffer.writeln(parameters);
     buffer.writeln(sql1);
     buffer.writeln(sql2);
+    for (var page in module.pagesByType(PageType.mapping)) {
+      final sql = sqlOfMapping(page as MappingPageMetaData);
+      buffer.write(sql);
+    }
     return buffer.toString();
   }
 
@@ -202,7 +207,7 @@ update:
         .map((element) => element.group(1))
         .toSet()
         .toList();
-    return '"' + names.join('","') + '"';
+    return names.isEmpty ? '' : ('"' + names.join('","') + '"');
   }
 
   /// Creates the joins and select items the foreign keys of the given [module].
@@ -261,4 +266,10 @@ update:
       }
     }
   }
+
+  /// Returns the sql statement definitions of a page with type PageType.mapping.
+  String sqlOfMapping(MappingPageMetaData page) {
+    String rc = '';
+    return rc;
+  }
 }
index 67a1e389ad3152ad2160a158909d68d0d0aff296..c62099a4c6a49af47d7c834dc97dcc99410257cf 100644 (file)
@@ -9,7 +9,8 @@ list:
   order: "benchmark_id"
   sql: |
     SELECT
-    t0.*    FROM benchmarks t0
+    t0.*
+    FROM benchmarks t0
     WHERE
     (:text='' OR benchmark_lastname like :text
       OR benchmark_firstname like :text)
index 34251b250feb31195fb9c84bde0993cff4ec1cb2..cc868b465a6c3f148f3e0dff474277c0688a814f 100644 (file)
@@ -9,7 +9,18 @@ list:
   order: "role_id"
   sql: |
     SELECT
-    t0.*    FROM roles t0
+    t0.*
+    FROM roles t0
+all:
+  type: list
+  parameters: []
+  order: "role_id"
+  sql: |
+    SELECT
+    t0.*
+    FROM roles t0
+    WHERE
+    1
 byId:
   type: record
   parameters: [ ":id" ]
diff --git a/rest_server/data/sql/rolestarter.sql.yaml b/rest_server/data/sql/rolestarter.sql.yaml
new file mode 100644 (file)
index 0000000..638d435
--- /dev/null
@@ -0,0 +1,52 @@
+---
+# DO NOT CHANGE. This file is created by the meta_tool
+# SQL statements of the module "RoleStarter":
+
+module: RoleStarter
+list:
+  type: list
+  parameters: []
+  order: "rolestarter_id"
+  sql: |
+    SELECT
+    t0.*,t1.role_name AS role,t2.starter_name AS starter
+    FROM rolestarter t0
+    JOIN roles t1 ON t1.role_id=t0.rolestarter_role
+    JOIN starters t2 ON t2.starter_id=t0.rolestarter_starter
+all:
+  type: list
+  parameters: []
+  order: "rolestarter_id"
+  sql: |
+    SELECT
+    t0.*,t1.role_name AS role,t2.starter_name AS starter
+    FROM rolestarter t0
+    JOIN roles t1 ON t1.role_id=t0.rolestarter_role
+    JOIN starters t2 ON t2.starter_id=t0.rolestarter_starter
+    WHERE
+    1
+byId:
+  type: record
+  parameters: [ ":id" ]
+  sql: "SELECT * FROM rolestarter WHERE rolestarter_id=:id;"
+delete:
+  type: delete
+  parameters: [ ":id" ]
+  sql: "DELETE * FROM rolestarter WHERE rolestarter_id=:id;"
+update:
+  type: update
+  parameters: [":id",":role",":starter",":order"]
+  sql: |
+    UPDATE rolestarter SET
+      rolestarter_role=:role,
+      rolestarter_starter=:starter,
+      rolestarter_order=:order,
+      rolestarter_changedat=NOW()
+    WHERE rolestarter_id=:id;
+insert:
+  type: insert
+  parameters: [":role",":starter",":order",":createdBy"]
+  sql: |
+    INSERT INTO rolestarter(rolestarter_role,rolestarter_starter,
+      rolestarter_order,rolestarter_createdby,rolestarter_createdat)
+    VALUES(:role,:starter,:order,:createdBy,NOW());
index 56262e3fc5513bfbad9540665744414717a21d77..75e0681e4184ea2835d56651b7009b37617f4330 100644 (file)
@@ -9,7 +9,18 @@ list:
   order: "starter_id"
   sql: |
     SELECT
-    t0.*    FROM starters t0
+    t0.*
+    FROM starters t0
+all:
+  type: list
+  parameters: []
+  order: "starter_id"
+  sql: |
+    SELECT
+    t0.*
+    FROM starters t0
+    WHERE
+    1
 byId:
   type: record
   parameters: [ ":id" ]
@@ -20,18 +31,18 @@ delete:
   sql: "DELETE * FROM starters WHERE starter_id=:id;"
 update:
   type: update
-  parameters: [":id",":name",":link",":icon"]
+  parameters: [":id",":name",":route",":icon"]
   sql: |
     UPDATE starters SET
       starter_name=:name,
-      starter_link=:link,
+      starter_route=:route,
       starter_icon=:icon,
       starter_changedat=NOW()
     WHERE starter_id=:id;
 insert:
   type: insert
-  parameters: [":name",":link",":icon",":createdBy"]
+  parameters: [":name",":route",":icon",":createdBy"]
   sql: |
-    INSERT INTO starters(starter_name,starter_link,starter_icon,
+    INSERT INTO starters(starter_name,starter_route,starter_icon,
       starter_createdby,starter_createdat)
-    VALUES(:name,:link,:icon,:createdBy,NOW());
+    VALUES(:name,:route,:icon,:createdBy,NOW());
index 957a3cbbfbb4e921aae14a76822c1b5084b0ed7a..e488a7f2798f844d3a77ccdf251c3f7e6ea40048 100644 (file)
@@ -9,7 +9,8 @@ list:
   order: "structure_id"
   sql: |
     SELECT
-    t0.*    FROM structures t0
+    t0.*
+    FROM structures t0
 byId:
   type: record
   parameters: [ ":id" ]
index 18133b38139c811ce59896030a922aa8b6c256ac..c399079607eba762d861c4c68d3f5e86771101b9 100644 (file)
@@ -9,7 +9,8 @@ list:
   order: "user_id"
   sql: |
     SELECT
-    t0.*,t1.role_name AS role    FROM users t0
+    t0.*,t1.role_name AS role
+    FROM users t0
     JOIN roles t1 ON t1.role_id=t0.user_role
     WHERE
     (:text='' OR user_name like :text
index 4c8ce98ee4a2acd27b456deefbf885bc255cfacf..da0afd5618f7f3c73e115dab6d4ae927479e01f0 100644 (file)
@@ -50,7 +50,7 @@ class RestServer {
   static const _version = 'V2021.08.19.00';
   static BaseLogger? unittestLogger;
   BaseLogger logger = MemoryLogger(LEVEL_FINE);
-  BaseConfiguration configuration = BaseConfiguration({}, globalLogger);
+  late BaseConfiguration configuration;
   var clientSessionTimeout = 15 * 60;
   String serviceName = 'exhibition';
   RestServer(
@@ -114,6 +114,7 @@ class RestServer {
         configuration.asInt('logLevel', section: 'service') ?? LEVEL_SUMMERY;
     logger = unittestLogger ?? Logger(logFile, level);
     globalLogger = logger;
+    logger.log('configuration read from $filename');
     ProcessSync(logger);
     FileSync.initialize(logger);
     logger.log(
@@ -274,14 +275,14 @@ class ServiceWorker {
   final int threadId;
   final String serviceName;
   int clientSessionTimeout = 30;
-  BaseLogger logger = globalLogger;
+  late BaseLogger logger;
   bool requestedCodecIsLatin1 = false;
   HttpRequest? currentRequest;
   String what = '';
   MySqlDb? db;
   String restVersion = '';
   FileSync? _fileSync = FileSync();
-  SqlStorage sqlStorage = SqlStorage(globalLogger);
+  late SqlStorage sqlStorage;
   String sqlTestPrimaryTable = '';
 
   ServiceWorker(this.threadId, this.configuration, this.serviceName) {
index 9f179209f9762299478df511127f32bfbf1fcef9..1c2dd52ec534c17e142eb039e636b884c0abeec9 100644 (file)
@@ -135,7 +135,8 @@ class SqlStorage {
       modules[moduleName] = SqlModule(moduleName, this);
     }
     final module = modules[moduleName];
-    for (var name in map.keys) {
+    final keys = map.keys.toList();
+    for (var name in keys) {
       switch (name) {
         case 'module':
           // already done.