/// [gerund]: true: a ver is used in the gerund form: this is better to
/// to read and remember.
static String constructWord(List<WordPart> wordParts,
- {bool normalName = true, gerund: true}) {
+ {bool normalName = true, gerund = true}) {
String rc = '';
for (var item in wordParts) {
switch (item.wordType) {
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) {
}
return rc;
}
+
/// Returns the module names as string list.
-List<String> moduleNames(){
+List<String> moduleNames() {
return [
'Benchmarks',
'Roles',
import '../../base/defines.dart';
import '../../base/helper.dart';
import '../../persistence/data_record.dart';
-class BenchmarkData extends DataRecord<int>{
+
+class BenchmarkData extends DataRecord<int> {
int? id;
String? lastName;
String? firstName;
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(
+ {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;
+ 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(){
+ 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;
+ 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();
final i18n = I18N();
-class CreateBenchmarkCustom extends State<CreateBenchmarkPage> with MessageLine {
+class CreateBenchmarkCustom extends State<CreateBenchmarkPage>
+ with MessageLine {
final globalData = GlobalData();
AttendedPage? attendedPage;
final _fieldData = _FieldData();
CreateBenchmarkCustom();
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('New Benchmark')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(child: buildFrame()));
+ return rc;
+ }
+
+ Widget buildFrame() {
final padding = GlobalThemeData.padding;
lastNameController.text = _fieldData.lastName;
firstNameController.text = _fieldData.firstName;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: lastNameController,
- decoration: InputDecoration(labelText: i18n.tr('Last Name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.lastName = value ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 = jsonToObject(value ?? '', dataType: DataType.date)
- ),
+ controller: birthdayController,
+ decoration: InputDecoration(labelText: i18n.tr('Birthday')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.birthday =
+ jsonToObject(value ?? '', dataType: DataType.date)),
weight: 6),
FormItem(
Row(children: [
weight: 6),
FormItem(
TextFormField(
- controller: weightController,
- decoration: InputDecoration(labelText: i18n.tr('Weight')),
- onSaved: (value) => _fieldData.weight = jsonToObject(value ?? '', dataType: DataType.float)
- ),
+ controller: weightController,
+ decoration: InputDecoration(labelText: i18n.tr('Weight')),
+ onSaved: (value) => _fieldData.weight =
+ jsonToObject(value ?? '', dataType: DataType.float)),
weight: 6),
FormItem(
TextFormField(
- controller: incomeController,
- decoration: InputDecoration(labelText: i18n.tr('Income')),
- onSaved: (value) => _fieldData.income = jsonToObject(value ?? '', dataType: DataType.currency)
- ),
+ controller: incomeController,
+ decoration: InputDecoration(labelText: i18n.tr('Income')),
+ onSaved: (value) => _fieldData.income =
+ jsonToObject(value ?? '', dataType: DataType.currency)),
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(),
- child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ lastNameController.dispose();
+ firstNameController.dispose();
+ emailController.dispose();
+ birthdayController.dispose();
+ weightController.dispose();
+ incomeController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- lastNameController.dispose();
- firstNameController.dispose();
- emailController.dispose();
- birthdayController.dispose();
- weightController.dispose();
- incomeController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String lastName = '';
String firstName = '';
String email = '';
double weight = 0;
double income = 0;
-
void toMap(Map<String, dynamic> map) {
map[':lastName'] = lastName;
map[':firstName'] = firstName;
GlobalData(),
BenchmarkMeta.instance.pageByName('create')!,
BenchmarkMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _CreateBenchmarkPageState extends CreateBenchmarkCustom {
- _CreateBenchmarkPageState(): super();
+ _CreateBenchmarkPageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
final i18n = I18N();
-class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage> with MessageLine {
+class DeleteBenchmarkCustom extends State<DeleteBenchmarkPage>
+ with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
DeleteBenchmarkCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
- final padding = GlobalThemeData.padding;
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Delete Benchmark')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
},
- parameters: {
- 'module': 'Benchmarks',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
+ final padding = GlobalThemeData.padding;
lastNameController.text = _fieldData.lastName;
firstNameController.text = _fieldData.firstName;
emailController.text = _fieldData.email;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: lastNameController,
- decoration: InputDecoration(labelText: i18n.tr('Last Name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.lastName = value ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 = jsonToObject(value ?? '', dataType: DataType.date)
- ),
+ controller: birthdayController,
+ decoration: InputDecoration(labelText: i18n.tr('Birthday')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.birthday =
+ jsonToObject(value ?? '', dataType: DataType.date)),
weight: 6),
FormItem(
Row(children: [
weight: 6),
FormItem(
TextFormField(
- controller: weightController,
- decoration: InputDecoration(labelText: i18n.tr('Weight')),
- onSaved: (value) => _fieldData.weight = jsonToObject(value ?? '', dataType: DataType.float)
- ),
+ controller: weightController,
+ decoration: InputDecoration(labelText: i18n.tr('Weight')),
+ onSaved: (value) => _fieldData.weight =
+ jsonToObject(value ?? '', dataType: DataType.float)),
weight: 6),
FormItem(
TextFormField(
- controller: incomeController,
- decoration: InputDecoration(labelText: i18n.tr('Income')),
- onSaved: (value) => _fieldData.income = jsonToObject(value ?? '', dataType: DataType.currency)
- ),
+ controller: incomeController,
+ decoration: InputDecoration(labelText: i18n.tr('Income')),
+ onSaved: (value) => _fieldData.income =
+ jsonToObject(value ?? '', dataType: DataType.currency)),
weight: 6),
FormItem(
ElevatedButton(
),
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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ lastNameController.dispose();
+ firstNameController.dispose();
+ emailController.dispose();
+ birthdayController.dispose();
+ weightController.dispose();
+ incomeController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
delete();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- lastNameController.dispose();
- firstNameController.dispose();
- emailController.dispose();
- birthdayController.dispose();
- weightController.dispose();
- incomeController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String lastName = '';
String firstName = '';
String email = '';
GlobalData(),
BenchmarkMeta.instance.pageByName('delete')!,
BenchmarkMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _DeleteBenchmarkPageState extends DeleteBenchmarkCustom {
- _DeleteBenchmarkPageState(int primaryKey): super(primaryKey);
+ _DeleteBenchmarkPageState(int primaryKey) : super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
class EditBenchmarkCustom extends State<EditBenchmarkPage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
EditBenchmarkCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
- final padding = GlobalThemeData.padding;
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Change Benchmark')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
},
- parameters: {
- 'module': 'Benchmarks',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
+ final padding = GlobalThemeData.padding;
lastNameController.text = _fieldData.lastName;
firstNameController.text = _fieldData.firstName;
emailController.text = _fieldData.email;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: lastNameController,
- decoration: InputDecoration(labelText: i18n.tr('Last Name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.lastName = value ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 = jsonToObject(value ?? '', dataType: DataType.date)
- ),
+ controller: birthdayController,
+ decoration: InputDecoration(labelText: i18n.tr('Birthday')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.birthday =
+ jsonToObject(value ?? '', dataType: DataType.date)),
weight: 6),
FormItem(
Row(children: [
weight: 6),
FormItem(
TextFormField(
- controller: weightController,
- decoration: InputDecoration(labelText: i18n.tr('Weight')),
- onSaved: (value) => _fieldData.weight = jsonToObject(value ?? '', dataType: DataType.float)
- ),
+ controller: weightController,
+ decoration: InputDecoration(labelText: i18n.tr('Weight')),
+ onSaved: (value) => _fieldData.weight =
+ jsonToObject(value ?? '', dataType: DataType.float)),
weight: 6),
FormItem(
TextFormField(
- controller: incomeController,
- decoration: InputDecoration(labelText: i18n.tr('Income')),
- onSaved: (value) => _fieldData.income = jsonToObject(value ?? '', dataType: DataType.currency)
- ),
+ controller: incomeController,
+ decoration: InputDecoration(labelText: i18n.tr('Income')),
+ onSaved: (value) => _fieldData.income =
+ jsonToObject(value ?? '', dataType: DataType.currency)),
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(),
- child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ lastNameController.dispose();
+ firstNameController.dispose();
+ emailController.dispose();
+ birthdayController.dispose();
+ weightController.dispose();
+ incomeController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
globalData.restPersistence!
.store(what: 'store', map: parameters)
.then((answer) {
- _fieldData.isFromBackend = false;
attendedPage!.pageStates.dbDataState.clear();
setState(() => 1);
});
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- lastNameController.dispose();
- firstNameController.dispose();
- emailController.dispose();
- birthdayController.dispose();
- weightController.dispose();
- incomeController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String lastName = '';
String firstName = '';
String email = '';
GlobalData(),
BenchmarkMeta.instance.pageByName('edit')!,
BenchmarkMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _EditBenchmarkPageState extends EditBenchmarkCustom {
- _EditBenchmarkPageState(int primaryKey): super(primaryKey);
+ _EditBenchmarkPageState(int primaryKey) : super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
rc = const CircularProgressIndicator();
} else {
if (snapshot.hasData) {
- final rows = attendedPage!.getRows(dbData: snapshot.data!,
- columnList: 'benchmark_id;benchmark_lastname;benchmark_firstname;benchmark_birthday;benchmark_active;benchmark_income',
+ final rows = attendedPage!.getRows(
+ dbData: snapshot.data!,
+ columnList:
+ 'benchmark_id;benchmark_lastname;benchmark_firstname;benchmark_birthday;benchmark_active;benchmark_income',
onDone: () => setState(() => 1),
routeEdit: '/Benchmarks/edit',
context: context);
return rc;
}
- Widget buildFrame({required JsonList rows}){
+ Widget buildFrame({required JsonList rows}) {
final padding = GlobalThemeData.padding;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: textController,
- decoration: InputDecoration(labelText: i18n.tr('Text')),
- onSaved: (value) => _fieldData.text = value ?? ''
- ),
+ controller: textController,
+ decoration: InputDecoration(labelText: i18n.tr('Text')),
+ onSaved: (value) => _fieldData.text = value ?? ''),
weight: 6),
FormItem(
ElevatedButton(
rows: rows as List<DataRow>,
);
Widget? tabBar =
- attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+ attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
final frameWidget = ListView(children: [
form,
if (tabBar != null) tabBar,
.then((message) => setState(() => resultController.text = message));
}
-@override
+ @override
void dispose() {
helperDummyUsage(DataType.string);
globalWidgetDummyUsage();
GlobalData(),
BenchmarkMeta.instance.pageByName('list')!,
BenchmarkMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _ListBenchmarkPageState extends ListBenchmarkCustom {
- _ListBenchmarkPageState(): super();
+ _ListBenchmarkPageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
CreateRoleCustom();
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('New Role')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(child: buildFrame()));
+ return rc;
+ }
+
+ Widget buildFrame() {
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 ?? ''
- ),
+ 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'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('New Role')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ nameController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- nameController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String name = '';
-
void toMap(Map<String, dynamic> map) {
map[':name'] = name;
map[':createdBy'] = GlobalData.loginUserName;
GlobalData(),
RoleMeta.instance.pageByName('create')!,
RoleMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _CreateRolePageState extends CreateRoleCustom {
- _CreateRolePageState(): super();
+ _CreateRolePageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
class EditRoleCustom extends State<EditRolePage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
EditRoleCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
- final padding = GlobalThemeData.padding;
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Change Role')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
},
- parameters: {
- 'module': 'Roles',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
+ 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 ?? ''
- ),
+ 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'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Role')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ nameController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
globalData.restPersistence!
.store(what: 'store', map: parameters)
.then((answer) {
- _fieldData.isFromBackend = false;
attendedPage!.pageStates.dbDataState.clear();
setState(() => 1);
});
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- nameController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String name = '';
void fromMap(Map<String, dynamic> map) {
GlobalData(),
RoleMeta.instance.pageByName('edit')!,
RoleMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _EditRolePageState extends EditRoleCustom {
- _EditRolePageState(int primaryKey): super(primaryKey);
+ _EditRolePageState(int primaryKey) : super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
rc = const CircularProgressIndicator();
} else {
if (snapshot.hasData) {
- final rows = attendedPage!.getRows(dbData: snapshot.data!,
+ final rows = attendedPage!.getRows(
+ dbData: snapshot.data!,
columnList: 'role_id;role_name',
onDone: () => setState(() => 1),
routeEdit: '/Roles/edit',
return rc;
}
- Widget buildFrame({required JsonList rows}){
+ Widget buildFrame({required JsonList rows}) {
final padding = GlobalThemeData.padding;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: textController,
- decoration: InputDecoration(labelText: i18n.tr('Text')),
- onSaved: (value) => _fieldData.text = value ?? ''
- ),
+ controller: textController,
+ decoration: InputDecoration(labelText: i18n.tr('Text')),
+ onSaved: (value) => _fieldData.text = value ?? ''),
weight: 6),
FormItem(
ElevatedButton(
color: GlobalThemeData.formBackgroundColor,
elevation: GlobalThemeData.formElevation,
margin:
- EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
child: Padding(
padding: EdgeInsets.symmetric(
vertical: padding, horizontal: padding),
rows: rows as List<DataRow>,
);
Widget? tabBar =
- attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+ attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
final frameWidget = ListView(children: [
form,
if (tabBar != null) tabBar,
GlobalData(),
RoleMeta.instance.pageByName('list')!,
RoleMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _ListRolePageState extends ListRoleCustom {
- _ListRolePageState(): super();
+ _ListRolePageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
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') ? 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;
+ 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();
final i18n = I18N();
-class CreateStructureCustom extends State<CreateStructurePage> with MessageLine {
+class CreateStructureCustom extends State<CreateStructurePage>
+ with MessageLine {
final globalData = GlobalData();
AttendedPage? attendedPage;
final _fieldData = _FieldData();
CreateStructureCustom();
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('New Structure')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(child: buildFrame()));
+ return rc;
+ }
+
+ Widget buildFrame() {
final padding = GlobalThemeData.padding;
scopeController.text = _fieldData.scope;
nameController.text = _fieldData.name;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: scopeController,
- decoration: InputDecoration(labelText: i18n.tr('Scope')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.scope = value ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 = jsonToObject(value ?? '', dataType: DataType.int)
- ),
+ controller: positionController,
+ decoration: InputDecoration(labelText: i18n.tr('Position')),
+ onSaved: (value) => _fieldData.position =
+ jsonToObject(value ?? '', dataType: DataType.int)),
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(),
- child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('New Structure')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ scopeController.dispose();
+ nameController.dispose();
+ valueController.dispose();
+ positionController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- scopeController.dispose();
- nameController.dispose();
- valueController.dispose();
- positionController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String scope = '';
String name = '';
String value = '';
int position = 0;
-
void toMap(Map<String, dynamic> map) {
map[':scope'] = scope;
map[':name'] = name;
GlobalData(),
StructureMeta.instance.pageByName('create')!,
StructureMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _CreateStructurePageState extends CreateStructureCustom {
- _CreateStructurePageState(): super();
+ _CreateStructurePageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
final i18n = I18N();
-class DeleteStructureCustom extends State<DeleteStructurePage> with MessageLine {
+class DeleteStructureCustom extends State<DeleteStructurePage>
+ with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
DeleteStructureCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
- final padding = GlobalThemeData.padding;
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Delete Structure')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
},
- parameters: {
- 'module': 'Structures',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
+ final padding = GlobalThemeData.padding;
scopeController.text = _fieldData.scope;
nameController.text = _fieldData.name;
valueController.text = _fieldData.value;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: scopeController,
- decoration: InputDecoration(labelText: i18n.tr('Scope')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.scope = value ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 = jsonToObject(value ?? '', dataType: DataType.int)
- ),
+ controller: positionController,
+ decoration: InputDecoration(labelText: i18n.tr('Position')),
+ onSaved: (value) => _fieldData.position =
+ jsonToObject(value ?? '', dataType: DataType.int)),
weight: 6),
FormItem(
ElevatedButton(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Delete Structure')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ scopeController.dispose();
+ nameController.dispose();
+ valueController.dispose();
+ positionController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
delete();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- scopeController.dispose();
- nameController.dispose();
- valueController.dispose();
- positionController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String scope = '';
String name = '';
String value = '';
GlobalData(),
StructureMeta.instance.pageByName('delete')!,
StructureMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
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;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
class EditStructureCustom extends State<EditStructurePage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
EditStructureCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
- final padding = GlobalThemeData.padding;
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Change Structure')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
},
- parameters: {
- 'module': 'Structures',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
+ final padding = GlobalThemeData.padding;
scopeController.text = _fieldData.scope;
nameController.text = _fieldData.name;
valueController.text = _fieldData.value;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: scopeController,
- decoration: InputDecoration(labelText: i18n.tr('Scope')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.scope = value ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 ?? ''
- ),
+ 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 = jsonToObject(value ?? '', dataType: DataType.int)
- ),
+ controller: positionController,
+ decoration: InputDecoration(labelText: i18n.tr('Position')),
+ onSaved: (value) => _fieldData.position =
+ jsonToObject(value ?? '', dataType: DataType.int)),
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(),
- child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change Structure')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ scopeController.dispose();
+ nameController.dispose();
+ valueController.dispose();
+ positionController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
globalData.restPersistence!
.store(what: 'store', map: parameters)
.then((answer) {
- _fieldData.isFromBackend = false;
attendedPage!.pageStates.dbDataState.clear();
setState(() => 1);
});
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- scopeController.dispose();
- nameController.dispose();
- valueController.dispose();
- positionController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String scope = '';
String name = '';
String value = '';
GlobalData(),
StructureMeta.instance.pageByName('edit')!,
StructureMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
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;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
rc = const CircularProgressIndicator();
} else {
if (snapshot.hasData) {
- final rows = attendedPage!.getRows(dbData: snapshot.data!,
- columnList: 'structure_id;structure_scope;structure_name;structure_value;structure_position',
+ final rows = attendedPage!.getRows(
+ dbData: snapshot.data!,
+ columnList:
+ 'structure_id;structure_scope;structure_name;structure_value;structure_position',
onDone: () => setState(() => 1),
routeEdit: '/Structures/edit',
context: context);
return rc;
}
- Widget buildFrame({required JsonList rows}){
+ Widget buildFrame({required JsonList rows}) {
final padding = GlobalThemeData.padding;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: textController,
- decoration: InputDecoration(labelText: i18n.tr('Text')),
- onSaved: (value) => _fieldData.text = value ?? ''
- ),
+ controller: textController,
+ decoration: InputDecoration(labelText: i18n.tr('Text')),
+ onSaved: (value) => _fieldData.text = value ?? ''),
weight: 6),
FormItem(
ElevatedButton(
color: GlobalThemeData.formBackgroundColor,
elevation: GlobalThemeData.formElevation,
margin:
- EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
child: Padding(
padding: EdgeInsets.symmetric(
vertical: padding, horizontal: padding),
rows: rows as List<DataRow>,
);
Widget? tabBar =
- attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+ attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
final frameWidget = ListView(children: [
form,
if (tabBar != null) tabBar,
GlobalData(),
StructureMeta.instance.pageByName('list')!,
StructureMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _ListStructurePageState extends ListStructureCustom {
- _ListStructurePageState(): super();
+ _ListStructurePageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/defines.dart';
import '../../base/helper.dart';
import '../../persistence/data_record.dart';
-class StructureData extends DataRecord<int>{
+
+class StructureData extends DataRecord<int> {
int? id;
String? scope;
String? name;
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(
+ {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;
+ 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(){
+ 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;
+ 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();
CreateUserCustom();
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('New User')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(child: buildFrame()));
+ return rc;
+ }
+
+ Widget buildFrame() {
final padding = GlobalThemeData.padding;
comboRolesFromBackend(
attendedPage: attendedPage!, onDone: () => setState(() => 1));
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: nameController,
- decoration: InputDecoration(labelText: i18n.tr('Name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.name = value ?? ''
- ),
+ controller: nameController,
+ decoration: InputDecoration(labelText: i18n.tr('Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.name = value ?? ''),
weight: 6),
FormItem(
TextFormField(
- controller: displayNameController,
- decoration: InputDecoration(labelText: i18n.tr('Display name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.displayName = value ?? ''
- ),
+ controller: displayNameController,
+ decoration: InputDecoration(labelText: i18n.tr('Display name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.displayName = value ?? ''),
weight: 6),
FormItem(
TextFormField(
- controller: emailController,
- decoration: InputDecoration(labelText: i18n.tr('EMail')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.email = value ?? ''
- ),
+ controller: emailController,
+ decoration: InputDecoration(labelText: i18n.tr('EMail')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.email = value ?? ''),
weight: 6),
FormItem(
DropdownButtonFormField<int>(
- value: _fieldData.role,
+ value: itemsRoles == null || itemsRoles.length == 1
+ ? 0
+ : _fieldData.role,
items: itemsRoles,
isExpanded: true,
decoration: InputDecoration(labelText: i18n.tr('Role')),
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(),
- child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('New User')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ nameController.dispose();
+ displayNameController.dispose();
+ emailController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- nameController.dispose();
- displayNameController.dispose();
- emailController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String name = '';
String displayName = '';
String email = '';
int role = 0;
-
void toMap(Map<String, dynamic> map) {
map[':name'] = name;
map[':displayName'] = displayName;
GlobalData(),
UserMeta.instance.pageByName('create')!,
UserMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _CreateUserPageState extends CreateUserCustom {
- _CreateUserPageState(): super();
+ _CreateUserPageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
class DeleteUserCustom extends State<DeleteUserPage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
DeleteUserCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Delete User')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
+ },
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
final padding = GlobalThemeData.padding;
comboRolesFromBackend(
attendedPage: attendedPage!, onDone: () => setState(() => 1));
final itemsRoles = comboRoles(
i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage!);
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
- },
- parameters: {
- 'module': 'Users',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
nameController.text = _fieldData.name;
displayNameController.text = _fieldData.displayName;
emailController.text = _fieldData.email;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: nameController,
- decoration: InputDecoration(labelText: i18n.tr('Name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.name = value ?? ''
- ),
+ controller: nameController,
+ decoration: InputDecoration(labelText: i18n.tr('Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.name = value ?? ''),
weight: 6),
FormItem(
TextFormField(
- controller: displayNameController,
- decoration: InputDecoration(labelText: i18n.tr('Display name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.displayName = value ?? ''
- ),
+ controller: displayNameController,
+ decoration: InputDecoration(labelText: i18n.tr('Display name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.displayName = value ?? ''),
weight: 6),
FormItem(
TextFormField(
- controller: emailController,
- decoration: InputDecoration(labelText: i18n.tr('EMail')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.email = value ?? ''
- ),
+ controller: emailController,
+ decoration: InputDecoration(labelText: i18n.tr('EMail')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.email = value ?? ''),
weight: 6),
FormItem(
DropdownButtonFormField<int>(
- value: _fieldData.role,
+ value: itemsRoles == null || itemsRoles.length == 1
+ ? 0
+ : _fieldData.role,
items: itemsRoles,
isExpanded: true,
decoration: InputDecoration(labelText: i18n.tr('Role')),
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Delete User')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ nameController.dispose();
+ displayNameController.dispose();
+ emailController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
delete();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- nameController.dispose();
- displayNameController.dispose();
- emailController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String name = '';
String displayName = '';
String email = '';
GlobalData(),
UserMeta.instance.pageByName('delete')!,
UserMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _DeleteUserPageState extends DeleteUserCustom {
- _DeleteUserPageState(int primaryKey): super(primaryKey);
+ _DeleteUserPageState(int primaryKey) : super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
+import '../../persistence/persistence.dart';
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
class EditUserCustom extends State<EditUserPage> with MessageLine {
final int primaryKey;
final globalData = GlobalData();
+ late Future<DbData> _futureDbData;
AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
EditUserCustom(this.primaryKey);
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Change User')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null) {
+ rc =
+ Text('backend problem: ${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
+ },
+ )));
+ return rc;
+ }
+
+ Widget buildFrame() {
final padding = GlobalThemeData.padding;
comboRolesFromBackend(
attendedPage: attendedPage!, onDone: () => setState(() => 1));
final itemsRoles = comboRoles(
i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage!);
- if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
- },
- parameters: {
- 'module': 'Users',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
nameController.text = _fieldData.name;
displayNameController.text = _fieldData.displayName;
emailController.text = _fieldData.email;
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: nameController,
- decoration: InputDecoration(labelText: i18n.tr('Name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.name = value ?? ''
- ),
+ controller: nameController,
+ decoration: InputDecoration(labelText: i18n.tr('Name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.name = value ?? ''),
weight: 6),
FormItem(
TextFormField(
- controller: displayNameController,
- decoration: InputDecoration(labelText: i18n.tr('Display name')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.displayName = value ?? ''
- ),
+ controller: displayNameController,
+ decoration: InputDecoration(labelText: i18n.tr('Display name')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.displayName = value ?? ''),
weight: 6),
FormItem(
TextFormField(
- controller: emailController,
- decoration: InputDecoration(labelText: i18n.tr('EMail')),
- validator: (input) => notEmpty(input),
- onSaved: (value) => _fieldData.email = value ?? ''
- ),
+ controller: emailController,
+ decoration: InputDecoration(labelText: i18n.tr('EMail')),
+ validator: (input) => notEmpty(input),
+ onSaved: (value) => _fieldData.email = value ?? ''),
weight: 6),
FormItem(
DropdownButtonFormField<int>(
- value: _fieldData.role,
+ value: itemsRoles == null || itemsRoles.length == 1
+ ? 0
+ : _fieldData.role,
items: itemsRoles,
isExpanded: true,
decoration: InputDecoration(labelText: i18n.tr('Role')),
weight: 6),
FormItem(
ElevatedButton(
- onPressed: () => verifyAndStore(),
- child: Text(i18n.tr('Save'))),
+ onPressed: () => verifyAndStore(), child: Text(i18n.tr('Save'))),
weight: 8,
gapAbove: 2 * padding),
FormItem(
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('Change User')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+ nameController.dispose();
+ displayNameController.dispose();
+ emailController.dispose();
+ super.dispose();
+ }
+
@override
void initState() {
super.initState();
globalData.restPersistence!
.store(what: 'store', map: parameters)
.then((answer) {
- _fieldData.isFromBackend = false;
attendedPage!.pageStates.dbDataState.clear();
setState(() => 1);
});
store();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
- nameController.dispose();
- displayNameController.dispose();
- emailController.dispose();
- super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
String name = '';
String displayName = '';
String email = '';
GlobalData(),
UserMeta.instance.pageByName('edit')!,
UserMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _EditUserPageState extends EditUserCustom {
- _EditUserPageState(int primaryKey): super(primaryKey);
+ _EditUserPageState(int primaryKey) : super(primaryKey);
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
rc = const CircularProgressIndicator();
} else {
if (snapshot.hasData) {
- final rows = attendedPage!.getRows(dbData: snapshot.data!,
- columnList: 'user_id;user_name;user_displayname;user_email;role',
+ final rows = attendedPage!.getRows(
+ dbData: snapshot.data!,
+ columnList:
+ 'user_id;user_name;user_displayname;user_email;role',
onDone: () => setState(() => 1),
routeEdit: '/Users/edit',
context: context);
return rc;
}
- Widget buildFrame({required JsonList rows}){
+ Widget buildFrame({required JsonList rows}) {
final padding = GlobalThemeData.padding;
comboRolesFromBackend(
attendedPage: attendedPage!, onDone: () => setState(() => 1));
final formItems = <FormItem>[
FormItem(
TextFormField(
- controller: textController,
- decoration: InputDecoration(labelText: i18n.tr('Text')),
- onSaved: (value) => _fieldData.text = value ?? ''
- ),
+ controller: textController,
+ decoration: InputDecoration(labelText: i18n.tr('Text')),
+ onSaved: (value) => _fieldData.text = value ?? ''),
weight: 6),
FormItem(
DropdownButtonFormField<int>(
- value: _fieldData.role,
+ value: itemsRoles == null || itemsRoles.length == 1
+ ? 0
+ : _fieldData.role,
items: itemsRoles,
isExpanded: true,
decoration: InputDecoration(labelText: i18n.tr('Role')),
color: GlobalThemeData.formBackgroundColor,
elevation: GlobalThemeData.formElevation,
margin:
- EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
child: Padding(
padding: EdgeInsets.symmetric(
vertical: padding, horizontal: padding),
rows: rows as List<DataRow>,
);
Widget? tabBar =
- attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
+ attendedPage!.buildChipBar(onTap: (offset) => setState(() => offset));
final frameWidget = ListView(children: [
form,
if (tabBar != null) tabBar,
GlobalData(),
UserMeta.instance.pageByName('list')!,
UserMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
}
class _ListUserPageState extends ListUserCustom {
- _ListUserPageState(): super();
+ _ListUserPageState() : super();
@override
void didChangeDependencies() {
final size = MediaQuery.of(context).size;
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload) {
+ if (afterReload == null) {
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
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') ? 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;
+ 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();
'${answer.substring(0, min<int>(answer.length, 8))}');
}
} else {
- rc = DbData.message(answer.substring(0, max<int>(answer.length, 120)));
+ rc = DbData.message(answer.substring(0, min<int>(answer.length, 120)));
}
if (logger.logLevel >= LEVEL_FINE) {
logger.log('answer: ${limitString(answer, sqlTraceLimit)}');
import 'dart:io';
+
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
-import '../persistence/rest_persistence.dart';
-import '../widget/attended_page.dart';
import '../base/application_name.dart';
import '../base/defines.dart';
import '../page/page_controller_exhibition.dart';
+import '../persistence/rest_persistence.dart';
+import '../widget/attended_page.dart';
typedef AppBarBuilder = Function(String);
Widget widget(PageControllerExhibition controller);
}
-class HomeDirectories {
- Directory configurations = Directory.current;
- Directory localData = Directory.current;
- HomeDirectories.dummy();
- HomeDirectories(String applicationName) {
- if (Platform.isLinux) {
- configurations = Directory('/etc/$applicationName');
- localData = Directory(path.join('/home', Platform.environment['LOGNAME'],
- '.local/share/$applicationName'));
- } else if (Platform.isAndroid) {
- getExternalStorageDirectory().then((dir) => localData = dir!);
- } else {
- throw FormatException('HomeDirectory.getHomePath(): unknown platform');
- }
- }
-}
-
-class GlobalTranslations {
- static final comboboxItemAll = i18n.tr('<All>');
- static final comboboxSelect = i18n.tr('<Please select>');
-}
-
-class GlobalThemeData {
- static final formBackgroundColor = Color.fromARGB(0xee, 0xee, 0xee, 0xee);
- static final formElevation = 10.0;
- static final formTextBackgroundColor = Colors.white;
- static final padding = 16.0;
-}
-
/// Storage for global resources. This is a singleton.
class GlobalData {
static const version = '2021.08.24.00';
static String baseDirectory = '';
static var serverEnvironment = ServerEnvironment.productive;
static final String applicationName = theApplicationName;
+ static String loginUserName = 'guest';
+ static int loginUserId = 0;
+ static int loginUserRole = 90;
final BaseLogger logger;
final AppBarBuilder appBarBuilder;
final DrawerBuilder drawerBuilder;
final FooterBuilder footerBuilder;
final BaseConfiguration configuration;
final RestPersistence? restPersistence;
- static String loginUserName = 'guest';
- static int loginUserId = 0;
- static int loginUserRole = 90;
HomeDirectories homeDirectories = HomeDirectories.dummy();
+ final navigatorStack = NavigatorStack();
factory GlobalData() => _instance ?? GlobalData();
+
GlobalData.dummy()
: this.internal(BaseConfiguration({}, globalLogger), (input) => '',
(input) => '', DummyFooter.builder, null, globalLogger);
this.logger) {
logger.log('Start');
_instance = this;
+ navigatorStack.globalData = this;
}
Future initializeAsync() async {
// Do customize!
}
/// Switches the page given by a [route].
- void navigate(BuildContext context, String route) {
- Navigator.pushNamed(context, route);
+ ///
+ /// [context] ist the build context of the current page.
+ ///
+ /// If [popIfPossible] is true and the calling page has this route
+ /// the [Navigator.pop()] is called. Otherwise [Navigator.pushNamed()]
+ /// is called. The Difference: pop() restores the previous state (in
+ /// filters...).
+ void navigate(BuildContext context, String route,
+ {bool popIfPossible = true}) {
+ navigatorStack.goto(context, route, popIfPossible: popIfPossible);
}
}
+
+class GlobalThemeData {
+ static final formBackgroundColor = Color.fromARGB(0xee, 0xee, 0xee, 0xee);
+ static final formElevation = 10.0;
+ static final formTextBackgroundColor = Colors.white;
+ static final padding = 16.0;
+}
+
+class GlobalTranslations {
+ static final comboboxItemAll = i18n.tr('<All>');
+ static final comboboxSelect = i18n.tr('<Please select>');
+}
+
+class HomeDirectories {
+ Directory configurations = Directory.current;
+ Directory localData = Directory.current;
+ HomeDirectories(String applicationName) {
+ if (Platform.isLinux) {
+ configurations = Directory('/etc/$applicationName');
+ localData = Directory(path.join('/home', Platform.environment['LOGNAME'],
+ '.local/share/$applicationName'));
+ } else if (Platform.isAndroid) {
+ getExternalStorageDirectory().then((dir) => localData = dir!);
+ } else {
+ throw FormatException('HomeDirectory.getHomePath(): unknown platform');
+ }
+ }
+ HomeDirectories.dummy();
+}
+
+/// Manages the call stack of the navigator.
+///
+/// This allows to access the calling page from the current page,
+/// e.g. to inform about changes.
+class NavigatorStack {
+ GlobalData? globalData;
+ final stack = <NavigatorStackEntry>[];
+
+ /// Switches the page given by a [route].
+ ///
+ /// [context] ist the build context of the current page.
+ ///
+ /// If [popIfPossible] is true and the calling page has this route
+ /// the [Navigator.pop()] is called. Otherwise [Navigator.pushNamed()]
+ /// is called. The Difference: pop() restores the previous state (in
+ /// filters...).
+ ///
+ /// If [registerWithParent] is true the parent calls register
+ void goto(BuildContext context, String route,
+ {bool popIfPossible = true, bool registerWithParent = false}) {
+ final ix = route.indexOf(';');
+ if (ix > 0) {
+ route = route.substring(0, ix);
+ }
+ if (popIfPossible &&
+ stack.length >= 2 &&
+ stack[stack.length - 2].route == route) {
+ pop(context);
+ } else {
+ /// Note: constructor of AttendedPage calls supplyTopOfStack()
+ /// to set NavigatorStackEntry.attendedPage.
+ stack.add(NavigatorStackEntry(
+ route: route, registerWithParent: registerWithParent));
+ Navigator.pushNamed(context, route);
+ }
+ }
+
+ /// Informs the parent that the current page has been changed.
+ ///
+ /// [route]: identifies the calling page. If null the previous stack
+ /// entry of the top of stack is used. Otherwise the latest entry
+ /// with that route.
+ void informAboutChanges(String? route) {
+ AttendedPage? parent;
+ if (route == null) {
+ if (stack.length >= 2) {
+ parent = stack[stack.length - 2].attendedPage;
+ } else {
+ for (var ix = stack.length - 1; ix >= 0; ix--) {
+ if (stack[ix].route == route) {
+ parent = stack[ix].attendedPage;
+ }
+ }
+ }
+ if (parent == null) {
+ globalData!.logger
+ .error('informAboutChanges(): parent ${route!} not found');
+ } else {
+ parent.noticeChange();
+ }
+ }
+ }
+
+ /// Removes the top of stack and return to the calling page.
+ ///
+ /// [context]: the context of the calling page.
+ void pop(BuildContext context) {
+ if (stack.isEmpty) {
+ globalData!.logger.error('NavigatorStack.pop(): empty stack');
+ } else {
+ stack.removeLast();
+ Navigator.pop(context);
+ }
+ }
+
+ /// Adds the missing attended page in the top of stack.
+ ///
+ /// This method must be called if the attended page has been
+ /// constructed.
+ ///
+ /// [route] identifies the page.
+ ///
+ /// [attendedPage] will be stored in the top of stage if missing that.
+ void supplyTopOfStack(String route, AttendedPage attendedPage) {
+ NavigatorStackEntry? last;
+ if (stack.isNotEmpty && (last = stack.last).route == route) {
+ last.attendedPage = attendedPage;
+ if (last.registerWithParent && stack.length >= 2) {
+ stack[stack.length - 2]
+ .attendedPage
+ ?.addListener(() => attendedPage.reload());
+ }
+ } else {
+ globalData!.logger.error(
+ 'supplyTopOfStack(): route $route not found. TOS: ' +
+ (last == null ? '<none>' : last.route));
+ }
+ }
+}
+
+/// Data class to store a navigation info of a page.
+class NavigatorStackEntry {
+ final String route;
+ final bool registerWithParent;
+ AttendedPage? attendedPage;
+ NavigatorStackEntry(
+ {required this.route,
+ required this.registerWithParent,
+ this.attendedPage});
+}
/// Note: There may be several instances of AttendedPage belonging to one
/// derived class of StatefulWidget (member "statefulWidget"). Do not store
/// states directly in this class. Store it in [PageStates].
-class AttendedPage {
+///
+/// The [ChangeNotifier] base class allows to inform the calling
+/// page. Example: the list page calls the edit page of one item.
+/// If the edit page stores changed attributes the calling list page
+/// must be informed and it rebuilds the list view.
+/// The [GlobalData.informCaller()] method can do that.
+class AttendedPage extends ChangeNotifier {
+ String route = '';
final ModuleMetaData moduleMetaData;
final PageMetaData pageMetaData;
final GlobalData globalData;
final StatefulWidget statefulWidget;
final State<StatefulWidget> state;
final PageStates pageStates;
- AttendedPage(this.statefulWidget, this.state, this.globalData,
- this.pageMetaData, this.moduleMetaData, this.pageStates);
+ final void Function(Function? afterReload)? reloadFunction;
+ AttendedPage(
+ this.statefulWidget,
+ this.state,
+ this.globalData,
+ this.pageMetaData,
+ this.moduleMetaData,
+ this.pageStates,
+ this.reloadFunction,
+ {String? route}) {
+ this.route = route ?? '/${moduleMetaData.moduleName}/${pageMetaData.name}';
+ globalData.navigatorStack.supplyTopOfStack(this.route, this);
+ }
/// Returns the list of attended widgets of this page.
List<AttendedWidget> attendedWidgets() {
return rc;
}
+ /// Calls [setState()] of the current page.
+ ///
+ /// If [afterReload] is not null this function is used as parameter of
+ /// setState().
+ void reload({Function? afterReload}) {
+ reloadFunction!(afterReload);
+ }
+
/// Creates a chip bar: a row of ChoiceChip instances (special buttons).
///
/// That chips allow to change the page of the db result.
List<DataRow> getRows(
{required DbData dbData,
required String columnList,
- required Function() onDone,
+ required Function() onDone, //@ToDo: remove
required String routeEdit,
required BuildContext context}) {
List<DataRow>? rc;
- if (dbData != null && dbData.recordList != null) {
+ if (dbData.recordList != null) {
rc = <DataRow>[];
dbData.recordList!.forEach((record) {
final cells = <DataCell>[];
return rc ?? <DataRow>[];
}
+ void noticeChange() {
+ notifyListeners();
+ }
+
+ void informAboutChanges({String? route}) {
+ globalData.navigatorStack.informAboutChanges(route);
+ }
+
/// Loads a record from the backend.
///
/// [name]: a unique name over all backend data requests.
/// Handles the page generation. Is a base class of [Generator].
class PageGenerator extends SqlGenerator {
+ static final templateBodyLoadData = '''SafeArea(
+ child: FutureBuilder<DbData>(
+ future: _futureDbData,
+ builder: (context, snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final dbData = snapshot.data!;
+ final record = dbData.singleRecord;
+ if (record == null){
+ rc = Text('backend problem: \${dbData.message ?? '<unknown>'}');
+ }
+ _fieldData.fromMap(record as JsonMap);
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: \${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
+ },
+ )));''';
+ static final templateBodySimple = '''SafeArea(
+ child: buildFrame()));''';
+ static final templateDidChangeDependencies = '''
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _futureDbData = globalData.restPersistence!.query(
+ what: 'query',
+ data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
+ }''';
+
static final templatePage = '''
// DO NOT CHANGE. This file is created by the meta_tool!
import 'package:flutter/material.dart';
GlobalData(),
UserMeta.instance.pageByName('edit')!,
UserMeta.instance,
- pageStates);
+ pageStates,
+ (afterReload) => rc.reload(afterReload));
pageStates.attendedPage = rc.attendedPage;
return rc;
}
attendedPage!.pageStates.screenHeight = size.height;
super.didChangeDependencies();
}
+
+ /// Renders the widget tree again.
+ void reload(Function? afterReload){
+ if (afterReload == null){
+ setState(() => 1);
+ } else {
+ setState(() => afterReload());
+ }
+ }
}
''';
#INIT_COMBOS final formItems = <FormItem>[
#FORM_ITEMS FormItem(
ElevatedButton(
- onPressed: () => search(), child: Text(i18n.tr('Search'))),
+ onPressed: () => search(),
+ child: Text(i18n.tr('Search'))),
weight: 12,
gapAbove: padding),
];
import '../../base/helper.dart';
import '../../base/i18n.dart';
import '../../base/validators.dart';
-import '../../services/global_widget.dart';
+#IMP_PERSISTENCEimport '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
import '../../widget/message_line.dart';
class EditUserCustom extends State<EditUserPage> with MessageLine {
#DEF_PRIMARY final globalData = GlobalData();
- AttendedPage? attendedPage;
+#DEF_FUTURE AttendedPage? attendedPage;
final _fieldData = _FieldData();
final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: 'EditUser');
#DEF_CONTROLLER EditUserCustom(#THIS_PRIMARY);
@override
Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('#PAGE_LABEL')),
+ drawer: globalData.drawerBuilder(context),
+ body: #BODY_BUILD
+ return rc;
+ }
+
+ Widget buildFrame() {
final padding = GlobalThemeData.padding;
-#INIT_COMBO#LOAD_RECORD#ASSIGN_CONTROLLER final formItems = <FormItem>[
+#INIT_COMBO#ASSIGN_CONTROLLER final formItems = <FormItem>[
#FORM_ITEMS FormItem(
ElevatedButton(
onPressed: () => #ACTION2(),
),
weight: 4)
];
- final rc = Scaffold(
- appBar: globalData.appBarBuilder(i18n.tr('#PAGE_LABEL')),
- 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,
- ))))));
+ final rc = Form(
+ key: _formKey,
+ child: Card(
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(
+ formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding,
+ ))));
return rc;
}
+#DIDCHANGE @override
+ void dispose() {
+ helperDummyUsage(DataType.int);
+ globalWidgetDummyUsage();
+#DISP_CONTROLLER super.dispose();
+ }
+
@override
void initState() {
super.initState();
#ACTION1();
}
}
-
- @override
- void dispose() {
- helperDummyUsage(DataType.int);
- globalWidgetDummyUsage();
-#DISP_CONTROLLER super.dispose();
- }
}
class _FieldData {
- bool isFromBackend = false;
#DEF_FIELD
#FROM_MAP#TO_MAP}
''';
''';
static final templateStorageDoneEdit = '''
- _fieldData.isFromBackend = false;
attendedPage!.pageStates.dbDataState.clear();
setState(() => 1);
''';
}
var validator = '';
if (validators.length == 1) {
- validator = ' validator: (input) => ${validators[0]},\n';
+ validator = ' validator: (input) => ${validators[0]},\n';
} else if (validators.length > 1) {
validator =
- ' validator: (input) => validateMultiple(input, [\n';
+ ' validator: (input) => validateMultiple(input, [\n';
for (var item in validators) {
validator += ' (input) => $item(input),\n';
}
? "jsonToObject(value ?? '', dataType: DataType.date)"
: "jsonToObject(value ?? '', dataType: ${field.dataType})");
rc = '''^TextFormField(
-#CONTR^ decoration: InputDecoration(labelText: i18n.tr('${field.label}')),
-#VALIDATOR^ onSaved: (value) => _fieldData.$name = $value
+#CONTR^ decoration: InputDecoration(labelText: i18n.tr('${field.label}')),
+#VALIDATOR^ onSaved: (value) => _fieldData.$name = $value
^)'''
.replaceFirst('#CONTR',
- withController ? '^ controller: ${name}Controller,\n' : '')
+ withController ? '^ controller: ${name}Controller,\n' : '')
.replaceFirst('#VALIDATOR', validator)
.replaceAll('^', indent);
break;
name2 = field.name;
}
rc = '''^DropdownButtonFormField<int>(
-^ value: _fieldData.$name,
+^ value: items$name2 == null || items$name2.length == 1
+^ ? 0
+^ : _fieldData.$name,
^ items: items$name2,
^ isExpanded: true,
^ decoration: InputDecoration(labelText: i18n.tr('${field.label}')),
return buffer.toString();
}
- /// Creates the part for loading the field data from the backend for [page].
- String buildLoadRecord(PageMetaData page) {
- String? rc;
- if (page.pageType == PageType.edit || page.pageType == PageType.delete) {
- rc = ''' if (!_fieldData.isFromBackend) {
- attendedPage?.loadRecord(
- name: 'record',
- reload: () => setState(() => 1),
- onDone: (record) {
- _fieldData.fromMap(record);
- _fieldData.isFromBackend = true;
- },
- parameters: {
- 'module': '${page.module.moduleName}',
- 'sql': 'byId',
- ':id': primaryKey
- });
- }
-''';
- }
- return rc ?? '';
- }
-
/// Creates the parameter definition of the [page].
///
/// The parameters will be used for storing the record at the backend.
var sqlType = '';
var setPrimary = '';
var callToMap = '';
+ var body = templateBodyLoadData;
+ var didChangeDependencies = templateDidChangeDependencies;
+ var definitionFuture = ' late Future<DbData> _futureDbData;';
+ var importPersistence = "import '../../persistence/persistence.dart';\n";
page.pageType == PageType.edit
? 'update'
: (page.pageType == PageType.delete ? 'delete' : 'insert');
sqlType = 'insert';
storageDone = templateStorageDoneCreate.replaceFirst(
'#MODULE', page.module.moduleName);
+ body = templateBodySimple;
+ didChangeDependencies = '';
+ definitionFuture = '';
+ importPersistence = '';
break;
case PageType.edit:
callToMap = ' _fieldData.toMap(parameters);\n';
break;
}
var rc = replaceVariables(templateRecordCustom, page)
+ .replaceFirst('#DIDCHANGE', didChangeDependencies)
.replaceFirst('#DEF_CONTROLLER', buildDefinitionControllers(page))
.replaceFirst('#INIT_COMBO', buildInitializeComboBoxes(page))
.replaceFirst('#FORM_ITEMS', buildFormItems(page, withController: true))
- .replaceFirst('#LOAD_RECORD', buildLoadRecord(page))
.replaceFirst('#PAGE_LABEL', page.label)
+ .replaceFirst('#BODY_BUILD', body)
.replaceFirst('#SQL_TYPE', sqlType)
.replaceFirst('#SET_PRIMARY', setPrimary)
.replaceFirst('#CALL_TO_MAP', callToMap)
'#DEF_PRIMARY', hasPrimary ? ' final int primaryKey;\n' : '')
.replaceFirst('#THIS_PRIMARY', hasPrimary ? 'this.primaryKey' : '')
.replaceFirst('#TO_MAP', buildToMap(page))
- .replaceFirst('#FROM_MAP', buildFromMap(page));
+ .replaceFirst('#FROM_MAP', buildFromMap(page))
+ .replaceFirst('#DEF_FUTURE', definitionFuture)
+ .replaceFirst('#IMP_PERSISTENCE', importPersistence);
return rc;
}
dependencies:
flutter:
sdk: flutter
+# provider: ^6.0.1
path: ^1.8.0
yaml: ^3.1.0
dart_bones: ^1.2.2
- url_launcher: ^6.0.9
- flutter_markdown: ^0.6.1
- flutter_bloc: ^7.1.0
- equatable: ^2.0.3
- permission_handler: ^8.1.6
- path_provider: ^2.0.1
+ url_launcher: ^6.0.12
+ flutter_markdown: ^0.6.8
+# flutter_bloc: ^7.1.0
+# equatable: ^2.0.3
+ permission_handler: ^8.2.5
+ path_provider: ^2.0.5
synchronized: ^3.0.0
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^1.0.2
+ # cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
- flutter_lints: ^1.0.0
+ flutter_lints: ^1.0.4
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec