]> gitweb.hamatoma.de Git - exhibition.git/commitdiff
Refactoring, new module starters
authorHamatoma <author.hamatoma.de>
Sat, 23 Oct 2021 08:33:05 +0000 (10:33 +0200)
committerHamatoma <author.hamatoma.de>
Sat, 23 Oct 2021 08:33:05 +0000 (10:33 +0200)
* Refactoring:
** UserMeta renamed to UsersMeta (filename-classname convention)
** Fields renamed: changed -> changedAt, created -> createdAt
** ListMetaPage: new: toolTipAddButton

50 files changed:
lib/meta/benchmarks_meta.dart
lib/meta/module_meta_data.dart
lib/meta/modules.dart
lib/meta/roles_meta.dart
lib/meta/starters_meta.dart [new file with mode: 0644]
lib/meta/structures_meta.dart
lib/meta/users_meta.dart
lib/page/benchmarks/benchmark_data.dart
lib/page/benchmarks/create_benchmark_page.dart
lib/page/benchmarks/delete_benchmark_page.dart
lib/page/benchmarks/edit_benchmark_page.dart
lib/page/benchmarks/list_benchmark_custom.dart
lib/page/benchmarks/list_benchmark_page.dart
lib/page/page_manager.dart
lib/page/roles/create_role_page.dart
lib/page/roles/edit_role_page.dart
lib/page/roles/list_role_custom.dart
lib/page/roles/list_role_page.dart
lib/page/roles/role_data.dart
lib/page/start_page.dart
lib/page/starters/create_starter_custom.dart [new file with mode: 0644]
lib/page/starters/create_starter_page.dart [new file with mode: 0644]
lib/page/starters/delete_starter_custom.dart [new file with mode: 0644]
lib/page/starters/delete_starter_page.dart [new file with mode: 0644]
lib/page/starters/edit_starter_custom.dart [new file with mode: 0644]
lib/page/starters/edit_starter_page.dart [new file with mode: 0644]
lib/page/starters/list_starter_custom.dart [new file with mode: 0644]
lib/page/starters/list_starter_page.dart [new file with mode: 0644]
lib/page/starters/starter_data.dart [new file with mode: 0644]
lib/page/structures/create_structure_page.dart
lib/page/structures/delete_structure_page.dart
lib/page/structures/edit_structure_page.dart
lib/page/structures/list_structure_custom.dart
lib/page/structures/list_structure_page.dart
lib/page/structures/structure_data.dart
lib/page/users/create_user_page.dart
lib/page/users/delete_user_page.dart
lib/page/users/edit_user_page.dart
lib/page/users/list_user_custom.dart
lib/page/users/list_user_page.dart
lib/page/users/user_data.dart
lib/setting/drawer_exhibition.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/starter.sql.yaml [new file with mode: 0644]
rest_server/data/sql/starters.sql.yaml [new file with mode: 0644]
rest_server/data/sql/structures.sql.yaml
rest_server/data/sql/users.sql.yaml

index 39a21e2dfa031e99ca71c251b67c1d639827b20d..b2d2ee74311614b0246e11bafb8a6aeb1316d9a3 100644 (file)
@@ -5,12 +5,12 @@ import 'module_meta_data.dart';
 final i18n = I18N();
 final M = i18n.module("Benchmarks");
 
