+import 'package:intl/intl.dart';
+import 'package:sprintf/sprintf.dart';
+
import 'defines.dart';
+import 'i18n.dart';
+
+final dbDateFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
+final dbDateOnlyFormat = DateFormat('yyyy-MM-dd');
+
+final i18n = I18N();
+
+final regExprDateSortable = RegExp(r'(\d{4})[-.](\d\d?)[.-](\d\d?)');
+final regExprDateStandard = RegExp(r'(\d\d?)[-.](\d\d?)[.-](\d{4})');
+final regExprDateTimeSortable =
+ RegExp(r'(\d{4})[-.](\d\d?)[.-](\d\d?)?(\D(\d\d?):(\d\d?)(:(\d\d?))?)?');
+final regExprDateTimeStandard =
+ // ......1.....1....2.....2....3.....34..5.....5.6.....67.8.....87.4
+ RegExp(r'(\d\d?)[-.](\d\d?)[.-](\d{4})(\D(\d\d?):(\d\d?)(:(\d\d?))?)?');
+final standardDateFormat = DateFormat('dd.MM.yyyy');
+final standardDateTimeFormat = DateFormat('dd.MM.yyyy HH:mm');
+
+final standardDateTimeFormatSeconds = DateFormat('dd.MM.yyyy HH:mm:ss');
+
+// ..................................1.....1....2.....2....3....3.4.5.....5.6.....67.....7.4
/// Handles the [input] as a pattern in a filter list:
///
/// Appends '*' if input does not end with a '*'.
///
/// Returns a SQL pattern string.
String asPattern(String input) {
- final rc = input.isEmpty || input.endsWith('*') ? input : input + '*';
+ final rc = input.endsWith('*') ? input : input + '*';
return rc.replaceAll('*', '%').replaceAll('?', '_');
}
-/// Converts a [name] to a camel case string.
+/// Converts an [object] into a string depending on the data type.
///
-/// A camelCase string starts with a uppercase character.
-String toCamelCase(String name) {
- final rc = name.isEmpty ? '' : (name[0].toUpperCase() + name.substring(1));
+/// [dbFormat]: true: the result is stored in the database.
+///
+/// [dateOnly]: true: only the date is part of the result, not the time.
+/// Only relevant for DateTime objects.
+///
+/// [withSeconds]: true: the result contains the seconds of the DateTime instance.
+/// Only relevant for DateTime objects.
+String asString(dynamic object,
+ {bool dbFormat = false, bool dateOnly = false, bool withSeconds = false}) {
+ String rc;
+ if (object is String) {
+ rc = object;
+ } else if (object is int) {
+ rc = object.toString();
+ } else if (object is bool) {
+ if (dbFormat) {
+ rc = object ? 'T' : 'F';
+ } else {
+ rc = object ? i18n.tr('Yes') : i18n.tr('No');
+ }
+ } else if (object is DateTime) {
+ if (dbFormat) {
+ if (dateOnly) {
+ rc = dbDateOnlyFormat.format(object);
+ } else {
+ rc = dbDateFormat.format(object);
+ }
+ } else if (dateOnly) {
+ rc = standardDateFormat.format(object);
+ } else if (withSeconds) {
+ rc = standardDateTimeFormatSeconds.format(object);
+ } else {
+ rc = standardDateTimeFormat.format(object);
+ }
+ } else if (object is double) {
+ rc = sprintf('%.2f', [object]);
+ } else {
+ rc = object.toString();
+ }
return rc;
}
-/// Returns the [dataType] specific value of [data].
-dynamic valueOf(DataType dataType, String data) {
+/// Converts a string [value] into a [dataType] specific object.
+///
+/// If conversion is not possible (wrong input), the [defaultValue] is returned
+dynamic fromString(String value,
+ {required DataType dataType, dynamic defaultValue}) {
dynamic rc;
+ RegExpMatch? match;
switch (dataType) {
+ case DataType.undefined:
+ rc = defaultValue;
+ break;
+ case DataType.string:
+ rc = value;
+ break;
case DataType.bool:
- rc = data == 'true';
+ if (value == 'T' || value == i18n.tr('Yes')) {
+ rc = true;
+ } else if (value == 'F' || value == i18n.tr('No')) {
+ rc = false;
+ } else {
+ rc = defaultValue;
+ }
break;
case DataType.currency:
case DataType.float:
- rc = double.tryParse(data);
+ rc = double.tryParse(value) ?? defaultValue;
break;
case DataType.date:
+ if ((match = regExprDateSortable.firstMatch(value)) != null) {
+ rc = DateTime(int.parse(match!.group(1)!), int.parse(match.group(2)!),
+ int.parse(match.group(3)!));
+ } else if ((match = regExprDateStandard.firstMatch(value)) != null) {
+ rc = DateTime(int.parse(match!.group(3)!), int.parse(match.group(2)!),
+ int.parse(match.group(1)!));
+ } else {
+ rc = defaultValue;
+ }
+ break;
case DataType.datetime:
- rc = DateTime.parse(data);
+ if ((match = regExprDateTimeSortable.firstMatch(value)) != null) {
+ rc = DateTime(
+ int.parse(match!.group(1)!),
+ int.parse(match.group(2)!),
+ int.parse(match.group(3)!),
+ match.groupCount < 6 ? 0 : int.parse(match.group(5) ?? '0'),
+ match.groupCount < 6 ? 0 : int.parse(match.group(6) ?? '0'),
+ match.groupCount < 8 ? 0 : int.parse(match.group(8) ?? '0'),
+ );
+ } else if ((match = regExprDateTimeStandard.firstMatch(value)) != null) {
+ rc = DateTime(
+ int.parse(match!.group(3)!),
+ int.parse(match.group(2)!),
+ int.parse(match.group(1)!),
+ match.groupCount < 6 ? 0 : int.parse(match.group(5) ?? '0'),
+ match.groupCount < 6 ? 0 : int.parse(match.group(6) ?? '0'),
+ match.groupCount < 8 ? 0 : int.parse(match.group(8) ?? '0'),
+ );
+ } else {
+ rc = defaultValue;
+ }
break;
case DataType.int:
case DataType.nat:
case DataType.reference:
- rc = int.tryParse(data);
- break;
- case DataType.string:
- rc = data;
+ rc = int.tryParse(value) ?? defaultValue;
+ if (dataType == DataType.nat && rc < 0) {
+ rc = defaultValue;
+ }
break;
- case DataType.undefined:
- throw FormatException('valueOf(): data type is undefined');
}
return rc;
}
+
+/// This function is only used to avoid compiler warning "unused import"
+/// for generated code.
+void helperDummyUsage() {
+ // nothing to do
+}
+
+/// Converts a [name] to a camel case string.
+///
+/// A camelCase string starts with a uppercase character.
+String toCamelCase(String name) {
+ final rc = name.isEmpty ? '' : (name[0].toUpperCase() + name.substring(1));
+ return rc;
+}
--- /dev/null
+import '../base/defines.dart';
+import '../base/i18n.dart';
+import 'module_meta_data.dart';
+
+final i18n = I18N();
+final M = i18n.module("Benchmarks");
+
+class BenchmarkMeta extends ModuleMetaData {
+ static BenchmarkMeta instance = BenchmarkMeta.internal();
+ factory BenchmarkMeta() {
+ return instance;
+ }
+ BenchmarkMeta.internal()
+ : super('Benchmarks', [
+ PropertyMetaData('id', i18n.tr('Id'), DataType.reference, ':primary:',
+ displayType: DisplayType.combobox),
+ PropertyMetaData(
+ 'lastName', i18n.tr('Last Name'), DataType.string, ':notnull:',
+ size: 64),
+ PropertyMetaData('firstName', i18n.tr('First Name', M),
+ DataType.string, ':unique:notnull:',
+ size: 32),
+ PropertyMetaData(
+ 'email', i18n.tr('EMail', M), DataType.string, ':unique:notnull:',
+ size: 255, validators: ['isEmail(input)']),
+ PropertyMetaData(
+ 'birthday', i18n.tr('Birthday'), DataType.date, ':notnull:'),
+ PropertyMetaData(
+ 'active', i18n.tr('Active'), DataType.bool, ':notnull:'),
+ PropertyMetaData(
+ 'weight', i18n.tr('Weight'), DataType.float, ''),
+ PropertyMetaData(
+ 'income', i18n.tr('Income'), DataType.currency, ''),
+ PropertyMetaData(
+ 'created', i18n.tr('Created'), DataType.datetime, ':hidden:'),
+ PropertyMetaData(
+ 'createdBy', i18n.tr('Created by'), DataType.string, ':hidden:',
+ size: 32),
+ PropertyMetaData(
+ 'changed', i18n.tr('Changed'), DataType.datetime, ':hidden:'),
+ PropertyMetaData(
+ 'changedBy', i18n.tr('Changed by'), DataType.string, ':hidden:',
+ size: 32),
+ ], [
+ PageMetaData(
+ 'New Benchmark',
+ PageType.create,
+ fields: [CopyDbFields('filters')],
+ ),
+ PageMetaData(
+ 'Change Benchmark',
+ PageType.edit,
+ fields: [CopyDbFields('filters')],
+ ),
+ PageMetaData(
+ 'Delete Benchmark',
+ PageType.delete,
+ fields: [CopyDbFields('filters')],
+ ),
+ ListPageMetaData(
+ 'Benchmarks Overview',
+ fields: [
+ PropertyMetaData(
+ 'text', i18n.tr('Text'), DataType.string, ':pattern:',
+ size: 64),
+ ],
+ tableColumns: 'benchmark_id;benchmark_lastname;benchmark_firstname;benchmark_birthday',
+ tableHeaders: i18n.tr(';Id;Last Name;First Name;Birthday'),
+ whereCondition: '''(:text='' OR benchmark_lastname like :text
+ OR benchmark_firstname like :text)''',
+ orderBy: 'benchmark_id',
+ ),
+ ]);
+ @override
+ void onInitialized() {
+ super.onInitialized();
+ }
+}
// DO NOT CHANGE. This file is created by the meta_tool
import 'module_meta_data.dart';
+import 'benchmarks_meta.dart';
import 'roles_meta.dart';
import 'structures_meta.dart';
import 'users_meta.dart';
-
/// Returns the meta data of the module given by [name].
/// Returns null if not found.
ModuleMetaData? moduleByName(String name) {
ModuleMetaData? rc;
switch (name) {
+ case 'Benchmarks':
+ rc = BenchmarkMeta();
+ break;
case 'Roles':
rc = RoleMeta();
break;
}
return rc;
}
-
/// Returns the module names as string list.
-List<String> moduleNames() {
+List<String> moduleNames(){
return [
+ 'Benchmarks',
'Roles',
'Structures',
'Users',
--- /dev/null
+// 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 BenchmarkData extends DataRecord<int>{
+ int? id;
+ String? lastName;
+ String? firstName;
+ String? email;
+ DateTime? birthday;
+ bool? active;
+ double? weight;
+ int? income;
+ DateTime? created;
+ String? createdBy;
+ DateTime? changed;
+ String? changedBy;
+ BenchmarkData({
+ this.id, this.lastName, this.firstName, this.email, this.birthday, this.active, this.weight, this.income, this.created, this.createdBy, this.changed, this.changedBy});
+ BenchmarkData.createFromMap(DataMap map) {
+ fromMap(map);
+ }
+ @override
+ void fromMap(DataMap map) {
+ id = map.containsKey('benchmark_id') ? fromString(map['benchmark_id'], dataType: DataType.reference) : null;
+ lastName = map.containsKey('benchmark_lastname') ? fromString(map['benchmark_lastname'], dataType: DataType.string) : null;
+ firstName = map.containsKey('benchmark_firstname') ? fromString(map['benchmark_firstname'], dataType: DataType.string) : null;
+ email = map.containsKey('benchmark_email') ? fromString(map['benchmark_email'], dataType: DataType.string) : null;
+ birthday = map.containsKey('benchmark_birthday') ? fromString(map['benchmark_birthday'], dataType: DataType.date) : null;
+ active = map.containsKey('benchmark_active') ? fromString(map['benchmark_active'], dataType: DataType.bool) : null;
+ weight = map.containsKey('benchmark_weight') ? fromString(map['benchmark_weight'], dataType: DataType.float) : null;
+ 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) : 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) : null;
+ changedBy = map.containsKey('benchmark_changedby') ? fromString(map['benchmark_changedby'], dataType: DataType.string) : null;
+ }
+ @override
+ int keyOf() {
+ return id ?? 0;
+ }
+ @override
+ String nameOfKey(){
+ return 'benchmark_id';
+ }
+ static DataType? dataTypeOf(String name) {
+ DataType? rc;
+ switch(name){
+ case 'id':
+ rc = DataType.reference;
+ break;
+ case 'lastName':
+ rc = DataType.string;
+ break;
+ case 'firstName':
+ rc = DataType.string;
+ break;
+ case 'email':
+ rc = DataType.string;
+ break;
+ case 'birthday':
+ rc = DataType.date;
+ break;
+ case 'active':
+ rc = DataType.bool;
+ break;
+ case 'weight':
+ rc = DataType.float;
+ break;
+ case 'income':
+ rc = DataType.currency;
+ break;
+ case 'created':
+ rc = DataType.datetime;
+ break;
+ case 'createdBy':
+ rc = DataType.string;
+ break;
+ case 'changed':
+ 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['benchmark_id'] = id;
+ map['benchmark_lastname'] = lastName;
+ map['benchmark_firstname'] = firstName;
+ map['benchmark_email'] = email;
+ map['benchmark_birthday'] = birthday;
+ map['benchmark_active'] = active;
+ map['benchmark_weight'] = weight;
+ map['benchmark_income'] = income;
+ map['benchmark_created'] = created;
+ map['benchmark_createdby'] = createdBy;
+ map['benchmark_changed'] = changed;
+ map['benchmark_changedby'] = changedBy;
+ return map;
+ }
+}
--- /dev/null
+// 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_benchmark_page.dart';
+
+final i18n = I18N();
+
+class CreateBenchmarkCustom extends State<CreateBenchmarkPage> with MessageLine {
+ final globalData = GlobalData();
+ AttendedPage? attendedPage;
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateBenchmark');
+ final lastNameController = TextEditingController();
+ final firstNameController = TextEditingController();
+ final emailController = TextEditingController();
+ final birthdayController = TextEditingController();
+ final activeController = TextEditingController();
+ final weightController = TextEditingController();
+ final incomeController = TextEditingController();
+ CreateBenchmarkCustom();
+ @override
+ Widget build(BuildContext context) {
+ final padding = GlobalThemeData.padding;
+ lastNameController.text = _fieldData.lastName;
+ firstNameController.text = _fieldData.firstName;
+ emailController.text = _fieldData.email;
+ birthdayController.text = asString(_fieldData.birthday);
+ activeController.text = asString(_fieldData.active);
+ weightController.text = asString(_fieldData.weight);
+ incomeController.text = asString(_fieldData.income);
+ final formItems = <FormItem>[
+ FormItem(
+ TextFormField(
+ controller: lastNameController,
+ decoration: InputDecoration(labelText: i18n.tr('Last Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.lastName = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: firstNameController,
+ decoration: InputDecoration(labelText: i18n.tr('First Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.firstName = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: emailController,
+ decoration: InputDecoration(labelText: i18n.tr('EMail')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.email = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: birthdayController,
+ decoration: InputDecoration(labelText: i18n.tr('Birthday')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.birthday = fromString(value ?? '', dataType: DataType.date)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: activeController,
+ decoration: InputDecoration(labelText: i18n.tr('Active')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.active = fromString(value ?? '', dataType: DataType.bool)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: weightController,
+ decoration: InputDecoration(labelText: i18n.tr('Weight')),
+ onSaved: (value) => _fieldData.weight = fromString(value ?? '', dataType: DataType.float)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: incomeController,
+ decoration: InputDecoration(labelText: i18n.tr('Income')),
+ onSaved: (value) => _fieldData.income = fromString(value ?? '', dataType: DataType.currency)
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Benchmarks/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('New Benchmark')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: 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 initState() {
+ super.initState();
+ }
+
+ void store() {
+ final parameters = <String, dynamic>{
+ 'module': 'Benchmarks',
+ '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, '/Benchmarks/edit;$id');
+ }
+ }
+ });
+ }
+
+ void verifyAndStore() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ store();
+ }
+ }
+
+ @override
+ void dispose() {
+ lastNameController.dispose();
+ firstNameController.dispose();
+ emailController.dispose();
+ birthdayController.dispose();
+ activeController.dispose();
+ weightController.dispose();
+ incomeController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String lastName = '';
+ String firstName = '';
+ String email = '';
+ DateTime? birthday;
+ bool active = false;
+ double weight = 0;
+ double income = 0;
+
+
+ void toMap(Map<String, dynamic> map) {
+ map[':lastName'] = lastName;
+ map[':firstName'] = firstName;
+ map[':email'] = email;
+ map[':birthday'] = asString(birthday);
+ map[':active'] = asString(active);
+ map[':weight'] = asString(weight);
+ map[':income'] = asString(income);
+ map[':createdBy'] = GlobalData.loginUserName;
+ }
+}
--- /dev/null
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/benchmarks_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'create_benchmark_custom.dart';
+
+class CreateBenchmarkPage extends StatefulWidget {
+ final PageStates pageStates = PageStates();
+ CreateBenchmarkPage() : super();
+ @override
+ _CreateBenchmarkPageState createState() {
+ final rc = _CreateBenchmarkPageState();
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), BenchmarkMeta.instance, pageStates);
+ pageStates.attendedPage = rc.attendedPage;
+ return rc;
+ }
+}
+
+class _CreateBenchmarkPageState extends CreateBenchmarkCustom {
+ _CreateBenchmarkPageState(): super();
+ @override
+ void didChangeDependencies() {
+ final size = MediaQuery.of(context).size;
+ attendedPage!.pageStates.screenWidth = size.width;
+ attendedPage!.pageStates.screenHeight = size.height;
+ super.didChangeDependencies();
+ }
+}
--- /dev/null
+// 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 'delete_benchmark_page.dart';
+
+final i18n = I18N();
+
+class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage> with MessageLine {
+ final int primaryKey;
+ final globalData = GlobalData();
+ AttendedPage? attendedPage;
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'DeleteBenchmark');
+ final lastNameController = TextEditingController();
+ final firstNameController = TextEditingController();
+ final emailController = TextEditingController();
+ final birthdayController = TextEditingController();
+ final activeController = TextEditingController();
+ final weightController = TextEditingController();
+ final incomeController = TextEditingController();
+ DeleteBenchmarkCustom(this.primaryKey);
+ @override
+ Widget build(BuildContext context) {
+ final padding = GlobalThemeData.padding;
+ attendedPage?.loadRecord(
+ name: 'record',
+ reload: () => setState(() => 1),
+ onDone: (record) => _fieldData.fromMap(record),
+ parameters: {'module': 'Benchmarks', 'sql': 'byId', ':id': primaryKey});
+ lastNameController.text = _fieldData.lastName;
+ firstNameController.text = _fieldData.firstName;
+ emailController.text = _fieldData.email;
+ birthdayController.text = asString(_fieldData.birthday);
+ activeController.text = asString(_fieldData.active);
+ weightController.text = asString(_fieldData.weight);
+ incomeController.text = asString(_fieldData.income);
+ final formItems = <FormItem>[
+ FormItem(
+ TextFormField(
+ controller: lastNameController,
+ decoration: InputDecoration(labelText: i18n.tr('Last Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.lastName = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: firstNameController,
+ decoration: InputDecoration(labelText: i18n.tr('First Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.firstName = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: emailController,
+ decoration: InputDecoration(labelText: i18n.tr('EMail')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.email = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: birthdayController,
+ decoration: InputDecoration(labelText: i18n.tr('Birthday')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.birthday = fromString(value ?? '', dataType: DataType.date)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: activeController,
+ decoration: InputDecoration(labelText: i18n.tr('Active')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.active = fromString(value ?? '', dataType: DataType.bool)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: weightController,
+ decoration: InputDecoration(labelText: i18n.tr('Weight')),
+ onSaved: (value) => _fieldData.weight = fromString(value ?? '', dataType: DataType.float)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: incomeController,
+ decoration: InputDecoration(labelText: i18n.tr('Income')),
+ onSaved: (value) => _fieldData.income = fromString(value ?? '', dataType: DataType.currency)
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => verifyAndDelete(),
+ child: Text(i18n.tr('Delete'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Benchmarks/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Delete Benchmark')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: 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 initState() {
+ super.initState();
+ }
+
+ void delete() {
+ final parameters = <String, dynamic>{
+ 'module': 'Benchmarks',
+ 'sql': 'delete',
+ };
+ parameters[':id'] = primaryKey;
+ globalData.restPersistence!
+ .store(what: 'store', map: parameters)
+ .then((answer) {
+ globalData.navigate(context, '/Benchmarks/list');
+ });
+ }
+
+ void verifyAndDelete() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ delete();
+ }
+ }
+
+ @override
+ void dispose() {
+ lastNameController.dispose();
+ firstNameController.dispose();
+ emailController.dispose();
+ birthdayController.dispose();
+ activeController.dispose();
+ weightController.dispose();
+ incomeController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String lastName = '';
+ String firstName = '';
+ String email = '';
+ DateTime? birthday;
+ bool active = false;
+ double weight = 0;
+ double income = 0;
+
+ void fromMap(Map<String, dynamic> map) {
+ lastName = map['benchmark_lastname'];
+ firstName = map['benchmark_firstname'];
+ email = map['benchmark_email'];
+ birthday = map['benchmark_birthday'];
+ active = map['benchmark_active'];
+ weight = map['benchmark_weight'];
+ income = map['benchmark_income'];
+ }
+}
--- /dev/null
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/benchmarks_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'delete_benchmark_custom.dart';
+
+class DeleteBenchmarkPage extends StatefulWidget {
+ final int primaryKey;
+ final PageStates pageStates = PageStates();
+ DeleteBenchmarkPage(this.primaryKey) : super();
+ @override
+ _DeleteBenchmarkPageState createState() {
+ final rc = _DeleteBenchmarkPageState(this.primaryKey);
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), BenchmarkMeta.instance, pageStates);
+ pageStates.attendedPage = rc.attendedPage;
+ return rc;
+ }
+}
+
+class _DeleteBenchmarkPageState extends DeleteBenchmarkCustom {
+ _DeleteBenchmarkPageState(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();
+ }
+}
--- /dev/null
+// 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 'edit_benchmark_page.dart';
+
+final i18n = I18N();
+
+class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
+ final int primaryKey;
+ final globalData = GlobalData();
+ AttendedPage? attendedPage;
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'EditBenchmark');
+ final lastNameController = TextEditingController();
+ final firstNameController = TextEditingController();
+ final emailController = TextEditingController();
+ final birthdayController = TextEditingController();
+ final activeController = TextEditingController();
+ final weightController = TextEditingController();
+ final incomeController = TextEditingController();
+ EditBenchmarkCustom(this.primaryKey);
+ @override
+ Widget build(BuildContext context) {
+ final padding = GlobalThemeData.padding;
+ attendedPage?.loadRecord(
+ name: 'record',
+ reload: () => setState(() => 1),
+ onDone: (record) => _fieldData.fromMap(record),
+ parameters: {'module': 'Benchmarks', 'sql': 'byId', ':id': primaryKey});
+ lastNameController.text = _fieldData.lastName;
+ firstNameController.text = _fieldData.firstName;
+ emailController.text = _fieldData.email;
+ birthdayController.text = asString(_fieldData.birthday);
+ activeController.text = asString(_fieldData.active);
+ weightController.text = asString(_fieldData.weight);
+ incomeController.text = asString(_fieldData.income);
+ final formItems = <FormItem>[
+ FormItem(
+ TextFormField(
+ controller: lastNameController,
+ decoration: InputDecoration(labelText: i18n.tr('Last Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.lastName = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: firstNameController,
+ decoration: InputDecoration(labelText: i18n.tr('First Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.firstName = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: emailController,
+ decoration: InputDecoration(labelText: i18n.tr('EMail')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.email = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: birthdayController,
+ decoration: InputDecoration(labelText: i18n.tr('Birthday')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.birthday = fromString(value ?? '', dataType: DataType.date)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: activeController,
+ decoration: InputDecoration(labelText: i18n.tr('Active')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.active = fromString(value ?? '', dataType: DataType.bool)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: weightController,
+ decoration: InputDecoration(labelText: i18n.tr('Weight')),
+ onSaved: (value) => _fieldData.weight = fromString(value ?? '', dataType: DataType.float)
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: incomeController,
+ decoration: InputDecoration(labelText: i18n.tr('Income')),
+ onSaved: (value) => _fieldData.income = fromString(value ?? '', dataType: DataType.currency)
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Benchmarks/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Change Benchmark')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: 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 initState() {
+ super.initState();
+ }
+
+ void store() {
+ final parameters = <String, dynamic>{
+ 'module': 'Benchmarks',
+ 'sql': 'update',
+ };
+ parameters[':id'] = primaryKey;
+ _fieldData.toMap(parameters);
+ globalData.restPersistence!
+ .store(what: 'store', map: parameters)
+ .then((answer) {});
+ }
+
+ void verifyAndStore() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ store();
+ }
+ }
+
+ @override
+ void dispose() {
+ lastNameController.dispose();
+ firstNameController.dispose();
+ emailController.dispose();
+ birthdayController.dispose();
+ activeController.dispose();
+ weightController.dispose();
+ incomeController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String lastName = '';
+ String firstName = '';
+ String email = '';
+ DateTime? birthday;
+ bool active = false;
+ double weight = 0;
+ double income = 0;
+
+ void fromMap(Map<String, dynamic> map) {
+ lastName = map['benchmark_lastname'];
+ firstName = map['benchmark_firstname'];
+ email = map['benchmark_email'];
+ birthday = map['benchmark_birthday'];
+ active = map['benchmark_active'];
+ weight = map['benchmark_weight'];
+ income = map['benchmark_income'];
+ }
+
+ void toMap(Map<String, dynamic> map) {
+ // please set outside: map[':id'] = primaryKey;
+ map[':lastName'] = lastName;
+ map[':firstName'] = firstName;
+ map[':email'] = email;
+ map[':birthday'] = asString(birthday);
+ map[':active'] = asString(active);
+ map[':weight'] = asString(weight);
+ map[':income'] = asString(income);
+ map[':changedBy'] = GlobalData.loginUserName;
+ }
+}
--- /dev/null
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/benchmarks_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'edit_benchmark_custom.dart';
+
+class EditBenchmarkPage extends StatefulWidget {
+ final int primaryKey;
+ final PageStates pageStates = PageStates();
+ EditBenchmarkPage(this.primaryKey) : super();
+ @override
+ _EditBenchmarkPageState createState() {
+ final rc = _EditBenchmarkPageState(this.primaryKey);
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), BenchmarkMeta.instance, pageStates);
+ pageStates.attendedPage = rc.attendedPage;
+ return rc;
+ }
+}
+
+class _EditBenchmarkPageState extends EditBenchmarkCustom {
+ _EditBenchmarkPageState(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();
+ }
+}
--- /dev/null
+// 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/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 'list_benchmark_page.dart';
+
+final i18n = I18N();
+
+class ListBenchmarkCustom extends State<ListBenchmarkPage> {
+ final globalData = GlobalData();
+ AttendedPage? attendedPage;
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateBenchmark');
+ final textController = TextEditingController();
+ ListBenchmarkCustom();
+ @override
+ Widget build(BuildContext context) {
+ 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 rows = attendedPage!.getRows(
+ columnList: 'benchmark_id;benchmark_lastname;benchmark_firstname;benchmark_birthday',
+ what: 'query',
+ parameters: {
+ 'module': 'Benchmarks',
+ 'sql': 'list',
+ 'offset': '0',
+ 'size': '10',
+ ':text': asPattern(_fieldData.text),
+ },
+ onDone: () => setState(() => 1),
+ routeEdit: '/Benchmarks/edit',
+ context: context);
+ final table = DataTable(
+ columns: <DataColumn>[
+ DataColumn(
+ label: Text(i18n.tr('Id')),
+ ),
+ DataColumn(
+ label: Text(i18n.tr('Last Name')),
+ ),
+ DataColumn(
+ label: Text(i18n.tr('First Name')),
+ ),
+ DataColumn(
+ label: Text(i18n.tr('Birthday')),
+ ),
+ ],
+ rows: rows,
+ );
+ final frameWidget = Column(children: [
+ form,
+ SizedBox(height: padding),
+ SizedBox(width: double.infinity, child: table),
+ ]);
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Overview benchmarks')),
+ drawer: globalData.drawerBuilder(context),
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {
+ globalData.navigate(context, '/Benchmarks/create');
+ },
+ child: const Icon(Icons.add),
+ //backgroundColor: Colors.green,
+ ),
+ body: SafeArea(child: frameWidget));
+ return rc;
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage();
+ globalWidgetDummyUsage();
+ textController.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ void search() {
+ attendedPage!.pageStates.dbDataState.clear();
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ setState(() => 1);
+ }
+ }
+}
+
+class _FieldData {
+ String text = '';
+}
--- /dev/null
+// DO NOT CHANGE. This file is created by the meta_tool!
+import 'package:flutter/material.dart';
+
+import '../../meta/benchmarks_meta.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import 'list_benchmark_custom.dart';
+
+class ListBenchmarkPage extends StatefulWidget {
+ final PageStates pageStates = PageStates();
+ ListBenchmarkPage() : super();
+ @override
+ _ListBenchmarkPageState createState() {
+ final rc = _ListBenchmarkPageState();
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), BenchmarkMeta.instance, pageStates);
+ pageStates.attendedPage = rc.attendedPage;
+ return rc;
+ }
+}
+
+class _ListBenchmarkPageState extends ListBenchmarkCustom {
+ _ListBenchmarkPageState(): super();
+ @override
+ void didChangeDependencies() {
+ final size = MediaQuery.of(context).size;
+ attendedPage!.pageStates.screenWidth = size.width;
+ attendedPage!.pageStates.screenHeight = size.height;
+ super.didChangeDependencies();
+ }
+}
import 'package:flutter/material.dart';
import 'page_manager_custom.dart';
+import 'benchmarks/create_benchmark_page.dart';
+import 'benchmarks/edit_benchmark_page.dart';
+import 'benchmarks/delete_benchmark_page.dart';
+import 'benchmarks/list_benchmark_page.dart';
import 'roles/create_role_page.dart';
import 'roles/edit_role_page.dart';
import 'roles/list_role_page.dart';
final parts = route.split(';');
final arg1 = parts.length < 2 ? 0 : int.parse(parts[1]);
switch (parts[0]) {
+ case '/Benchmarks/create':
+ rc = CreateBenchmarkPage();
+ break;
+ case '/Benchmarks/edit':
+ rc = EditBenchmarkPage(arg1);
+ break;
+ case '/Benchmarks/delete':
+ rc = DeleteBenchmarkPage(arg1);
+ break;
+ case '/Benchmarks/list':
+ rc = ListBenchmarkPage();
+ break;
case '/Roles/create':
rc = CreateRolePage();
break;
// 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_role_page.dart';
final i18n = I18N();
-class CreateRoleCustom extends State<CreateRolePage> {
+class CreateRoleCustom extends State<CreateRolePage> with MessageLine {
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateRole');
+ final nameController = TextEditingController();
CreateRoleCustom();
@override
Widget build(BuildContext context) {
final padding = GlobalThemeData.padding;
+ nameController.text = _fieldData.name;
+ 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(
+ ElevatedButton(
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Roles/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Role data')),
+ appBar: globalData.appBarBuilder(i18n.tr('New Role')),
drawer: globalData.drawerBuilder(context),
body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ child: 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;
}
void initState() {
super.initState();
}
+
+ void store() {
+ final parameters = <String, dynamic>{
+ 'module': 'Roles',
+ '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, '/Roles/edit;$id');
+ }
+ }
+ });
+ }
+
+ void verifyAndStore() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ store();
+ }
+ }
+
+ @override
+ void dispose() {
+ nameController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String name = '';
+
+
+ void toMap(Map<String, dynamic> map) {
+ map[':name'] = name;
+ map[':createdBy'] = GlobalData.loginUserName;
+ }
}
}
class _CreateRolePageState extends CreateRoleCustom {
- _CreateRolePageState() : super();
+ _CreateRolePageState(): super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// 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 'edit_role_page.dart';
final i18n = I18N();
-class EditRoleCustom extends State<EditRolePage> {
+class EditRoleCustom extends State<EditRolePage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'EditRole');
+ final nameController = TextEditingController();
EditRoleCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
final padding = GlobalThemeData.padding;
+ attendedPage?.loadRecord(
+ name: 'record',
+ reload: () => setState(() => 1),
+ onDone: (record) => _fieldData.fromMap(record),
+ parameters: {'module': 'Roles', 'sql': 'byId', ':id': primaryKey});
+ nameController.text = _fieldData.name;
+ 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(
+ ElevatedButton(
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Roles/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Role data')),
+ appBar: globalData.appBarBuilder(i18n.tr('Change Role')),
drawer: globalData.drawerBuilder(context),
body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ child: 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;
}
void initState() {
super.initState();
}
+
+ void store() {
+ final parameters = <String, dynamic>{
+ 'module': 'Roles',
+ 'sql': 'update',
+ };
+ parameters[':id'] = primaryKey;
+ _fieldData.toMap(parameters);
+ globalData.restPersistence!
+ .store(what: 'store', map: parameters)
+ .then((answer) {});
+ }
+
+ void verifyAndStore() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ store();
+ }
+ }
+
+ @override
+ void dispose() {
+ nameController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String name = '';
+
+ void fromMap(Map<String, dynamic> map) {
+ name = map['role_name'];
+ }
+
+ void toMap(Map<String, dynamic> map) {
+ // please set outside: map[':id'] = primaryKey;
+ map[':name'] = name;
+ map[':changedBy'] = GlobalData.loginUserName;
+ }
}
}
class _EditRolePageState extends EditRoleCustom {
- _EditRolePageState(int primaryKey) : super(primaryKey);
+ _EditRolePageState(int primaryKey): super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// It will never overridden by the meta_tool.
import 'package:flutter/material.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';
class ListRoleCustom extends State<ListRolePage> {
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateRole');
+ final textController = TextEditingController();
ListRoleCustom();
@override
Widget build(BuildContext context) {
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 rows = attendedPage!.getRows(
+ columnList: 'role_id;role_name',
+ what: 'query',
+ parameters: {
+ 'module': 'Roles',
+ 'sql': 'list',
+ 'offset': '0',
+ 'size': '10',
+ ':text': _fieldData.text,
+ },
+ onDone: () => setState(() => 1),
+ routeEdit: '/Roles/edit',
+ context: context);
+ final table = DataTable(
+ columns: <DataColumn>[
+ DataColumn(
+ label: Text(i18n.tr('d;Name')),
+ ),
+ ],
+ rows: rows,
+ );
+ final frameWidget = Column(children: [
+ form,
+ SizedBox(height: padding),
+ SizedBox(width: double.infinity, child: table),
+ ]);
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Role data')),
+ appBar: globalData.appBarBuilder(i18n.tr('Overview roles')),
drawer: globalData.drawerBuilder(context),
- body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {
+ globalData.navigate(context, '/Roles/create');
+ },
+ child: const Icon(Icons.add),
+ //backgroundColor: Colors.green,
+ ),
+ body: SafeArea(child: frameWidget));
return rc;
}
+ @override
+ void dispose() {
+ helperDummyUsage();
+ globalWidgetDummyUsage();
+ textController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
}
+
+ void search() {
+ attendedPage!.pageStates.dbDataState.clear();
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ setState(() => 1);
+ }
+ }
+}
+
+class _FieldData {
+ String text = '';
}
}
class _ListRolePageState extends ListRoleCustom {
- _ListRolePageState() : super();
+ _ListRolePageState(): super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
import '../../base/defines.dart';
import '../../base/helper.dart';
import '../../persistence/data_record.dart';
-
-class RoleData extends DataRecord<int> {
+class RoleData extends DataRecord<int>{
int? id;
String? name;
DateTime? created;
String? createdBy;
DateTime? changed;
String? changedBy;
- RoleData(
- {this.id,
- this.name,
- this.created,
- this.createdBy,
- this.changed,
- this.changedBy});
+ RoleData({
+ this.id, this.name, this.created, this.createdBy, this.changed, this.changedBy});
RoleData.createFromMap(DataMap map) {
fromMap(map);
}
@override
void fromMap(DataMap map) {
- id = map.containsKey('role_id')
- ? valueOf(DataType.reference, map['role_id'])
- : null;
- name = map.containsKey('role_name')
- ? valueOf(DataType.string, map['role_name'])
- : null;
- created = map.containsKey('role_created')
- ? valueOf(DataType.datetime, map['role_created'])
- : null;
- createdBy = map.containsKey('role_createdby')
- ? valueOf(DataType.string, map['role_createdby'])
- : null;
- changed = map.containsKey('role_changed')
- ? valueOf(DataType.datetime, map['role_changed'])
- : null;
- changedBy = map.containsKey('role_changedby')
- ? valueOf(DataType.string, map['role_changedby'])
- : null;
+ id = map.containsKey('role_id') ? fromString(map['role_id'], dataType: DataType.reference) : null;
+ 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) : 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) : null;
+ changedBy = map.containsKey('role_changedby') ? fromString(map['role_changedby'], dataType: DataType.string) : null;
}
-
@override
int keyOf() {
return id ?? 0;
}
-
@override
- String nameOfKey() {
+ String nameOfKey(){
return 'role_id';
}
-
static DataType? dataTypeOf(String name) {
DataType? rc;
- switch (name) {
- case 'id':
- rc = DataType.reference;
- break;
- case 'name':
- rc = DataType.string;
- break;
- case 'created':
- rc = DataType.datetime;
- break;
- case 'createdBy':
- rc = DataType.string;
- break;
- case 'changed':
- rc = DataType.datetime;
- break;
- case 'changedBy':
- rc = DataType.string;
- break;
- default:
- break;
+ switch(name){
+ case 'id':
+ rc = DataType.reference;
+ break;
+ case 'name':
+ rc = DataType.string;
+ break;
+ case 'created':
+ rc = DataType.datetime;
+ break;
+ case 'createdBy':
+ rc = DataType.string;
+ break;
+ case 'changed':
+ rc = DataType.datetime;
+ break;
+ case 'changedBy':
+ rc = DataType.string;
+ break;
+ default:
+ break;
}
return rc;
}
-
@override
DataMap toMap({DataMap? map, bool clear = true}) {
map ??= DataMap();
// 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_structure_page.dart';
final i18n = I18N();
-class CreateStructureCustom extends State<CreateStructurePage> {
+class CreateStructureCustom extends State<CreateStructurePage> with MessageLine {
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateStructure');
+ final scopeController = TextEditingController();
+ final nameController = TextEditingController();
+ final valueController = TextEditingController();
+ final positionController = TextEditingController();
CreateStructureCustom();
@override
Widget build(BuildContext context) {
final padding = GlobalThemeData.padding;
+ scopeController.text = _fieldData.scope;
+ nameController.text = _fieldData.name;
+ valueController.text = _fieldData.value;
+ positionController.text = asString(_fieldData.position);
+ final formItems = <FormItem>[
+ FormItem(
+ TextFormField(
+ controller: scopeController,
+ decoration: InputDecoration(labelText: i18n.tr('Scope')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.scope = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: nameController,
+ decoration: InputDecoration(labelText: i18n.tr('Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.name = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: valueController,
+ decoration: InputDecoration(labelText: i18n.tr('Value')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.value = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: positionController,
+ decoration: InputDecoration(labelText: i18n.tr('Position')),
+ onSaved: (value) => _fieldData.position = fromString(value ?? '', dataType: DataType.int)
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Structures/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Structure data')),
+ appBar: globalData.appBarBuilder(i18n.tr('New Structure')),
drawer: globalData.drawerBuilder(context),
body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ child: 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;
}
void initState() {
super.initState();
}
+
+ void store() {
+ final parameters = <String, dynamic>{
+ 'module': 'Structures',
+ '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, '/Structures/edit;$id');
+ }
+ }
+ });
+ }
+
+ void verifyAndStore() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ store();
+ }
+ }
+
+ @override
+ void dispose() {
+ scopeController.dispose();
+ nameController.dispose();
+ valueController.dispose();
+ positionController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String scope = '';
+ String name = '';
+ String value = '';
+ int position = 0;
+
+
+ void toMap(Map<String, dynamic> map) {
+ map[':scope'] = scope;
+ map[':name'] = name;
+ map[':value'] = value;
+ map[':position'] = asString(position);
+ map[':createdBy'] = GlobalData.loginUserName;
+ }
}
@override
_CreateStructurePageState createState() {
final rc = _CreateStructurePageState();
- rc.attendedPage = AttendedPage(
- this, rc, GlobalData(), StructureMeta.instance, pageStates);
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), StructureMeta.instance, pageStates);
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _CreateStructurePageState extends CreateStructureCustom {
- _CreateStructurePageState() : super();
+ _CreateStructurePageState(): super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// 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 'delete_structure_page.dart';
final i18n = I18N();
-class DeleteStructureCustom extends State<DeleteStructurePage> {
+class DeleteStructureCustom extends State<DeleteStructurePage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'DeleteStructure');
+ final scopeController = TextEditingController();
+ final nameController = TextEditingController();
+ final valueController = TextEditingController();
+ final positionController = TextEditingController();
DeleteStructureCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
final padding = GlobalThemeData.padding;
+ attendedPage?.loadRecord(
+ name: 'record',
+ reload: () => setState(() => 1),
+ onDone: (record) => _fieldData.fromMap(record),
+ parameters: {'module': 'Structures', 'sql': 'byId', ':id': primaryKey});
+ scopeController.text = _fieldData.scope;
+ nameController.text = _fieldData.name;
+ valueController.text = _fieldData.value;
+ positionController.text = asString(_fieldData.position);
+ final formItems = <FormItem>[
+ FormItem(
+ TextFormField(
+ controller: scopeController,
+ decoration: InputDecoration(labelText: i18n.tr('Scope')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.scope = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: nameController,
+ decoration: InputDecoration(labelText: i18n.tr('Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.name = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: valueController,
+ decoration: InputDecoration(labelText: i18n.tr('Value')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.value = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: positionController,
+ decoration: InputDecoration(labelText: i18n.tr('Position')),
+ onSaved: (value) => _fieldData.position = fromString(value ?? '', dataType: DataType.int)
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => verifyAndDelete(),
+ child: Text(i18n.tr('Delete'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Structures/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Structure data')),
+ appBar: globalData.appBarBuilder(i18n.tr('Delete Structure')),
drawer: globalData.drawerBuilder(context),
body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ child: 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;
}
void initState() {
super.initState();
}
+
+ void delete() {
+ final parameters = <String, dynamic>{
+ 'module': 'Structures',
+ 'sql': 'delete',
+ };
+ parameters[':id'] = primaryKey;
+ globalData.restPersistence!
+ .store(what: 'store', map: parameters)
+ .then((answer) {
+ globalData.navigate(context, '/Structures/list');
+ });
+ }
+
+ void verifyAndDelete() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ delete();
+ }
+ }
+
+ @override
+ void dispose() {
+ scopeController.dispose();
+ nameController.dispose();
+ valueController.dispose();
+ positionController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String scope = '';
+ String name = '';
+ String value = '';
+ int position = 0;
+
+ void fromMap(Map<String, dynamic> map) {
+ scope = map['structure_scope'];
+ name = map['structure_name'];
+ value = map['structure_value'];
+ position = map['structure_position'];
+ }
}
@override
_DeleteStructurePageState createState() {
final rc = _DeleteStructurePageState(this.primaryKey);
- rc.attendedPage = AttendedPage(
- this, rc, GlobalData(), StructureMeta.instance, pageStates);
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), StructureMeta.instance, pageStates);
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _DeleteStructurePageState extends DeleteStructureCustom {
- _DeleteStructurePageState(int primaryKey) : super(primaryKey);
+ _DeleteStructurePageState(int primaryKey): super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// 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 'edit_structure_page.dart';
final i18n = I18N();
-class EditStructureCustom extends State<EditStructurePage> {
+class EditStructureCustom extends State<EditStructurePage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'EditStructure');
+ final scopeController = TextEditingController();
+ final nameController = TextEditingController();
+ final valueController = TextEditingController();
+ final positionController = TextEditingController();
EditStructureCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
final padding = GlobalThemeData.padding;
+ attendedPage?.loadRecord(
+ name: 'record',
+ reload: () => setState(() => 1),
+ onDone: (record) => _fieldData.fromMap(record),
+ parameters: {'module': 'Structures', 'sql': 'byId', ':id': primaryKey});
+ scopeController.text = _fieldData.scope;
+ nameController.text = _fieldData.name;
+ valueController.text = _fieldData.value;
+ positionController.text = asString(_fieldData.position);
+ final formItems = <FormItem>[
+ FormItem(
+ TextFormField(
+ controller: scopeController,
+ decoration: InputDecoration(labelText: i18n.tr('Scope')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.scope = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: nameController,
+ decoration: InputDecoration(labelText: i18n.tr('Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.name = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: valueController,
+ decoration: InputDecoration(labelText: i18n.tr('Value')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.value = value ?? ''
+ ),
+ weight: 6),
+ FormItem(
+ TextFormField(
+ controller: positionController,
+ decoration: InputDecoration(labelText: i18n.tr('Position')),
+ onSaved: (value) => _fieldData.position = fromString(value ?? '', dataType: DataType.int)
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
+ weight: 8,
+ gapAbove: 2 * padding),
+ FormItem(
+ ElevatedButton(
+ onPressed: () {
+ attendedPage!.pageStates.dbDataState.clear();
+ globalData.navigate(context, '/Structures/list');
+ },
+ child: Text(i18n.tr('Cancel')),
+ ),
+ weight: 4)
+ ];
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Structure data')),
+ appBar: globalData.appBarBuilder(i18n.tr('Change Structure')),
drawer: globalData.drawerBuilder(context),
body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ child: 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;
}
void initState() {
super.initState();
}
+
+ void store() {
+ final parameters = <String, dynamic>{
+ 'module': 'Structures',
+ 'sql': 'update',
+ };
+ parameters[':id'] = primaryKey;
+ _fieldData.toMap(parameters);
+ globalData.restPersistence!
+ .store(what: 'store', map: parameters)
+ .then((answer) {});
+ }
+
+ void verifyAndStore() {
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ store();
+ }
+ }
+
+ @override
+ void dispose() {
+ scopeController.dispose();
+ nameController.dispose();
+ valueController.dispose();
+ positionController.dispose();
+ super.dispose();
+ }
+}
+
+class _FieldData {
+ String scope = '';
+ String name = '';
+ String value = '';
+ int position = 0;
+
+ void fromMap(Map<String, dynamic> map) {
+ scope = map['structure_scope'];
+ name = map['structure_name'];
+ value = map['structure_value'];
+ position = map['structure_position'];
+ }
+
+ void toMap(Map<String, dynamic> map) {
+ // please set outside: map[':id'] = primaryKey;
+ map[':scope'] = scope;
+ map[':name'] = name;
+ map[':value'] = value;
+ map[':position'] = asString(position);
+ map[':changedBy'] = GlobalData.loginUserName;
+ }
}
@override
_EditStructurePageState createState() {
final rc = _EditStructurePageState(this.primaryKey);
- rc.attendedPage = AttendedPage(
- this, rc, GlobalData(), StructureMeta.instance, pageStates);
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), StructureMeta.instance, pageStates);
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _EditStructurePageState extends EditStructureCustom {
- _EditStructurePageState(int primaryKey) : super(primaryKey);
+ _EditStructurePageState(int primaryKey): super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// It will never overridden by the meta_tool.
import 'package:flutter/material.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';
class ListStructureCustom extends State<ListStructurePage> {
final globalData = GlobalData();
AttendedPage? attendedPage;
-
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateStructure');
+ final textController = TextEditingController();
ListStructureCustom();
@override
Widget build(BuildContext context) {
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 rows = attendedPage!.getRows(
+ columnList: 'structure_id;structure_scope;structure_name;structure_value;structure_position',
+ what: 'query',
+ parameters: {
+ 'module': 'Structures',
+ 'sql': 'list',
+ 'offset': '0',
+ 'size': '10',
+ ':text': _fieldData.text,
+ },
+ onDone: () => setState(() => 1),
+ routeEdit: '/Structures/edit',
+ context: context);
+ final table = DataTable(
+ columns: <DataColumn>[
+ DataColumn(
+ label: Text(i18n.tr('d;Scope;Name;Value;Position')),
+ ),
+ ],
+ rows: rows,
+ );
+ final frameWidget = Column(children: [
+ form,
+ SizedBox(height: padding),
+ SizedBox(width: double.infinity, child: table),
+ ]);
final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Structure data')),
+ appBar: globalData.appBarBuilder(i18n.tr('Overview structures')),
drawer: globalData.drawerBuilder(context),
- body: SafeArea(
- child: WidgetForm.flexibleGridAttended(
- attendedPage!.attendedWidgets(),
- screenWidth: attendedPage!.pageStates.screenWidth,
- padding: padding)));
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {
+ globalData.navigate(context, '/Structures/create');
+ },
+ child: const Icon(Icons.add),
+ //backgroundColor: Colors.green,
+ ),
+ body: SafeArea(child: frameWidget));
return rc;
}
+ @override
+ void dispose() {
+ helperDummyUsage();
+ globalWidgetDummyUsage();
+ textController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
}
+
+ void search() {
+ attendedPage!.pageStates.dbDataState.clear();
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ setState(() => 1);
+ }
+ }
+}
+
+class _FieldData {
+ String text = '';
}
@override
_ListStructurePageState createState() {
final rc = _ListStructurePageState();
- rc.attendedPage = AttendedPage(
- this, rc, GlobalData(), StructureMeta.instance, pageStates);
+ rc.attendedPage =
+ AttendedPage(this, rc, GlobalData(), StructureMeta.instance, pageStates);
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _ListStructurePageState extends ListStructureCustom {
- _ListStructurePageState() : super();
+ _ListStructurePageState(): super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
--- /dev/null
+// 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 StructureData extends DataRecord<int>{
+ int? id;
+ String? scope;
+ String? name;
+ String? value;
+ int? position;
+ DateTime? created;
+ String? createdBy;
+ DateTime? changed;
+ String? changedBy;
+ StructureData({
+ this.id, this.scope, this.name, this.value, this.position, this.created, this.createdBy, this.changed, this.changedBy});
+ StructureData.createFromMap(DataMap map) {
+ fromMap(map);
+ }
+ @override
+ void fromMap(DataMap map) {
+ id = map.containsKey('structure_id') ? fromString(map['structure_id'], dataType: DataType.reference) : null;
+ scope = map.containsKey('structure_scope') ? fromString(map['structure_scope'], dataType: DataType.string) : null;
+ name = map.containsKey('structure_name') ? fromString(map['structure_name'], dataType: DataType.string) : null;
+ value = map.containsKey('structure_value') ? fromString(map['structure_value'], dataType: DataType.string) : null;
+ 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) : 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) : null;
+ changedBy = map.containsKey('structure_changedby') ? fromString(map['structure_changedby'], dataType: DataType.string) : null;
+ }
+ @override
+ int keyOf() {
+ return id ?? 0;
+ }
+ @override
+ String nameOfKey(){
+ return 'structure_id';
+ }
+ static DataType? dataTypeOf(String name) {
+ DataType? rc;
+ switch(name){
+ case 'id':
+ rc = DataType.reference;
+ break;
+ case 'scope':
+ rc = DataType.string;
+ break;
+ case 'name':
+ rc = DataType.string;
+ break;
+ case 'value':
+ rc = DataType.string;
+ break;
+ case 'position':
+ rc = DataType.int;
+ break;
+ case 'created':
+ rc = DataType.datetime;
+ break;
+ case 'createdBy':
+ rc = DataType.string;
+ break;
+ case 'changed':
+ 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['structure_id'] = id;
+ map['structure_scope'] = scope;
+ map['structure_name'] = name;
+ map['structure_value'] = value;
+ map['structure_position'] = position;
+ map['structure_created'] = created;
+ map['structure_createdby'] = createdBy;
+ map['structure_changed'] = changed;
+ map['structure_changedby'] = changedBy;
+ return map;
+ }
+}
// 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';
controller: nameController,
decoration: InputDecoration(labelText: i18n.tr('Name')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.name = value ?? '',
+ onSaved: (value) => _fieldData.name = value ?? ''
),
weight: 6),
FormItem(
controller: displayNameController,
decoration: InputDecoration(labelText: i18n.tr('Display name')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.displayName = value ?? '',
+ onSaved: (value) => _fieldData.displayName = value ?? ''
),
weight: 6),
FormItem(
controller: emailController,
decoration: InputDecoration(labelText: i18n.tr('EMail')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.email = value ?? '',
+ onSaved: (value) => _fieldData.email = value ?? ''
),
weight: 6),
FormItem(
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
String email = '';
int role = 0;
+
void toMap(Map<String, dynamic> map) {
map[':name'] = name;
map[':displayName'] = displayName;
map[':email'] = email;
- map[':role'] = role;
+ map[':role'] = asString(role);
map[':createdBy'] = GlobalData.loginUserName;
}
}
}
class _CreateUserPageState extends CreateUserCustom {
- _CreateUserPageState() : super();
+ _CreateUserPageState(): super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// 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';
controller: nameController,
decoration: InputDecoration(labelText: i18n.tr('Name')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.name = value ?? '',
+ onSaved: (value) => _fieldData.name = value ?? ''
),
weight: 6),
FormItem(
controller: displayNameController,
decoration: InputDecoration(labelText: i18n.tr('Display name')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.displayName = value ?? '',
+ onSaved: (value) => _fieldData.displayName = value ?? ''
),
weight: 6),
FormItem(
controller: emailController,
decoration: InputDecoration(labelText: i18n.tr('EMail')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.email = value ?? '',
+ onSaved: (value) => _fieldData.email = value ?? ''
),
weight: 6),
FormItem(
}
class _DeleteUserPageState extends DeleteUserCustom {
- _DeleteUserPageState(int primaryKey) : super(primaryKey);
+ _DeleteUserPageState(int primaryKey): super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
// 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';
controller: nameController,
decoration: InputDecoration(labelText: i18n.tr('Name')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.name = value ?? '',
+ onSaved: (value) => _fieldData.name = value ?? ''
),
weight: 6),
FormItem(
controller: displayNameController,
decoration: InputDecoration(labelText: i18n.tr('Display name')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.displayName = value ?? '',
+ onSaved: (value) => _fieldData.displayName = value ?? ''
),
weight: 6),
FormItem(
controller: emailController,
decoration: InputDecoration(labelText: i18n.tr('EMail')),
validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.email = value ?? '',
+ onSaved: (value) => _fieldData.email = value ?? ''
),
weight: 6),
FormItem(
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(),
+ child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
map[':name'] = name;
map[':displayName'] = displayName;
map[':email'] = email;
- map[':role'] = role;
+ map[':role'] = asString(role);
map[':changedBy'] = GlobalData.loginUserName;
}
}
}
class _EditUserPageState extends EditUserCustom {
- _EditUserPageState(int primaryKey) : super(primaryKey);
+ _EditUserPageState(int primaryKey): super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
TextFormField(
controller: textController,
decoration: InputDecoration(labelText: i18n.tr('Text')),
- onSaved: (value) => _fieldData.text = value ?? '',
+ onSaved: (value) => _fieldData.text = value ?? ''
),
weight: 6),
FormItem(
@override
void dispose() {
+ helperDummyUsage();
+ globalWidgetDummyUsage();
textController.dispose();
super.dispose();
}
}
class _ListUserPageState extends ListUserCustom {
- _ListUserPageState() : super();
+ _ListUserPageState(): super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
import '../../base/defines.dart';
import '../../base/helper.dart';
import '../../persistence/data_record.dart';
-
-class UserData extends DataRecord<int> {
+class UserData extends DataRecord<int>{
int? id;
String? name;
String? displayName;
String? createdBy;
DateTime? changed;
String? changedBy;
- UserData(
- {this.id,
- this.name,
- this.displayName,
- this.email,
- this.role,
- this.created,
- this.createdBy,
- this.changed,
- this.changedBy});
+ UserData({
+ this.id, this.name, this.displayName, this.email, this.role, this.created, this.createdBy, this.changed, this.changedBy});
UserData.createFromMap(DataMap map) {
fromMap(map);
}
@override
void fromMap(DataMap map) {
- id = map.containsKey('user_id')
- ? valueOf(DataType.reference, map['user_id'])
- : null;
- name = map.containsKey('user_name')
- ? valueOf(DataType.string, map['user_name'])
- : null;
- displayName = map.containsKey('user_displayname')
- ? valueOf(DataType.string, map['user_displayname'])
- : null;
- email = map.containsKey('user_email')
- ? valueOf(DataType.string, map['user_email'])
- : null;
- role = map.containsKey('user_role')
- ? valueOf(DataType.reference, map['user_role'])
- : null;
- created = map.containsKey('user_created')
- ? valueOf(DataType.datetime, map['user_created'])
- : null;
- createdBy = map.containsKey('user_createdby')
- ? valueOf(DataType.string, map['user_createdby'])
- : null;
- changed = map.containsKey('user_changed')
- ? valueOf(DataType.datetime, map['user_changed'])
- : null;
- changedBy = map.containsKey('user_changedby')
- ? valueOf(DataType.string, map['user_changedby'])
- : null;
+ id = map.containsKey('user_id') ? fromString(map['user_id'], dataType: DataType.reference) : null;
+ name = map.containsKey('user_name') ? fromString(map['user_name'], dataType: DataType.string) : null;
+ displayName = map.containsKey('user_displayname') ? fromString(map['user_displayname'], dataType: DataType.string) : null;
+ email = map.containsKey('user_email') ? fromString(map['user_email'], dataType: DataType.string) : null;
+ 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) : 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) : null;
+ changedBy = map.containsKey('user_changedby') ? fromString(map['user_changedby'], dataType: DataType.string) : null;
}
-
@override
int keyOf() {
return id ?? 0;
}
-
@override
- String nameOfKey() {
+ String nameOfKey(){
return 'user_id';
}
-
static DataType? dataTypeOf(String name) {
DataType? rc;
- switch (name) {
- case 'id':
- rc = DataType.reference;
- break;
- case 'name':
- rc = DataType.string;
- break;
- case 'displayName':
- rc = DataType.string;
- break;
- case 'email':
- rc = DataType.string;
- break;
- case 'role':
- rc = DataType.reference;
- break;
- case 'created':
- rc = DataType.datetime;
- break;
- case 'createdBy':
- rc = DataType.string;
- break;
- case 'changed':
- rc = DataType.datetime;
- break;
- case 'changedBy':
- rc = DataType.string;
- break;
- default:
- break;
+ switch(name){
+ case 'id':
+ rc = DataType.reference;
+ break;
+ case 'name':
+ rc = DataType.string;
+ break;
+ case 'displayName':
+ rc = DataType.string;
+ break;
+ case 'email':
+ rc = DataType.string;
+ break;
+ case 'role':
+ rc = DataType.reference;
+ break;
+ case 'created':
+ rc = DataType.datetime;
+ break;
+ case 'createdBy':
+ rc = DataType.string;
+ break;
+ case 'changed':
+ rc = DataType.datetime;
+ break;
+ case 'changedBy':
+ rc = DataType.string;
+ break;
+ default:
+ break;
}
return rc;
}
-
@override
DataMap toMap({DataMap? map, bool clear = true}) {
map ??= DataMap();
{'module': 'global', 'sql': 'comboRoles'}, onDone);
}
+/// This function is only used to avoid compiler warning "unused import"
+/// for generated code.
+void globalWidgetDummyUsage() {
+ // nothing to do
+}
+
List<DropdownMenuItem<int>>? _combo(String name, String columnValue,
String columnText, String? textUndefined, AttendedPage attendedPage) {
final records = attendedPage.pageStates.dbDataState.listResponse(name);
final type = item.dataType.toString();
//id = data.containsKey('id') ? int.tryParse(data['id']) : null;
buffer.writeln(
- " ${item.name} = map.containsKey('$name') ? valueOf($type, "
- "map['$name']) : null;");
+ " ${item.name} = map.containsKey('$name') ? "
+ "fromString(map['$name'], dataType: $type) : null;");
}
buffer.writeln(' }');
final name = primary == null ? 'id' : primary.name;
GeneratorBase.classToFilename(module.moduleNameSingular) +
'_data.dart';
final directory = name.toLowerCase();
- writeFile('../../lib/page/$directory/$filename',
+ writeFile('../lib/page/$directory/$filename',
generator.createModuleData(module));
}
}
logger.log(line);
}
- String toCamelCase(String name) {
- final rc = name.isEmpty ? '' : (name[0].toUpperCase() + name.substring(1));
- return rc;
- }
-
/// Writes a given [contents] into a file named [filename];
void writeFile(String filename, String contents) {
logger.log('creating $filename ...');
import 'package:dart_bones/dart_bones.dart';
import '../lib/base/defines.dart';
+import '../lib/base/helper.dart';
import '../lib/meta/module_meta_data.dart';
import '../lib/meta/modules.dart';
import 'generator.dart';
@override
void dispose() {
+ helperDummyUsage();
+ globalWidgetDummyUsage();
#DISPOSE_CONTROLLER super.dispose();
}
// 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';
#DEF_FIELD
#FROM_MAP#TO_MAP}
''';
- static final templateStorageDoneCreate =
- '''
+ static final templateStorageDoneCreate = '''
if (answer.startsWith('id:')) {
final id = int.tryParse(answer.substring(3));
for (var field in page.fields) {
if (field.widgetType == WidgetType.property &&
(field as PropertyMetaData).displayType == DisplayType.text) {
- buffer.writeln(
- ' ${field.name}Controller.text = _fieldData.${field.name};');
+ var value = '_fieldData.${field.name}';
+ if (field.dataType != DataType.string) {
+ value = 'asString($value)';
+ }
+ buffer.writeln(' ${field.name}Controller.text = $value;');
}
}
return buffer.toString();
value = '0';
break;
case DataType.date:
- type = 'Date';
- value = 'Date()';
- break;
case DataType.datetime:
- type = 'DateTime';
- value = 'DateTime()';
+ type = 'DateTime?';
+ value = 'null';
break;
case DataType.string:
type = 'String';
break;
// throw FormatException('buildDefinitionFields(): missing ${field2.dataType}');
}
- buffer.writeln(" $type $name = $value;");
+ if (value == 'null') {
+ buffer.writeln(" $type $name;");
+ } else {
+ buffer.writeln(" $type $name = $value;");
+ }
}
return buffer.toString();
}
}
validator += ' ]),\n';
}
+ final value = field.dataType == DataType.string
+ ? "value ?? ''"
+ : (field.dataType == DataType.date
+ ? "fromString(value ?? '', dataType: DataType.date)"
+ : "fromString(value ?? '', dataType: ${field.dataType})");
rc = '''^TextFormField(
#CONTR^ decoration: InputDecoration(labelText: i18n.tr('${field.label}')),
-#VALIDATOR^ onSaved: (value) => _fieldData.$name = value ?? '',
+#VALIDATOR^ onSaved: (value) => _fieldData.$name = $value
^)'''
.replaceFirst('#CONTR',
withController ? '^ controller: ${name}Controller,\n' : '')
? '.toString()'
: '';
var value = '_fieldData.$name$suffix';
- if (field is PropertyMetaData && field.hasOption(':pattern')){
+ if (field is PropertyMetaData && field.hasOption(':pattern')) {
value = 'asPattern($value)';
}
buffer.writeln(" ':$name': $value,");
String buildToMap(PageMetaData page) {
String? rc;
if (page.pageType == PageType.edit || page.pageType == PageType.create) {
- final buffer = StringBuffer('\n void toMap(Map<String, dynamic> map) {\n');
+ final buffer =
+ StringBuffer('\n void toMap(Map<String, dynamic> map) {\n');
if (page.pageType == PageType.edit) {
buffer.writeln(" // please set outside: map[':id'] = primaryKey;");
}
continue;
}
final name = field.name;
- buffer.writeln(" map[':$name'] = $name;");
+ final value =
+ field.dataType == DataType.string ? name : 'asString($name)';
+ buffer.writeln(" map[':$name'] = $value;");
}
buffer.writeln(" map[':#'] = GlobalData.loginUserName;".replaceFirst(
'#', page.pageType == PageType.edit ? 'changedBy' : 'createdBy'));
/// Handles the SQL generation part of the generator.
class SqlGenerator extends GeneratorBase {
+ static final regExprParameters = RegExp(r'(:\w+)');
+
SqlGenerator(BaseLogger logger) : super(logger);
/// Returns a DDL statement creating the database table of the [module].
for (var page in listPages) {
if (page is ListPageMetaData) {
var whereCondition = page.whereCondition;
- if (whereCondition.endsWith('\n')){
- whereCondition = whereCondition.substring(0, whereCondition.length - 1);
+ if (whereCondition.endsWith('\n')) {
+ whereCondition =
+ whereCondition.substring(0, whereCondition.length - 1);
}
String selectItems2 = '';
var selectItems =
buffer.writeln(''' type: list
parameters: [$parameters]
order: "$order"
- sql: "SELECT
-$selectItems t0.*$selectItems2
- FROM $tableName t0
-$joins$whereCondition ;"''');
+ 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');
}
}
}
buffer.write(sqlText);
var items = module.standardColumns('changedBy');
var parameters = addToBuffer(' parameters: [', maxLength: 80);
- var assignments = addToBuffer(' ', maxLength: 80);
+ var assignments = StringBuffer();
var firstParameter = true;
- var firstAssignment = true;
for (var item in items) {
if (!item.hasOption('hidden')) {
addToBuffer('":${item.name}"',
separator: firstParameter ? null : ',',
indent: 4,
buffer: parameters);
- firstParameter = false;
if (!item.hasOption('primary')) {
- addToBuffer('${item.columnName}=:${item.name}',
- maxLength: 80,
- separator: firstAssignment ? null : ',',
- indent: 4,
- buffer: assignments);
- firstAssignment = false;
+ assignments.writeln(' ${item.columnName}=:${item.name},');
}
+ firstParameter = false;
}
}
parameters.write(']');
var item = module.properties['changed']!;
- addToBuffer('${item.columnName}=NOW()',
- maxLength: 80, separator: ',', indent: 4, buffer: assignments);
+ assignments.write(' ${item.columnName}=NOW()');
// parameters: [":id", ":name", ":displayname", ":email", ":changedby"]
buffer.writeln(parameters);
- buffer.write(' sql: "UPDATE $tableName SET\n');
+ 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
- buffer.write(' WHERE ${list[0].columnName}=:${list[0].name};"\n');
+ buffer.write(' WHERE ${list[0].columnName}=:${list[0].name};\n');
items = module.standardColumns('createdBy');
parameters = addToBuffer(' parameters: [', maxLength: 80);
- final sql1 = addToBuffer(' sql: "INSERT INTO $tableName(', maxLength: 80);
- final sql2 = addToBuffer(' VALUES(', maxLength: 80);
+ final sql1 = StringBuffer(' sql: |\n');
+ addToBuffer(' INSERT INTO $tableName(',
+ maxLength: 80, buffer: sql1, indent: 4);
+ final sql2 = addToBuffer(
+ ' VALUES(',
+ maxLength: 80,
+ );
var first = true;
for (var item in items) {
if (!item.hasOption('primary')) {
item = module.properties['created']!;
addToBuffer('${item.columnName})',
maxLength: 80, separator: ',', indent: 4, buffer: sql1);
- addToBuffer('NOW());"',
+ addToBuffer('NOW());',
maxLength: 80, separator: ',', indent: 4, buffer: sql2);
// parameters: [":name", ":displayname", ":email", ":changedby"]
buffer.write('''insert:
buffer.writeln(sql2);
return buffer.toString();
}
- static final regExprParameters = RegExp(r'(:\w+)');
+
/// Searches the parameters in the [whereCondition] and checks it against
/// the [fields].
String findParameters(String whereCondition, List<WidgetMetaData> fields) {
- final names = regExprParameters.allMatches(whereCondition)
+ final names = regExprParameters
+ .allMatches(whereCondition)
.map((element) => element.group(1))
- .toSet().toList();
+ .toSet()
+ .toList();
return '"' + names.join('","') + '"';
}
--- /dev/null
+## This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+#Sat Oct 16 12:51:13 CEST 2021
+sdk.dir=/opt/android
-name: meta-tool
+name: meta_tool
description: A generator of programming code for building Flutter apps.
version: 1.0.0
homepage: https://github.com/hamatoma/exhibition
environment:
- sdk: ">=2.12.0 <3.0.0"
+# sdk: ">=2.15.0 <3.0.0"
+ sdk: ">=2.15.0-163.0.dev <3.0.0"
dependencies:
meta: ^1.7.0
sprintf: ^6.0.0
yaml: ^3.1.0
path: ^1.8.0
+ dart_bones: ^1.2.2
dev_dependencies:
pedantic: ^1.11.1
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+import 'package:test/test.dart';
+//import 'package:path/path.dart';
+
+import '../lib/base/defines.dart';
+import '../lib/base/helper.dart';
+import '../lib/base/i18n.dart';
+
+final i18n = I18N();
+
+void main() {
+ final logger = MemoryLogger(LEVEL_FINE);
+ I18N.internal(logger);
+ FileSync.initialize(logger);
+ //final fileSync = FileSync();
+ //final baseDir = init(logger);
+ //final targetDir = join(baseDir, nodeTarget);
+ //fileSync.ensureDirectory(targetDir);
+ group('fromString', () {
+ test('bool', () {
+ expect(fromString('T', dataType: DataType.bool, defaultValue: false), isTrue);
+ expect(fromString('F', dataType: DataType.bool, defaultValue: true), isFalse);
+ expect(fromString(i18n.tr('Yes'), dataType: DataType.bool, defaultValue: false), isTrue);
+ expect(fromString(i18n.tr('No'), dataType: DataType.bool, defaultValue: true), isFalse);
+ expect(fromString('', dataType: DataType.bool, defaultValue: false), isFalse);
+ expect(fromString('', dataType: DataType.bool, defaultValue: true), isTrue);
+ });
+ test('int', ()
+ {
+ expect(fromString('123', dataType: DataType.int, defaultValue: -1),
+ 123);
+ expect(fromString('-1234', dataType: DataType.int, defaultValue: -1),
+ -1234);
+ expect(fromString('', dataType: DataType.int, defaultValue: -1),
+ -1);
+ expect(fromString('a15', dataType: DataType.int, defaultValue: -1),
+ -1);
+ });
+ test('nat', ()
+ {
+ expect(fromString('123', dataType: DataType.nat, defaultValue: -1),
+ 123);
+ expect(fromString('-1234', dataType: DataType.nat, defaultValue: -1),
+ -1);
+ expect(fromString('', dataType: DataType.nat, defaultValue: -1),
+ -1);
+ expect(fromString('a15', dataType: DataType.nat, defaultValue: -1),
+ -1);
+ });
+ test('reference', ()
+ {
+ expect(fromString('123', dataType: DataType.reference, defaultValue: -1),
+ 123);
+ expect(fromString('-1234', dataType: DataType.reference, defaultValue: -1),
+ -1234);
+ expect(fromString('', dataType: DataType.reference, defaultValue: -1),
+ -1);
+ expect(fromString('a15', dataType: DataType.reference, defaultValue: -1),
+ -1);
+ });
+ test('float', ()
+ {
+ expect(fromString('123.76', dataType: DataType.float, defaultValue: -1),
+ 123.76);
+ expect(fromString('-4123.76', dataType: DataType.float, defaultValue: -1),
+ -4123.76);
+ expect(fromString('', dataType: DataType.float, defaultValue: -99999999),
+ -99999999);
+ expect(fromString('Nothing', dataType: DataType.float, defaultValue: -99999999),
+ -99999999);
+ });
+ test('currency', ()
+ {
+ expect(fromString('123.76', dataType: DataType.currency, defaultValue: -1),
+ 123.76);
+ expect(fromString('-4123.76', dataType: DataType.currency, defaultValue: -1),
+ -4123.76);
+ expect(fromString('', dataType: DataType.currency, defaultValue: -99999999),
+ -99999999);
+ expect(fromString('Nothing', dataType: DataType.currency, defaultValue: -99999999),
+ -99999999);
+ });
+ test('date', ()
+ {
+ expect(fromString('7.3.1987', dataType: DataType.date),
+ DateTime(1987, 3, 7));
+ expect(fromString('17.12.2035', dataType: DataType.date),
+ DateTime(2035, 12, 17));
+ expect(fromString('2012.6.2', dataType: DataType.date),
+ DateTime(2012, 6, 2));
+ expect(fromString('1923.10.31', dataType: DataType.date),
+ DateTime(1923, 10, 31));
+ expect(fromString('17.12.21', dataType: DataType.date),
+ isNull);
+ });
+ test('datetime', ()
+ {
+ expect(fromString('17.12.2035', dataType: DataType.datetime),
+ DateTime(2035, 12, 17));
+ expect(fromString('7.3.1987', dataType: DataType.datetime),
+ DateTime(1987, 3, 7));
+ expect(fromString('2012.6.2', dataType: DataType.datetime),
+ DateTime(2012, 6, 2));
+ expect(fromString('1923.10.31', dataType: DataType.datetime),
+ DateTime(1923, 10, 31));
+ expect(fromString('17.12.21', dataType: DataType.datetime),
+ isNull);
+ expect(fromString('7.3.1987T2:44', dataType: DataType.datetime),
+ DateTime(1987, 3, 7, 2, 44));
+ expect(fromString('17.12.2035 13:59:22', dataType: DataType.datetime),
+ DateTime(2035, 12, 17, 13, 59, 22));
+ expect(fromString('2012.6.2/23:59:59', dataType: DataType.datetime),
+ DateTime(2012, 6, 2, 23, 59, 59));
+ expect(fromString('1923.10.31-3:4', dataType: DataType.datetime),
+ DateTime(1923, 10, 31, 3, 4));
+ });
+ });
+ group('asPattern', () {
+ test('unchanged', () {
+ expect(asPattern('A test!123'), 'A test!123%');
+ });
+ test('with *', () {
+ expect(asPattern('*Wu*ff'), '%Wu%ff%');
+ });
+ test('empty', () {
+ expect(asPattern(''), '%');
+ });
+ test('with ?', () {
+ expect(asPattern('M??r'), 'M__r%');
+ });
+ test('mixed', () {
+ expect(asPattern('*M?i*r'), '%M_i%r%');
+ });
+ });
+ group('asString', () {
+ test('bool', () {
+ expect(asString(true), i18n.tr('Yes'));
+ expect(asString(false), i18n.tr('No'));
+ expect(asString(true, dbFormat: true), 'T');
+ expect(asString(false, dbFormat: true), 'F');
+ });
+ test('int', () {
+ expect(asString(12345), '12345');
+ expect(asString(-33), '-33');
+ expect(asString(-33, dbFormat: true), '-33');
+ expect(asString(884433, dbFormat: true), '884433');
+ });
+ test('double', () {
+ expect(asString(7733.0), '7733.00');
+ expect(asString(-123.77), '-123.77');
+ expect(asString(1E-99), '.00');
+ expect(asString(7733.0, dbFormat: true), '7733.00');
+ expect(asString(-123.77, dbFormat: true), '-123.77');
+ });
+ test('Date', () {
+ expect(asString(DateTime(2021, 10, 3), dateOnly: true), '03.10.2021');
+ expect(
+ asString(DateTime(2021, 10, 3, 9, 33), dateOnly: true), '03.10.2021');
+ expect(asString(DateTime(2021, 10, 3, 9, 33), dateOnly: false),
+ '03.10.2021 09:33');
+ expect(asString(DateTime(2021, 10, 3, 9, 33, 14), dateOnly: false),
+ '03.10.2021 09:33');
+ expect(
+ asString(DateTime(2021, 10, 3, 9, 33, 14),
+ dateOnly: false, withSeconds: true),
+ '03.10.2021 09:33:14');
+ expect(asString(DateTime(2021, 7, 3), dbFormat: true, dateOnly: true),
+ '2021-07-03');
+ expect(
+ asString(DateTime(2021, 10, 3, 9, 33),
+ dbFormat: true, dateOnly: true),
+ '2021-10-03');
+ expect(
+ asString(DateTime(2021, 7, 3, 9, 33),
+ dbFormat: true, dateOnly: false),
+ '2021-07-03 09:33:00');
+ expect(
+ asString(DateTime(2021, 10, 3, 9, 33, 14),
+ dbFormat: true, dateOnly: false),
+ '2021-10-03 09:33:14');
+ expect(
+ asString(DateTime(2021, 10, 3, 9, 33, 14),
+ dbFormat: true, dateOnly: false, withSeconds: true),
+ '2021-10-03 09:33:14');
+ });
+ test('string', () {
+ expect(asString('A test!123'), 'A test!123');
+ expect(asString('A test!123', dbFormat: true), 'A test!123');
+ });
+ test('string', () {
+ expect(asString('A test!123'), 'A test!123');
+ });
+ test('string', () {
+ expect(asString('A test!123'), 'A test!123');
+ });
+ });
+}
--- /dev/null
+---
+# DO NOT CHANGE. This file is created by the meta_tool
+# SQL statements of the module "Benchmarks":
+
+module: Benchmarks
+list:
+ type: list
+ parameters: [":text"]
+ order: "benchmark_id"
+ sql: |
+ SELECT
+ t0.* FROM benchmarks t0
+ WHERE
+ (:text='' OR benchmark_lastname like :text
+ OR benchmark_firstname like :text)
+byId:
+ type: record
+ parameters: [ ":id" ]
+ sql: "SELECT * FROM benchmarks WHERE benchmark_id=:id;"
+delete:
+ type: delete
+ parameters: [ ":id" ]
+ sql: "DELETE * FROM benchmarks WHERE benchmark_id=:id;"
+update:
+ type: update
+ parameters: [":id",":lastName",":firstName",":email",":birthday",":active",
+ ":weight",":income"]
+ sql: |
+ UPDATE benchmarks SET
+ benchmark_lastname=:lastName,
+ benchmark_firstname=:firstName,
+ benchmark_email=:email,
+ benchmark_birthday=:birthday,
+ benchmark_active=:active,
+ benchmark_weight=:weight,
+ benchmark_income=:income,
+ benchmark_changed=NOW()
+ WHERE benchmark_id=:id;
+insert:
+ type: insert
+ parameters: [":lastName",":firstName",":email",":birthday",":active",":weight",
+ ":income",":createdBy"]
+ sql: |
+ INSERT INTO benchmarks(benchmark_lastname,benchmark_firstname,
+ benchmark_email,benchmark_birthday,benchmark_active,benchmark_weight,
+ benchmark_income,benchmark_createdby,benchmark_created)
+ VALUES(:lastName,:firstName,:email,:birthday,:active,:weight,:income,
+ :createdBy,NOW());
type: list
parameters: []
order: "role_id"
- sql: "SELECT
- t0.*
- FROM roles t0
- ;"
+ sql: |
+ SELECT
+ t0.* FROM roles t0
byId:
type: record
parameters: [ ":id" ]
update:
type: update
parameters: [":id",":name"]
- sql: "UPDATE roles SET
- role_name=:name,role_changed=NOW()
- WHERE role_id=:id;"
+ sql: |
+ UPDATE roles SET
+ role_name=:name,
+ role_changed=NOW()
+ WHERE role_id=:id;
insert:
type: insert
parameters: [":name",":createdBy"]
- sql: "INSERT INTO roles(role_name,role_createdby,role_created)
- VALUES(:name,:createdBy,NOW());"
+ sql: |
+ INSERT INTO roles(role_name,role_createdby,role_created)
+ VALUES(:name,:createdBy,NOW());
type: list
parameters: []
order: "structure_id"
- sql: "SELECT
- t0.*
- FROM structures t0
- ;"
+ sql: |
+ SELECT
+ t0.* FROM structures t0
byId:
type: record
parameters: [ ":id" ]
update:
type: update
parameters: [":id",":scope",":name",":value",":position"]
- sql: "UPDATE structures SET
- structure_scope=:scope,structure_name=:name,structure_value=:value,
- structure_position=:position,structure_changed=NOW()
- WHERE structure_id=:id;"
+ sql: |
+ UPDATE structures SET
+ structure_scope=:scope,
+ structure_name=:name,
+ structure_value=:value,
+ structure_position=:position,
+ structure_changed=NOW()
+ WHERE structure_id=:id;
insert:
type: insert
parameters: [":scope",":name",":value",":position",":createdBy"]
- sql: "INSERT INTO structures(structure_scope,structure_name,structure_value,
+ sql: |
+ INSERT INTO structures(structure_scope,structure_name,structure_value,
structure_position,structure_createdby,structure_created)
- VALUES(:scope,:name,:value,:position,:createdBy,NOW());"
+ VALUES(:scope,:name,:value,:position,:createdBy,NOW());
type: list
parameters: [":text",":role"]
order: "user_id"
- sql: "SELECT
- t0.*,t1.role_name AS role
- FROM users t0
+ sql: |
+ SELECT
+ 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
OR user_displayname like :text OR user_email like :text)
AND (:role=0 OR :role=user_role)
- ;"
byId:
type: record
parameters: [ ":id" ]
update:
type: update
parameters: [":id",":name",":displayName",":email",":role"]
- sql: "UPDATE users SET
- user_name=:name,user_displayname=:displayName,user_email=:email,
- user_role=:role,user_changed=NOW()
- WHERE user_id=:id;"
+ sql: |
+ UPDATE users SET
+ user_name=:name,
+ user_displayname=:displayName,
+ user_email=:email,
+ user_role=:role,
+ user_changed=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,
+ sql: |
+ INSERT INTO users(user_name,user_displayname,user_email,user_role,
user_createdby,user_created)
- VALUES(:name,:displayName,:email,:role,:createdBy,NOW());"
+ VALUES(:name,:displayName,:email,:role,:createdBy,NOW());
--- /dev/null
+/// The flutter test environment is not usable for helper.dart
+/// See metadata/test/helper.dart for tests (with dart test environment)
+
flutter config linux
}
function Finish(){
- pub upgrade
+ dart pub upgrade
}
if [ -z "$APP" ]; then
Usage "missing PROJECT"