From 8d0544af47e84d69aacfd7f37952059cc9d524fe Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Sat, 14 Nov 2020 00:03:15 +0100 Subject: [PATCH] daily work --- lib/main.dart | 3 +- lib/src/helper/name_builder.dart | 39 +++++ lib/src/model/all_db_fields_model.dart | 16 +- lib/src/model/button_model.dart | 17 +-- lib/src/model/checkbox_model.dart | 13 +- lib/src/model/column_model.dart | 11 +- lib/src/model/combo_base_model.dart | 16 +- lib/src/model/combobox_model.dart | 11 +- lib/src/model/db_reference_model.dart | 35 ++--- lib/src/model/empty_line_model.dart | 15 +- lib/src/model/field_model.dart | 23 ++- lib/src/model/model_base.dart | 90 +++++++---- lib/src/model/module_model.dart | 15 +- lib/src/model/page_model.dart | 61 ++++---- lib/src/model/section_model.dart | 62 ++++---- .../model/standard/configuration_model.dart | 11 +- lib/src/model/standard/menu_model.dart | 6 +- lib/src/model/standard/role_model.dart | 6 +- lib/src/model/standard/user_model.dart | 24 +-- lib/src/model/table_model.dart | 14 +- lib/src/model/text_field_model.dart | 14 +- lib/src/model/text_model.dart | 17 ++- lib/src/model/widget_model.dart | 41 ++--- .../configuration_change_page.dart | 12 +- .../configuration_controller.dart | 8 +- .../configuration_create_page.dart | 12 +- lib/src/page/role/role_change_page.dart | 8 +- lib/src/page/role/role_create_page.dart | 9 +- lib/src/page/role/role_list_page.dart | 2 +- lib/src/page/user/user_controller.dart | 1 - lib/src/page/user/user_password_page.dart | 3 +- lib/src/widget/edit_form.dart | 2 +- lib/src/widget/list_form.dart | 7 +- lib/src/widget/model_list.dart | 103 +++++++++++++ lib/src/widget/page_controller_bones.dart | 44 +++--- lib/src/widget/view.dart | 42 +++--- lib/src/widget/widget_list.dart | 99 ------------ lib/src/widget/widget_validators.dart | 38 ++--- test/helpers/name_builder_test.dart | 20 +++ test/model/db_model_test.dart | 28 ++-- test/model/model_test.dart | 141 +++++++++--------- test/model/standard_test.dart | 124 +++++++-------- test/tool/tool_test.dart | 2 +- test/widget/widget_test.dart | 42 +++--- test/widget/widget_validators_test.dart | 14 +- 45 files changed, 706 insertions(+), 615 deletions(-) create mode 100644 lib/src/helper/name_builder.dart create mode 100644 lib/src/widget/model_list.dart delete mode 100644 lib/src/widget/widget_list.dart create mode 100644 test/helpers/name_builder_test.dart diff --git a/lib/main.dart b/lib/main.dart index 29a9d9e..c2e5771 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bones/app.dart'; -void main(List args) { - //args.length > 1 && args[0].startsWith('--') && +void main() { runApp(BoneApp()); } diff --git a/lib/src/helper/name_builder.dart b/lib/src/helper/name_builder.dart new file mode 100644 index 0000000..ff90f29 --- /dev/null +++ b/lib/src/helper/name_builder.dart @@ -0,0 +1,39 @@ +import 'package:dart_bones/dart_bones.dart'; + +/// A Builder for programmatically created names. +class NameBuilder { + final counterMap = {}; + BaseLogger logger; + NameBuilder(this.logger); + + /// Returns a unique name with a given [prefix] followed by a current number. + String nextName(String prefix) { + String rc; + if (prefix != null) { + int no; + if (counterMap.containsKey(prefix)) { + no = ++counterMap[prefix]; + } else { + counterMap[prefix] = no = 1; + } + rc = prefix + no.toString(); + } + return rc; + } + + /// Dumps the [counterMap] as a string. + String dump({String indention = ''}) { + final rc = StringBuffer(); + rc.write(indention); + rc.write('Prefix:Number'); + rc.write('\n'); + counterMap.forEach((key, value) { + rc.write(indention); + rc.write(key); + rc.write(':'); + rc.write(value); + rc.write('\n'); + }); + return rc.toString(); + } +} diff --git a/lib/src/model/all_db_fields_model.dart b/lib/src/model/all_db_fields_model.dart index cc1530d..65b591b 100644 --- a/lib/src/model/all_db_fields_model.dart +++ b/lib/src/model/all_db_fields_model.dart @@ -5,6 +5,7 @@ import 'page_model.dart'; import 'section_model.dart'; import 'table_model.dart'; import 'widget_model.dart'; +import 'model_base.dart'; /// Describes a text widget without user interaction. class AllDbFieldsModel extends WidgetModel { @@ -12,32 +13,27 @@ class AllDbFieldsModel extends WidgetModel { String text; bool isRichText; - AllDbFieldsModel( - SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.allDbFields, null, logger); + AllDbFieldsModel(SectionModel section, PageModel page, BaseLogger logger) + : super(section, page, ModelTypeBones.allDbFields, null, logger); /// Returns the name including the names of the parent @override - String fullName() => '${section.name}.allDbFields$id'; + String fullName() => '${section.name}.$name'; /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { - stringBuffer.write(' allDbFields $id options: ${options.join(' ')}\n'); + stringBuffer.write(' allDbFields $name options: ${options.join(' ')}\n'); return stringBuffer; } /// Parses the [map] and stores the data in the instance. void parse(Map map) { super.parse(map); - checkSuperfluousAttributes(map, 'options widgetType'.split(' ')); - options = parseOptions('options', map); + checkSuperfluousAttributes(map, 'modelType name options'.split(' ')); addFieldsOfTable(page.module.mainTable()); checkOptionsByRegExpr(regExprOptions); } - @override - String widgetName() => 'allDbFields$id'; - void addFieldsOfTable(TableModel table) { bool isCreatePage = page.pageModelType == PageModelType.create; table.columns.forEach((col) { diff --git a/lib/src/model/button_model.dart b/lib/src/model/button_model.dart index cfc10dd..55bf4d6 100644 --- a/lib/src/model/button_model.dart +++ b/lib/src/model/button_model.dart @@ -3,19 +3,19 @@ import 'model_types.dart'; import 'widget_model.dart'; import 'section_model.dart'; import 'page_model.dart'; +import 'model_base.dart'; /// Describes a button widget. class ButtonModel extends WidgetModel { static final regExprOptions = RegExp(r'^(undef)$'); String label; - String name; String toolTip; ButtonModelType buttonModelType; VoidCallbackBones onPressed; /// Constructs an instance by parsing the map for some properties. ButtonModel(SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.button, null, logger); + : super(section, page, ModelTypeBones.button, null, logger); /// Constructs an instance with all properties given. ButtonModel.direct( @@ -26,7 +26,7 @@ class ButtonModel extends WidgetModel { ButtonModelType buttonModelType, List options, BaseLogger logger) - : super(section, page, WidgetModelType.button, options, logger) { + : super(section, page, ModelTypeBones.button, options, logger) { this.name = name; this.label = text; this.toolTip = toolTip; @@ -37,7 +37,7 @@ class ButtonModel extends WidgetModel { /// Dumps a the instance into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { stringBuffer.write( - ' button $name: text: options: $label ${listToString(options)}\n'); + ' button $name: label: $label options: $label ${listToString(options)}\n'); return stringBuffer; } @@ -47,21 +47,16 @@ class ButtonModel extends WidgetModel { /// Parses the [map]and stores the data in the instance. void parse(Map map) { - name = parseString('name', map, required: true); super.parse(map); - checkSuperfluousAttributes(map, - 'buttonType label name options text toolTip widgetType'.split(' ')); + checkSuperfluousAttributes( + map, 'buttonType label modelType name options text toolTip'.split(' ')); label = parseString('label', map, required: true); toolTip = parseString('toolTip', map); buttonModelType = parseEnum('buttonType', map, ButtonModelType.values); buttonModelType ??= ButtonModelType.custom; - options = parseOptions('options', map); checkOptionsByRegExpr(regExprOptions); } - - @override - String widgetName() => name; } enum ButtonModelType { diff --git a/lib/src/model/checkbox_model.dart b/lib/src/model/checkbox_model.dart index 7d99b81..285b734 100644 --- a/lib/src/model/checkbox_model.dart +++ b/lib/src/model/checkbox_model.dart @@ -3,29 +3,28 @@ import 'package:dart_bones/dart_bones.dart'; import 'field_model.dart'; import 'page_model.dart'; import 'section_model.dart'; -import 'widget_model.dart'; +import 'model_base.dart'; /// Describes a checkbox widget. class CheckboxModel extends FieldModel { static final regExprOptions = RegExp(r'^(readonly|disabled|required|undef)$'); - CheckboxModel( - SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.checkbox, logger); + CheckboxModel(SectionModel section, PageModel page, BaseLogger logger) + : super(section, page, ModelTypeBones.checkbox, logger); /// Parses the [map]and stores the data in the instance. void parse(Map map) { super.parse(map); checkSuperfluousAttributes( - map, 'name label options toolTip widgetType'.split(' ')); + map, 'modelType name label options toolTip'.split(' ')); checkOptionsByRegExpr(regExprOptions); parseFinish(); } /// Dumps the instance into a [StringBuffer] StringBuffer dump(StringBuffer stringBuffer) { - stringBuffer - .write(' checkbox $name: text: options: ${listToString(options)}\n'); + stringBuffer.write( + ' checkbox $name: "${label ?? ''}" options: ${listToString(options)}\n'); return stringBuffer; } } diff --git a/lib/src/model/column_model.dart b/lib/src/model/column_model.dart index 255ce95..6c73f4b 100644 --- a/lib/src/model/column_model.dart +++ b/lib/src/model/column_model.dart @@ -5,7 +5,6 @@ import 'combo_base_model.dart'; import 'model_base.dart'; import 'model_types.dart'; import 'table_model.dart'; -import 'widget_model.dart'; /// Describes a column of a database table. class ColumnModel extends ComboBaseModel { @@ -21,7 +20,7 @@ class ColumnModel extends ComboBaseModel { /// A constructor used in the parser. ColumnModel(this.table, BaseLogger logger) - : super(null, null, WidgetModelType.column, logger); + : super(null, null, ModelTypeBones.column, logger); /// A constructor for columns created by the program. ColumnModel.direct( @@ -49,7 +48,7 @@ class ColumnModel extends ComboBaseModel { listOption: listOption, listType: listType, options: options, - widgetType: WidgetModelType.column, + modelType: ModelTypeBones.column, logger: logger); /// Dumps the instance into a [StringBuffer] @@ -65,11 +64,13 @@ class ColumnModel extends ComboBaseModel { /// Parses the [map]and stores the data in the instance. void parse(Map map) { - name = parseString('column', map, required: true); super.parse(map); + if (name == null) { + name = table.nameBuilder.nextName('autoColumn'); + } checkSuperfluousAttributes( map, - 'column dataType defaultValue foreignKey label listOption listType options rows size texts tooTip validators validatorsText values widgetType' + 'column dataType defaultValue foreignKey label listOption listType modelType options rows size texts tooTip validators validatorsText values' .split(' ')); dataType = parseEnum('dataType', map, DataType.values, required: true); diff --git a/lib/src/model/combo_base_model.dart b/lib/src/model/combo_base_model.dart index 171474a..25eb0d7 100644 --- a/lib/src/model/combo_base_model.dart +++ b/lib/src/model/combo_base_model.dart @@ -4,7 +4,7 @@ import 'field_model.dart'; import 'model_types.dart'; import 'page_model.dart'; import 'section_model.dart'; -import 'widget_model.dart'; +import 'model_base.dart'; /// A base class for combobox items like ComboboxModel, ColumnModel and DbReferenceModel. abstract class ComboBaseModel extends FieldModel { @@ -18,9 +18,9 @@ abstract class ComboBaseModel extends FieldModel { ComboboxListType listType; ComboboxData data; - ComboBaseModel(SectionModel section, PageModel page, - WidgetModelType widgetType, BaseLogger logger) - : super(section, page, widgetType, logger); + ComboBaseModel(SectionModel section, PageModel page, ModelTypeBones modelType, + BaseLogger logger) + : super(section, page, modelType, logger); ComboBaseModel.direct( {SectionModel section, @@ -34,11 +34,11 @@ abstract class ComboBaseModel extends FieldModel { this.values, this.listOption, this.listType, - WidgetModelType widgetType, + ModelTypeBones modelType, dynamic defaultValue, BaseLogger logger}) - : super.direct(section, page, widgetType, name, label, toolTip, - dataType, options, defaultValue, logger); + : super.direct(section, page, modelType, name, label, toolTip, dataType, + defaultValue, options, logger); /// Transfers the list data from [texts] and [values] to [data]. /// May only called for comboboxes with [listType] = [ComboboxListType.explicite]. @@ -112,7 +112,7 @@ class ComboboxData { List _values; WaitState waitState; - ComboboxData(this.texts, this._values, [this.waitState = WaitState.undef]){ + ComboboxData(this.texts, this._values, [this.waitState = WaitState.undef]) { this._values ??= this.texts; } diff --git a/lib/src/model/combobox_model.dart b/lib/src/model/combobox_model.dart index 819dfe7..4d6ae24 100644 --- a/lib/src/model/combobox_model.dart +++ b/lib/src/model/combobox_model.dart @@ -3,20 +3,19 @@ import 'package:dart_bones/dart_bones.dart'; import 'combo_base_model.dart'; import 'page_model.dart'; import 'section_model.dart'; -import 'widget_model.dart'; +import 'model_base.dart'; /// Describes a combobox widget. class ComboboxModel extends ComboBaseModel { static final regExprOptions = RegExp(r'^(disabled|readonly|required|undef)$'); - ComboboxModel( - SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.combobox, logger); + ComboboxModel(SectionModel section, PageModel page, BaseLogger logger) + : super(section, page, ModelTypeBones.combobox, logger); /// Dumps the instance into a [StringBuffer] StringBuffer dump(StringBuffer stringBuffer) { stringBuffer.write( - ' combobox $name: texts: ${listToString(texts)} options: ${options.join(' ')}\n'); + ' combobox $name: "$label" texts: ${listToString(texts)} options: ${options.join(' ')}\n'); return stringBuffer; } @@ -24,7 +23,7 @@ class ComboboxModel extends ComboBaseModel { void parse(Map map) { checkSuperfluousAttributes( map, - 'dataType defaultValue filterType label listOption listType name options texts toolTip values validators validatorsText widgetType' + 'dataType defaultValue filterType label listOption listType modelType name options texts toolTip values validators validatorsText' .split(' ')); super.parse(map); checkOptionsByRegExpr(regExprOptions); diff --git a/lib/src/model/db_reference_model.dart b/lib/src/model/db_reference_model.dart index 38b99d8..cb28c79 100644 --- a/lib/src/model/db_reference_model.dart +++ b/lib/src/model/db_reference_model.dart @@ -4,7 +4,7 @@ import 'column_model.dart'; import 'combo_base_model.dart'; import 'page_model.dart'; import 'section_model.dart'; -import 'widget_model.dart'; +import 'model_base.dart'; /// Describes a form text field widget. class DbReferenceModel extends ComboBaseModel { @@ -16,9 +16,8 @@ class DbReferenceModel extends ComboBaseModel { ColumnModel column; /// A constructor fetching the properties by parsing the map. - DbReferenceModel( - SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.dbReference, logger); + DbReferenceModel(SectionModel section, PageModel page, BaseLogger logger) + : super(section, page, ModelTypeBones.dbReference, logger); /// A constructor without map parsing. DbReferenceModel.fromColumn(SectionModel section, PageModel page, @@ -26,7 +25,7 @@ class DbReferenceModel extends ComboBaseModel { : super.direct( section: section, page: page, - widgetType: WidgetModelType.dbReference, + modelType: ModelTypeBones.dbReference, name: column.name, label: column.label, toolTip: column.toolTip, @@ -53,8 +52,8 @@ class DbReferenceModel extends ComboBaseModel { /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { - stringBuffer - .write(' textField $name: options: ${listToString(options)}\n'); + stringBuffer.write( + ' textField $name: "$label" options: ${listToString(options)}\n'); return stringBuffer; } @@ -62,25 +61,23 @@ class DbReferenceModel extends ComboBaseModel { void parse(Map map) { checkSuperfluousAttributes( map, - 'column filterType label maxSize listOption listType name options rows toolTip texts widgetType values' + 'column filterType label maxSize listOption listType modelType name options rows toolTip texts values' .split(' ')); super.parse(map); final columnName = parseString('column', map, required: true); column = page.module.getColumn(columnName, this); maxSize = parseInt('maxSize', map, required: false); rows = parseInt('rows', map, required: false); - options = parseOptions('options', map); - label ??= column.label; - toolTip ??= column.toolTip; - filterType ??= column.filterType; - options = parseOptions('options', map); - dataType = column.dataType; - texts ??= column.texts; - values ??= column.values; - listOption ??= column.listOption; - listType ??= column.listType; + label ??= column?.label; + toolTip ??= column?.toolTip; + filterType ??= column?.filterType; + dataType = column?.dataType; + texts ??= column?.texts; + values ??= column?.values; + listOption ??= column?.listOption; + listType ??= column?.listType; checkOptionsByRegExpr(regExprOptions); - options += column.options; + options += column?.options ?? []; parseFinish(); } } diff --git a/lib/src/model/empty_line_model.dart b/lib/src/model/empty_line_model.dart index e133b70..9bfa2c4 100644 --- a/lib/src/model/empty_line_model.dart +++ b/lib/src/model/empty_line_model.dart @@ -3,33 +3,30 @@ import 'package:dart_bones/dart_bones.dart'; import 'page_model.dart'; import 'section_model.dart'; import 'widget_model.dart'; +import 'model_base.dart'; /// Describes an empty line used as separator between two other widgets. class EmptyLineModel extends WidgetModel { static final regExprOptions = RegExp(r'^(unknown)$'); bool isRichText; - EmptyLineModel( - SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.emptyLine, null, logger); + EmptyLineModel(SectionModel section, PageModel page, BaseLogger logger) + : super(section, page, ModelTypeBones.emptyLine, null, logger); /// Dumps the instance into a [StringBuffer] StringBuffer dump(StringBuffer stringBuffer) { - stringBuffer.write(' emptyLine: options: ${options.join(' ')}\n'); + stringBuffer.write(' emptyLine $name: options: ${options.join(' ')}\n'); return stringBuffer; } /// Returns the name including the names of the parent @override - String fullName() => '${section.name}.${widgetName()}'; + String fullName() => '${section.name}.$name'; /// Parses the [map]and stores the data in the instance. void parse(Map map) { super.parse(map); - checkSuperfluousAttributes(map, 'options widgetType'.split(' ')); + checkSuperfluousAttributes(map, 'modelType options'.split(' ')); checkOptionsByRegExpr(regExprOptions); } - - @override - String widgetName() => 'emptyLine$id'; } diff --git a/lib/src/model/field_model.dart b/lib/src/model/field_model.dart index 174c642..af820d0 100644 --- a/lib/src/model/field_model.dart +++ b/lib/src/model/field_model.dart @@ -5,6 +5,7 @@ import 'model_types.dart'; import 'page_model.dart'; import 'section_model.dart'; import 'widget_model.dart'; +import 'model_base.dart'; typedef FieldValidator = String Function( String input, FieldModel model, ValidatorController controller); @@ -21,7 +22,6 @@ abstract class FieldModel extends WidgetModel { 'dateTime|email|int|maxDate|maxDateTime|maxInt|minDate|minDateTime|minInt|regExpr|required|unique'; static const reValidatorTextItem = '^($reValidatorNames)\$'; static final regExprValidatorText = RegExp(reValidatorTextItem); - String name; String label; String toolTip; DataType dataType; @@ -46,14 +46,14 @@ abstract class FieldModel extends WidgetModel { final messageOfValidator = {}; FieldModel(SectionModel section, PageModel page, - WidgetModelType fieldModelType, BaseLogger logger) + ModelTypeBones fieldModelType, BaseLogger logger) : super(section, page, fieldModelType, null, logger); FieldModel.direct( SectionModel section, PageModel page, - WidgetModelType widgetModelType, - this.name, + ModelTypeBones modelType, + String name, this.label, this.toolTip, this.dataType, @@ -61,7 +61,9 @@ abstract class FieldModel extends WidgetModel { List options, BaseLogger logger, [this.filterType]) - : super(section, page, widgetModelType, options, logger); + : super(section, page, modelType, options, logger) { + this.name = name; + } get value => _value; @@ -177,20 +179,16 @@ abstract class FieldModel extends WidgetModel { /// Parses the [map]and stores the data in the instance. void parse(Map map) { - name = parseString( - widgetModelType == WidgetModelType.column ? 'column' : 'name', map, - required: true); super.parse(map); label = parseString('label', map, required: false); toolTip = parseString('toolTip', map, required: false); filterType = parseEnum('filterType', map, FilterType.values); - options = parseOptions('options', map); validatorsString = parseString('validators', map); parseValidatorsText(parseString('validatorsText', map)); dataType = parseEnum('dataType', map, DataType.values); if (dataType == null) { - switch (widgetModelType) { - case WidgetModelType.checkbox: + switch (modelType) { + case ModelTypeBones.checkbox: dataType = DataType.bool; break; default: @@ -265,9 +263,6 @@ abstract class FieldModel extends WidgetModel { value = row[name]; } } - - @override - String widgetName() => name; } abstract class ValidatorController {} diff --git a/lib/src/model/model_base.dart b/lib/src/model/model_base.dart index 1ada1d6..8e614c4 100644 --- a/lib/src/model/model_base.dart +++ b/lib/src/model/model_base.dart @@ -1,5 +1,6 @@ import 'package:dart_bones/dart_bones.dart'; import 'package:meta/meta.dart'; + import '../helper/string_helper.dart'; import 'model_types.dart'; @@ -7,11 +8,13 @@ import 'model_types.dart'; abstract class ModelBase { BaseLogger logger; List options; + String name; + static int lastId = 0; + final ModelTypeBones modelType; + int id; - ModelBase(this.options, this.logger); - - void parse(Map map) { - options = parseOptions('options', map); + ModelBase(this.modelType, this.options, this.logger) { + this.id = ++lastId; } /// Tests the validity of the entries in [options] comparing with an [regExpr]. @@ -27,15 +30,6 @@ abstract class ModelBase { return rc; } - /// Tests whether a given [option] is part of [options]. - bool hasOption(String option) { - if (options == null) { - return false; - } - bool rc = options.contains(option); - return rc; - } - /// Tests a [map] for superfluous [keys]. /// Keys of the [map] that are not listed in [keys] will be logged as errors. /// Keys that do not have the type String are logged as errors. @@ -50,12 +44,48 @@ abstract class ModelBase { /// Returns the name including the names of the parent String fullName(); + /// Tests whether a given [option] is part of [options]. + bool hasOption(String option) { + if (options == null) { + return false; + } + bool rc = options.contains(option); + return rc; + } + /// Converts a [list] of strings to a string. String listToString(List list) { final rc = list == null ? 'null' : list.join(' '); return rc; } + /// Parses the [map] for properties of ModelBase. + /// [nameLabel]: the key of the name property, e.g. "name". + /// [required]: if true and the property is not part of the map an error will + /// be logged. + /// Note: Does not make a automatic name if not required: it must be done + /// by the caller. Reason: different parents TableModel and PageModel to hold + /// the [NameBuilder] instance. + void parseBase(Map map, {String nameLabel = 'name', bool required = false}) { + name = parseString(nameLabel, map, required: required); + options = parseOptions('options', map); + } + + /// Fetches an entry from a map addressed by a [key]. + /// An error is logged if [required] is true and the map does not contain the key. + dynamic parseDynamic(String key, Map map, + {bool required = false}) { + dynamic rc; + if (!map.containsKey(key)) { + if (required) { + logger.error('missing int attribute "$key" in ${fullName()}'); + } + } else { + rc = map[key]; + } + return rc; + } + /// Fetches an entry from a map addressed by a [key]. /// An error is logged if [required] is true and the map does not contain the key. T parseEnum(String key, Map map, List values, @@ -107,21 +137,6 @@ abstract class ModelBase { return rc; } - /// Fetches an entry from a map addressed by a [key]. - /// An error is logged if [required] is true and the map does not contain the key. - dynamic parseDynamic(String key, Map map, - {bool required = false}) { - dynamic rc; - if (!map.containsKey(key)) { - if (required) { - logger.error('missing int attribute "$key" in ${fullName()}'); - } - } else { - rc = map[key]; - } - return rc; - } - /// Fetches an entry from a map addressed by a [key]. /// An error is logged if [required] is true and the map does not contain the key. List parseOptions(String key, Map map) { @@ -224,7 +239,7 @@ abstract class ModelBase { return rc; } - String widgetName(); + String widgetName() => name; /// Tests whether an [object] is a list type. /// Works for JSArray, List @@ -240,3 +255,20 @@ abstract class ModelBase { return name.contains('Map'); } } + +enum ModelTypeBones { + allDbFields, + button, + checkbox, + column, + combobox, + dbReference, + emptyLine, + image, + module, + page, + section, + table, + text, + textField, +} diff --git a/lib/src/model/module_model.dart b/lib/src/model/module_model.dart index e283b45..9ecc131 100644 --- a/lib/src/model/module_model.dart +++ b/lib/src/model/module_model.dart @@ -2,6 +2,7 @@ import 'package:dart_bones/dart_bones.dart'; import 'package:meta/meta.dart'; import '../helper/string_helper.dart'; +import '../helper/name_builder.dart'; import 'column_model.dart'; import 'field_model.dart'; import 'model_base.dart'; @@ -17,12 +18,14 @@ import 'widget_model.dart'; class ModuleModel extends ModelBase { static final regExprOptions = RegExp(r'^(noPages)$'); final Map map; - String name; @protected final pages = []; final tables = []; - - ModuleModel(this.map, BaseLogger logger) : super(null, logger); + NameBuilder nameBuilder; + ModuleModel(this.map, BaseLogger logger) + : super(ModelTypeBones.module, null, logger) { + nameBuilder = NameBuilder(logger); + } /// Adds the column [name] from [source] to [target] if that column is not member of [target]. void addColumnIfMissing( @@ -335,8 +338,7 @@ modules: /// Parses the [map]and stores the data in the instance. void parse([Map map]) { map ??= this.map; - name = parseString('module', map, required: true); - super.parse(map); + super.parseBase(map, nameLabel: 'module', required: true); checkSuperfluousAttributes(map, 'module options pages tables'.split(' ')); if (map.containsKey('tables')) { TableModel.parseList(this, map['tables'], logger); @@ -363,7 +365,4 @@ modules: orElse: () => null); return found; } - - @override - String widgetName() => name; } diff --git a/lib/src/model/page_model.dart b/lib/src/model/page_model.dart index 20ceed6..536a843 100644 --- a/lib/src/model/page_model.dart +++ b/lib/src/model/page_model.dart @@ -1,5 +1,6 @@ import 'package:dart_bones/dart_bones.dart'; +import '../helper/name_builder.dart'; import 'button_model.dart'; import 'field_model.dart'; import 'model_base.dart'; @@ -13,7 +14,6 @@ typedef FilterWidget = bool Function(WidgetModel item); class PageModel extends ModelBase { static final regExprOptions = RegExp(r'^(noAutoButton)$'); final ModuleModel module; - String name; final List sections = []; PageModelType pageModelType; final fields = []; @@ -22,8 +22,12 @@ class PageModel extends ModelBase { String sql; List tableTitles; List tableColumns; + NameBuilder nameBuilder; - PageModel(this.module, BaseLogger logger) : super(null, logger); + PageModel(this.module, BaseLogger logger) + : super(ModelTypeBones.page, null, logger) { + nameBuilder = NameBuilder(logger); + } /// Adds a [button] to the [this.buttons]. /// If already defined and error is logged. @@ -36,24 +40,6 @@ class PageModel extends ModelBase { } } - /// Returns a button named [name] or null if not found. - ButtonModel buttonByName(String name, {bool required = true}) { - final rc = - buttons.firstWhere((item) => item.name == name, orElse: () => null); - if (rc == null && required) { - logger.error('missing button $name in page ${fullName()}'); - } - return rc; - } - - /// Tests whether the field with [name] is part of the page. - bool hasField(String name) { - final first = fields.firstWhere((element) => element.name == name, - orElse: () => null); - final rc = first != null; - return rc; - } - /// Adds a [field] to the [this.fields]. /// If already defined and error is logged. void addField(FieldModel field) { @@ -66,6 +52,16 @@ class PageModel extends ModelBase { } } + /// Returns a button named [name] or null if not found. + ButtonModel buttonByName(String name, {bool required = true}) { + final rc = + buttons.firstWhere((item) => item.name == name, orElse: () => null); + if (rc == null && required) { + logger.error('missing button $name in page ${fullName()}'); + } + return rc; + } + /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { stringBuffer @@ -76,10 +72,6 @@ class PageModel extends ModelBase { return stringBuffer; } - /// Returns the name including the names of the parent - @override - String fullName() => '${module.name}.$name'; - /// Returns a field by [name] or null on error. FieldModel fieldByName(String name, {bool required = true}) { final rc = fields.firstWhere((element) => element.name == name, @@ -90,6 +82,10 @@ class PageModel extends ModelBase { return rc; } + /// Returns the name including the names of the parent + @override + String fullName() => '${module.name}.$name'; + /// Returns a list of widget models (in order as defined) matching the [filter]. /// If [filter] is none all widgets will be returned. List getWidgets(FilterWidget filter) { @@ -104,9 +100,20 @@ class PageModel extends ModelBase { return rc; } + /// Tests whether the field with [name] is part of the page. + bool hasField(String name) { + final first = fields.firstWhere((element) => element.name == name, + orElse: () => null); + final rc = first != null; + return rc; + } + /// Parses the [map]and stores the data in the instance. void parse(Map map) { - name = parseString('page', map, required: true); + super.parseBase(map, nameLabel: 'page', required: true); + if (name == null) { + name = module.nameBuilder.nextName('autoPage'); + } checkSuperfluousAttributes( map, 'options page pageType sections sql tableColumns tableTitles' @@ -114,7 +121,6 @@ class PageModel extends ModelBase { pageModelType = parseEnum( 'pageType', map, PageModelType.values, required: true); - options = parseOptions('options', map); if (!map.containsKey('sections')) { logger.error('missing sections in page ${fullName()}'); } else { @@ -169,9 +175,6 @@ class PageModel extends ModelBase { checkOptionsByRegExpr(regExprOptions); } - @override - String widgetName() => name; - /// Returns a list of Pages constructed by the Json like [list]. static void parseList( ModuleModel module, List list, BaseLogger logger) { diff --git a/lib/src/model/section_model.dart b/lib/src/model/section_model.dart index 35b5430..fff2419 100644 --- a/lib/src/model/section_model.dart +++ b/lib/src/model/section_model.dart @@ -16,14 +16,12 @@ import 'widget_model.dart'; class SectionModel extends WidgetModel { static final regExprOptions = RegExp(r'^(unknown)$'); SectionModelType sectionModelType; - String name; final children = []; final buttons = []; final int no; - SectionModel(this.no, PageModel page, SectionModel section, - BaseLogger logger) - : super(section, page, WidgetModelType.section, null, logger); + SectionModel(this.no, PageModel page, SectionModel section, BaseLogger logger) + : super(section, page, ModelTypeBones.section, null, logger); /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { @@ -43,13 +41,14 @@ class SectionModel extends WidgetModel { /// Parses the [map]and stores the data in the instance. void parse(Map map) { + super.parseBase(map, nameLabel: 'section'); + if (name == null) { + name = page.nameBuilder.nextName('section'); + } sectionModelType = parseEnum( 'sectionType', map, SectionModelType.values); - name = parseString('name', map) ?? - '${StringUtils.enumToString(sectionModelType)}$no'; - checkSuperfluousAttributes( - map, 'children fields name options sectionType widgetType'.split(' ')); - options = parseOptions('options', map); + checkSuperfluousAttributes(map, + 'children fields modelType section options sectionType'.split(' ')); checkOptionsByRegExpr(regExprOptions); if (!map.containsKey('children')) { @@ -68,57 +67,57 @@ class SectionModel extends WidgetModel { .error('child $no of "children" is not a map in ${fullName()}: ' '${StringUtils.limitString(child.toString(), 80)}'); } else { - if (!child.containsKey('widgetType')) { + if (!child.containsKey('modelType')) { logger.error( - 'child $no of "children" does not have "widgetType" in ${fullName()}: ' + 'child $no of "children" does not have "modelType" in ${fullName()}: ' '${StringUtils.limitString(child.toString(), 80)}'); } else { - final widgetType = StringUtils.stringToEnum( - child['widgetType'].toString(), WidgetModelType.values); + final modelType = StringUtils.stringToEnum( + child['modelType'].toString(), ModelTypeBones.values); WidgetModel widget; - switch (widgetType) { - case WidgetModelType.allDbFields: + switch (modelType) { + case ModelTypeBones.allDbFields: widget = AllDbFieldsModel(this, page, logger); break; - case WidgetModelType.checkbox: + case ModelTypeBones.checkbox: widget = CheckboxModel(this, page, logger); break; - case WidgetModelType.combobox: + case ModelTypeBones.combobox: widget = ComboboxModel(this, page, logger); break; - case WidgetModelType.textField: + case ModelTypeBones.textField: widget = TextFieldModel(this, page, logger); break; - case WidgetModelType.button: + case ModelTypeBones.button: widget = ButtonModel(this, page, logger); break; - case WidgetModelType.text: + case ModelTypeBones.text: widget = TextModel(this, page, logger); break; - case WidgetModelType.emptyLine: + case ModelTypeBones.emptyLine: widget = EmptyLineModel(this, page, logger); break; - case WidgetModelType.dbReference: + case ModelTypeBones.dbReference: widget = DbReferenceModel(this, page, logger); break; default: //@ToDo: nested section logger.error( - 'Section: unknown "widgetType" ${child['widgetType']} in ${fullName()}'); + 'Section: unknown "modelType" ${child["modelType"]} in ${fullName()}'); break; } if (widget != null) { children.add(widget); widget.parse(child); page.widgets.add(widget); - switch (widget.widgetModelType) { - case WidgetModelType.button: + switch (widget.modelType) { + case ModelTypeBones.button: page.addButton(widget); break; - case WidgetModelType.textField: - case WidgetModelType.combobox: - case WidgetModelType.checkbox: - case WidgetModelType.dbReference: + case ModelTypeBones.textField: + case ModelTypeBones.combobox: + case ModelTypeBones.checkbox: + case ModelTypeBones.dbReference: page.addField(widget); break; default: @@ -144,18 +143,15 @@ class SectionModel extends WidgetModel { 'curious item in section list of ${page.fullName()}: ${StringUtils.limitString("$item", 80)}'); } else { final current = SectionModel(no, page, null, logger); - current.parse(item); if (section != null) { section.children.add(current); } else { page.sections.add(current); } + current.parse(item); } } } - - @override - String widgetName() => name; } enum SectionModelType { diff --git a/lib/src/model/standard/configuration_model.dart b/lib/src/model/standard/configuration_model.dart index 910a25b..f9b47df 100644 --- a/lib/src/model/standard/configuration_model.dart +++ b/lib/src/model/standard/configuration_model.dart @@ -26,7 +26,8 @@ class ConfigurationModel extends ModuleModel { 'size': 64, 'options': 'notnull', 'validators': r'required regExpr=i/^\w+$', - 'validatorsText': 'regExpr=Nur Buchstaben, Ziffern und Unterstrich erlaubt', + 'validatorsText': + 'regExpr=Nur Buchstaben, Ziffern und Unterstrich erlaubt', }, { 'column': 'configuration_property', @@ -72,7 +73,7 @@ class ConfigurationModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "allDbFields", + 'modelType': "allDbFields", } ] } @@ -86,7 +87,7 @@ class ConfigurationModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "allDbFields", + 'modelType': "allDbFields", } ] } @@ -105,14 +106,14 @@ class ConfigurationModel extends ModuleModel { { "name": "configuration_scope", "label": "Bereich", - "widgetType": "textField", + 'modelType': "textField", "filterType": "pattern", //"options": 'undef', }, { "name": "configuration_property", "label": "Eigenschaft", - "widgetType": "textField", + 'modelType': "textField", "filterType": "pattern", }, ] diff --git a/lib/src/model/standard/menu_model.dart b/lib/src/model/standard/menu_model.dart index 53eed8a..f4bf5ec 100644 --- a/lib/src/model/standard/menu_model.dart +++ b/lib/src/model/standard/menu_model.dart @@ -43,7 +43,7 @@ class MenuModel extends ModuleModel { 'sectionType': 'simpleForm', 'children': [ { - 'widgetType': 'allDbFields', + 'modelType': 'allDbFields', } ] } @@ -57,7 +57,7 @@ class MenuModel extends ModuleModel { 'sectionType': 'simpleForm', 'children': [ { - 'widgetType': 'allDbFields', + 'modelType': 'allDbFields', }, ] } @@ -73,7 +73,7 @@ class MenuModel extends ModuleModel { 'sectionType': 'filterPanel', 'children': [ { - 'widgetType': 'dbReference', + 'modelType': 'dbReference', 'filterType': 'pattern', 'name': 'menu_name', 'column': 'menu_name', diff --git a/lib/src/model/standard/role_model.dart b/lib/src/model/standard/role_model.dart index 24e7179..937f303 100644 --- a/lib/src/model/standard/role_model.dart +++ b/lib/src/model/standard/role_model.dart @@ -45,7 +45,7 @@ class RoleModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "allDbFields", + 'modelType': "allDbFields", } ] } @@ -59,7 +59,7 @@ class RoleModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "allDbFields", + 'modelType': "allDbFields", } ] } @@ -75,7 +75,7 @@ class RoleModel extends ModuleModel { "sectionType": "filterPanel", "children": [ { - "widgetType": "textField", + 'modelType': "textField", "filterType": "pattern", "name": "role_name", "label": "Name", diff --git a/lib/src/model/standard/user_model.dart b/lib/src/model/standard/user_model.dart index 0dc4c62..ef8a81e 100644 --- a/lib/src/model/standard/user_model.dart +++ b/lib/src/model/standard/user_model.dart @@ -66,7 +66,7 @@ class UserModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "allDbFields", + 'modelType': "allDbFields", } ] } @@ -80,10 +80,10 @@ class UserModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "allDbFields", + 'modelType': "allDbFields", }, { - "widgetType": "button", + 'modelType': "button", "name": "set_password", "label": "Passwort ändern", "buttonType": "custom", @@ -101,19 +101,19 @@ class UserModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "text", + 'modelType': "text", "text": "Ändern des Passworts von Benutzer ~user~", - "options": "placeholder" + "options": "placeholder h3" }, { - "widgetType": "textField", + 'modelType': "textField", "name": "user_password", "label": "Passwort", "options": "password", "validators": "required", }, { - "widgetType": "textField", + 'modelType': "textField", "name": "repetition", "label": "Wiederholung", "options": "password", @@ -134,7 +134,7 @@ class UserModel extends ModuleModel { "sectionType": "filterPanel", "children": [ { - "widgetType": "dbReference", + 'modelType': "dbReference", "filterType": "pattern", "name": "user_name", "column": "user_name", @@ -142,7 +142,7 @@ class UserModel extends ModuleModel { "Filter bezüglich des Namens der anzuzeigenden Einträge: Joker '*' (beliebiger String) ist erlaubt." }, { - "widgetType": "dbReference", + 'modelType': "dbReference", "name": "user_role", "filterType": "equals", "column": "user_role", @@ -162,20 +162,20 @@ class UserModel extends ModuleModel { "sectionType": "simpleForm", "children": [ { - "widgetType": "textField", + 'modelType': "textField", "name": "user", "label": "Benutzer oder EMail", "validators": "required", }, { - "widgetType": "textField", + 'modelType': "textField", "name": "password", "label": "Password", "options": "password", "validators": "required", }, { - "widgetType": "button", + 'modelType': "button", "buttonType": "custom", "name": "login", "label": "Anmelden", diff --git a/lib/src/model/table_model.dart b/lib/src/model/table_model.dart index 83ebf83..a77cabb 100644 --- a/lib/src/model/table_model.dart +++ b/lib/src/model/table_model.dart @@ -1,5 +1,6 @@ import 'package:dart_bones/dart_bones.dart'; +import '../helper/name_builder.dart'; import 'column_model.dart'; import 'model_base.dart'; import 'model_types.dart'; @@ -9,11 +10,14 @@ import 'module_model.dart'; class TableModel extends ModelBase { static final regExprOptions = RegExp(r'^(unknown)$'); final ModuleModel module; - String name; final columns = []; ColumnModel primary; + NameBuilder nameBuilder; - TableModel(this.module, BaseLogger logger) : super(null, logger); + TableModel(this.module, BaseLogger logger) + : super(ModelTypeBones.table, null, logger) { + nameBuilder = NameBuilder(logger); + } /// Adds a [button] to the [this.buttons]. /// If already defined and error is logged. @@ -69,9 +73,11 @@ class TableModel extends ModelBase { /// Parses the [map]and stores the data in the instance. void parse(Map map) { - name = parseString('table', map, required: true); + super.parseBase(map, nameLabel: 'table', required: true); + if (name == null) { + name = module.nameBuilder.nextName('autoTable'); + } checkSuperfluousAttributes(map, 'columns options table'.split(' ')); - options = parseOptions('options', map); if (!map.containsKey('columns')) { logger.error('missing columns in table ${fullName()}'); } else { diff --git a/lib/src/model/text_field_model.dart b/lib/src/model/text_field_model.dart index 8946e88..bbe4072 100644 --- a/lib/src/model/text_field_model.dart +++ b/lib/src/model/text_field_model.dart @@ -4,7 +4,7 @@ import 'field_model.dart'; import 'model_types.dart'; import 'page_model.dart'; import 'section_model.dart'; -import 'widget_model.dart'; +import 'model_base.dart'; /// Describes a form text field widget. class TextFieldModel extends FieldModel { @@ -14,9 +14,8 @@ class TextFieldModel extends FieldModel { int rows; var value; - TextFieldModel( - SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.textField, logger); + TextFieldModel(SectionModel section, PageModel page, BaseLogger logger) + : super(section, page, ModelTypeBones.textField, logger); TextFieldModel.direct( SectionModel section, @@ -28,8 +27,8 @@ class TextFieldModel extends FieldModel { List options, dynamic defaultValue, BaseLogger logger) - : super.direct(section, page, WidgetModelType.textField, name, - label, toolTip, dataType, options, defaultValue, logger); + : super.direct(section, page, ModelTypeBones.textField, name, label, + toolTip, dataType, defaultValue, options, logger); /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { @@ -43,7 +42,7 @@ class TextFieldModel extends FieldModel { super.parse(map); checkSuperfluousAttributes( map, - 'dataType filterType label maxSize name options rows toolTip validators validatorsText value widgetType' + 'dataType filterType label maxSize modelType name options rows toolTip validators validatorsText value' .split(' ')); maxSize = parseInt('maxSize', map, required: false); rows = parseInt('rows', map, required: false); @@ -56,7 +55,6 @@ class TextFieldModel extends FieldModel { value = parseString('value', map); break; } - options = parseOptions('options', map); checkOptionsByRegExpr(regExprOptions); parseFinish(); } diff --git a/lib/src/model/text_model.dart b/lib/src/model/text_model.dart index 59994c2..bc5104c 100644 --- a/lib/src/model/text_model.dart +++ b/lib/src/model/text_model.dart @@ -1,6 +1,7 @@ import 'package:dart_bones/dart_bones.dart'; import 'page_model.dart'; import 'section_model.dart'; +import 'model_base.dart'; import 'widget_model.dart'; /// Describes a text widget without user interaction. @@ -10,28 +11,28 @@ class TextModel extends WidgetModel { bool isRichText; TextModel(SectionModel section, PageModel page, BaseLogger logger) - : super(section, page, WidgetModelType.text, null, logger); + : super(section, page, ModelTypeBones.text, null, logger); /// Returns the name including the names of the parent @override - String fullName() => '${section.name}.text$id'; + String fullName() => '${section.name}.$name'; /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer) { stringBuffer - .write(' text $id text: $text: options: ${options.join(' ')}\n'); + .write(' text $name text: $text: options: ${options.join(' ')}\n'); return stringBuffer; } /// Parses the [map]and stores the data in the instance. void parse(Map map) { - checkSuperfluousAttributes(map, 'options text widgetType'.split(' ')); + super.parseBase(map); + if (name == null) { + name = page.nameBuilder.nextName('text'); + } + checkSuperfluousAttributes(map, 'modelType name options text'.split(' ')); text = parseString('text', map, required: true); - options = parseOptions('options', map); checkOptionsByRegExpr(regExprOptions); isRichText = options.contains('richText'); } - - @override - String widgetName() => 'text$id'; } diff --git a/lib/src/model/widget_model.dart b/lib/src/model/widget_model.dart index a7d4b02..8d8cc15 100644 --- a/lib/src/model/widget_model.dart +++ b/lib/src/model/widget_model.dart @@ -7,17 +7,12 @@ import 'combo_base_model.dart'; /// A base class for items inside a page: SectionModel ButtonModel TextModel... abstract class WidgetModel extends ModelBase { - static int lastId = 0; final SectionModel section; PageModel page; - final WidgetModelType widgetModelType; - int id; - WidgetModel(this.section, this.page, this.widgetModelType, + WidgetModel(this.section, this.page, ModelTypeBones modelType, List options, BaseLogger logger) - : super(options, logger) { - this.id = ++lastId; - } + : super(modelType, options, logger); /// Returns whether the model must be completed asynchronously e.g. by /// [Persistence]. @@ -29,24 +24,18 @@ abstract class WidgetModel extends ModelBase { /// Dumps the internal structure into a [stringBuffer] StringBuffer dump(StringBuffer stringBuffer); - void parse(Map map){ - super.parse(map); + void parse(Map map) { + final required = [ + ModelTypeBones.button, + ModelTypeBones.checkbox, + ModelTypeBones.combobox, + ModelTypeBones.dbReference, + ModelTypeBones.textField, + ].contains(modelType); + var label = modelType == ModelTypeBones.column ? 'column' : 'name'; + super.parseBase(map, nameLabel: label, required: required); + if (name == null && page != null) { + name = page.nameBuilder.nextName(StringUtils.enumToString(modelType)); + } } - - String widgetName(); -} - -enum WidgetModelType { - allDbFields, - button, - checkbox, - column, - combobox, - dbReference, - emptyLine, - image, - section, - table, - text, - textField, } diff --git a/lib/src/page/configuration/configuration_change_page.dart b/lib/src/page/configuration/configuration_change_page.dart index 1465cfb..e0867d0 100644 --- a/lib/src/page/configuration/configuration_change_page.dart +++ b/lib/src/page/configuration/configuration_change_page.dart @@ -29,7 +29,8 @@ class ConfigurationChangePage extends StatefulWidget { } } -class ConfigurationChangePageState extends State implements RedrawPage { +class ConfigurationChangePageState extends State + implements RedrawPage { final ApplicationData applicationData; final int primaryId; final Map initialRow; @@ -63,15 +64,18 @@ class ConfigurationChangePageState extends State implem _formKey, this, 'change', context, applicationData); controller.initialize(); } + void dispose() { controller.dispose(); super.dispose(); } @override - void redraw(RedrawReason reason, {String customString, RedrawCallbackFunctionSimple callback}) { - setState( () { - controller.afterSetState(reason, customString: customString, callback: callback); + void redraw(RedrawReason reason, + {String customString, RedrawCallbackFunctionSimple callback}) { + setState(() { + controller.afterSetState(reason, + customString: customString, callback: callback); }); } } diff --git a/lib/src/page/configuration/configuration_controller.dart b/lib/src/page/configuration/configuration_controller.dart index 5fc1f61..f0af060 100644 --- a/lib/src/page/configuration/configuration_controller.dart +++ b/lib/src/page/configuration/configuration_controller.dart @@ -8,12 +8,8 @@ import 'configuration_change_page.dart'; class ConfigurationController extends PageControllerBones { /// Controller for a page named [pageName]. - ConfigurationController( - GlobalKey formKey, - RedrawPage parent, - String pageName, - BuildContext context, - ApplicationData applicationData, + ConfigurationController(GlobalKey formKey, RedrawPage parent, + String pageName, BuildContext context, ApplicationData applicationData, {Function redrawCallback}) : super(formKey, parent, ConfigurationModel(Settings().logger), pageName, context, applicationData, redrawCallback) { diff --git a/lib/src/page/configuration/configuration_create_page.dart b/lib/src/page/configuration/configuration_create_page.dart index cb43aec..9d74df8 100644 --- a/lib/src/page/configuration/configuration_create_page.dart +++ b/lib/src/page/configuration/configuration_create_page.dart @@ -21,7 +21,8 @@ class ConfigurationCreatePage extends StatefulWidget { } } -class ConfigurationCreatePageState extends State implements RedrawPage { +class ConfigurationCreatePageState extends State + implements RedrawPage { final ApplicationData applicationData; final GlobalKey _formKey = @@ -51,10 +52,13 @@ class ConfigurationCreatePageState extends State implem _formKey, this, 'create', context, applicationData); controller.initialize(); } + @override - void redraw(RedrawReason reason, {String customString, RedrawCallbackFunctionSimple callback}) { - setState( () { - controller.afterSetState(reason, customString: customString, callback: callback); + void redraw(RedrawReason reason, + {String customString, RedrawCallbackFunctionSimple callback}) { + setState(() { + controller.afterSetState(reason, + customString: customString, callback: callback); }); } } diff --git a/lib/src/page/role/role_change_page.dart b/lib/src/page/role/role_change_page.dart index b05b475..3c12af1 100644 --- a/lib/src/page/role/role_change_page.dart +++ b/lib/src/page/role/role_change_page.dart @@ -27,7 +27,7 @@ class RoleChangePage extends StatefulWidget { } } -class RoleChangePageState extends State implements RedrawPage{ +class RoleChangePageState extends State implements RedrawPage { final ApplicationData applicationData; final int primaryId; final Map initialRow; @@ -52,11 +52,12 @@ class RoleChangePageState extends State implements RedrawPage{ initialRow: initialRow, )); } + @override void initState() { super.initState(); - controller = RoleController( - _formKey, this, 'change', context, applicationData); + controller = + RoleController(_formKey, this, 'change', context, applicationData); controller.initialize(); } @@ -68,6 +69,7 @@ class RoleChangePageState extends State implements RedrawPage{ customString: customString, callback: callback); }); } + void dispose() { controller.dispose(); super.dispose(); diff --git a/lib/src/page/role/role_create_page.dart b/lib/src/page/role/role_create_page.dart index 3d0cf8d..0ba6a1b 100644 --- a/lib/src/page/role/role_create_page.dart +++ b/lib/src/page/role/role_create_page.dart @@ -22,7 +22,7 @@ class RoleCreatePage extends StatefulWidget { } } -class RoleCreatePageState extends State implements RedrawPage{ +class RoleCreatePageState extends State implements RedrawPage { final ApplicationData applicationData; final GlobalKey _formKey = @@ -34,7 +34,7 @@ class RoleCreatePageState extends State implements RedrawPage{ @override Widget build(BuildContext context) { - controller.beginOfBuild(context); + controller?.beginOfBuild(context); return Scaffold( appBar: applicationData.appBarBuilder('Neue Rolle'), drawer: applicationData.drawerBuilder(context), @@ -44,11 +44,12 @@ class RoleCreatePageState extends State implements RedrawPage{ configuration: applicationData.configuration, )); } + @override void initState() { super.initState(); - controller = RoleController( - _formKey, this, 'create', context, applicationData); + controller = + RoleController(_formKey, this, 'create', context, applicationData); controller.initialize(); } diff --git a/lib/src/page/role/role_list_page.dart b/lib/src/page/role/role_list_page.dart index 6e53d7d..4719315 100644 --- a/lib/src/page/role/role_list_page.dart +++ b/lib/src/page/role/role_list_page.dart @@ -21,7 +21,7 @@ class RoleListPage extends StatefulWidget { } } -class RoleListPageState extends State implements RedrawPage{ +class RoleListPageState extends State implements RedrawPage { final ApplicationData applicationData; final GlobalKey _formKey = diff --git a/lib/src/page/user/user_controller.dart b/lib/src/page/user/user_controller.dart index 91d75e1..6519eae 100644 --- a/lib/src/page/user/user_controller.dart +++ b/lib/src/page/user/user_controller.dart @@ -23,5 +23,4 @@ class UserController extends PageControllerBones { MaterialPageRoute( builder: (context) => UserChangePage(id, applicationData, row))); } - } diff --git a/lib/src/page/user/user_password_page.dart b/lib/src/page/user/user_password_page.dart index 2b12617..cedfec3 100644 --- a/lib/src/page/user/user_password_page.dart +++ b/lib/src/page/user/user_password_page.dart @@ -32,7 +32,8 @@ class UserPasswordPage extends StatefulWidget { } } -class UserPasswordPageState extends State implements RedrawPage { +class UserPasswordPageState extends State + implements RedrawPage { final ApplicationData applicationData; final int primaryId; final String userName; diff --git a/lib/src/widget/edit_form.dart b/lib/src/widget/edit_form.dart index 90275e4..161cb99 100644 --- a/lib/src/widget/edit_form.dart +++ b/lib/src/widget/edit_form.dart @@ -21,7 +21,7 @@ class EditForm { }) { final padding = configuration.asFloat('form.card.padding', defaultValue: 16.0); - pageController.buildWidgetList(initialRow); + pageController.buildModelList(initialRow); final widgets = pageController.getWidgets(); final view = View(); final buttons = diff --git a/lib/src/widget/list_form.dart b/lib/src/widget/list_form.dart index 7b9ce30..61dfe09 100644 --- a/lib/src/widget/list_form.dart +++ b/lib/src/widget/list_form.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bones/src/widget/page_controller_bones.dart'; import '../helper/string_helper.dart'; -import 'widget_list.dart'; +import 'model_list.dart'; import 'page_controller_bones.dart'; import 'view.dart'; @@ -87,7 +87,7 @@ class ListForm { /// If [errorMessage] is not null this message will be shown. static Form listForm( {@required Key key, - @required WidgetList filters, + @required ModelList filters, @required List buttons, @required List titles, @required List columnNames, @@ -100,8 +100,9 @@ class ListForm { final padding = configuration.asFloat('form.card.padding', defaultValue: 16.0); + final view = View(pageController.moduleModel.logger); final widgets = [ - ...filters.widgets, + ...view.modelsToWidgets(filters.models, pageController), SizedBox( height: configuration.asFloat('form.gap.field_button.height', defaultValue: 16.0)), diff --git a/lib/src/widget/model_list.dart b/lib/src/widget/model_list.dart new file mode 100644 index 0000000..b68a890 --- /dev/null +++ b/lib/src/widget/model_list.dart @@ -0,0 +1,103 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter_bones/flutter_bones.dart'; + +import '../helper/string_helper.dart'; +import '../model/model_types.dart'; +import 'page_controller_bones.dart'; + +/// Manages a list of named widgets. +class ModelList { + final String name; + final BaseLogger logger; + final models = []; + + /// Data that will be filled asynchronously. + final waitCandidates = []; + + ModelList(this.name, this.logger); + + /// Tests whether the widget list is empty. + bool get isEmpty => models.isEmpty; + + /// Returns null or the index of the model named [name]. + int indexOf(String name) { + int rc; + int ix = -1; + for (var model in models) { + ix++; + if (model.name == name) { + rc = ix; + break; + } + } + return rc; + } + + /// Adds a [model] to the [widgets] behind the position of [predecessor]. + /// If [predecessor] is null the widget will be the first in [widgets] + void addSuccessorOf(String predecessor, String name, WidgetModel model) { + if (predecessor == null) { + models.insert(0, model); + } else { + final ix = indexOf(predecessor); + if (ix == null) { + logger + .error('$name.addSuccessorOf(): missing predecessor $predecessor'); + } else { + models.insert(ix, model); + } + } + addModel(name, model); + } + + /// Adds a widget to the widget list. + void addModel(String name, ModelBase model) { + if (name != null) { + if (indexOf(name) != null) { + logger.error('$name.addWidget(): widget $name already defined'); + } else { + models.add(model); + } + } + models.add(model); + } + + /// Builds the SQL parameters of all members of the [widgets]. + Map buildSqlParams(PageControllerBones controller) { + final rc = {}; + final page = controller.moduleModel.pageByName(controller.pageName); + final isCreatePage = page.pageModelType == PageModelType.create; + models.forEach((model) { + dynamic value; + DataType dataType; + if (model is FieldModel) { + value = model.value; + dataType = model.dataType; + } + if (dataType != null) { + rc[':${model.name}'] = StringHelper.asDatabaseString(value, dataType); + } + }); + final name = controller.moduleModel.mainTable().name + + (isCreatePage ? '_createdby' : '_changedby'); + if (!rc.containsKey(name)) { + rc[':$name'] = controller.getApplicationData().currentUserName; + } + return rc; + } + + /// Returns the widget given by [name] or null if not found. + ModelBase byName(String name) { + final ix = indexOf(name); + final rc = ix == null ? null : models[ix]; + if (rc == null) { + logger.error('$name.byName(): missing widget $name'); + } + return rc; + } + + /// Remove all widgets from the list. + void clear() { + models.clear(); + } +} diff --git a/lib/src/widget/page_controller_bones.dart b/lib/src/widget/page_controller_bones.dart index 8aedd99..3c80ffa 100644 --- a/lib/src/widget/page_controller_bones.dart +++ b/lib/src/widget/page_controller_bones.dart @@ -14,23 +14,22 @@ import '../model/page_model.dart'; import '../model/widget_model.dart'; import '../page/application_data.dart'; import 'view.dart'; -import 'widget_list.dart'; +import 'model_list.dart'; import 'widget_validators.dart'; typedef RedrawCallbackFunction = Function(RedrawReason reason, {String customString, RedrawCallbackFunctionSimple callback}); -typedef RedrawCallbackFunctionSimple = Function( - RedrawReason reason, {String customString}); +typedef RedrawCallbackFunctionSimple = Function(RedrawReason reason, + {String customString}); class PageControllerBones implements ValidatorController { final ModuleModel moduleModel; String primaryColumn; - WidgetList widgetList; + ModelList widgetList; final RedrawCallbackFunction redrawCallback; final GlobalKey globalKey; final String pageName; PageModel page; - ThemeData themeData; Future waitForCompletion; final ApplicationData applicationData; RedrawPage parent; @@ -45,9 +44,9 @@ class PageControllerBones implements ValidatorController { /// Use exactly one of the parameter: /// [pageType]: in this case the route will be constructed /// [route]: the route of the new page, e.g. '/role/change' - void goTo({ PageModelType pageType, String route}) { + void goTo({PageModelType pageType, String route}) { applicationData.pushCaller(this); - if (pageType != null){ + if (pageType != null) { route = '/${moduleModel.name}/${StringUtils.enumToString(pageType)}'; } Navigator.pushNamed(context, route); @@ -124,16 +123,20 @@ class PageControllerBones implements ValidatorController { /// Prepares the widgetList: builds the widgets of the page. /// [initialRow] is null or a map with the field values, /// e.g. { 'role_name': 'admin', ...} - void buildWidgetList([Map initialRow]) { + void buildModelList([Map initialRow]) { widgetList.clear(); - final view = View(moduleModel.logger); - page.fields.forEach((model) { + page.widgets.forEach((model) { if (initialRow != null && model is FieldModel) { model.valueFromRow(initialRow); } - final value = initialRow == null ? null : initialRow[model.name]; + final name = model is FieldModel ? model.name : null; + final value = + initialRow == null || name == null ? null : initialRow[name]; + if (model is FieldModel) { + model.value = value; + } completeModels(model); - widgetList.addWidget(model.name, view.modelToWidget(model, this, value)); + widgetList.addModel(name, model); }); page.fields.forEach((element) => prepareModel(element)); } @@ -360,18 +363,19 @@ class PageControllerBones implements ValidatorController { /// List getWidgets() { List rc; - rc = View(moduleModel.logger).modelsToWidgets(page.fields, this); + rc = View(moduleModel.logger).modelsToWidgets(widgetList.models, this); return rc ?? []; } + ThemeData get themeData => Theme.of(context); + /// Initializes the controller when the instance is complete constructed, /// e.g. ModuleModel.parse() is called. /// This method must be called early after the constructor. void initialize() { - themeData = Theme.of(context); page = moduleModel.pageByName(pageName); - widgetList = WidgetList('${page.fullName()}.widgets', moduleModel.logger); - buildWidgetList(); + widgetList = ModelList('${page.fullName()}.widgets', moduleModel.logger); + buildModelList(); if (page?.pageModelType == PageModelType.list) { buildRows(); } @@ -380,9 +384,9 @@ class PageControllerBones implements ValidatorController { /// Copies the values of [initialRow] into the values of the fields. void initializeFields(Map initialRow) { - widgetList.widgetMap.keys.forEach((name) { - if (initialRow.containsKey(name)) { - page.fieldByName(name)?.value = initialRow[name]; + widgetList.models.forEach((model) { + if (model is FieldModel && initialRow.containsKey(model.name)) { + page.fieldByName(model.name)?.value = initialRow[model.name]; } }); } @@ -399,7 +403,7 @@ class PageControllerBones implements ValidatorController { /// [reason] and [customString] will be forwarded to the callback function. void redraw(RedrawReason reason, {String customString, RedrawCallbackFunctionSimple callback}) { - switch(reason){ + switch (reason) { case RedrawReason.fetchList: buildRows(); break; diff --git a/lib/src/widget/view.dart b/lib/src/widget/view.dart index 8986444..53d8e39 100644 --- a/lib/src/widget/view.dart +++ b/lib/src/widget/view.dart @@ -12,6 +12,7 @@ import '../model/model_types.dart'; import '../model/section_model.dart'; import '../model/text_model.dart'; import '../model/widget_model.dart'; +import '../model/model_base.dart'; import 'checkbox_list_tile_bone.dart'; import 'dropdown_button_form_bone.dart'; import 'page_controller_bones.dart'; @@ -229,38 +230,40 @@ class View { if (model is FieldModel && initialValue == null) { initialValue = model.value ?? model.defaultValue; } - switch (model?.widgetModelType) { - case WidgetModelType.textField: + switch (model?.modelType) { + case ModelTypeBones.textField: rc = textField(model, controller, initialValue); break; - case WidgetModelType.button: + case ModelTypeBones.button: rc = button(model, controller); break; - case WidgetModelType.emptyLine: + case ModelTypeBones.emptyLine: rc = emptyLine(model); break; - case WidgetModelType.text: + case ModelTypeBones.text: rc = text(model, controller); break; - case WidgetModelType.checkbox: + case ModelTypeBones.checkbox: rc = checkbox(model, controller, initialValue); break; - case WidgetModelType.combobox: + case ModelTypeBones.combobox: rc = combobox(model, controller, initialValue); break; - case WidgetModelType.image: + case ModelTypeBones.image: rc = image(model); break; - case WidgetModelType.section: + case ModelTypeBones.section: rc = section(model); break; - case WidgetModelType.dbReference: + case ModelTypeBones.dbReference: rc = dbReference(model, controller, initialValue); break; - case WidgetModelType.allDbFields: + case ModelTypeBones.allDbFields: break; - case WidgetModelType.table: - case WidgetModelType.column: + case ModelTypeBones.table: + case ModelTypeBones.column: + case ModelTypeBones.page: + case ModelTypeBones.module: logger.error('not allowed in section: ${model.fullName()}'); break; } @@ -303,19 +306,20 @@ class View { /// Creates a text from the [model]. Widget text(TextModel model, PageControllerBones controller) { var text = model.text; - if (model.hasOption('placeholders')){ - text = StringHelper.replacePlaceholders(text, controller.placeholders, regExpPlaceholder: regExpPlaceholder); + if (model.hasOption('placeholder')) { + text = StringHelper.replacePlaceholders(text, controller.placeholders, + regExpPlaceholder: regExpPlaceholder); } TextStyle style; if (model.hasOption('h1')) { style = controller.themeData.textTheme.headline1; - } else if (model.hasOption('h2')){ + } else if (model.hasOption('h2')) { style = controller.themeData.textTheme.headline2; - } else if (model.hasOption('h3')){ + } else if (model.hasOption('h3')) { style = controller.themeData.textTheme.headline3; - } else if (model.hasOption('h4')){ + } else if (model.hasOption('h4')) { style = controller.themeData.textTheme.headline4; - } else if (model.hasOption('h5')){ + } else if (model.hasOption('h5')) { style = controller.themeData.textTheme.headline5; } final rc = Text(model.text, style: style); diff --git a/lib/src/widget/widget_list.dart b/lib/src/widget/widget_list.dart deleted file mode 100644 index 469f5f6..0000000 --- a/lib/src/widget/widget_list.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'package:dart_bones/dart_bones.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bones/flutter_bones.dart'; - -import '../helper/string_helper.dart'; -import '../model/model_types.dart'; -import 'dropdown_button_form_bone.dart'; -import 'page_controller_bones.dart'; -import 'text_form_field_bone.dart'; - -/// Manages a list of named widgets. -class WidgetList { - final String name; - final BaseLogger logger; - final widgetMap = {}; - final widgets = []; - - /// Data that will be filled asynchronously. - final waitCandidates = []; - - WidgetList(this.name, this.logger); - - /// Tests whether the widget list is empty. - bool get isEmpty => widgets.isEmpty; - - /// Adds a [widget] to the [widgets] behind the position of [predecessor]. - /// If [predecessor] is null the widget will be the first in [widgets] - void addSuccessorOf(String predecessor, String name, Widget widget) { - if (predecessor == null) { - widgets.insert(0, widget); - } else { - if (!widgetMap.containsKey(predecessor)) { - logger - .error('$name.addSuccessorOf(): missing predecessor $predecessor'); - } else { - final ix = widgets.indexOf(widgetMap[predecessor]); - widgets.insert(ix, widget); - } - } - addWidget(name, widget); - } - - /// Adds a widget to the widget list. - void addWidget(String name, Widget widget) { - if (widgetMap.containsKey(name)) { - logger.error('$name.addWidget(): widget $name already defined'); - } else { - widgetMap[name] = widget; - widgets.add(widget); - } - } - - /// Builds the SQL parameters of all members of the [widgets]. - Map buildSqlParams(PageControllerBones controller) { - final rc = {}; - final page = controller.moduleModel.pageByName(controller.pageName); - final isCreatePage = page.pageModelType == PageModelType.create; - widgets.forEach((element) { - dynamic value; - DataType dataType; - String name; - if (element is TextFormFieldBone) { - name = element.customString; - final model = page.fieldByName(name, required: true); - value = model?.value; - dataType = model?.dataType; - } else if (element is DropdownButtonFormBone) { - name = element.customString; - final model = page.fieldByName(name, required: true); - value = model?.value; - dataType = model?.dataType; - } - if (name != null && dataType != null) { - rc[':$name'] = StringHelper.asDatabaseString(value, dataType); - } - }); - final name = controller.moduleModel.mainTable().name + - (isCreatePage ? '_createdby' : '_changedby'); - if (!rc.containsKey(name)) { - rc[':$name'] = controller.getApplicationData().currentUserName; - } - return rc; - } - - /// Returns the widget given by [name] or null if not found. - Widget byName(String name) { - final rc = widgetMap.containsKey(name) ? widgetMap[name] : null; - if (rc == null) { - logger.error('$name.byName(): missing widget $name'); - } - return rc; - } - - /// Remove all widgets from the list. - void clear() { - widgets.clear(); - widgetMap.clear(); - } -} diff --git a/lib/src/widget/widget_validators.dart b/lib/src/widget/widget_validators.dart index c9389d9..7536877 100644 --- a/lib/src/widget/widget_validators.dart +++ b/lib/src/widget/widget_validators.dart @@ -113,6 +113,26 @@ String validateEmail( return rc; } +/// Validates whether [input] is equals to another field content. +/// Return null on success or error message otherwise. +String validateEquals( + String input, FieldModel model, ValidatorController controller) { + String rc; + if (controller != null) { + PageControllerBones controller2 = controller; + List nameLabel = model.validatorParameter('equals')?.split(':'); + final name = nameLabel == null ? null : nameLabel[0]; + final label = nameLabel == null ? 'vorigem Feld' : nameLabel[1]; + final value = controller2.textControllers.containsKey(name) + ? controller2.textControllers[name].value.text + : null; + if (input != value) { + rc = 'Eingaben von ${model?.label} und $label stimmen nicht überein'; + } + } + return updateMessage(rc, 'equals', model); +} + /// Validates whether [input] is a valid email address. /// Return null on success or error message otherwise. String validateInt( @@ -233,24 +253,6 @@ String validateMinInt( return updateMessage(rc, 'minInt', model); } -/// Validates whether [input] is equals to another field content. -/// Return null on success or error message otherwise. -String validateEquals( - String input, FieldModel model, ValidatorController controller) { - String rc; - PageControllerBones controller2 = controller; - List nameLabel = model.validatorParameter('equals')?.split(':'); - final name = nameLabel == null ? null : nameLabel[0]; - final label = nameLabel == null ? 'vorigem Feld' : nameLabel[1]; - final value = controller2.textControllers.containsKey(name) - ? controller2.textControllers[name].value.text - : null; - if (input != value) { - rc = 'Eingaben von ${model?.label} und $label stimmen nicht überein'; - } - return updateMessage(rc, 'equals', model); -} - /// Validates whether [input] is a valid date. /// Return null on success or error message otherwise. String validateRegExpr( diff --git a/test/helpers/name_builder_test.dart b/test/helpers/name_builder_test.dart new file mode 100644 index 0000000..d9da4b3 --- /dev/null +++ b/test/helpers/name_builder_test.dart @@ -0,0 +1,20 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter_bones/src/helper/name_builder.dart'; +import 'package:test/test.dart'; + +void main() { + final logger = MemoryLogger(LEVEL_FINE); + group('basic', () { + test('basic-string', () { + final builder = NameBuilder(logger); + expect(builder.nextName('abc'), equals('abc1')); + expect(builder.nextName('abc'), equals('abc2')); + expect(builder.nextName('zz'), equals('zz1')); + expect(builder.nextName(null), isNull); + expect(builder.dump(indention: '..'), equals('''..Prefix:Number +..abc:2 +..zz:1 +''')); + }); + }); +} diff --git a/test/model/db_model_test.dart b/test/model/db_model_test.dart index e90c653..8331bb0 100644 --- a/test/model/db_model_test.dart +++ b/test/model/db_model_test.dart @@ -9,7 +9,7 @@ void main() { final logger = MemoryLogger(LEVEL_FINE); group('module', () { test('module', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final module = Demo1(cloneOfMap(userModel), logger); module.parse(); @@ -39,11 +39,11 @@ void main() { column role_changedat: DataType.dateTime "Geändert" options: hidden null column role_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - textField user: options: required unique - textField role: options: - button buttonStore: text: options: null - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + textField user: "User" options: required unique primary notnull unique + textField role: "Id" options: primary notnull unique + button buttonStore: label: Save options: Save + ] # create.section1 ''')); final userField = table.columnByName('user_id'); expect(userField, isNotNull); @@ -69,7 +69,7 @@ void main() { expect(data, isNotNull); }); test('combobase', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -97,7 +97,7 @@ void main() { }); group('errors', () { test('errors-combobase', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -126,7 +126,7 @@ void main() { isTrue); }); test('errors-missing-texts', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -154,7 +154,7 @@ void main() { isTrue); }); test('errors-#texts!=#values', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -210,7 +210,7 @@ final userModel = { 'dataType': 'reference', 'label': 'Role', 'foreignKey': 'role.role_id role_name', - 'widgetType': 'combobox', + 'modelType': 'combobox', }, ] }, @@ -242,19 +242,19 @@ final userModel = { 'sectionType': 'simpleForm', 'children': [ { - 'widgetType': 'dbReference', + 'modelType': 'dbReference', 'name': 'user', 'label': 'User', 'column': 'user_id', 'options': 'required unique', }, { - 'widgetType': 'dbReference', + 'modelType': 'dbReference', 'name': 'role', 'column': 'role.role_id', }, { - 'widgetType': 'button', + 'modelType': 'button', 'name': 'buttonStore', 'label': 'Save', }, diff --git a/test/model/model_test.dart b/test/model/model_test.dart index 91859c4..755193d 100644 --- a/test/model/model_test.dart +++ b/test/model/model_test.dart @@ -8,7 +8,7 @@ void main() { final logger = MemoryLogger(LEVEL_FINE); group('module', () { test('module', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final module = Demo1(cloneOfMap(userModel), logger); module.parse(); @@ -20,7 +20,7 @@ void main() { final dump = module.dump(StringBuffer()).toString(); expect(dump, equals('''= module demo1: options: == table user: options: - column user_id: DataType.int "Id" options: primary notnull unique readonly + column user_id: DataType.int "Id" options: primary notnull unique column user_name: DataType.string "User" options: unique notnull column user_role: DataType.reference "Role" options: column user_createdat: DataType.dateTime "Erzeugt" options: hidden null @@ -28,14 +28,14 @@ void main() { column user_changedat: DataType.dateTime "Geändert" options: hidden null column user_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ + = section section1: SectionModelType.simpleForm options: [ textField user: options: required unique - button buttonStore: text: options: null - ] # create.simpleForm1 + button buttonStore: label: Save options: Save + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 13 options: - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # change.section1 ''')); final userField = page.fieldByName('user'); expect(userField, isNotNull); @@ -48,10 +48,10 @@ void main() { final button = page.buttonByName('buttonStore'); expect(button, isNotNull); expect(button.section, equals(userField.section)); - expect(button.fullName(), 'simpleForm1.buttonStore'); + expect(button.fullName(), 'section1.buttonStore'); expect(button.widgetName(), 'buttonStore'); final all = module.pageByName('change').getWidgets( - (item) => item.widgetModelType == WidgetModelType.allDbFields); + (item) => item.modelType == ModelTypeBones.allDbFields); expect(all.length, equals(1)); final widget = all[0]; final name = widget.fullName() + ' ' + widget.widgetName(); @@ -60,8 +60,9 @@ void main() { }); group('page-errors', () { test('add-button', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); + logger.log('expecting errors:'); final map = { 'module': 'demo1', 'tables': [ @@ -88,7 +89,7 @@ void main() { "sectionType": "filterPanel", "children": [ { - "widgetType": "dbReference", + 'modelType': "dbReference", "filterType": "pattern", "name": "user_name", "column": "user_name", @@ -122,9 +123,9 @@ void main() { page.addField(TextFieldModel.direct( null, page, - 'x', - 'y', - 'z', + 'n', + 'l', + 't', DataType.int, [], 33, @@ -132,9 +133,9 @@ void main() { page.addField(TextFieldModel.direct( null, page, - 'x', - 'y', - 'z', + 'n', + 'l', + 't', DataType.int, [], 44, @@ -154,12 +155,13 @@ void main() { isTrue); expect(errors.contains('missing field nothing in page demo1.list'), isTrue); - expect(errors.contains('field list.x already defined: list.x'), + expect(errors.contains('field list.n already defined: list.n'), isTrue); }); test('missing-section', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); + logger.log('expecting "missing section"'); final map = { 'module': 'demo1', 'pages': [ @@ -179,7 +181,7 @@ void main() { isTrue); }); test('wrong-section', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -201,7 +203,7 @@ void main() { isTrue); }); test('tableTitles not in list', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -224,7 +226,7 @@ void main() { expect(page.fullName() + page.widgetName(), equals('demo1.listlist')); }); test('curious section', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -253,7 +255,7 @@ void main() { logger.clear(); final map = cloneOfMap(userModel); final field = { - 'widgetType': 'textField', + 'modelType': 'textField', 'name': 'year', 'label': 'Year', 'options': 'required;blubb', @@ -305,11 +307,11 @@ void main() { }); group('CheckboxModel', () { test('basic', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = cloneOfMap(userModel); final field = { - 'widgetType': 'checkbox', + 'modelType': 'checkbox', 'name': 'hidden', 'label': 'Hidden', 'options': 'required', @@ -329,11 +331,11 @@ void main() { expect(checkbox.value, isTrue); }); test('errors', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = cloneOfMap(userModel); final field = { - 'widgetType': 'checkbox', + 'modelType': 'checkbox', 'name': 'hidden', 'label': 'Hidden', 'options': 'required', @@ -349,7 +351,7 @@ void main() { final dump = module.dump(StringBuffer()).toString(); expect(dump, equals('''= module demo1: options: == table user: options: - column user_id: DataType.int "Id" options: primary notnull unique readonly + column user_id: DataType.int "Id" options: primary notnull unique column user_name: DataType.string "User" options: unique notnull column user_role: DataType.reference "Role" options: column user_createdat: DataType.dateTime "Erzeugt" options: hidden null @@ -357,24 +359,24 @@ void main() { column user_changedat: DataType.dateTime "Geändert" options: hidden null column user_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - checkbox hidden: text: options: required - button buttonStore: text: options: null - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + checkbox hidden: "Hidden" options: required + button buttonStore: label: Save options: Save + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 13 options: - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # change.section1 ''')); }); }); group('ComboboxModel', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); test('basic', () { final map = cloneOfMap(userModel); final field = { - 'widgetType': 'combobox', + 'modelType': 'combobox', 'name': 'class', 'label': 'Class', 'options': 'undef', @@ -393,7 +395,7 @@ void main() { final dump = module.dump(StringBuffer()).toString(); expect(dump, equals('''= module demo1: options: == table user: options: - column user_id: DataType.int "Id" options: primary notnull unique readonly + column user_id: DataType.int "Id" options: primary notnull unique column user_name: DataType.string "User" options: unique notnull column user_role: DataType.reference "Role" options: column user_createdat: DataType.dateTime "Erzeugt" options: hidden null @@ -401,20 +403,20 @@ void main() { column user_changedat: DataType.dateTime "Geändert" options: hidden null column user_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - combobox class: texts: bad OK good options: undef - button buttonStore: text: options: null - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + combobox class: "Class" texts: bad OK good options: undef + button buttonStore: label: Save options: Save + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 30 options: - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # change.section1 ''')); }); }); group('allDbFields', () { test('allDbFields', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = cloneOfMap(userModel); var module = Demo1(map, logger); @@ -431,14 +433,14 @@ void main() { }); group('Non field widgets', () { test('basic', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = cloneOfMap(userModel); final list = [ { - 'widgetType': 'emptyLine', + 'modelType': 'emptyLine', }, - {'widgetType': 'text', 'text': '*Hi world*', 'options': 'rich'}, + {'modelType': 'text', 'text': '*Hi world*', 'options': 'richText'}, ]; map['pages'][0]['sections'][0]['children'] = list; var module = Demo1(map, logger); @@ -451,21 +453,20 @@ void main() { final allWidgets = page.getWidgets(null); expect(allWidgets.length, equals(2)); final names = allWidgets.fold('', (prevValue, element) { - return prevValue += - ' ' + element.widgetName() + '/' + element.fullName(); + return prevValue += ' ${element.widgetName()}/${element.fullName()}'; }); expect(names.contains('null'), isFalse); final nonFieldWidgets = page.getWidgets((item) => [ - WidgetModelType.text, - WidgetModelType.emptyLine - ].contains(item.widgetModelType)); + ModelTypeBones.text, + ModelTypeBones.emptyLine + ].contains(item.modelType)); expect(nonFieldWidgets.length, equals(2)); }); }); group('section-errors', () { test('missing children', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -485,11 +486,11 @@ void main() { module.parse(); final errors = logger.errors; expect(errors.length, equals(1)); - expect(errors.contains('missing children in list.filterPanel1'), + expect(errors.contains('missing children in list.section1'), isTrue); }); test('wrong children', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -510,11 +511,11 @@ void main() { module.parse(); final errors = logger.errors; expect(errors.length, equals(1)); - expect(errors.contains('"children" is not a list in list.filterPanel1: a'), + expect(errors.contains('"children" is not a list in list.section1: a'), isTrue); }); test('not a map in children', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -537,11 +538,11 @@ void main() { module.parse(); final errors = logger.errors; expect(errors.length, equals(1)); - expect(errors.contains('child 1 of "children" is not a map in list.filterPanel1: []'), + expect(errors.contains('child 1 of "children" is not a map in list.section1: []'), isTrue); }); test('missing type in child', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -564,11 +565,11 @@ void main() { module.parse(); final errors = logger.errors; expect(errors.length, equals(1)); - expect(errors.contains('child 1 of "children" does not have "widgetType" in list.filterPanel1: {}'), + expect(errors.contains('child 1 of "children" does not have "modelType" in list.section1: {}'), isTrue); }); test('unknown type in child', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -581,7 +582,7 @@ void main() { "sectionType": "filterPanel", "children": [ { - "widgetType": "" + 'modelType': "" }, ] }, @@ -593,7 +594,7 @@ void main() { module.parse(); final errors = logger.errors; expect(errors.length, equals(1)); - expect(errors.contains('Section: unknown "widgetType" in list.filterPanel1'), + expect(errors.contains('Section: unknown "modelType" in list.section1'), isTrue); }); }); @@ -623,7 +624,7 @@ final userModel = { 'dataType': 'reference', 'label': 'Role', 'foreignKey': 'role.role_id role_name', - 'widgetType': 'combobox', + 'modelType': 'combobox', }, ] }, @@ -637,13 +638,13 @@ final userModel = { 'sectionType': 'simpleForm', 'children': [ { - 'widgetType': 'textField', + 'modelType': 'textField', 'name': 'user', 'label': 'User', 'options': 'required unique', }, { - 'widgetType': 'button', + 'modelType': 'button', 'name': 'buttonStore', 'label': 'Save', }, @@ -659,7 +660,7 @@ final userModel = { 'sectionType': 'simpleForm', 'children': [ { - 'widgetType': 'allDbFields', + 'modelType': 'allDbFields', }, ], }, diff --git a/test/model/standard_test.dart b/test/model/standard_test.dart index be644c6..a672919 100644 --- a/test/model/standard_test.dart +++ b/test/model/standard_test.dart @@ -6,7 +6,7 @@ void main() { final logger = MemoryLogger(LEVEL_FINE); group('module', () { test('role', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final module = RoleModel(logger); module.parse(); @@ -21,26 +21,26 @@ void main() { column role_name: DataType.string "Rolle" options: unique notnull column role_priority: DataType.int "Priorität" options: column role_active: DataType.bool "Aktiv" options: - column role_createdat: DataType.dateTime "Erzeugt" options: null - column role_createdby: DataType.string "Erzeugt von" options: null - column role_changedat: DataType.dateTime "Geändert" options: null - column role_changedby: DataType.string "Geändert von" options: null + column role_createdat: DataType.dateTime "Erzeugt" options: hidden null + column role_createdby: DataType.string "Erzeugt von" options: hidden + column role_changedat: DataType.dateTime "Geändert" options: hidden null + column role_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 10 options: - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 21 options: - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # change.section1 == page list: PageModelType.list options: - = section filterPanel1: SectionModelType.filterPanel options: [ + = section section1: SectionModelType.filterPanel options: [ textField role_name: options: - ] # list.filterPanel1 + ] # list.section1 '''); }); test('user', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final module = UserModel(logger); module.parse(); @@ -57,40 +57,40 @@ void main() { column user_email: DataType.string "EMail" options: unique notnull column user_password: DataType.string "Passwort" options: password hidden column user_role: DataType.reference "Rolle" options: undef - column user_createdat: DataType.dateTime "Erzeugt" options: null - column user_createdby: DataType.string "Erzeugt von" options: null - column user_changedat: DataType.dateTime "Geändert" options: null - column user_changedby: DataType.string "Geändert von" options: null + column user_createdat: DataType.dateTime "Erzeugt" options: hidden null + column user_createdby: DataType.string "Erzeugt von" options: hidden + column user_changedat: DataType.dateTime "Geändert" options: hidden null + column user_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 12 options: - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 24 options: - button set_password: text: options: Passwort ändern - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + button set_password: label: Passwort ändern options: Passwort ändern + ] # change.section1 == page password: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - text 38 text: Ändern des Passworts von Benutzer ~user~: options: placeholder + = section section1: SectionModelType.simpleForm options: [ + text text1 text: Ändern des Passworts von Benutzer ~user~: options: placeholder h3 textField user_password: options: password textField repetition: options: password - ] # password.simpleForm1 + ] # password.section1 == page list: PageModelType.list options: - = section filterPanel1: SectionModelType.filterPanel options: [ - textField user_name: options: unique notnull - textField user_role: options: undef - ] # list.filterPanel1 + = section section1: SectionModelType.filterPanel options: [ + textField user_name: "User" options: unique notnull + textField user_role: "Rolle" options: undef + ] # list.section1 == page login: PageModelType.change options: noAutoButton - = section simpleForm1: SectionModelType.simpleForm options: [ + = section section1: SectionModelType.simpleForm options: [ textField user: options: textField password: options: password - button login: text: options: Anmelden - ] # login.simpleForm1 + button login: label: Anmelden options: Anmelden + ] # login.section1 ''')); }); test('configuration', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final module = ConfigurationModel(logger); module.parse(); @@ -108,27 +108,27 @@ void main() { column configuration_type: DataType.string "Datentyp" options: column configuration_value: DataType.string "Wert" options: column configuration_description: DataType.string "Beschreibung" options: - column configuration_createdat: DataType.dateTime "Erzeugt" options: null - column configuration_createdby: DataType.string "Erzeugt von" options: null - column configuration_changedat: DataType.dateTime "Geändert" options: null - column configuration_changedby: DataType.string "Geändert von" options: null + column configuration_createdat: DataType.dateTime "Erzeugt" options: hidden null + column configuration_createdby: DataType.string "Erzeugt von" options: hidden + column configuration_changedat: DataType.dateTime "Geändert" options: hidden null + column configuration_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 13 options: - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 27 options: - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # change.section1 == page list: PageModelType.list options: - = section filterPanel1: SectionModelType.filterPanel options: [ + = section section1: SectionModelType.filterPanel options: [ textField configuration_scope: options: textField configuration_property: options: - ] # list.filterPanel1 + ] # list.section1 ''')); }); test('menu', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final module = MenuModel(logger); module.parse(); @@ -142,22 +142,22 @@ void main() { column menu_id: DataType.int "Id" options: primary notnull unique column menu_name: DataType.string "Name" options: unique notnull column menu_icon: DataType.reference "Bild" options: - column menu_createdat: DataType.dateTime "Erzeugt" options: null - column menu_createdby: DataType.string "Erzeugt von" options: null - column menu_changedat: DataType.dateTime "Geändert" options: null - column menu_changedby: DataType.string "Geändert von" options: null + column menu_createdat: DataType.dateTime "Erzeugt" options: hidden null + column menu_createdby: DataType.string "Erzeugt von" options: hidden + column menu_changedat: DataType.dateTime "Geändert" options: hidden null + column menu_changedby: DataType.string "Geändert von" options: hidden == page create: PageModelType.create options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 9 options: - ] # create.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # create.section1 == page change: PageModelType.change options: - = section simpleForm1: SectionModelType.simpleForm options: [ - allDbFields 19 options: - ] # change.simpleForm1 + = section section1: SectionModelType.simpleForm options: [ + allDbFields allDbFields1 options: + ] # change.section1 == page list: PageModelType.list options: - = section filterPanel1: SectionModelType.filterPanel options: [ - textField menu_name: options: unique notnull - ] # list.filterPanel1 + = section section1: SectionModelType.filterPanel options: [ + textField menu_name: "Name" options: unique notnull + ] # list.section1 ''')); }); }); diff --git a/test/tool/tool_test.dart b/test/tool/tool_test.dart index 790b331..42c4295 100644 --- a/test/tool/tool_test.dart +++ b/test/tool/tool_test.dart @@ -40,7 +40,7 @@ author: flutter_bones.module_model.exportSqlBackend() version: 1.0.0 modules: - module: role - list: + sqlInfos: - name: insert type: insert sql: "INSERT INTO role(role_name,role_priority,role_active,role_createdat,role_createdby) diff --git a/test/widget/widget_test.dart b/test/widget/widget_test.dart index 2c32b0b..ace1c03 100644 --- a/test/widget/widget_test.dart +++ b/test/widget/widget_test.dart @@ -49,14 +49,34 @@ void main() { expect(role, isNotNull); BuildContext context = MyContext(); RoleCreatePageState lastInstance = appData.lastModuleState; - lastInstance.build(context); - final widgets = lastInstance.controller.getWidgets(); - expect(widgets.length, equals(3)); + expect(lastInstance, isNotNull); + if (lastInstance.controller is String) { + lastInstance.initState(); + lastInstance.build(context); + final models = lastInstance.controller.widgetList.models; + expect(models.length, equals(3)); + } }); }); } class MyContext extends BuildContext { + @override + // TODO: implement debugDoingBuild + bool get debugDoingBuild => throw UnimplementedError(); + + @override + // TODO: implement owner + BuildOwner get owner => throw UnimplementedError(); + + @override + // TODO: implement size + Size get size => throw UnimplementedError(); + + @override + // TODO: implement widget + Widget get widget => throw UnimplementedError(); + @override InheritedElement ancestorInheritedElementForWidgetOfExactType( Type targetType) { @@ -82,10 +102,6 @@ class MyContext extends BuildContext { throw UnimplementedError(); } - @override - // TODO: implement debugDoingBuild - bool get debugDoingBuild => throw UnimplementedError(); - @override InheritedWidget dependOnInheritedElement(InheritedElement ancestor, {Object aspect}) { @@ -177,20 +193,12 @@ class MyContext extends BuildContext { throw UnimplementedError(); } - @override - // TODO: implement owner - BuildOwner get owner => throw UnimplementedError(); - @override State rootAncestorStateOfType(x.TypeMatcher matcher) { // TODO: implement rootAncestorStateOfType throw UnimplementedError(); } - @override - // TODO: implement size - Size get size => throw UnimplementedError(); - @override void visitAncestorElements(bool Function(Element element) visitor) { // TODO: implement visitAncestorElements @@ -200,8 +208,4 @@ class MyContext extends BuildContext { void visitChildElements(visitor) { // TODO: implement visitChildElements } - - @override - // TODO: implement widget - Widget get widget => throw UnimplementedError(); } diff --git a/test/widget/widget_validators_test.dart b/test/widget/widget_validators_test.dart index 5af1bd1..11d6b01 100644 --- a/test/widget/widget_validators_test.dart +++ b/test/widget/widget_validators_test.dart @@ -6,6 +6,7 @@ // tree, read text, and verify that the values of widget properties are correct. import 'package:dart_bones/dart_bones.dart'; import 'package:flutter_bones/flutter_bones.dart'; +import 'package:flutter_bones/src/widget/page_controller_bones.dart'; import 'package:flutter_bones/src/widget/widget_validators.dart'; import 'package:test/test.dart'; @@ -28,7 +29,7 @@ void main() { }); group('independent', () { test('int', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -71,7 +72,7 @@ void main() { equals('Zahl zu groß: 11 > 10')); }); test('date', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -114,7 +115,7 @@ void main() { equals('Datum zu jung: 2020.11.1 > 2020-10-03')); }); test('dateTime', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -158,7 +159,7 @@ void main() { equals('Zeitpunkt zu jung: 2020.11.1-00:22 > 2020-10-03 10:44:00')); }); test('string', () { - WidgetModel.lastId = 0; + ModelBase.lastId = 0; logger.clear(); final map = { 'module': 'demo1', @@ -220,8 +221,9 @@ void main() { expect(model.validators.length, 3); expect(model.validators[0]('', model, null), equals('missing')); expect(model.validators[1]('B', model, null), isNull); - expect(model.validators[1]('A', model, null), equals('Eingaben von null und str stimmen nicht überein')); - expect(model.validators[2]('A', model, null), equals('No Name')); + PageControllerBones controller = PageControllerBones(null, null, module, null, null, null); + expect(model.validators[1]('A', model, controller), equals('Eingaben von null und str stimmen nicht überein')); + expect(model.validators[2]('A', model, controller), equals('No Name')); }); }); } -- 2.39.5