-class BenchmarkMeta extends ModuleMetaData {
-  static BenchmarkMeta instance = BenchmarkMeta.internal();
-  factory BenchmarkMeta() {
+class BenchmarksMeta extends ModuleMetaData {
+  static BenchmarksMeta instance = BenchmarksMeta.internal();
+  factory BenchmarksMeta() {
     return instance;
   }
-  BenchmarkMeta.internal()
+  BenchmarksMeta.internal()
       : super('Benchmarks', [
           PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
               displayType: DisplayType.combobox),
@@ -30,13 +30,13 @@ class BenchmarkMeta extends ModuleMetaData {
               displayType: DisplayType.switchWidget),
           PropertyMetaData('weight', i18n.tr('Weight'), DataType.float, ''),
           PropertyMetaData('income', i18n.tr('Income'), DataType.currency, ''),
-          PropertyMetaData(
-              'created', i18n.tr('Created'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('createdAt', i18n.tr('Created at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
               size: 32),
-          PropertyMetaData(
-              'changed', i18n.tr('Changed'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('changedAt', i18n.tr('Changed at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
               size: 32),
@@ -44,17 +44,17 @@ class BenchmarkMeta extends ModuleMetaData {
           PageMetaData(
             'New Benchmark',
             PageType.create,
-            fields: [CopyDbFields('filters')],
+            fields: [CopyDbFields('fields')],
           ),
           PageMetaData(
             'Change Benchmark',
             PageType.edit,
-            fields: [CopyDbFields('filters')],
+            fields: [CopyDbFields('fields')],
           ),
           PageMetaData(
             'Delete Benchmark',
             PageType.delete,
-            fields: [CopyDbFields('filters')],
+            fields: [CopyDbFields('fields')],
           ),
           ListPageMetaData(
             'Benchmarks Overview',
@@ -63,6 +63,7 @@ class BenchmarkMeta extends ModuleMetaData {
                   'text', i18n.tr('Text'), DataType.string, ':pattern:',
                   size: 64),
             ],
+            toolTipAddButton: i18n.tr('Add a benchmark item'),
             tableColumns:
                 'benchmark_id;benchmark_lastname;benchmark_firstname;benchmark_birthday;benchmark_active;benchmark_income',
             tableHeaders:
index 1a657817a7ed799a1d1b4917f7a558587f44522f..659d4888c470d050780eb5f1bea8053a6219f9a4 100644 (file)
@@ -56,6 +56,7 @@ class ListPageMetaData extends PageMetaData {
   final String selectItems;
   final String joinItems;
   final String widgetsBelowFilter;
+  final String toolTipAddButton;
 
   /// Constructor.
   ///
@@ -98,7 +99,8 @@ class ListPageMetaData extends PageMetaData {
       this.orderBy = '',
       this.selectItems = '',
       this.joinItems = '',
-      this.widgetsBelowFilter = ''})
+      this.widgetsBelowFilter = '',
+      this.toolTipAddButton = ''})
       : super(label, PageType.list,
             name: name, fields: fields, globalComboBoxes: globalComboBoxes);
 }
@@ -108,11 +110,11 @@ class MetaException extends FormatException {}
 /// Stores the meta data of a module.
 class ModuleMetaData {
   static final metaColumns = [
-    'created',
+    'createdAt',
     'createdBy',
-    'changed',
+    'changedAt',
     'changedBy',
-    'deleted',
+    'deletedAt',
     'deletedBy'
   ];
 
index 10f555eb1da275d0f6de2b9bd1b7a8386cf69e84..13cd8da81f1851f9499b4653d73197e070b8036c 100644 (file)
@@ -2,6 +2,7 @@
 import 'module_meta_data.dart';
 import 'benchmarks_meta.dart';
 import 'roles_meta.dart';
+import 'starters_meta.dart';
 import 'structures_meta.dart';
 import 'users_meta.dart';
 
@@ -11,16 +12,19 @@ ModuleMetaData? moduleByName(String name) {
   ModuleMetaData? rc;
   switch (name) {
     case 'Benchmarks':
-      rc = BenchmarkMeta();
+      rc = BenchmarksMeta();
       break;
     case 'Roles':
-      rc = RoleMeta();
+      rc = RolesMeta();
+      break;
+    case 'Starters':
+      rc = StartersMeta();
       break;
     case 'Structures':
-      rc = StructureMeta();
+      rc = StructuresMeta();
       break;
     case 'Users':
-      rc = UserMeta();
+      rc = UsersMeta();
       break;
     default:
       break;
@@ -33,6 +37,7 @@ List<String> moduleNames() {
   return [
     'Benchmarks',
     'Roles',
+    'Starters',
     'Structures',
     'Users',
   ];
index e91e3fc6b5c7f95d4d8a9e5e160fb6a9f1996a6e..ed494696ecac1aee9276f9c5481f515a9c5960da 100644 (file)
@@ -5,33 +5,33 @@ import 'module_meta_data.dart';
 final i18n = I18N();
 final M = i18n.module("Roles");
 
-class RoleMeta extends ModuleMetaData {
-  static RoleMeta instance = RoleMeta.internal();
-  factory RoleMeta() {
+class RolesMeta extends ModuleMetaData {
+  static RolesMeta instance = RolesMeta.internal();
+  factory RolesMeta() {
     return instance;
   }
-  RoleMeta.internal()
+  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(
-              'created', i18n.tr('Created'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('createdAt', i18n.tr('Created at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
               size: 32),
           PropertyMetaData(
-              'changed', i18n.tr('Changed'), DataType.datetime, ':hidden:'),
+              '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('filters')]),
+              fields: [CopyDbFields('fields')]),
           PageMetaData('Change Role', PageType.edit,
-              fields: [CopyDbFields('filters')]),
+              fields: [CopyDbFields('fields')]),
           ListPageMetaData(
             'Roles Overview',
             fields: [
@@ -39,8 +39,9 @@ class RoleMeta extends ModuleMetaData {
                   ':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'),
+            tableHeaders: i18n.tr(';Id;Name'),
           ),
         ]);
   @override
diff --git a/lib/meta/starters_meta.dart b/lib/meta/starters_meta.dart
new file mode 100644 (file)
index 0000000..150ab1f
--- /dev/null
@@ -0,0 +1,59 @@
+import '../base/defines.dart';
+import '../base/i18n.dart';
+import 'module_meta_data.dart';
+
+final i18n = I18N();
+final M = i18n.module("Starters");
+
+class StartersMeta extends ModuleMetaData {
+  static StartersMeta instance = StartersMeta.internal();
+  factory StartersMeta() {
+    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:',
+                  size: 64),
+            ],
+            toolTipAddButton: i18n.tr('Add a new starter'),
+            tableColumns: 'starter_id;starter_name;starter_link;starter_icon',
+            tableHeaders: i18n.tr(';Id;Name;Link;Icon'),
+          ),
+        ]);
+  @override
+  void onInitialized() {
+    super.onInitialized();
+  }
+}
index 7bfccdc0da4a99167ade466dce98590287e5877a..2f5814937e532bdd528371986632327a2d1569dc 100644 (file)
@@ -5,12 +5,12 @@ import 'module_meta_data.dart';
 final i18n = I18N();
 final M = i18n.module("Structures");
 
-class StructureMeta extends ModuleMetaData {
-  static StructureMeta instance = StructureMeta.internal();
-  factory StructureMeta() {
+class StructuresMeta extends ModuleMetaData {
+  static StructuresMeta instance = StructuresMeta.internal();
+  factory StructuresMeta() {
     return instance;
   }
-  StructureMeta.internal()
+  StructuresMeta.internal()
       : super('Structures', [
           PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
               displayType: DisplayType.combobox),
@@ -25,23 +25,23 @@ class StructureMeta extends ModuleMetaData {
               size: 32),
           PropertyMetaData(
               'position', i18n.tr('Position', M), DataType.int, ''),
-          PropertyMetaData(
-              'created', i18n.tr('Created'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('createdAt', i18n.tr('Created at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
               size: 32),
-          PropertyMetaData(
-              'changed', i18n.tr('Changed'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('changedAt', i18n.tr('Changed at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
               size: 32),
         ], [
           PageMetaData('New Structure', PageType.create,
-              fields: [CopyDbFields('filters')]),
+              fields: [CopyDbFields('fields')]),
           PageMetaData('Change Structure', PageType.edit,
-              fields: [CopyDbFields('filters')]),
+              fields: [CopyDbFields('fields')]),
           PageMetaData('Delete Structure', PageType.delete,
-              fields: [CopyDbFields('filters')]),
+              fields: [CopyDbFields('fields')]),
           ListPageMetaData(
             'Structures Overview',
             fields: [
@@ -49,9 +49,10 @@ class StructureMeta extends ModuleMetaData {
                   ':where=!text IS NONE OR structure_name like !text OR structure_value like !text:',
                   size: 64),
             ],
+            toolTipAddButton: i18n.tr('Add a structure item'),
             tableColumns:
                 'structure_id;structure_scope;structure_name;structure_value;structure_position',
-            tableHeaders: i18n.tr('Id;Scope;Name;Value;Position'),
+            tableHeaders: i18n.tr(';Id;Scope;Name;Value;Position'),
           ),
         ]);
   @override
index d6807b5844157d26b5cfbca55bbe7d7514e2e85d..40c017dbfea6afd054c9daad740ab5071759fc75 100644 (file)
@@ -5,12 +5,12 @@ import 'module_meta_data.dart';
 final i18n = I18N();
 final M = i18n.module("Users");
 
-class UserMeta extends ModuleMetaData {
-  static UserMeta instance = UserMeta.internal();
-  factory UserMeta() {
+class UsersMeta extends ModuleMetaData {
+  static UsersMeta instance = UsersMeta.internal();
+  factory UsersMeta() {
     return instance;
   }
-  UserMeta.internal()
+  UsersMeta.internal()
       : super('Users', [
           PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
               displayType: DisplayType.combobox),
@@ -27,13 +27,13 @@ class UserMeta extends ModuleMetaData {
               'role', i18n.tr('Role'), DataType.reference, ':notnull:',
               displayType: DisplayType.combobox,
               foreignKey: 'roles.role_id;role_name;role'),
-          PropertyMetaData(
-              'created', i18n.tr('Created'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('createdAt', i18n.tr('Created at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
               size: 32),
-          PropertyMetaData(
-              'changed', i18n.tr('Changed'), DataType.datetime, ':hidden:'),
+          PropertyMetaData('changedAt', i18n.tr('Changed at'),
+              DataType.datetime, ':hidden:'),
           PropertyMetaData(
               'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
               size: 32),
@@ -66,6 +66,7 @@ class UserMeta extends ModuleMetaData {
                   displayType: DisplayType.combobox,
                   foreignKey: 'roles.role_id;role_name;role'),
             ],
+            toolTipAddButton: i18n.tr('Add a new user'),
             tableColumns: 'user_id;user_name;user_displayname;user_email;role',
             tableHeaders: i18n.tr(';Id;Name;Display Name;Email;Role'),
             globalComboBoxes: 'comboRoles',
index aacaf1966463e07155464c1331dbb890230aa045..c693772ee77fd35075f3e136afa78526e4772c6a 100644 (file)
@@ -12,9 +12,9 @@ class BenchmarkData extends DataRecord<int> {
   bool? active;
   double? weight;
   int? income;
-  DateTime? created;
+  DateTime? createdAt;
   String? createdBy;
-  DateTime? changed;
+  DateTime? changedAt;
   String? changedBy;
   BenchmarkData(
       {this.id,
@@ -25,9 +25,9 @@ class BenchmarkData extends DataRecord<int> {
       this.active,
       this.weight,
       this.income,
-      this.created,
+      this.createdAt,
       this.createdBy,
-      this.changed,
+      this.changedAt,
       this.changedBy});
   BenchmarkData.createFromMap(DataMap map) {
     fromMap(map);
@@ -58,14 +58,14 @@ class BenchmarkData extends DataRecord<int> {
     income = map.containsKey('benchmark_income')
         ? fromString(map['benchmark_income'], dataType: DataType.currency)
         : null;
-    created = map.containsKey('benchmark_created')
-        ? fromString(map['benchmark_created'], dataType: DataType.datetime)
+    createdAt = map.containsKey('benchmark_createdat')
+        ? fromString(map['benchmark_createdat'], dataType: DataType.datetime)
         : null;
     createdBy = map.containsKey('benchmark_createdby')
         ? fromString(map['benchmark_createdby'], dataType: DataType.string)
         : null;
-    changed = map.containsKey('benchmark_changed')
-        ? fromString(map['benchmark_changed'], dataType: DataType.datetime)
+    changedAt = map.containsKey('benchmark_changedat')
+        ? fromString(map['benchmark_changedat'], dataType: DataType.datetime)
         : null;
     changedBy = map.containsKey('benchmark_changedby')
         ? fromString(map['benchmark_changedby'], dataType: DataType.string)
@@ -109,13 +109,13 @@ class BenchmarkData extends DataRecord<int> {
       case 'income':
         rc = DataType.currency;
         break;
-      case 'created':
+      case 'createdAt':
         rc = DataType.datetime;
         break;
       case 'createdBy':
         rc = DataType.string;
         break;
-      case 'changed':
+      case 'changedAt':
         rc = DataType.datetime;
         break;
       case 'changedBy':
@@ -141,9 +141,9 @@ class BenchmarkData extends DataRecord<int> {
     map['benchmark_active'] = active;
     map['benchmark_weight'] = weight;
     map['benchmark_income'] = income;
-    map['benchmark_created'] = created;
+    map['benchmark_createdat'] = createdAt;
     map['benchmark_createdby'] = createdBy;
-    map['benchmark_changed'] = changed;
+    map['benchmark_changedat'] = changedAt;
     map['benchmark_changedby'] = changedBy;
     return map;
   }
index 2dc827211c30fbfb936cd4e0382e041e58fedcb8..bac42c040b39c8b8c9d3e280c494892bbc652382 100644 (file)
@@ -16,8 +16,8 @@ class CreateBenchmarkPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        BenchmarkMeta.instance.pageByName('create')!,
-        BenchmarkMeta.instance,
+        BenchmarksMeta.instance.pageByName('create')!,
+        BenchmarksMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 9891dd61ce179429fbd2bc3be3a1700329fec10d..d521ed4bfa12678cd9f4761392b7741b709a81e5 100644 (file)
@@ -17,8 +17,8 @@ class DeleteBenchmarkPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        BenchmarkMeta.instance.pageByName('delete')!,
-        BenchmarkMeta.instance,
+        BenchmarksMeta.instance.pageByName('delete')!,
+        BenchmarksMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 32c93167338833b461a2cf89a4d28efbcecc05a3..43e540f00d2a2a71255b0a0a76758ed7523b67bf 100644 (file)
@@ -17,8 +17,8 @@ class EditBenchmarkPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        BenchmarkMeta.instance.pageByName('edit')!,
-        BenchmarkMeta.instance,
+        BenchmarksMeta.instance.pageByName('edit')!,
+        BenchmarksMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 2907e7e1cf989f94544e08732080504522cd06ab..b20bc85dd2c3a91b1b66fa7c894fca4e787a6537 100644 (file)
@@ -29,11 +29,11 @@ class ListBenchmarkCustom extends State<ListBenchmarkPage> {
       appBar: globalData.appBarBuilder(i18n.tr('Overview benchmarks')),
       drawer: globalData.drawerBuilder(context),
       floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          globalData.navigate(context, '/Benchmarks/create');
-        },
-        child: const Icon(Icons.add),
-      ),
+          onPressed: () {
+            globalData.navigate(context, '/Benchmarks/create');
+          },
+          child: const Icon(Icons.add),
+          tooltip: 'Add a benchmark item'),
       body: SafeArea(
           child: FutureBuilder<DbData>(
         future: _futureDbData,
index 1f6410f8a96caf4e1ea779729df50a53297e8818..6e1c6afc54266239ac45c5b65bc93c4153e2b054 100644 (file)
@@ -16,8 +16,8 @@ class ListBenchmarkPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        BenchmarkMeta.instance.pageByName('list')!,
-        BenchmarkMeta.instance,
+        BenchmarksMeta.instance.pageByName('list')!,
+        BenchmarksMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index cea3c7319ae429f4b4832da5892c65b653951998..7eb726613b43fdf7ccc032ecb0701dbd84e04ee6 100644 (file)
@@ -9,6 +9,10 @@ import 'benchmarks/list_benchmark_page.dart';
 import 'roles/create_role_page.dart';
 import 'roles/edit_role_page.dart';
 import 'roles/list_role_page.dart';
+import 'starters/create_starter_page.dart';
+import 'starters/edit_starter_page.dart';
+import 'starters/delete_starter_page.dart';
+import 'starters/list_starter_page.dart';
 import 'structures/create_structure_page.dart';
 import 'structures/edit_structure_page.dart';
 import 'structures/delete_structure_page.dart';
@@ -55,6 +59,18 @@ class PageManager {
       case '/Roles/list':
         rc = ListRolePage();
         break;
+      case '/Starters/create':
+        rc = CreateStarterPage();
+        break;
+      case '/Starters/edit':
+        rc = EditStarterPage(arg1);
+        break;
+      case '/Starters/delete':
+        rc = DeleteStarterPage(arg1);
+        break;
+      case '/Starters/list':
+        rc = ListStarterPage();
+        break;
       case '/Structures/create':
         rc = CreateStructurePage();
         break;
index d6cf4eed1bd17193a2ed010503a1e155091a9f01..2601a43b78ee66c87aefd31a8ae5f18ba43e3df5 100644 (file)
@@ -16,8 +16,8 @@ class CreateRolePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        RoleMeta.instance.pageByName('create')!,
-        RoleMeta.instance,
+        RolesMeta.instance.pageByName('create')!,
+        RolesMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 8ce66cb7a5584bedea8c2c74e0222777137386f4..9a7a3d3b8fda7cbf43a3e862d6a9dfb76ab5527c 100644 (file)
@@ -17,8 +17,8 @@ class EditRolePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        RoleMeta.instance.pageByName('edit')!,
-        RoleMeta.instance,
+        RolesMeta.instance.pageByName('edit')!,
+        RolesMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index d2c3c8d7785472b25781491c0e32012322a3a36a..9f190cd465ecba1f38ff078fe9cbf29eddabdc1a 100644 (file)
@@ -29,11 +29,11 @@ class ListRoleCustom extends State<ListRolePage> {
       appBar: globalData.appBarBuilder(i18n.tr('Overview roles')),
       drawer: globalData.drawerBuilder(context),
       floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          globalData.navigate(context, '/Roles/create');
-        },
-        child: const Icon(Icons.add),
-      ),
+          onPressed: () {
+            globalData.navigate(context, '/Roles/create');
+          },
+          child: const Icon(Icons.add),
+          tooltip: 'Add a new role'),
       body: SafeArea(
           child: FutureBuilder<DbData>(
         future: _futureDbData,
@@ -95,7 +95,10 @@ class ListRoleCustom extends State<ListRolePage> {
     final table = DataTable(
       columns: <DataColumn>[
         DataColumn(
-          label: Text(i18n.tr('d;Name')),
+          label: Text(i18n.tr('Id')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Name')),
         ),
       ],
       rows: rows as List<DataRow>,
@@ -107,6 +110,7 @@ class ListRoleCustom extends State<ListRolePage> {
         onTap: (offset) {
           _fieldData.theOffset = offset;
           requestRecords();
+          setState(() => 1);
         });
     final frameWidget = ListView(children: [
       form,
index 91335a8873159ae251477dca3f283f364a01f46b..41a4331c51f3a2c254f4a7d394904e9de8842ddc 100644 (file)
@@ -16,8 +16,8 @@ class ListRolePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        RoleMeta.instance.pageByName('list')!,
-        RoleMeta.instance,
+        RolesMeta.instance.pageByName('list')!,
+        RolesMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 7b019ac2a91f45014e85d58768020138f8a121a4..317e9db322431a63638a7434a12f96b33d94af03 100644 (file)
@@ -6,16 +6,16 @@ import '../../persistence/data_record.dart';
 class RoleData extends DataRecord<int> {
   int? id;
   String? name;
-  DateTime? created;
+  DateTime? createdAt;
   String? createdBy;
-  DateTime? changed;
+  DateTime? changedAt;
   String? changedBy;
   RoleData(
       {this.id,
       this.name,
-      this.created,
+      this.createdAt,
       this.createdBy,
-      this.changed,
+      this.changedAt,
       this.changedBy});
   RoleData.createFromMap(DataMap map) {
     fromMap(map);
@@ -28,14 +28,14 @@ class RoleData extends DataRecord<int> {
     name = map.containsKey('role_name')
         ? fromString(map['role_name'], dataType: DataType.string)
         : null;
-    created = map.containsKey('role_created')
-        ? fromString(map['role_created'], dataType: DataType.datetime)
+    createdAt = map.containsKey('role_createdat')
+        ? fromString(map['role_createdat'], dataType: DataType.datetime)
         : null;
     createdBy = map.containsKey('role_createdby')
         ? fromString(map['role_createdby'], dataType: DataType.string)
         : null;
-    changed = map.containsKey('role_changed')
-        ? fromString(map['role_changed'], dataType: DataType.datetime)
+    changedAt = map.containsKey('role_changedat')
+        ? fromString(map['role_changedat'], dataType: DataType.datetime)
         : null;
     changedBy = map.containsKey('role_changedby')
         ? fromString(map['role_changedby'], dataType: DataType.string)
@@ -61,13 +61,13 @@ class RoleData extends DataRecord<int> {
       case 'name':
         rc = DataType.string;
         break;
-      case 'created':
+      case 'createdAt':
         rc = DataType.datetime;
         break;
       case 'createdBy':
         rc = DataType.string;
         break;
-      case 'changed':
+      case 'changedAt':
         rc = DataType.datetime;
         break;
       case 'changedBy':
@@ -87,9 +87,9 @@ class RoleData extends DataRecord<int> {
     }
     map['role_id'] = id;
     map['role_name'] = name;
-    map['role_created'] = created;
+    map['role_createdat'] = createdAt;
     map['role_createdby'] = createdBy;
-    map['role_changed'] = changed;
+    map['role_changedat'] = changedAt;
     map['role_changedby'] = changedBy;
     return map;
   }
index 8c79d6f59e62de8f702ade7f165593959f854a5d..ab5b3b077da49f4c32c5e1e569f61c5baf125985 100644 (file)
@@ -96,7 +96,7 @@ class StartPageState extends State<StartPage> {
                     RestPersistence.fromConfig(configuration, logger),
                     logger);
                 globalData.initializeAsync().then((value) {
-                  globalData.navigate(context, '/Users/list');
+                  globalData.navigate(context, '/Starters/list');
                 });
               }
             });
diff --git a/lib/page/starters/create_starter_custom.dart b/lib/page/starters/create_starter_custom.dart
new file mode 100644 (file)
index 0000000..fffaf2f
--- /dev/null
@@ -0,0 +1,152 @@
+// 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 '../../base/validators.dart';
+import '../../services/global_widget.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import '../../widget/message_line.dart';
+import '../../widget/widget_form.dart';
+import 'create_starter_page.dart';
+
+final i18n = I18N();
+
+class CreateStarterCustom extends State<CreateStarterPage> with MessageLine {
+  final globalData = GlobalData();
+  AttendedPage? attendedPage;
+  final _fieldData = _FieldData();
+  final GlobalKey<FormState> _formKey =
+      GlobalKey<FormState>(debugLabel: 'CreateStarter');
+  final nameController = TextEditingController();
+  final linkController = TextEditingController();
+  final iconController = TextEditingController();
+  CreateStarterCustom();
+  @override
+  Widget build(BuildContext context) {
+    final rc = Scaffold(
+        appBar: globalData.appBarBuilder(i18n.tr('New Starter')),
+        drawer: globalData.drawerBuilder(context),
+        body: SafeArea(child: buildFrame()));
+    return rc;
+  }
+
+  Widget buildFrame() {
+    final padding = GlobalThemeData.padding;
+    nameController.text = _fieldData.name;
+    linkController.text = _fieldData.link;
+    iconController.text = _fieldData.icon;
+    final formItems = <FormItem>[
+      FormItem(
+          TextFormField(
+              controller: nameController,
+              decoration: InputDecoration(labelText: i18n.tr('Name')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.name = value ?? ''),
+          weight: 6),
+      FormItem(
+          TextFormField(
+              controller: linkController,
+              decoration: InputDecoration(labelText: i18n.tr('Link')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.link = value ?? ''),
+          weight: 6),
+      FormItem(
+          TextFormField(
+              controller: iconController,
+              decoration: InputDecoration(labelText: i18n.tr('Icon')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.icon = value ?? ''),
+          weight: 6),
+      FormItem(
+          ElevatedButton(
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
+          weight: 8,
+          gapAbove: 2 * padding),
+      FormItem(
+          ElevatedButton(
+            onPressed: () {
+              attendedPage!.pageStates.dbDataState.clear();
+              globalData.navigate(context, '/Starters/list');
+            },
+            child: Text(i18n.tr('Cancel')),
+          ),
+          weight: 4)
+    ];
+    final rc = Form(
+        key: _formKey,
+        child: Card(
+            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,
+                ))));
+    return rc;
+  }
+
+  @override
+  void dispose() {
+    helperDummyUsage(DataType.int);
+    globalWidgetDummyUsage();
+    nameController.dispose();
+    linkController.dispose();
+    iconController.dispose();
+    super.dispose();
+  }
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  void onStore() {
+    final parameters = <String, dynamic>{
+      'module': 'Starters',
+      'sql': 'insert',
+    };
+    _fieldData.toMap(parameters);
+    globalData.restPersistence!
+        .store(what: 'store', map: parameters)
+        .then((answer) {
+      if (answer.startsWith('id:')) {
+        final id = int.tryParse(answer.substring(3));
+        if (id == null || id == 0) {
+          setError(i18n.tr('Saving data failed: $answer'));
+          setState(() => 1);
+        } else {
+          attendedPage!.pageStates.dbDataState.clear();
+          globalData.navigate(context, '/Starters/edit;$id');
+        }
+      }
+    });
+  }
+
+  void onVerifyAndStore() {
+    if (_formKey.currentState!.validate()) {
+      _formKey.currentState!.save();
+      onStore();
+    }
+  }
+}
+
+class _FieldData {
+  String name = '';
+  String link = '';
+  String icon = '';
+
+  void toMap(Map<String, dynamic> map) {
+    map[':name'] = name;
+    map[':link'] = link;
+    map[':icon'] = icon;
+    map[':createdBy'] = GlobalData.loginUserName;
+  }
+}
diff --git a/lib/page/starters/create_starter_page.dart b/lib/page/starters/create_starter_page.dart
new file mode 100644 (file)
index 0000000..29fc58b
--- /dev/null
@@ -0,0 +1,61 @@
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/starters_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'create_starter_custom.dart';
+
+class CreateStarterPage extends StatefulWidget {
+  final PageStates pageStates = PageStates();
+  CreateStarterPage() : super();
+  @override
+  _CreateStarterPageState createState() {
+    final rc = _CreateStarterPageState();
+    rc.attendedPage = AttendedPage(
+        this,
+        rc,
+        GlobalData(),
+        StartersMeta.instance.pageByName('create')!,
+        StartersMeta.instance,
+        pageStates,
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
+    pageStates.attendedPage = rc.attendedPage;
+    return rc;
+  }
+}
+
+class _CreateStarterPageState extends CreateStarterCustom {
+  _CreateStarterPageState() : 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/starters/delete_starter_custom.dart b/lib/page/starters/delete_starter_custom.dart
new file mode 100644 (file)
index 0000000..c99708d
--- /dev/null
@@ -0,0 +1,164 @@
+// 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 '../../base/validators.dart';
+import '../../persistence/persistence.dart';
+import '../../services/global_widget.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import '../../widget/message_line.dart';
+import '../../widget/widget_form.dart';
+import 'delete_starter_page.dart';
+
+final i18n = I18N();
+
+class DeleteStarterCustom extends State<DeleteStarterPage> with MessageLine {
+  final int primaryKey;
+  final globalData = GlobalData();
+  late Future<DbData> _futureDbData;
+  AttendedPage? attendedPage;
+  final _fieldData = _FieldData();
+  final GlobalKey<FormState> _formKey =
+      GlobalKey<FormState>(debugLabel: 'DeleteStarter');
+  final nameController = TextEditingController();
+  final linkController = TextEditingController();
+  final iconController = TextEditingController();
+  DeleteStarterCustom(this.primaryKey);
+  @override
+  Widget build(BuildContext context) {
+    final rc = Scaffold(
+        appBar: globalData.appBarBuilder(i18n.tr('Delete Starter')),
+        drawer: globalData.drawerBuilder(context),
+        body: SafeArea(
+            child: FutureBuilder<DbData>(
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
+    return rc;
+  }
+
+  Widget buildFrame() {
+    final padding = GlobalThemeData.padding;
+    nameController.text = _fieldData.name;
+    linkController.text = _fieldData.link;
+    iconController.text = _fieldData.icon;
+    final formItems = <FormItem>[
+      FormItem(
+          TextFormField(
+              controller: nameController,
+              decoration: InputDecoration(labelText: i18n.tr('Name')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.name = value ?? ''),
+          weight: 6),
+      FormItem(
+          TextFormField(
+              controller: linkController,
+              decoration: InputDecoration(labelText: i18n.tr('Link')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.link = value ?? ''),
+          weight: 6),
+      FormItem(
+          TextFormField(
+              controller: iconController,
+              decoration: InputDecoration(labelText: i18n.tr('Icon')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.icon = value ?? ''),
+          weight: 6),
+      FormItem(
+          ElevatedButton(
+              onPressed: () => onVerifyAndDelete(),
+              child: Text(i18n.tr('Delete'))),
+          weight: 8,
+          gapAbove: 2 * padding),
+      FormItem(
+          ElevatedButton(
+            onPressed: () {
+              attendedPage!.pageStates.dbDataState.clear();
+              globalData.navigate(context, '/Starters/list');
+            },
+            child: Text(i18n.tr('Cancel')),
+          ),
+          weight: 4)
+    ];
+    final rc = Form(
+        key: _formKey,
+        child: Card(
+            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,
+                ))));
+    return rc;
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+    requestRecord();
+  }
+
+  @override
+  void dispose() {
+    helperDummyUsage(DataType.int);
+    globalWidgetDummyUsage();
+    nameController.dispose();
+    linkController.dispose();
+    iconController.dispose();
+    super.dispose();
+  }
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onDelete() {
+    final parameters = <String, dynamic>{
+      'module': 'Starters',
+      'sql': 'delete',
+      ':id': primaryKey
+    };
+    globalData.restPersistence!
+        .store(what: 'store', map: parameters)
+        .then((answer) {
+      globalData.navigate(context, '/Starters/list');
+    });
+  }
+
+  void onVerifyAndDelete() {
+    if (_formKey.currentState!.validate()) {
+      _formKey.currentState!.save();
+      onDelete();
+    }
+  }
+}
+
+class _FieldData {
+  String name = '';
+  String link = '';
+  String icon = '';
+
+  void fromMap(Map<String, dynamic> map) {
+    name = map['starter_name'];
+    link = map['starter_link'];
+    icon = map['starter_icon'];
+  }
+}
diff --git a/lib/page/starters/delete_starter_page.dart b/lib/page/starters/delete_starter_page.dart
new file mode 100644 (file)
index 0000000..9d872e6
--- /dev/null
@@ -0,0 +1,62 @@
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/starters_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'delete_starter_custom.dart';
+
+class DeleteStarterPage extends StatefulWidget {
+  final int primaryKey;
+  final PageStates pageStates = PageStates();
+  DeleteStarterPage(this.primaryKey) : super();
+  @override
+  _DeleteStarterPageState createState() {
+    final rc = _DeleteStarterPageState(this.primaryKey);
+    rc.attendedPage = AttendedPage(
+        this,
+        rc,
+        GlobalData(),
+        StartersMeta.instance.pageByName('delete')!,
+        StartersMeta.instance,
+        pageStates,
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
+    pageStates.attendedPage = rc.attendedPage;
+    return rc;
+  }
+}
+
+class _DeleteStarterPageState extends DeleteStarterCustom {
+  _DeleteStarterPageState(int primaryKey) : super(primaryKey);
+  @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/starters/edit_starter_custom.dart b/lib/page/starters/edit_starter_custom.dart
new file mode 100644 (file)
index 0000000..60c5384
--- /dev/null
@@ -0,0 +1,175 @@
+// 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 '../../base/validators.dart';
+import '../../persistence/persistence.dart';
+import '../../services/global_widget.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import '../../widget/message_line.dart';
+import '../../widget/widget_form.dart';
+import 'edit_starter_page.dart';
+
+final i18n = I18N();
+
+class EditStarterCustom extends State<EditStarterPage> with MessageLine {
+  final int primaryKey;
+  final globalData = GlobalData();
+  late Future<DbData> _futureDbData;
+  AttendedPage? attendedPage;
+  final _fieldData = _FieldData();
+  final GlobalKey<FormState> _formKey =
+      GlobalKey<FormState>(debugLabel: 'EditStarter');
+  final nameController = TextEditingController();
+  final linkController = TextEditingController();
+  final iconController = TextEditingController();
+  EditStarterCustom(this.primaryKey);
+  @override
+  Widget build(BuildContext context) {
+    final rc = Scaffold(
+        appBar: globalData.appBarBuilder(i18n.tr('Change Starter')),
+        drawer: globalData.drawerBuilder(context),
+        body: SafeArea(
+            child: FutureBuilder<DbData>(
+                future: _futureDbData,
+                builder: (context, snapshot) {
+                  final rc = attendedPage!.loadRecord(snapshot, (record) {
+                    _fieldData.fromMap(record);
+                    return buildFrame();
+                  });
+                  return rc;
+                })));
+    return rc;
+  }
+
+  Widget buildFrame() {
+    final padding = GlobalThemeData.padding;
+    nameController.text = _fieldData.name;
+    linkController.text = _fieldData.link;
+    iconController.text = _fieldData.icon;
+    final formItems = <FormItem>[
+      FormItem(
+          TextFormField(
+              controller: nameController,
+              decoration: InputDecoration(labelText: i18n.tr('Name')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.name = value ?? ''),
+          weight: 6),
+      FormItem(
+          TextFormField(
+              controller: linkController,
+              decoration: InputDecoration(labelText: i18n.tr('Link')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.link = value ?? ''),
+          weight: 6),
+      FormItem(
+          TextFormField(
+              controller: iconController,
+              decoration: InputDecoration(labelText: i18n.tr('Icon')),
+              validator: (input) => notEmpty(input),
+              onSaved: (value) => _fieldData.icon = value ?? ''),
+          weight: 6),
+      FormItem(
+          ElevatedButton(
+              onPressed: () => onVerifyAndStore(),
+              child: Text(i18n.tr('Save'))),
+          weight: 8,
+          gapAbove: 2 * padding),
+      FormItem(
+          ElevatedButton(
+            onPressed: () {
+              attendedPage!.pageStates.dbDataState.clear();
+              globalData.navigate(context, '/Starters/list');
+            },
+            child: Text(i18n.tr('Cancel')),
+          ),
+          weight: 4)
+    ];
+    final rc = Form(
+        key: _formKey,
+        child: Card(
+            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,
+                ))));
+    return rc;
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+    requestRecord();
+  }
+
+  @override
+  void dispose() {
+    helperDummyUsage(DataType.int);
+    globalWidgetDummyUsage();
+    nameController.dispose();
+    linkController.dispose();
+    iconController.dispose();
+    super.dispose();
+  }
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  void requestRecord() => _futureDbData = globalData.restPersistence!.query(
+      what: 'query',
+      data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+
+  void onStore() {
+    final parameters = <String, dynamic>{
+      'module': 'Starters',
+      'sql': 'update',
+      ':id': primaryKey
+    };
+    _fieldData.toMap(parameters);
+    globalData.restPersistence!
+        .store(what: 'store', map: parameters)
+        .then((answer) {
+      requestRecord();
+      attendedPage!.pageStates.dbDataState.clear();
+      setState(() => 1);
+    });
+  }
+
+  void onVerifyAndStore() {
+    if (_formKey.currentState!.validate()) {
+      _formKey.currentState!.save();
+      onStore();
+    }
+  }
+}
+
+class _FieldData {
+  String name = '';
+  String link = '';
+  String icon = '';
+
+  void fromMap(Map<String, dynamic> map) {
+    name = map['starter_name'];
+    link = map['starter_link'];
+    icon = map['starter_icon'];
+  }
+
+  void toMap(Map<String, dynamic> map) {
+    // please set outside: map[':id'] = primaryKey;
+    map[':name'] = name;
+    map[':link'] = link;
+    map[':icon'] = icon;
+    map[':changedBy'] = GlobalData.loginUserName;
+  }
+}
diff --git a/lib/page/starters/edit_starter_page.dart b/lib/page/starters/edit_starter_page.dart
new file mode 100644 (file)
index 0000000..a1022ae
--- /dev/null
@@ -0,0 +1,62 @@
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/starters_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'edit_starter_custom.dart';
+
+class EditStarterPage extends StatefulWidget {
+  final int primaryKey;
+  final PageStates pageStates = PageStates();
+  EditStarterPage(this.primaryKey) : super();
+  @override
+  _EditStarterPageState createState() {
+    final rc = _EditStarterPageState(this.primaryKey);
+    rc.attendedPage = AttendedPage(
+        this,
+        rc,
+        GlobalData(),
+        StartersMeta.instance.pageByName('edit')!,
+        StartersMeta.instance,
+        pageStates,
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
+    pageStates.attendedPage = rc.attendedPage;
+    return rc;
+  }
+}
+
+class _EditStarterPageState extends EditStarterCustom {
+  _EditStarterPageState(int primaryKey) : super(primaryKey);
+  @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/starters/list_starter_custom.dart b/lib/page/starters/list_starter_custom.dart
new file mode 100644 (file)
index 0000000..e2cce7e
--- /dev/null
@@ -0,0 +1,173 @@
+// 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_starter_page.dart';
+
+final i18n = I18N();
+
+class ListStarterCustom extends State<ListStarterPage> {
+  final globalData = GlobalData();
+  late Future<DbData> _futureDbData;
+  AttendedPage? attendedPage;
+  final _fieldData = _FieldData();
+  final GlobalKey<FormState> _formKey =
+      GlobalKey<FormState>(debugLabel: 'CreateStarter');
+  final textController = TextEditingController();
+  ListStarterCustom();
+  @override
+  Widget build(BuildContext context) {
+    final rc = Scaffold(
+      appBar: globalData.appBarBuilder(i18n.tr('Overview starters')),
+      drawer: globalData.drawerBuilder(context),
+      floatingActionButton: FloatingActionButton(
+          onPressed: () {
+            globalData.navigate(context, '/Starters/create');
+          },
+          child: const Icon(Icons.add),
+          tooltip: 'Add a new starter'),
+      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:
+                      'starter_id;starter_name;starter_link;starter_icon',
+                  onDone: () => setState(() => 1),
+                  routeEdit: '/Starters/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(
+          TextFormField(
+              controller: textController,
+              decoration: InputDecoration(labelText: i18n.tr('Text')),
+              onSaved: (value) => _fieldData.text = value ?? ''),
+          weight: 6),
+      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('Name')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Link')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Icon')),
+        ),
+      ],
+      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();
+    textController.dispose();
+    super.dispose();
+  }
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  void requestRecords() =>
+      _futureDbData = globalData.restPersistence!.query(what: 'query', data: {
+        'module': 'Starters',
+        'sql': 'list',
+        'offset': _fieldData.theOffset,
+        'size': _fieldData.thePageSize,
+        ':text': _fieldData.text,
+      });
+
+  void search() {
+    attendedPage!.pageStates.dbDataState.clear();
+    if (_formKey.currentState!.validate()) {
+      _formKey.currentState!.save();
+      requestRecords();
+      setState(() => 1);
+    }
+  }
+}
+
+class _FieldData {
+  int thePageSize = 10;
+  int theOffset = 0;
+  String text = '';
+}
diff --git a/lib/page/starters/list_starter_page.dart b/lib/page/starters/list_starter_page.dart
new file mode 100644 (file)
index 0000000..a0849ef
--- /dev/null
@@ -0,0 +1,61 @@
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/starters_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'list_starter_custom.dart';
+
+class ListStarterPage extends StatefulWidget {
+  final PageStates pageStates = PageStates();
+  ListStarterPage() : super();
+  @override
+  _ListStarterPageState createState() {
+    final rc = _ListStarterPageState();
+    rc.attendedPage = AttendedPage(
+        this,
+        rc,
+        GlobalData(),
+        StartersMeta.instance.pageByName('list')!,
+        StartersMeta.instance,
+        pageStates,
+        (afterReload, rebuild) =>
+            rc.reload(afterReload: afterReload, rebuild: rebuild));
+    pageStates.attendedPage = rc.attendedPage;
+    return rc;
+  }
+}
+
+class _ListStarterPageState extends ListStarterCustom {
+  _ListStarterPageState() : 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/starters/starter_data.dart b/lib/page/starters/starter_data.dart
new file mode 100644 (file)
index 0000000..cf9a884
--- /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 StarterData extends DataRecord<int> {
+  int? id;
+  String? name;
+  String? link;
+  String? icon;
+  DateTime? createdAt;
+  String? createdBy;
+  DateTime? changedAt;
+  String? changedBy;
+  StarterData(
+      {this.id,
+      this.name,
+      this.link,
+      this.icon,
+      this.createdAt,
+      this.createdBy,
+      this.changedAt,
+      this.changedBy});
+  StarterData.createFromMap(DataMap map) {
+    fromMap(map);
+  }
+  @override
+  void fromMap(DataMap map) {
+    id = map.containsKey('starter_id')
+        ? fromString(map['starter_id'], dataType: DataType.reference)
+        : null;
+    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)
+        : null;
+    icon = map.containsKey('starter_icon')
+        ? fromString(map['starter_icon'], dataType: DataType.string)
+        : null;
+    createdAt = map.containsKey('starter_createdat')
+        ? fromString(map['starter_createdat'], dataType: DataType.datetime)
+        : null;
+    createdBy = map.containsKey('starter_createdby')
+        ? fromString(map['starter_createdby'], dataType: DataType.string)
+        : null;
+    changedAt = map.containsKey('starter_changedat')
+        ? fromString(map['starter_changedat'], dataType: DataType.datetime)
+        : null;
+    changedBy = map.containsKey('starter_changedby')
+        ? fromString(map['starter_changedby'], dataType: DataType.string)
+        : null;
+  }
+
+  @override
+  int keyOf() {
+    return id ?? 0;
+  }
+
+  @override
+  String nameOfKey() {
+    return 'starter_id';
+  }
+
+  static DataType? dataTypeOf(String name) {
+    DataType? rc;
+    switch (name) {
+      case 'id':
+        rc = DataType.reference;
+        break;
+      case 'name':
+        rc = DataType.string;
+        break;
+      case 'link':
+        rc = DataType.string;
+        break;
+      case 'icon':
+        rc = DataType.string;
+        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['starter_id'] = id;
+    map['starter_name'] = name;
+    map['starter_link'] = link;
+    map['starter_icon'] = icon;
+    map['starter_createdat'] = createdAt;
+    map['starter_createdby'] = createdBy;
+    map['starter_changedat'] = changedAt;
+    map['starter_changedby'] = changedBy;
+    return map;
+  }
+}
index 3eec391222f90ff2fe7ceed21a9ea461caef4738..a46570beeb8feb21de7b8cf3110380c7dbf8b5a9 100644 (file)
@@ -16,8 +16,8 @@ class CreateStructurePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        StructureMeta.instance.pageByName('create')!,
-        StructureMeta.instance,
+        StructuresMeta.instance.pageByName('create')!,
+        StructuresMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index fc458a6ed4b3400fadd504413e59ebe1aad2013a..b974f29b5c9e555b8fd547d1aa6a3f69614fac28 100644 (file)
@@ -17,8 +17,8 @@ class DeleteStructurePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        StructureMeta.instance.pageByName('delete')!,
-        StructureMeta.instance,
+        StructuresMeta.instance.pageByName('delete')!,
+        StructuresMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 8baf89cf63ff720d76a850377da40f67ce4c3d9a..b8c92b97bc888d9b45dcc52bc0d9700a303f4c7e 100644 (file)
@@ -17,8 +17,8 @@ class EditStructurePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        StructureMeta.instance.pageByName('edit')!,
-        StructureMeta.instance,
+        StructuresMeta.instance.pageByName('edit')!,
+        StructuresMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 04f0d643380fbdf434c90ac78557fc4af93b51c8..952c08ce54205dccffe6e42f38cbe5395e68e8f1 100644 (file)
@@ -29,11 +29,11 @@ class ListStructureCustom extends State<ListStructurePage> {
       appBar: globalData.appBarBuilder(i18n.tr('Overview structures')),
       drawer: globalData.drawerBuilder(context),
       floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          globalData.navigate(context, '/Structures/create');
-        },
-        child: const Icon(Icons.add),
-      ),
+          onPressed: () {
+            globalData.navigate(context, '/Structures/create');
+          },
+          child: const Icon(Icons.add),
+          tooltip: 'Add a structure item'),
       body: SafeArea(
           child: FutureBuilder<DbData>(
         future: _futureDbData,
@@ -96,7 +96,19 @@ class ListStructureCustom extends State<ListStructurePage> {
     final table = DataTable(
       columns: <DataColumn>[
         DataColumn(
-          label: Text(i18n.tr('d;Scope;Name;Value;Position')),
+          label: Text(i18n.tr('Id')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Scope')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Name')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Value')),
+        ),
+        DataColumn(
+          label: Text(i18n.tr('Position')),
         ),
       ],
       rows: rows as List<DataRow>,
@@ -108,6 +120,7 @@ class ListStructureCustom extends State<ListStructurePage> {
         onTap: (offset) {
           _fieldData.theOffset = offset;
           requestRecords();
+          setState(() => 1);
         });
     final frameWidget = ListView(children: [
       form,
index c60cda366bea073996f4e5da9c78ec94e2261178..cc03dc12396c4d4cabddfead75a5143030fe8055 100644 (file)
@@ -16,8 +16,8 @@ class ListStructurePage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        StructureMeta.instance.pageByName('list')!,
-        StructureMeta.instance,
+        StructuresMeta.instance.pageByName('list')!,
+        StructuresMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index b09010a3f2f345e492af1876b00ee51fcbf1fe5b..c5d858608d25bf6e5a0285994c5ecd617fefeb8f 100644 (file)
@@ -9,9 +9,9 @@ class StructureData extends DataRecord<int> {
   String? name;
   String? value;
   int? position;
-  DateTime? created;
+  DateTime? createdAt;
   String? createdBy;
-  DateTime? changed;
+  DateTime? changedAt;
   String? changedBy;
   StructureData(
       {this.id,
@@ -19,9 +19,9 @@ class StructureData extends DataRecord<int> {
       this.name,
       this.value,
       this.position,
-      this.created,
+      this.createdAt,
       this.createdBy,
-      this.changed,
+      this.changedAt,
       this.changedBy});
   StructureData.createFromMap(DataMap map) {
     fromMap(map);
@@ -43,14 +43,14 @@ class StructureData extends DataRecord<int> {
     position = map.containsKey('structure_position')
         ? fromString(map['structure_position'], dataType: DataType.int)
         : null;
-    created = map.containsKey('structure_created')
-        ? fromString(map['structure_created'], dataType: DataType.datetime)
+    createdAt = map.containsKey('structure_createdat')
+        ? fromString(map['structure_createdat'], dataType: DataType.datetime)
         : null;
     createdBy = map.containsKey('structure_createdby')
         ? fromString(map['structure_createdby'], dataType: DataType.string)
         : null;
-    changed = map.containsKey('structure_changed')
-        ? fromString(map['structure_changed'], dataType: DataType.datetime)
+    changedAt = map.containsKey('structure_changedat')
+        ? fromString(map['structure_changedat'], dataType: DataType.datetime)
         : null;
     changedBy = map.containsKey('structure_changedby')
         ? fromString(map['structure_changedby'], dataType: DataType.string)
@@ -85,13 +85,13 @@ class StructureData extends DataRecord<int> {
       case 'position':
         rc = DataType.int;
         break;
-      case 'created':
+      case 'createdAt':
         rc = DataType.datetime;
         break;
       case 'createdBy':
         rc = DataType.string;
         break;
-      case 'changed':
+      case 'changedAt':
         rc = DataType.datetime;
         break;
       case 'changedBy':
@@ -114,9 +114,9 @@ class StructureData extends DataRecord<int> {
     map['structure_name'] = name;
     map['structure_value'] = value;
     map['structure_position'] = position;
-    map['structure_created'] = created;
+    map['structure_createdat'] = createdAt;
     map['structure_createdby'] = createdBy;
-    map['structure_changed'] = changed;
+    map['structure_changedat'] = changedAt;
     map['structure_changedby'] = changedBy;
     return map;
   }
index 8f11c9419884bc4dcadc23bb2a1d859c91153784..a4763713cd512d45a3a3e8fb1dcab506919b4dd9 100644 (file)
@@ -16,8 +16,8 @@ class CreateUserPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        UserMeta.instance.pageByName('create')!,
-        UserMeta.instance,
+        UsersMeta.instance.pageByName('create')!,
+        UsersMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 6b563ac2291d0c69d74ede9694c93a5652154e9d..d87137a01ef0bfe58d3df5e713570be4568e4b21 100644 (file)
@@ -17,8 +17,8 @@ class DeleteUserPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        UserMeta.instance.pageByName('delete')!,
-        UserMeta.instance,
+        UsersMeta.instance.pageByName('delete')!,
+        UsersMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index b1ca38cd459f254d527e4e040600fb90ce330d2b..9b0c24f67e88d28efa1b524dfc79034dba0e7e01 100644 (file)
@@ -17,8 +17,8 @@ class EditUserPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        UserMeta.instance.pageByName('edit')!,
-        UserMeta.instance,
+        UsersMeta.instance.pageByName('edit')!,
+        UsersMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 330f896923311d9c0318f4e3ab0289fff47f1cb8..4d5be2f151ff1fb02f833f98fe6d665e07e1fc69 100644 (file)
@@ -29,11 +29,11 @@ class ListUserCustom extends State<ListUserPage> {
       appBar: globalData.appBarBuilder(i18n.tr('Overview users')),
       drawer: globalData.drawerBuilder(context),
       floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          globalData.navigate(context, '/Users/create');
-        },
-        child: const Icon(Icons.add),
-      ),
+          onPressed: () {
+            globalData.navigate(context, '/Users/create');
+          },
+          child: const Icon(Icons.add),
+          tooltip: 'Add a new user'),
       body: SafeArea(
           child: FutureBuilder<DbData>(
         future: _futureDbData,
@@ -135,6 +135,7 @@ class ListUserCustom extends State<ListUserPage> {
         onTap: (offset) {
           _fieldData.theOffset = offset;
           requestRecords();
+          setState(() => 1);
         });
     final frameWidget = ListView(children: [
       form,
index 186994f2303729a907928eeb204ac164618af112..41a1c6c7391d179182e4c928036245f2b1cc1196 100644 (file)
@@ -16,8 +16,8 @@ class ListUserPage extends StatefulWidget {
         this,
         rc,
         GlobalData(),
-        UserMeta.instance.pageByName('list')!,
-        UserMeta.instance,
+        UsersMeta.instance.pageByName('list')!,
+        UsersMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
index 427c74dd6d64aa0a256204886143e310c2180530..61a9eea5b17da750ea7aa5ed8b9f29feeafdbe0a 100644 (file)
@@ -9,9 +9,9 @@ class UserData extends DataRecord<int> {
   String? displayName;
   String? email;
   int? role;
-  DateTime? created;
+  DateTime? createdAt;
   String? createdBy;
-  DateTime? changed;
+  DateTime? changedAt;
   String? changedBy;
   UserData(
       {this.id,
@@ -19,9 +19,9 @@ class UserData extends DataRecord<int> {
       this.displayName,
       this.email,
       this.role,
-      this.created,
+      this.createdAt,
       this.createdBy,
-      this.changed,
+      this.changedAt,
       this.changedBy});
   UserData.createFromMap(DataMap map) {
     fromMap(map);
@@ -43,14 +43,14 @@ class UserData extends DataRecord<int> {
     role = map.containsKey('user_role')
         ? fromString(map['user_role'], dataType: DataType.reference)
         : null;
-    created = map.containsKey('user_created')
-        ? fromString(map['user_created'], dataType: DataType.datetime)
+    createdAt = map.containsKey('user_createdat')
+        ? fromString(map['user_createdat'], dataType: DataType.datetime)
         : null;
     createdBy = map.containsKey('user_createdby')
         ? fromString(map['user_createdby'], dataType: DataType.string)
         : null;
-    changed = map.containsKey('user_changed')
-        ? fromString(map['user_changed'], dataType: DataType.datetime)
+    changedAt = map.containsKey('user_changedat')
+        ? fromString(map['user_changedat'], dataType: DataType.datetime)
         : null;
     changedBy = map.containsKey('user_changedby')
         ? fromString(map['user_changedby'], dataType: DataType.string)
@@ -85,13 +85,13 @@ class UserData extends DataRecord<int> {
       case 'role':
         rc = DataType.reference;
         break;
-      case 'created':
+      case 'createdAt':
         rc = DataType.datetime;
         break;
       case 'createdBy':
         rc = DataType.string;
         break;
-      case 'changed':
+      case 'changedAt':
         rc = DataType.datetime;
         break;
       case 'changedBy':
@@ -114,9 +114,9 @@ class UserData extends DataRecord<int> {
     map['user_displayname'] = displayName;
     map['user_email'] = email;
     map['user_role'] = role;
-    map['user_created'] = created;
+    map['user_createdat'] = createdAt;
     map['user_createdby'] = createdBy;
-    map['user_changed'] = changed;
+    map['user_changedat'] = changedAt;
     map['user_changedby'] = changedBy;
     return map;
   }
index da7b246e6f41f6442042b799f51cbf8b2916de17..d7160d7756b49597e0e220f0b01fee75f1262c7c 100644 (file)
@@ -1,4 +1,5 @@
 import 'package:dart_bones/dart_bones.dart';
+import 'package:exhibition/base/helper.dart';
 import 'package:exhibition/page/page_manager.dart';
 import 'package:flutter/material.dart';
 
@@ -73,6 +74,9 @@ class MenuConverter {
   IconData iconByName(String name, BaseLogger logger) {
     IconData? rc;
     switch (name) {
+      case 'widgets_outlined':
+        rc = Icons.widgets_outlined;
+        break;
       case 'people_outlined':
         rc = Icons.people_outline;
         break;
@@ -118,17 +122,21 @@ class MenuItem {
     final collection = PageManager();
     return <MenuItem>[
       MenuItem(
-          'Benchmarks',
+          i18n.tr('Benchmarks'),
           () => collection.newPageByRoute('/Benchmarks/list'),
           converter.iconByName('analytics_outlined', logger)),
-      MenuItem('Users', () => collection.newPageByRoute('/Users/list'),
+      MenuItem(
+          i18n.tr('Starters'),
+          () => collection.newPageByRoute('/Starters/list'),
+          converter.iconByName('widgets_outlined', logger)),
+      MenuItem(i18n.tr('Users'), () => collection.newPageByRoute('/Users/list'),
           converter.iconByName('people_outlined', logger)),
-      MenuItem('Protokoll', () => collection.newPageByRoute('/log'),
+      MenuItem(i18n.tr('Protocol'), () => collection.newPageByRoute('/log'),
           converter.iconByName('line_weight_outlined', logger)),
-      MenuItem('Information', () => collection.newPageByRoute('/info'),
+      MenuItem(i18n.tr('Information'), () => collection.newPageByRoute('/info'),
           converter.iconByName('info_outline', logger)),
       MenuItem(
-          'Konfiguration',
+          i18n.tr('Configuration'),
           () => collection.newPageByRoute('/configuration'),
           converter.iconByName('settings_applications_outlined', logger)),
     ];
index 9252dadffff9014ad9935f52ae99ba2e9db5a8ff..80e4a377be50c295fc3fdbbc181d6e96545ad9b4 100644 (file)
@@ -50,8 +50,8 @@ DEF_PRIMARY  final PageStates pageStates = PageStates();
         this,
         rc,
         GlobalData(),
-        UserMeta.instance.pageByName('edit')!,
-        UserMeta.instance,
+        UsersMeta.instance.pageByName('edit')!,
+        UsersMeta.instance,
         pageStates,
         (afterReload, rebuild) =>
             rc.reload(afterReload: afterReload, rebuild: rebuild));
@@ -134,6 +134,7 @@ class ListUserCustom extends State<ListUserPage> {
           globalData.navigate(context, '/Users/create');
         },
         child: const Icon(Icons.add),
+        tooltip: #TIP_ADD
       ),
       body: SafeArea(
           child: FutureBuilder<DbData>(
@@ -470,8 +471,9 @@ StatefulWidget? customPageByRoute(String route) {
           (field as PropertyMetaData).displayType == DisplayType.text) {
         var value = '_fieldData.${field.name}';
         if (field.dataType != DataType.string) {
-          value = field.dataType == DataType.date ? 'asString($value, dateOnly: true)'
-          : 'asString($value)';
+          value = field.dataType == DataType.date
+              ? 'asString($value, dateOnly: true)'
+              : 'asString($value)';
         }
         buffer.writeln('    ${field.name}Controller.text = $value;');
       }
@@ -807,6 +809,8 @@ StatefulWidget? customPageByRoute(String route) {
 
   /// Returns a Dart class definition of the [page] that should not be modified.
   String createListPage(ListPageMetaData page) {
+    final toolTip =
+        page.toolTipAddButton.isEmpty ? 'null' : "'${page.toolTipAddButton}'";
     var rc = replaceVariables(templateListCustom, page)
         .replaceFirst('#DEF_CONTROLLERS', buildDefinitionControllers(page))
         .replaceFirst('#INIT_COMBOS', buildInitializeComboBoxes(page))
@@ -817,7 +821,8 @@ StatefulWidget? customPageByRoute(String route) {
         .replaceFirst('#DISPOSE_CONTROLLER', buildDisposeControllers(page))
         .replaceFirst('#DEF_FIELDS', buildDefinitionFields(page))
         .replaceFirst('#EDIT1', 'Edit')
-        .replaceFirst('#EDIT2', 'edit');
+        .replaceFirst('#EDIT2', 'edit')
+        .replaceFirst('#TIP_ADD', toolTip);
     return rc;
   }
 
@@ -872,8 +877,8 @@ StatefulWidget? customPageByRoute(String route) {
         storageDone = templateStorageDoneCreate.replaceFirst(
             '#MODULE', page.module.moduleName);
         body = templateBodySimple;
-        didChangeDependencies = definitionFuture = importPersistence
-        = informAboutChanges = setPrimary = requestRecord = '';
+        didChangeDependencies = definitionFuture = importPersistence =
+            informAboutChanges = setPrimary = requestRecord = '';
         break;
       case PageType.edit:
         callToMap = '    _fieldData.toMap(parameters);\n';
index 1eb09262a8d8f50e70b497f25472e7f0340f4cb0..106d2eb46436d643948f61d1ef6d878bb5186504 100644 (file)
@@ -135,14 +135,17 @@ update:
       }
     }
     parameters.write(']');
-    var item = module.properties['changed']!;
+    if (! module.properties.containsKey('changedAt')){
+      logger.error('Module $moduleName misses changedAt');
+    }
+    var item = module.properties['changedAt']!;
     assignments.write('      ${item.columnName}=NOW()');
     // parameters: [":id", ":name", ":displayname", ":email", ":changedby"]
     buffer.writeln(parameters);
     buffer.write('  sql: |\n');
     buffer.write('    UPDATE $tableName SET\n');
     buffer.writeln(assignments);
-    //user_name=:name, user_displayname=:displayname, user_email=:email, user_changed=NOW(), user_changedby=:changedby
+    //user_name=:name, user_displayname=:displayname, user_email=:email, user_changedAt=NOW(), user_changedby=:changedby
     buffer.write('    WHERE ${list[0].columnName}=:${list[0].name};\n');
 
     items = module.standardColumns('createdBy');
@@ -176,12 +179,12 @@ update:
       }
     }
     parameters.write(']');
-    item = module.properties['created']!;
+    item = module.properties['createdAt']!;
     addToBuffer('${item.columnName})',
         maxLength: 80, separator: ',', indent: 4, buffer: sql1);
     addToBuffer('NOW());',
         maxLength: 80, separator: ',', indent: 4, buffer: sql2);
-    // parameters: [":name", ":displayname", ":email", ":changedby"]
+    // parameters: [":name", ":displayname", ":email", ":createdAt"]
     buffer.write('''insert:
   type: insert
 ''');
index 1214dba820493b3f2245c47fc4d0eaacc297997a..67a1e389ad3152ad2160a158909d68d0d0aff296 100644 (file)
@@ -34,7 +34,7 @@ update:
       benchmark_active=:active,
       benchmark_weight=:weight,
       benchmark_income=:income,
-      benchmark_changed=NOW()
+      benchmark_changedat=NOW()
     WHERE benchmark_id=:id;
 insert:
   type: insert
@@ -43,6 +43,6 @@ insert:
   sql: |
     INSERT INTO benchmarks(benchmark_lastname,benchmark_firstname,
       benchmark_email,benchmark_birthday,benchmark_active,benchmark_weight,
-      benchmark_income,benchmark_createdby,benchmark_created)
+      benchmark_income,benchmark_createdby,benchmark_createdat)
     VALUES(:lastName,:firstName,:email,:birthday,:active,:weight,:income,
       :createdBy,NOW());
index 901ab649172f2b082469bbde9fba655a625c01bf..34251b250feb31195fb9c84bde0993cff4ec1cb2 100644 (file)
@@ -24,11 +24,11 @@ update:
   sql: |
     UPDATE roles SET
       role_name=:name,
-      role_changed=NOW()
+      role_changedat=NOW()
     WHERE role_id=:id;
 insert:
   type: insert
   parameters: [":name",":createdBy"]
   sql: |
-    INSERT INTO roles(role_name,role_createdby,role_created)
+    INSERT INTO roles(role_name,role_createdby,role_createdat)
     VALUES(:name,:createdBy,NOW());
diff --git a/rest_server/data/sql/starter.sql.yaml b/rest_server/data/sql/starter.sql.yaml
new file mode 100644 (file)
index 0000000..56262e3
--- /dev/null
@@ -0,0 +1,37 @@
+---
+# DO NOT CHANGE. This file is created by the meta_tool
+# SQL statements of the module "Starters":
+
+module: Starters
+list:
+  type: list
+  parameters: []
+  order: "starter_id"
+  sql: |
+    SELECT
+    t0.*    FROM starters t0
+byId:
+  type: record
+  parameters: [ ":id" ]
+  sql: "SELECT * FROM starters WHERE starter_id=:id;"
+delete:
+  type: delete
+  parameters: [ ":id" ]
+  sql: "DELETE * FROM starters WHERE starter_id=:id;"
+update:
+  type: update
+  parameters: [":id",":name",":link",":icon"]
+  sql: |
+    UPDATE starters SET
+      starter_name=:name,
+      starter_link=:link,
+      starter_icon=:icon,
+      starter_changedat=NOW()
+    WHERE starter_id=:id;
+insert:
+  type: insert
+  parameters: [":name",":link",":icon",":createdBy"]
+  sql: |
+    INSERT INTO starters(starter_name,starter_link,starter_icon,
+      starter_createdby,starter_createdat)
+    VALUES(:name,:link,:icon,:createdBy,NOW());
diff --git a/rest_server/data/sql/starters.sql.yaml b/rest_server/data/sql/starters.sql.yaml
new file mode 100644 (file)
index 0000000..56262e3
--- /dev/null
@@ -0,0 +1,37 @@
+---
+# DO NOT CHANGE. This file is created by the meta_tool
+# SQL statements of the module "Starters":
+
+module: Starters
+list:
+  type: list
+  parameters: []
+  order: "starter_id"
+  sql: |
+    SELECT
+    t0.*    FROM starters t0
+byId:
+  type: record
+  parameters: [ ":id" ]
+  sql: "SELECT * FROM starters WHERE starter_id=:id;"
+delete:
+  type: delete
+  parameters: [ ":id" ]
+  sql: "DELETE * FROM starters WHERE starter_id=:id;"
+update:
+  type: update
+  parameters: [":id",":name",":link",":icon"]
+  sql: |
+    UPDATE starters SET
+      starter_name=:name,
+      starter_link=:link,
+      starter_icon=:icon,
+      starter_changedat=NOW()
+    WHERE starter_id=:id;
+insert:
+  type: insert
+  parameters: [":name",":link",":icon",":createdBy"]
+  sql: |
+    INSERT INTO starters(starter_name,starter_link,starter_icon,
+      starter_createdby,starter_createdat)
+    VALUES(:name,:link,:icon,:createdBy,NOW());
index eb68f178aee44d54485ebdfe4b7e98b87570a196..957a3cbbfbb4e921aae14a76822c1b5084b0ed7a 100644 (file)
@@ -27,12 +27,12 @@ update:
       structure_name=:name,
       structure_value=:value,
       structure_position=:position,
-      structure_changed=NOW()
+      structure_changedat=NOW()
     WHERE structure_id=:id;
 insert:
   type: insert
   parameters: [":scope",":name",":value",":position",":createdBy"]
   sql: |
     INSERT INTO structures(structure_scope,structure_name,structure_value,
-      structure_position,structure_createdby,structure_created)
+      structure_position,structure_createdby,structure_createdat)
     VALUES(:scope,:name,:value,:position,:createdBy,NOW());
index 00a4637ee4780a60dd194a529d595403bb158590..18133b38139c811ce59896030a922aa8b6c256ac 100644 (file)
@@ -32,12 +32,12 @@ update:
       user_displayname=:displayName,
       user_email=:email,
       user_role=:role,
-      user_changed=NOW()
+      user_changedat=NOW()
     WHERE user_id=:id;
 insert:
   type: insert
   parameters: [":name",":displayName",":email",":role",":createdBy"]
   sql: |
     INSERT INTO users(user_name,user_displayname,user_email,user_role,
-      user_createdby,user_created)
+      user_createdby,user_createdat)
     VALUES(:name,:displayName,:email,:role,:createdBy,NOW());